feat(integrations): stock-price tools and expanded Parallel surface#911
Conversation
Adds five new `stock_*` tools (quote, exchange_rate, options, crypto_series, commodity) backed by the financial-apis backend route, and four new `parallel_*` tools (chat, research, enrich, dataset) for the expanded Parallel API. Wires both surfaces into the researcher and planner agents so questions like "what is the price of BTC?" route to a dedicated data tool instead of the generic web search. New `integrations.stock_prices` toggle gates registration.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (1)
📝 WalkthroughWalkthroughExpanded integrations with new parallel tools and a new stock_prices integration; updated planner/researcher agent tool allowlists; added config toggle for stock_prices; and wired conditional runtime registration of the new tools. Changes
Sequence Diagram(s)sequenceDiagram
participant Agent as Agent (planner / researcher)
participant Runtime as Runtime / Tool Registry
participant Integration as Integration Client
participant Backend as Integrations Backend
Agent->>Runtime: Request plan or invoke tool (e.g., `parallel_research` / `stock_quote`)
Runtime->>Integration: Validate params, build payload, POST /agent-integrations/{parallel|stock}/...
Integration->>Backend: Forward POST to backend endpoint
Backend-->>Integration: 200 OK + JSON (result, costUsd, optional findallId)
Integration-->>Runtime: Return ToolResult (formatted text + cost metadata)
Runtime-->>Agent: Deliver ToolResult
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
src/openhuman/integrations/parallel.rs (1)
1-920: Consider splitting this file in a follow-up.The file now exceeds ~1200 lines (including tests). Per coding guidelines, source files should be ≤ ~500 lines. Consider extracting the new tools into a sibling file (e.g.,
parallel_advanced.rsorparallel_chat.rs+parallel_research.rs) to improve maintainability.This is a non-blocking suggestion for a future cleanup. As per coding guidelines: "Source files should be ≤ ~500 lines; split modules when growing to improve maintainability."
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/openhuman/integrations/parallel.rs` around lines 1 - 920, The file is too large; split the Parallel integration into smaller modules to meet the ≤~500-line guideline—extract related tools and their response types into new files and re-export them from the parent module. For example, move ParallelChatTool (plus ChatResponse/ChatChoice/ChatMessage), ParallelResearchTool (ResearchResponse), ParallelEnrichTool (EnrichResponse), and ParallelDatasetTool (DatasetResponse) into one or more new files (e.g., parallel_chat.rs, parallel_research.rs, parallel_enrich.rs / parallel_dataset.rs) while keeping ParallelSearchTool, ParallelExtractTool, and shared utilities (truncate_chars, IntegrationClient use, async_trait/serde imports) in the original file or a shared helpers file; update the module declarations to pub use or pub mod the new files and adjust imports (retain symbols: ParallelChatTool, ParallelResearchTool, ParallelEnrichTool, ParallelDatasetTool, ParallelSearchTool, ParallelExtractTool, truncate_chars, SearchResponse, ExtractResponse) so callers keep the same API.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@src/openhuman/integrations/parallel.rs`:
- Around line 1-920: The file is too large; split the Parallel integration into
smaller modules to meet the ≤~500-line guideline—extract related tools and their
response types into new files and re-export them from the parent module. For
example, move ParallelChatTool (plus ChatResponse/ChatChoice/ChatMessage),
ParallelResearchTool (ResearchResponse), ParallelEnrichTool (EnrichResponse),
and ParallelDatasetTool (DatasetResponse) into one or more new files (e.g.,
parallel_chat.rs, parallel_research.rs, parallel_enrich.rs /
parallel_dataset.rs) while keeping ParallelSearchTool, ParallelExtractTool, and
shared utilities (truncate_chars, IntegrationClient use, async_trait/serde
imports) in the original file or a shared helpers file; update the module
declarations to pub use or pub mod the new files and adjust imports (retain
symbols: ParallelChatTool, ParallelResearchTool, ParallelEnrichTool,
ParallelDatasetTool, ParallelSearchTool, ParallelExtractTool, truncate_chars,
SearchResponse, ExtractResponse) so callers keep the same API.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 4bcfbd35-cc73-4afd-9542-df8ae06b42e1
📒 Files selected for processing (7)
src/openhuman/agent/agents/planner/agent.tomlsrc/openhuman/agent/agents/researcher/agent.tomlsrc/openhuman/config/schema/tools.rssrc/openhuman/integrations/mod.rssrc/openhuman/integrations/parallel.rssrc/openhuman/integrations/stock_prices.rssrc/openhuman/tools/ops.rs
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/openhuman/tools/ops.rs`:
- Around line 303-338: Add unit tests that assert the tool registry includes the
new Parallel* (ParallelChatTool, ParallelResearchTool, ParallelEnrichTool,
ParallelDatasetTool) and Stock* (StockQuoteTool, StockExchangeRateTool,
StockOptionsTool, StockCryptoSeriesTool, StockCommodityTool) registrations when
their respective toggles (root_config.integrations.parallel.enabled and
root_config.integrations.stock_prices.enabled) are true, and that they are
absent when those toggles are false; locate the registry-building function that
pushes these tools (the code that calls
crate::openhuman::integrations::ParallelChatTool::new,
ParallelResearchTool::new, ParallelEnrichTool::new, ParallelDatasetTool::new,
StockQuoteTool::new, StockExchangeRateTool::new, StockOptionsTool::new,
StockCryptoSeriesTool::new, StockCommodityTool::new) and add focused tests that
construct a minimal root_config with toggles on/off, run the registry creation,
and assert presence/absence of the corresponding tool types (and add similar
assertions to the relevant JSON-RPC e2e test file if integration coverage is
required).
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 4794addf-1a59-43a6-ac83-19139a00a034
📒 Files selected for processing (2)
src/openhuman/config/schema/tools.rssrc/openhuman/tools/ops.rs
| tools.push(Box::new( | ||
| crate::openhuman::integrations::ParallelChatTool::new(Arc::clone(&client)), | ||
| )); | ||
| tools.push(Box::new( | ||
| crate::openhuman::integrations::ParallelResearchTool::new(Arc::clone(&client)), | ||
| )); | ||
| tools.push(Box::new( | ||
| crate::openhuman::integrations::ParallelEnrichTool::new(Arc::clone(&client)), | ||
| )); | ||
| tools.push(Box::new( | ||
| crate::openhuman::integrations::ParallelDatasetTool::new(Arc::clone(&client)), | ||
| )); | ||
| tracing::debug!("[integrations] registered parallel tools"); | ||
| } else { | ||
| tracing::debug!("[integrations] parallel disabled — skipping"); | ||
| } | ||
| if root_config.integrations.stock_prices.enabled { | ||
| tools.push(Box::new( | ||
| crate::openhuman::integrations::StockQuoteTool::new(Arc::clone(&client)), | ||
| )); | ||
| tools.push(Box::new( | ||
| crate::openhuman::integrations::StockExchangeRateTool::new(Arc::clone(&client)), | ||
| )); | ||
| tools.push(Box::new( | ||
| crate::openhuman::integrations::StockOptionsTool::new(Arc::clone(&client)), | ||
| )); | ||
| tools.push(Box::new( | ||
| crate::openhuman::integrations::StockCryptoSeriesTool::new(Arc::clone(&client)), | ||
| )); | ||
| tools.push(Box::new( | ||
| crate::openhuman::integrations::StockCommodityTool::new(Arc::clone(&client)), | ||
| )); | ||
| tracing::debug!("[integrations] registered stock_prices tools"); | ||
| } else { | ||
| tracing::debug!("[integrations] stock_prices disabled — skipping"); | ||
| } |
There was a problem hiding this comment.
Add regression tests for new toggle-gated tool registrations.
Lines 303-338 add nine new tool registrations, but this file’s tests do not assert presence/absence of these new parallel_* and stock_* tools under enabled/disabled toggles. Please add focused registry tests to lock this behavior.
✅ Suggested test scaffold
+ #[test]
+ fn all_tools_registers_new_parallel_and_stock_tools_when_enabled() {
+ let tmp = TempDir::new().unwrap();
+ let security = Arc::new(SecurityPolicy::default());
+ let mem_cfg = MemoryConfig {
+ backend: "markdown".into(),
+ ..MemoryConfig::default()
+ };
+ let mem: Arc<dyn Memory> =
+ Arc::from(crate::openhuman::memory::create_memory(&mem_cfg, tmp.path()).unwrap());
+ let browser = BrowserConfig::default();
+ let http = crate::openhuman::config::HttpRequestConfig::default();
+ let mut cfg = test_config(&tmp);
+ cfg.integrations.parallel.enabled = true;
+ cfg.integrations.stock_prices.enabled = true;
+
+ let tools = all_tools(
+ Arc::new(cfg.clone()),
+ &security,
+ mem,
+ &browser,
+ &http,
+ tmp.path(),
+ &HashMap::new(),
+ &cfg,
+ );
+ let names: Vec<&str> = tools.iter().map(|t| t.name()).collect();
+ for expected in [
+ "parallel_chat",
+ "parallel_research",
+ "parallel_enrich",
+ "parallel_dataset",
+ "stock_quote",
+ "stock_exchange_rate",
+ "stock_options",
+ "stock_crypto_series",
+ "stock_commodity",
+ ] {
+ assert!(names.contains(&expected), "{expected} must be registered; got: {names:?}");
+ }
+ }
+
+ #[test]
+ fn all_tools_skips_new_parallel_and_stock_tools_when_disabled() {
+ let tmp = TempDir::new().unwrap();
+ let security = Arc::new(SecurityPolicy::default());
+ let mem_cfg = MemoryConfig {
+ backend: "markdown".into(),
+ ..MemoryConfig::default()
+ };
+ let mem: Arc<dyn Memory> =
+ Arc::from(crate::openhuman::memory::create_memory(&mem_cfg, tmp.path()).unwrap());
+ let browser = BrowserConfig::default();
+ let http = crate::openhuman::config::HttpRequestConfig::default();
+ let mut cfg = test_config(&tmp);
+ cfg.integrations.parallel.enabled = false;
+ cfg.integrations.stock_prices.enabled = false;
+
+ let tools = all_tools(
+ Arc::new(cfg.clone()),
+ &security,
+ mem,
+ &browser,
+ &http,
+ tmp.path(),
+ &HashMap::new(),
+ &cfg,
+ );
+ let names: Vec<&str> = tools.iter().map(|t| t.name()).collect();
+ for unexpected in [
+ "parallel_chat",
+ "parallel_research",
+ "parallel_enrich",
+ "parallel_dataset",
+ "stock_quote",
+ "stock_exchange_rate",
+ "stock_options",
+ "stock_crypto_series",
+ "stock_commodity",
+ ] {
+ assert!(
+ !names.contains(&unexpected),
+ "{unexpected} must NOT be registered; got: {names:?}"
+ );
+ }
+ }As per coding guidelines: “Ship unit tests and coverage for behavior you are adding or changing before building additional features on top” and “Rust code must be unit-tested for new/changed behavior before stacking features; run via cargo test and extend tests/json_rpc_e2e.rs for RPC integration tests”.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/openhuman/tools/ops.rs` around lines 303 - 338, Add unit tests that
assert the tool registry includes the new Parallel* (ParallelChatTool,
ParallelResearchTool, ParallelEnrichTool, ParallelDatasetTool) and Stock*
(StockQuoteTool, StockExchangeRateTool, StockOptionsTool, StockCryptoSeriesTool,
StockCommodityTool) registrations when their respective toggles
(root_config.integrations.parallel.enabled and
root_config.integrations.stock_prices.enabled) are true, and that they are
absent when those toggles are false; locate the registry-building function that
pushes these tools (the code that calls
crate::openhuman::integrations::ParallelChatTool::new,
ParallelResearchTool::new, ParallelEnrichTool::new, ParallelDatasetTool::new,
StockQuoteTool::new, StockExchangeRateTool::new, StockOptionsTool::new,
StockCryptoSeriesTool::new, StockCommodityTool::new) and add focused tests that
construct a minimal root_config with toggles on/off, run the registry creation,
and assert presence/absence of the corresponding tool types (and add similar
assertions to the relevant JSON-RPC e2e test file if integration coverage is
required).
The two echo-style postprocess tests (whitespace-only context and
conversation context) shared the global LocalAiService singleton and
OPENHUMAN_OLLAMA_BASE_URL env var with sibling tests but did not
acquire LOCAL_AI_TEST_MUTEX, allowing another test's mock response
('Hello, world.') to leak in and fail the exact-equality assertion.
Summary
Add five
stock_*tools and four newparallel_*tools so research-style agents can answer questions like "what is the price of BTC?" with a dedicated market-data call instead of a generic web search, and tackle deeper, structured research without bouncing through search/extract loops.Backed by:
/agent-integrations/financial-apis/*Changes
New module —
src/openhuman/integrations/stock_prices.rs(5 tools, all backend-proxied):stock_quote—GLOBAL_QUOTEfor stocks/indices (AAPL, SPY)stock_exchange_rate— FX and crypto spot price (BTC/USD, EUR/USD) — the canonical "price of BTC" pathstock_options— realtime options chain (optional greeks)stock_crypto_series— daily OHLCVstock_commodity— WTI / BRENT / NATURAL_GASExtended —
src/openhuman/integrations/parallel.rs(4 new tools):parallel_chat— research-grounded chat (speed/lite/base/core)parallel_research— Task API deep research; blocks inline (wait=true)parallel_enrich— sync structured enrichment with required output schemaparallel_dataset— FindAll dataset generation, returnsfindall_idWiring:
IntegrationsConfig.stock_prices: IntegrationToggle(defaults on, like the others)tools/ops.rsregisters all new tools, gated by their respective togglesagents/researcher/agent.toml) gains the full Parallel + stock-prices surfaceagents/planner/agent.toml) gains read-only research and stock tools so plans can be grounded in real numbersPer the renaming ask, the user-facing name is stock_prices rather than "alphavantage" — the Alpha Vantage provider is an implementation detail of the backend route.
Test plan
cargo checkcleancargo test --lib openhuman::integrations::— 66/66 pass (16 new tests for the new tools: metadata, schema-required fields, validation rejection, response deserialisation)stock_exchange_rateSummary by CodeRabbit
New Features
Tests