refactor(tools): move domain-owned tools into modules (#2977)

This commit is contained in:
Steven Enamakel
2026-05-29 13:08:50 -07:00
committed by GitHub
parent f89501312a
commit 2920e4724a
87 changed files with 155 additions and 158 deletions
+1
View File
@@ -313,6 +313,7 @@ Deep link plugin is registered where supported; behavior is platform-specific (s
- **`src/openhuman/`** — Domain logic. Current domains: `about_app`, `accessibility`, `agent`, `app_state`, `approval`, `autocomplete`, `billing`, `channels`, `composio`, `config`, `context`, `cost`, `credentials`, `cron`, `doctor`, `embeddings`, `encryption`, `health`, `heartbeat`, `integrations`, `learning`, `local_ai`, `meet`, `meet_agent`, `memory`, `migration`, `node_runtime`, `notifications`, `overlay`, `people`, `prompt_injection`, `provider_surfaces`, `providers`, `redirect_links`, `referral`, `routing`, `scheduler_gate`, `screen_intelligence`, `security`, `service`, `skills`, `socket`, `subconscious`, `team`, `text_input`, `threads`, `tokenjuice`, `tool_timeout`, `tools`, `tree_summarizer`, `update`, `voice`, `wallet`, `webhooks`, `webview_accounts`, `webview_apis`, `webview_notifications`. RPC controllers in per-domain `rpc.rs`; use **`RpcOutcome<T>`** pattern (see "RPC Controller Pattern" below). - **`src/openhuman/`** — Domain logic. Current domains: `about_app`, `accessibility`, `agent`, `app_state`, `approval`, `autocomplete`, `billing`, `channels`, `composio`, `config`, `context`, `cost`, `credentials`, `cron`, `doctor`, `embeddings`, `encryption`, `health`, `heartbeat`, `integrations`, `learning`, `local_ai`, `meet`, `meet_agent`, `memory`, `migration`, `node_runtime`, `notifications`, `overlay`, `people`, `prompt_injection`, `provider_surfaces`, `providers`, `redirect_links`, `referral`, `routing`, `scheduler_gate`, `screen_intelligence`, `security`, `service`, `skills`, `socket`, `subconscious`, `team`, `text_input`, `threads`, `tokenjuice`, `tool_timeout`, `tools`, `tree_summarizer`, `update`, `voice`, `wallet`, `webhooks`, `webview_accounts`, `webview_apis`, `webview_notifications`. RPC controllers in per-domain `rpc.rs`; use **`RpcOutcome<T>`** pattern (see "RPC Controller Pattern" below).
- **`src/openhuman/` module layout**: **New** functionality must live in a **dedicated subdirectory** (e.g. `openhuman/my_domain/mod.rs` plus related files, or a new subfolder under an existing domain). Do **not** add new standalone `*.rs` files directly at `src/openhuman/` root (`dev_paths.rs` and `util.rs` are grandfathered). - **`src/openhuman/` module layout**: **New** functionality must live in a **dedicated subdirectory** (e.g. `openhuman/my_domain/mod.rs` plus related files, or a new subfolder under an existing domain). Do **not** add new standalone `*.rs` files directly at `src/openhuman/` root (`dev_paths.rs` and `util.rs` are grandfathered).
- **Tool ownership rule**: Tool implementations that belong to a domain/module must live in that owning module's `tools.rs` (and optional `tools/` submodules), not in `src/openhuman/tools/impl/`. Re-export those tool types from `src/openhuman/tools/mod.rs` so callers continue to import agent-callable tools through `crate::openhuman::tools::*`. Keep `src/openhuman/tools/impl/` only for genuinely cross-cutting tool families without a clear owning domain (for example filesystem, browser/computer control, and generic system/network utilities).
- **Controller schema contract**: Shared controller metadata types live in `src/core/types.rs` / `src/core/mod.rs` (`ControllerSchema`, `FieldSchema`, `TypeSchema`) and are consumed by adapters (RPC/CLI). - **Controller schema contract**: Shared controller metadata types live in `src/core/types.rs` / `src/core/mod.rs` (`ControllerSchema`, `FieldSchema`, `TypeSchema`) and are consumed by adapters (RPC/CLI).
- **Domain schema files**: For each domain, define controller schema metadata in a dedicated module inside the domain folder (example: `src/openhuman/cron/schemas.rs`) and export from the domain `mod.rs`. - **Domain schema files**: For each domain, define controller schema metadata in a dedicated module inside the domain folder (example: `src/openhuman/cron/schemas.rs`) and export from the domain `mod.rs`.
- **Controller-only exposure rule**: Expose domain functionality to **CLI and JSON-RPC through the controller registry** (`schemas.rs` + registered handlers wired into `src/core/all.rs`). Do **not** add domain-specific branches in `src/core/cli.rs` or `src/core/jsonrpc.rs`. - **Controller-only exposure rule**: Expose domain functionality to **CLI and JSON-RPC through the controller registry** (`schemas.rs` + registered handlers wired into `src/core/all.rs`). Do **not** add domain-specific branches in `src/core/cli.rs` or `src/core/jsonrpc.rs`.
+4 -4
View File
@@ -306,11 +306,11 @@ Canonical mapping of every product feature to its test source(s). Drives gap-fil
| ID | Feature | Layer | Test path(s) | Status | Notes | | ID | Feature | Layer | Test path(s) | Status | Notes |
| ----- | ------------------------------------------ | ----- | ----------------------------------------------------------------------------------------------------------------- | ------ | ---------------------------------------------------------------------- | | ----- | ------------------------------------------ | ----- | ----------------------------------------------------------------------------------------------------------------- | ------ | ---------------------------------------------------------------------- |
| 8.4.1 | Save Preference (general / situational) | RU | `src/openhuman/tools/impl/agent/save_preference_tests.rs` | ✅ | `save_preference` tool → `user_pref_{general,situational}`, topic-keyed | | 8.4.1 | Save Preference (general / situational) | RU | `src/openhuman/agent/tools/save_preference_tests.rs` | ✅ | `save_preference` tool → `user_pref_{general,situational}`, topic-keyed |
| 8.4.2 | Lane A — Standing Prefs in System Prompt | RU | `src/openhuman/learning/prompt_sections.rs`, `src/openhuman/agent/harness/session/turn_tests.rs` | ✅ | General prefs rendered into the system prompt at thread start | | 8.4.2 | Lane A — Standing Prefs in System Prompt | RU | `src/openhuman/learning/prompt_sections.rs`, `src/openhuman/agent/harness/session/turn_tests.rs` | ✅ | General prefs rendered into the system prompt at thread start |
| 8.4.3 | Lane B — Situational Recall (vector-gated) | RU | `src/openhuman/memory/store/unified/query_tests.rs::recall_relevant_by_vector_gates_on_similarity` | ✅ | Per-turn; relevant query injects, unrelated suppresses | | 8.4.3 | Lane B — Situational Recall (vector-gated) | RU | `src/openhuman/memory/store/unified/query_tests.rs::recall_relevant_by_vector_gates_on_similarity` | ✅ | Per-turn; relevant query injects, unrelated suppresses |
| 8.4.4 | Same-Topic Contradiction (replace) | RU | `src/openhuman/tools/impl/agent/save_preference_tests.rs::recategorising_moves_pref_between_namespaces` | ✅ | `ON CONFLICT REPLACE`; a topic lives in exactly one scope | | 8.4.4 | Same-Topic Contradiction (replace) | RU | `src/openhuman/agent/tools/save_preference_tests.rs::recategorising_moves_pref_between_namespaces` | ✅ | `ON CONFLICT REPLACE`; a topic lives in exactly one scope |
| 8.4.5 | Cross-Topic Contradiction Surfacing | RU | `src/openhuman/tools/impl/agent/save_preference_tests.rs::save_surfaces_related_preference_for_contradiction_check` | ✅ | Related prefs surfaced in the tool result for the chat agent to resolve | | 8.4.5 | Cross-Topic Contradiction Surfacing | RU | `src/openhuman/agent/tools/save_preference_tests.rs::save_surfaces_related_preference_for_contradiction_check` | ✅ | Related prefs surfaced in the tool result for the chat agent to resolve |
| 8.4.6 | vector_chunks Model-Signature Recall Guard | RU | `src/openhuman/memory/store/unified/query_tests.rs::vector_recall_excludes_other_model_signature` | ✅ | Excludes cross-model vectors; dim-guards legacy rows | | 8.4.6 | vector_chunks Model-Signature Recall Guard | RU | `src/openhuman/memory/store/unified/query_tests.rs::vector_recall_excludes_other_model_signature` | ✅ | Excludes cross-model vectors; dim-guards legacy rows |
--- ---
@@ -368,7 +368,7 @@ Canonical mapping of every product feature to its test source(s). Drives gap-fil
| ------ | ------------------------- | ----- | ----------------------------------------------------- | ------ | ----- | | ------ | ------------------------- | ----- | ----------------------------------------------------- | ------ | ----- |
| 10.3.1 | Incoming Message Sync | RU+WD | `src/openhuman/channels/tests/`, `gmail-flow.spec.ts` | ✅ | | | 10.3.1 | Incoming Message Sync | RU+WD | `src/openhuman/channels/tests/`, `gmail-flow.spec.ts` | ✅ | |
| 10.3.2 | Message Deduplication | RU | `src/openhuman/channels/tests/` | ✅ | | | 10.3.2 | Message Deduplication | RU | `src/openhuman/channels/tests/` | ✅ | |
| 10.3.3 | WhatsApp Agent Retrieval | RU | `src/openhuman/tools/impl/whatsapp_data/` (this PR), `tests/json_rpc_e2e.rs::whatsapp_data_agent_tools_e2e_1341` (this PR) | ✅ | Three read-only agent tools wrap the local SQLite store; ingest stays internal-only. See [`docs/whatsapp-data-flow.md`](whatsapp-data-flow.md). | | 10.3.3 | WhatsApp Agent Retrieval | RU | `src/openhuman/whatsapp_data/tools/` (this PR), `tests/json_rpc_e2e.rs::whatsapp_data_agent_tools_e2e_1341` (this PR) | ✅ | Three read-only agent tools wrap the local SQLite store; ingest stays internal-only. See [`docs/whatsapp-data-flow.md`](whatsapp-data-flow.md). |
| 10.3.4 | Real-Time vs Delayed Sync | RU | `src/openhuman/channels/tests/runtime_dispatch.rs` | ✅ | | | 10.3.4 | Real-Time vs Delayed Sync | RU | `src/openhuman/channels/tests/runtime_dispatch.rs` | ✅ | |
### 10.4 Messaging Operations ### 10.4 Messaging Operations
+3 -3
View File
@@ -17,7 +17,7 @@ The code path is split across several layers:
- built-in agent definitions in `src/openhuman/agent/agents/` - built-in agent definitions in `src/openhuman/agent/agents/`
- harness data + task-local plumbing in `src/openhuman/agent/harness/` - harness data + task-local plumbing in `src/openhuman/agent/harness/`
- main session lifecycle in `src/openhuman/agent/harness/session/` - main session lifecycle in `src/openhuman/agent/harness/session/`
- delegation tools in `src/openhuman/tools/impl/agent/` - delegation tools in `src/openhuman/agent/tools/`
- synthesised `delegate_*` tools in `src/openhuman/tools/orchestrator_tools.rs` - synthesised `delegate_*` tools in `src/openhuman/tools/orchestrator_tools.rs`
If you only read one file, the system looks simpler than it is. The actual runtime path crosses all of them. If you only read one file, the system looks simpler than it is. The actual runtime path crosses all of them.
@@ -42,7 +42,7 @@ If you only read one file, the system looks simpler than it is. The actual runti
### Subagent path ### Subagent path
- `src/openhuman/tools/impl/agent/spawn_subagent.rs` - `src/openhuman/agent/tools/spawn_subagent.rs`
Runtime tool entrypoint for explicit subagent spawns. Runtime tool entrypoint for explicit subagent spawns.
- `src/openhuman/agent/harness/fork_context.rs` - `src/openhuman/agent/harness/fork_context.rs`
Task-local parent and fork context. Task-local parent and fork context.
@@ -330,7 +330,7 @@ That history format is what the next iteration reasons from.
## Where `spawn_subagent` Enters ## Where `spawn_subagent` Enters
The explicit delegation tool lives in `src/openhuman/tools/impl/agent/spawn_subagent.rs`. The explicit delegation tool lives in `src/openhuman/agent/tools/spawn_subagent.rs`.
Its flow is: Its flow is:
+1 -1
View File
@@ -120,7 +120,7 @@ You are an autonomous developer agent. Your job is to pick a GitHub issue and de
**Not blocked on #2707** — can be done now. **Not blocked on #2707** — can be done now.
The `cron_add` logic exists in the agent tool (`src/openhuman/tools/impl/cron/add.rs`) but isn't exposed as an RPC controller. Need to add it to `src/openhuman/cron/schemas.rs`. The `cron_add` logic exists in the agent tool (`src/openhuman/cron/tools/add.rs`) but isn't exposed as an RPC controller. Need to add it to `src/openhuman/cron/schemas.rs`.
**Changes:** **Changes:**
- `src/openhuman/cron/schemas.rs` — Add `"add"` controller with inputs: `name`, `schedule`, `prompt`, `session_target`, `model`, `agent_id`, `delivery`, `delete_after_run` - `src/openhuman/cron/schemas.rs` — Add `"add"` controller with inputs: `name`, `schedule`, `prompt`, `session_target`, `model`, `agent_id`, `delivery`, `delete_after_run`
+1 -1
View File
@@ -60,7 +60,7 @@ The scanner write-path RPCs are registered as **internal-only** in [`src/core/al
The agent surfaces are exclusively read-only: The agent surfaces are exclusively read-only:
- [`src/openhuman/tools/impl/whatsapp_data/`](../src/openhuman/tools/impl/whatsapp_data/) — `whatsapp_data_list_chats`, `whatsapp_data_list_messages`, `whatsapp_data_search_messages`. All three wrap their RPC counterparts and emit a `"provider": "whatsapp"` tag in the response so the agent can cite WhatsApp as the source. - [`src/openhuman/whatsapp_data/tools/`](../src/openhuman/whatsapp_data/tools/) — `whatsapp_data_list_chats`, `whatsapp_data_list_messages`, `whatsapp_data_search_messages`. All three wrap their RPC counterparts and emit a `"provider": "whatsapp"` tag in the response so the agent can cite WhatsApp as the source.
- [`src/openhuman/memory/query/`](../src/openhuman/memory/query/) — generic `memory_tree_*` tools. Filter by `source_kind: "chat"` or query directly; WhatsApp chat-day transcripts are tagged `whatsapp` so they surface in cross-source flows. - [`src/openhuman/memory/query/`](../src/openhuman/memory/query/) — generic `memory_tree_*` tools. Filter by `source_kind: "chat"` or query directly; WhatsApp chat-day transcripts are tagged `whatsapp` so they surface in cross-source flows.
## Why the orchestrator only lists three of these ## Why the orchestrator only lists three of these
+2 -2
View File
@@ -104,8 +104,8 @@ The agent never sees the choice — it just calls into `Sandbox::run(...)` and t
- `src/openhuman/cron/scheduler.rs` — wraps shell jobs in `SecurityPolicy::from_config`. - `src/openhuman/cron/scheduler.rs` — wraps shell jobs in `SecurityPolicy::from_config`.
- `src/openhuman/tools/local_cli.rs`, `tools/ops.rs`, and most `tools/impl/{system,network,memory,agent}/*.rs` — every executable tool consults `SecurityPolicy`. - `src/openhuman/tools/local_cli.rs`, `tools/ops.rs`, and most `tools/impl/{system,network,memory,agent}/*.rs` — every executable tool consults `SecurityPolicy`.
- `src/openhuman/tools/impl/network/{curl,http_request,composio}.rs` — risk-classify outbound calls. - `src/openhuman/tools/impl/network/{curl,http_request,composio}.rs` — risk-classify outbound calls.
- `src/openhuman/tools/impl/memory/{store,forget}.rs` — sensitive-write tracking. - `src/openhuman/memory/tools/{store,forget}.rs` — sensitive-write tracking.
- `src/openhuman/tools/impl/agent/delegate.rs` — sub-agent dispatch goes through the autonomy gate. - `src/openhuman/agent/tools/delegate.rs` — sub-agent dispatch goes through the autonomy gate.
- `src/openhuman/credentials/` — uses `SecretStore` and `redact`. - `src/openhuman/credentials/` — uses `SecretStore` and `redact`.
## Tests ## Tests
+1 -1
View File
@@ -28,7 +28,7 @@ In-process pub/sub plus typed request/response. Owns the global `EventBus` singl
## Called by ## Called by
- ~33 sites across the workspace. Hot consumers: - ~33 sites across the workspace. Hot consumers:
- `src/openhuman/agent/bus.rs`, `agent/triage/{events,evaluator,escalation}.rs`, `tools/impl/agent/{dispatch,spawn_subagent}.rs` — agent + sub-agent events. - `src/openhuman/agent/bus.rs`, `agent/triage/{events,evaluator,escalation}.rs`, `agent/tools/{dispatch,spawn_subagent}.rs` — agent + sub-agent events.
- `src/openhuman/memory/conversations/bus.rs` — conversation persistence subscriber. - `src/openhuman/memory/conversations/bus.rs` — conversation persistence subscriber.
- `src/openhuman/channels/bus.rs``ChannelInboundSubscriber`. - `src/openhuman/channels/bus.rs``ChannelInboundSubscriber`.
- `src/openhuman/cron/{bus,scheduler}.rs``CronDeliverySubscriber` + `CronJobTriggered` emission. - `src/openhuman/cron/{bus,scheduler}.rs``CronDeliverySubscriber` + `CronJobTriggered` emission.
+1 -1
View File
@@ -1092,7 +1092,7 @@ fn is_provider_user_state_message(lower: &str) -> bool {
// personal Composio v3 tenant rejected with a 401 because the stored // personal Composio v3 tenant rejected with a 401 because the stored
// API key is invalid / revoked / has the wrong prefix. The canonical // API key is invalid / revoked / has the wrong prefix. The canonical
// wire shape rendered by // wire shape rendered by
// `src/openhuman/composio/tools/impl/network/composio.rs::response_error` // `src/openhuman/composio/composio/tools/direct.rs::response_error`
// and the various direct-mode op wrappers is: // and the various direct-mode op wrappers is:
// //
// `[composio-direct] list_connections failed: Composio v3 // `[composio-direct] list_connections failed: Composio v3
+1 -1
View File
@@ -34,7 +34,7 @@ Multi-agent orchestration domain. Owns the LLM tool-calling loop, sub-agent disp
- `src/openhuman/composio/bus.rs` — Composio trigger envelopes go through `agent::triage`. - `src/openhuman/composio/bus.rs` — Composio trigger envelopes go through `agent::triage`.
- `src/openhuman/notifications/rpc.rs` — surfaces agent runs to the UI. - `src/openhuman/notifications/rpc.rs` — surfaces agent runs to the UI.
- `src/openhuman/learning/{reflection,tool_tracker,user_profile}.rs` — read transcripts + tool outcomes. - `src/openhuman/learning/{reflection,tool_tracker,user_profile}.rs` — read transcripts + tool outcomes.
- `src/openhuman/tools/impl/agent/{dispatch,spawn_subagent}.rs``spawn_subagent` tool delegates here. - `src/openhuman/agent/tools/{dispatch,spawn_subagent}.rs``spawn_subagent` tool delegates here.
- `src/core/all.rs` — controller registry wires `all_agent_registered_controllers`. - `src/core/all.rs` — controller registry wires `all_agent_registered_controllers`.
## Tests ## Tests
+2 -2
View File
@@ -167,8 +167,8 @@ pub struct AgentDefinition {
/// so that reading a TOML makes the distinction obvious: `tools` is /// so that reading a TOML makes the distinction obvious: `tools` is
/// "what I execute directly", `subagents` is "what I can delegate to". /// "what I execute directly", `subagents` is "what I can delegate to".
/// ///
/// [`ArchetypeDelegationTool`]: crate::openhuman::tools::impl::agent::ArchetypeDelegationTool /// [`ArchetypeDelegationTool`]: crate::openhuman::agent::tools::ArchetypeDelegationTool
/// [`SkillDelegationTool`]: crate::openhuman::tools::impl::agent::SkillDelegationTool /// [`SkillDelegationTool`]: crate::openhuman::agent::tools::SkillDelegationTool
#[serde(default)] #[serde(default)]
pub subagents: Vec<SubagentEntry>, pub subagents: Vec<SubagentEntry>,
+1
View File
@@ -43,6 +43,7 @@ mod schemas;
pub mod stop_hooks; pub mod stop_hooks;
pub mod task_board; pub mod task_board;
pub mod tool_policy; pub mod tool_policy;
pub mod tools;
pub mod tree_loader; pub mod tree_loader;
pub mod triage; pub mod triage;
pub use schemas::{ pub use schemas::{
+1
View File
@@ -1,5 +1,6 @@
mod ops; mod ops;
mod schemas; mod schemas;
pub mod tools;
mod types; mod types;
pub use ops::{ pub use ops::{
+1
View File
@@ -20,6 +20,7 @@
pub mod index; pub mod index;
pub mod search; pub mod search;
pub mod store; pub mod store;
pub mod tools;
pub use index::{ pub use index::{
code_tokens, count_code_files, current_ref, index_ref, structural_doc, IndexMode, IndexReport, code_tokens, count_code_files, current_ref, index_ref, structural_doc, IndexMode, IndexReport,
+2 -2
View File
@@ -689,7 +689,7 @@ const MODE_DIRECT_PAT: &str = COMPOSIO_MODE_DIRECT;
/// (calls `api.tinyhumans.ai/agent-integrations/composio/*`). /// (calls `api.tinyhumans.ai/agent-integrations/composio/*`).
/// ///
/// `Direct` wraps the existing direct-mode HTTP wrapper from /// `Direct` wraps the existing direct-mode HTTP wrapper from
/// `tools/impl/network/composio.rs` that calls /// `composio/tools/direct.rs` that calls
/// `https://backend.composio.dev/api/v{2,3}` with `x-api-key`. The /// `https://backend.composio.dev/api/v{2,3}` with `x-api-key`. The
/// direct client does not currently cover every endpoint the /// direct client does not currently cover every endpoint the
/// backend-proxied path exposes (no per-toolkit allowlist, no /// backend-proxied path exposes (no per-toolkit allowlist, no
@@ -801,7 +801,7 @@ pub fn create_composio_client(
// ── Direct-mode response reshapers ────────────────────────────────── // ── Direct-mode response reshapers ──────────────────────────────────
// //
// The direct-mode `ComposioTool` (in `tools/impl/network/composio.rs`) // The direct-mode `ComposioTool` (in `composio/tools/direct.rs`)
// speaks `backend.composio.dev/api/v3/*` natively. The helpers below // speaks `backend.composio.dev/api/v3/*` natively. The helpers below
// reshape those v3 responses into the same envelopes the // reshape those v3 responses into the same envelopes the
// backend-proxied [`ComposioClient`] returns, so callers in `ops.rs` / // backend-proxied [`ComposioClient`] returns, so callers in `ops.rs` /
+4
View File
@@ -45,6 +45,10 @@ use super::providers::{
}; };
use super::types::ComposioToolsResponse; use super::types::ComposioToolsResponse;
mod direct;
pub use direct::{ComposioAction, ComposioConnectedAccount, ComposioTool};
/// Decision returned by [`evaluate_tool_visibility`]. /// Decision returned by [`evaluate_tool_visibility`].
enum ToolDecision { enum ToolDecision {
/// Action is curated for this toolkit and user scope allows it. /// Action is curated for this toolkit and user scope allows it.
@@ -1091,5 +1091,5 @@ impl ComposioConnectedAccount {
} }
#[cfg(test)] #[cfg(test)]
#[path = "composio_tests.rs"] #[path = "direct_tests.rs"]
mod tests; mod tests;
+1 -1
View File
@@ -734,7 +734,7 @@ mod search_config_tests {
/// (the async push surface that the backend currently mediates via /// (the async push surface that the backend currently mediates via
/// socket.io) do not work in direct mode — the user has to enable them /// socket.io) do not work in direct mode — the user has to enable them
/// out-of-band on Composio's dashboard and configure their own webhook /// out-of-band on Composio's dashboard and configure their own webhook
/// sink. See `tools/impl/network/composio.rs` for the underlying client. /// sink. See `composio/tools/direct.rs` for the underlying client.
pub const COMPOSIO_MODE_BACKEND: &str = "backend"; pub const COMPOSIO_MODE_BACKEND: &str = "backend";
pub const COMPOSIO_MODE_DIRECT: &str = "direct"; pub const COMPOSIO_MODE_DIRECT: &str = "direct";
+1 -1
View File
@@ -54,4 +54,4 @@ current channel + reply target — that is the routing path for the Telegram
- Unit: `ops_tests.rs`, `scheduler_tests.rs`, `store_tests.rs`. - Unit: `ops_tests.rs`, `scheduler_tests.rs`, `store_tests.rs`.
- Schema/parsing coverage lives inside `schedule.rs` and `schemas.rs` `#[cfg(test)] mod tests` blocks. - Schema/parsing coverage lives inside `schedule.rs` and `schemas.rs` `#[cfg(test)] mod tests` blocks.
- Delivery validation: `tools::impl::cron::add::tests` (announce-mode `allowed_users` checks). - Delivery validation: `cron::tools::add::tests` (announce-mode `allowed_users` checks).
+1
View File
@@ -4,6 +4,7 @@ mod schedule;
mod schemas; mod schemas;
pub mod seed; pub mod seed;
mod store; mod store;
pub mod tools;
mod types; mod types;
pub mod scheduler; pub mod scheduler;
+1 -28
View File
@@ -6,38 +6,11 @@
//! endpoints directly when enabled; those callers must keep configured base URLs //! endpoints directly when enabled; those callers must keep configured base URLs
//! trusted because requests leave the local core process. //! trusted because requests leave the local core process.
pub mod apify;
pub mod brave;
pub mod client; pub mod client;
pub mod google_places; pub mod tools;
pub mod parallel;
pub mod querit;
pub mod searxng;
pub mod seltz;
pub mod stock_prices;
pub mod tinyfish;
pub mod twilio;
pub mod types; pub mod types;
pub use apify::{ApifyGetRunResultsTool, ApifyGetRunStatusTool, ApifyRunActorTool};
pub use brave::{
BraveImageSearchTool, BraveNewsSearchTool, BraveVideoSearchTool, BraveWebSearchTool,
};
pub use client::{build_client, pricing_for_config, IntegrationClient}; pub use client::{build_client, pricing_for_config, IntegrationClient};
pub use google_places::{GooglePlacesDetailsTool, GooglePlacesSearchTool};
pub use parallel::{
ParallelChatTool, ParallelDatasetTool, ParallelEnrichTool, ParallelExtractTool,
ParallelResearchTool, ParallelSearchTool,
};
pub use querit::QueritSearchTool;
pub use searxng::{SearxngSearchArgs, SearxngSearchResponse, SearxngSearchTool};
pub use seltz::SeltzSearchTool;
pub use stock_prices::{
StockCommodityTool, StockCryptoSeriesTool, StockExchangeRateTool, StockOptionsTool,
StockQuoteTool,
};
pub use tinyfish::{TinyFishAgentRunTool, TinyFishFetchTool, TinyFishSearchTool};
pub use twilio::TwilioCallTool;
pub use types::{ pub use types::{
BackendResponse, IntegrationPricing, IntegrationPricingEntry, PricingIntegrations, ToolScope, BackendResponse, IntegrationPricing, IntegrationPricingEntry, PricingIntegrations, ToolScope,
}; };
+34
View File
@@ -0,0 +1,34 @@
use super::IntegrationClient;
mod apify;
mod brave;
mod google_places;
mod parallel;
mod querit;
mod searxng;
mod seltz;
mod stock_prices;
mod tinyfish;
mod twilio;
pub use apify::{ApifyGetRunResultsTool, ApifyGetRunStatusTool, ApifyRunActorTool};
pub use brave::{
BraveImageSearchTool, BraveNewsSearchTool, BraveVideoSearchTool, BraveWebSearchTool,
};
pub use google_places::{GooglePlacesDetailsTool, GooglePlacesSearchTool};
pub use parallel::{
ParallelChatTool, ParallelDatasetTool, ParallelEnrichTool, ParallelExtractTool,
ParallelResearchTool, ParallelSearchTool, SearchResponse, SearchResultItem,
};
pub use querit::QueritSearchTool;
pub use searxng::{
normalize_categories, SearxngSearchArgs, SearxngSearchResponse, SearxngSearchTool,
MAX_RESULTS as SEARXNG_MAX_RESULTS,
};
pub use seltz::SeltzSearchTool;
pub use stock_prices::{
StockCommodityTool, StockCryptoSeriesTool, StockExchangeRateTool, StockOptionsTool,
StockQuoteTool,
};
pub use tinyfish::{TinyFishAgentRunTool, TinyFishFetchTool, TinyFishSearchTool};
pub use twilio::TwilioCallTool;
@@ -10,7 +10,8 @@
//! //!
//! The backend handles Twilio API credentials, billing, and rate limiting. //! The backend handles Twilio API credentials, billing, and rate limiting.
use super::{IntegrationClient, ToolScope}; use super::IntegrationClient;
use crate::openhuman::integrations::ToolScope;
use crate::openhuman::tools::traits::{PermissionLevel, Tool, ToolResult}; use crate::openhuman::tools::traits::{PermissionLevel, Tool, ToolResult};
use async_trait::async_trait; use async_trait::async_trait;
use serde::Deserialize; use serde::Deserialize;
+2 -2
View File
@@ -5,8 +5,8 @@ use crate::openhuman::agent::harness::AgentDefinitionRegistry;
use crate::openhuman::agent::Agent; use crate::openhuman::agent::Agent;
use crate::openhuman::config::rpc as config_rpc; use crate::openhuman::config::rpc as config_rpc;
use crate::openhuman::inference::provider::traits::build_tool_instructions_text; use crate::openhuman::inference::provider::traits::build_tool_instructions_text;
use crate::openhuman::integrations::searxng::MAX_RESULTS as SEARXNG_MAX_RESULTS;
use crate::openhuman::security::{SecurityPolicy, ToolOperation}; use crate::openhuman::security::{SecurityPolicy, ToolOperation};
use crate::openhuman::tools::SEARXNG_MAX_RESULTS;
use super::write_dispatch; use super::write_dispatch;
@@ -737,7 +737,7 @@ fn build_rpc_params(
let mut params = Map::new(); let mut params = Map::new();
params.insert("query".to_string(), Value::String(query)); params.insert("query".to_string(), Value::String(query));
if let Some(categories) = optional_string_array(&args, "categories")? { if let Some(categories) = optional_string_array(&args, "categories")? {
crate::openhuman::integrations::searxng::normalize_categories(categories.clone()) crate::openhuman::tools::normalize_categories(categories.clone())
.map_err(|err| ToolCallError::InvalidParams(err.to_string()))?; .map_err(|err| ToolCallError::InvalidParams(err.to_string()))?;
params.insert("categories".to_string(), Value::from(categories)); params.insert("categories".to_string(), Value::from(categories));
} }
+1
View File
@@ -26,6 +26,7 @@ pub mod read_rpc;
pub mod remember; pub mod remember;
pub mod schema; pub mod schema;
pub mod sync; pub mod sync;
pub mod tools;
pub mod util; pub mod util;
// Tree instances — policy and orchestration over the generic memory_tree engine. // Tree instances — policy and orchestration over the generic memory_tree engine.
+2 -2
View File
@@ -27,8 +27,8 @@ Trust boundary for the autonomous core. Owns the autonomy / risk policy, sandbox
- `src/openhuman/cron/scheduler.rs` — wraps shell jobs in `SecurityPolicy::from_config`. - `src/openhuman/cron/scheduler.rs` — wraps shell jobs in `SecurityPolicy::from_config`.
- `src/openhuman/tools/local_cli.rs`, `tools/ops.rs`, and most `tools/impl/{system,network,memory,agent}/*.rs` — every executable tool consults `SecurityPolicy`. - `src/openhuman/tools/local_cli.rs`, `tools/ops.rs`, and most `tools/impl/{system,network,memory,agent}/*.rs` — every executable tool consults `SecurityPolicy`.
- `src/openhuman/tools/impl/network/{curl,http_request,composio}.rs` — risk-classify outbound calls. - `src/openhuman/tools/impl/network/{curl,http_request,composio}.rs` — risk-classify outbound calls.
- `src/openhuman/tools/impl/memory/{store,forget}.rs` — sensitive-write tracking. - `src/openhuman/memory/tools/{store,forget}.rs` — sensitive-write tracking.
- `src/openhuman/tools/impl/agent/delegate.rs` — sub-agent dispatch goes through autonomy gate. - `src/openhuman/agent/tools/delegate.rs` — sub-agent dispatch goes through autonomy gate.
- `src/openhuman/credentials/` — uses `SecretStore` and `redact`. - `src/openhuman/credentials/` — uses `SecretStore` and `redact`.
## Tests ## Tests
+1 -1
View File
@@ -444,7 +444,7 @@ fn emit_progress(location: &BoardLocation, cards: &[TaskBoardCard]) {
} }
/// Process-global lock that test code (here and in /// Process-global lock that test code (here and in
/// `tools::impl::agent::todo`) uses to serialize access to the shared /// `agent::tools::todo`) uses to serialize access to the shared
/// scratch store under `cargo test`'s parallel runner. /// scratch store under `cargo test`'s parallel runner.
#[cfg(test)] #[cfg(test)]
pub(crate) fn scratch_test_lock() -> std::sync::MutexGuard<'static, ()> { pub(crate) fn scratch_test_lock() -> std::sync::MutexGuard<'static, ()> {
-14
View File
@@ -1,25 +1,11 @@
pub mod agent;
pub mod audio;
pub mod browser; pub mod browser;
pub mod codegraph;
pub mod computer; pub mod computer;
pub mod cron;
pub mod filesystem; pub mod filesystem;
pub mod memory;
pub mod network; pub mod network;
pub mod system; pub mod system;
pub mod wallet;
pub mod whatsapp_data;
pub use agent::*;
pub use audio::*;
pub use browser::*; pub use browser::*;
pub use codegraph::*;
pub use computer::*; pub use computer::*;
pub use cron::*;
pub use filesystem::*; pub use filesystem::*;
pub use memory::*;
pub use network::*; pub use network::*;
pub use system::*; pub use system::*;
pub use wallet::*;
pub use whatsapp_data::*;
-2
View File
@@ -1,5 +1,4 @@
mod clob_auth; mod clob_auth;
mod composio;
mod curl; mod curl;
mod gitbooks; mod gitbooks;
mod gmail_unsubscribe; mod gmail_unsubscribe;
@@ -12,7 +11,6 @@ mod url_guard;
mod web_fetch; mod web_fetch;
mod web_search; mod web_search;
pub use composio::{ComposioAction, ComposioConnectedAccount, ComposioTool};
pub use curl::CurlTool; pub use curl::CurlTool;
pub use gitbooks::{GitbooksGetPageTool, GitbooksSearchTool}; pub use gitbooks::{GitbooksGetPageTool, GitbooksSearchTool};
pub use gmail_unsubscribe::GmailUnsubscribeTool; pub use gmail_unsubscribe::GmailUnsubscribeTool;
@@ -1,6 +1,6 @@
use crate::openhuman::integrations::parallel::{SearchResponse, SearchResultItem}; use crate::openhuman::integrations::IntegrationClient;
use crate::openhuman::integrations::{IntegrationClient, SeltzSearchTool};
use crate::openhuman::tools::traits::{Tool, ToolCallOptions, ToolResult}; use crate::openhuman::tools::traits::{Tool, ToolCallOptions, ToolResult};
use crate::openhuman::tools::{SearchResponse, SearchResultItem, SeltzSearchTool};
use async_trait::async_trait; use async_trait::async_trait;
use serde_json::{json, Value}; use serde_json::{json, Value};
use sha2::{Digest, Sha256}; use sha2::{Digest, Sha256};
+9
View File
@@ -11,6 +11,15 @@ pub(crate) mod user_filter;
#[path = "impl/mod.rs"] #[path = "impl/mod.rs"]
pub(crate) mod implementations; pub(crate) mod implementations;
pub use crate::openhuman::agent::tools::*;
pub use crate::openhuman::audio_toolkit::tools::*;
pub use crate::openhuman::codegraph::tools::*;
pub use crate::openhuman::composio::tools::*;
pub use crate::openhuman::cron::tools::*;
pub use crate::openhuman::integrations::tools::*;
pub use crate::openhuman::memory::tools::*;
pub use crate::openhuman::wallet::tools::*;
pub use crate::openhuman::whatsapp_data::tools::*;
pub use implementations::*; pub use implementations::*;
pub use ops::*; pub use ops::*;
pub use policy::{DefaultToolPolicy, PolicyDecision, ToolPolicy}; pub use policy::{DefaultToolPolicy, PolicyDecision, ToolPolicy};
+63 -79
View File
@@ -388,34 +388,24 @@ pub fn all_tools_with_runtime(
// pick it up once direct Parallel routing lands. // pick it up once direct Parallel routing lands.
let client = crate::openhuman::integrations::build_client(root_config); let client = crate::openhuman::integrations::build_client(root_config);
if let Some(client) = client { if let Some(client) = client {
tools.push(Box::new(crate::openhuman::tools::ParallelSearchTool::new(
Arc::clone(&client),
)));
tools.push(Box::new(crate::openhuman::tools::ParallelExtractTool::new(
Arc::clone(&client),
)));
tools.push(Box::new(crate::openhuman::tools::ParallelChatTool::new(
Arc::clone(&client),
)));
tools.push(Box::new( tools.push(Box::new(
crate::openhuman::integrations::ParallelSearchTool::new(Arc::clone( crate::openhuman::tools::ParallelResearchTool::new(Arc::clone(&client)),
&client,
)),
));
tools.push(Box::new(
crate::openhuman::integrations::ParallelExtractTool::new(Arc::clone(
&client,
)),
));
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,
)),
)); ));
tools.push(Box::new(crate::openhuman::tools::ParallelEnrichTool::new(
Arc::clone(&client),
)));
tools.push(Box::new(crate::openhuman::tools::ParallelDatasetTool::new(
Arc::clone(&client),
)));
// Layer the unified web_search slot too so the // Layer the unified web_search slot too so the
// agent's default research path keeps working. // agent's default research path keeps working.
tools.push(Box::new(WebSearchTool::new( tools.push(Box::new(WebSearchTool::new(
@@ -437,29 +427,25 @@ pub fn all_tools_with_runtime(
SearchEngine::Brave => { SearchEngine::Brave => {
tracing::debug!("[search] active engine = brave (BYO direct API)"); tracing::debug!("[search] active engine = brave (BYO direct API)");
let api_key = search.brave.api_key.clone(); let api_key = search.brave.api_key.clone();
tools.push(Box::new(crate::openhuman::tools::BraveWebSearchTool::new(
api_key.clone(),
max_results,
timeout_secs,
)));
tools.push(Box::new(crate::openhuman::tools::BraveNewsSearchTool::new(
api_key.clone(),
max_results,
timeout_secs,
)));
tools.push(Box::new( tools.push(Box::new(
crate::openhuman::integrations::BraveWebSearchTool::new( crate::openhuman::tools::BraveImageSearchTool::new(
api_key.clone(), api_key.clone(),
max_results, max_results,
timeout_secs, timeout_secs,
), ),
)); ));
tools.push(Box::new( tools.push(Box::new(
crate::openhuman::integrations::BraveNewsSearchTool::new( crate::openhuman::tools::BraveVideoSearchTool::new(
api_key.clone(),
max_results,
timeout_secs,
),
));
tools.push(Box::new(
crate::openhuman::integrations::BraveImageSearchTool::new(
api_key.clone(),
max_results,
timeout_secs,
),
));
tools.push(Box::new(
crate::openhuman::integrations::BraveVideoSearchTool::new(
api_key, api_key,
max_results, max_results,
timeout_secs, timeout_secs,
@@ -469,21 +455,19 @@ pub fn all_tools_with_runtime(
SearchEngine::Querit => { SearchEngine::Querit => {
tracing::debug!("[search] active engine = querit (BYO direct API)"); tracing::debug!("[search] active engine = querit (BYO direct API)");
tools.push(Box::new( tools.push(Box::new(
crate::openhuman::integrations::QueritSearchTool::new_web_search_tool( crate::openhuman::tools::QueritSearchTool::new_web_search_tool(
search.querit.api_key.clone(),
None,
max_results,
timeout_secs,
),
));
tools.push(Box::new(
crate::openhuman::integrations::QueritSearchTool::new(
search.querit.api_key.clone(), search.querit.api_key.clone(),
None, None,
max_results, max_results,
timeout_secs, timeout_secs,
), ),
)); ));
tools.push(Box::new(crate::openhuman::tools::QueritSearchTool::new(
search.querit.api_key.clone(),
None,
max_results,
timeout_secs,
)));
} }
} }
} }
@@ -552,14 +536,14 @@ pub fn all_tools_with_runtime(
if let Some(client) = crate::openhuman::integrations::build_client(root_config) { if let Some(client) = crate::openhuman::integrations::build_client(root_config) {
tracing::debug!("[integrations] client built successfully"); tracing::debug!("[integrations] client built successfully");
if root_config.integrations.apify.is_active() { if root_config.integrations.apify.is_active() {
tools.push(Box::new(crate::openhuman::tools::ApifyRunActorTool::new(
Arc::clone(&client),
)));
tools.push(Box::new( tools.push(Box::new(
crate::openhuman::integrations::ApifyRunActorTool::new(Arc::clone(&client)), crate::openhuman::tools::ApifyGetRunStatusTool::new(Arc::clone(&client)),
)); ));
tools.push(Box::new( tools.push(Box::new(
crate::openhuman::integrations::ApifyGetRunStatusTool::new(Arc::clone(&client)), crate::openhuman::tools::ApifyGetRunResultsTool::new(Arc::clone(&client)),
));
tools.push(Box::new(
crate::openhuman::integrations::ApifyGetRunResultsTool::new(Arc::clone(&client)),
)); ));
tracing::debug!("[integrations] registered apify tools"); tracing::debug!("[integrations] registered apify tools");
} else { } else {
@@ -567,10 +551,10 @@ pub fn all_tools_with_runtime(
} }
if root_config.integrations.google_places.is_active() { if root_config.integrations.google_places.is_active() {
tools.push(Box::new( tools.push(Box::new(
crate::openhuman::integrations::GooglePlacesSearchTool::new(Arc::clone(&client)), crate::openhuman::tools::GooglePlacesSearchTool::new(Arc::clone(&client)),
)); ));
tools.push(Box::new( tools.push(Box::new(
crate::openhuman::integrations::GooglePlacesDetailsTool::new(Arc::clone(&client)), crate::openhuman::tools::GooglePlacesDetailsTool::new(Arc::clone(&client)),
)); ));
tracing::debug!("[integrations] registered google_places tools"); tracing::debug!("[integrations] registered google_places tools");
} else { } else {
@@ -586,43 +570,43 @@ pub fn all_tools_with_runtime(
); );
} }
if root_config.integrations.tinyfish.is_active() { if root_config.integrations.tinyfish.is_active() {
tools.push(Box::new(crate::openhuman::tools::TinyFishSearchTool::new(
Arc::clone(&client),
)));
tools.push(Box::new(crate::openhuman::tools::TinyFishFetchTool::new(
Arc::clone(&client),
)));
tools.push(Box::new( tools.push(Box::new(
crate::openhuman::integrations::TinyFishSearchTool::new(Arc::clone(&client)), crate::openhuman::tools::TinyFishAgentRunTool::new(Arc::clone(&client)),
));
tools.push(Box::new(
crate::openhuman::integrations::TinyFishFetchTool::new(Arc::clone(&client)),
));
tools.push(Box::new(
crate::openhuman::integrations::TinyFishAgentRunTool::new(Arc::clone(&client)),
)); ));
tracing::debug!("[integrations] registered tinyfish tools"); tracing::debug!("[integrations] registered tinyfish tools");
} else { } else {
tracing::debug!("[integrations] tinyfish disabled — skipping"); tracing::debug!("[integrations] tinyfish disabled — skipping");
} }
if root_config.integrations.stock_prices.is_active() { if root_config.integrations.stock_prices.is_active() {
tools.push(Box::new(crate::openhuman::tools::StockQuoteTool::new(
Arc::clone(&client),
)));
tools.push(Box::new( tools.push(Box::new(
crate::openhuman::integrations::StockQuoteTool::new(Arc::clone(&client)), crate::openhuman::tools::StockExchangeRateTool::new(Arc::clone(&client)),
)); ));
tools.push(Box::new(crate::openhuman::tools::StockOptionsTool::new(
Arc::clone(&client),
)));
tools.push(Box::new( tools.push(Box::new(
crate::openhuman::integrations::StockExchangeRateTool::new(Arc::clone(&client)), crate::openhuman::tools::StockCryptoSeriesTool::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)),
)); ));
tools.push(Box::new(crate::openhuman::tools::StockCommodityTool::new(
Arc::clone(&client),
)));
tracing::debug!("[integrations] registered stock_prices tools"); tracing::debug!("[integrations] registered stock_prices tools");
} else { } else {
tracing::debug!("[integrations] stock_prices disabled — skipping"); tracing::debug!("[integrations] stock_prices disabled — skipping");
} }
if root_config.integrations.twilio.is_active() { if root_config.integrations.twilio.is_active() {
tools.push(Box::new( tools.push(Box::new(crate::openhuman::tools::TwilioCallTool::new(
crate::openhuman::integrations::TwilioCallTool::new(Arc::clone(&client)), Arc::clone(&client),
)); )));
tracing::debug!("[integrations] registered twilio tools"); tracing::debug!("[integrations] registered twilio tools");
} else { } else {
tracing::debug!("[integrations] twilio disabled — skipping"); tracing::debug!("[integrations] twilio disabled — skipping");
+6 -6
View File
@@ -11,8 +11,8 @@ use serde_json::{json, Map, Value};
use crate::core::all::{ControllerFuture, RegisteredController}; use crate::core::all::{ControllerFuture, RegisteredController};
use crate::core::{ControllerSchema, FieldSchema, TypeSchema}; use crate::core::{ControllerSchema, FieldSchema, TypeSchema};
use crate::openhuman::config::rpc as config_rpc; use crate::openhuman::config::rpc as config_rpc;
use crate::openhuman::integrations::searxng::MAX_RESULTS as SEARXNG_MAX_RESULTS;
use crate::openhuman::tools::traits::Tool; use crate::openhuman::tools::traits::Tool;
use crate::openhuman::tools::SEARXNG_MAX_RESULTS;
use crate::rpc::RpcOutcome; use crate::rpc::RpcOutcome;
pub fn all_controller_schemas() -> Vec<ControllerSchema> { pub fn all_controller_schemas() -> Vec<ControllerSchema> {
@@ -517,7 +517,7 @@ fn handle_web_search(params: Map<String, Value>) -> ControllerFuture {
}); });
let resp = client let resp = client
.post::<crate::openhuman::integrations::parallel::SearchResponse>( .post::<crate::openhuman::tools::SearchResponse>(
"/agent-integrations/parallel/search", "/agent-integrations/parallel/search",
&body, &body,
) )
@@ -568,7 +568,7 @@ fn handle_seltz_search(params: Map<String, Value>) -> ControllerFuture {
"[rpc][tools.seltz_search] start" "[rpc][tools.seltz_search] start"
); );
let tool = crate::openhuman::integrations::SeltzSearchTool::new( let tool = crate::openhuman::tools::SeltzSearchTool::new(
config.seltz.api_key.clone(), config.seltz.api_key.clone(),
config.seltz.api_url.clone(), config.seltz.api_url.clone(),
max_results, max_results,
@@ -650,7 +650,7 @@ fn handle_querit_search(params: Map<String, Value>) -> ControllerFuture {
"[rpc][tools.querit_search] start" "[rpc][tools.querit_search] start"
); );
let tool = crate::openhuman::integrations::QueritSearchTool::new( let tool = crate::openhuman::tools::QueritSearchTool::new(
config.search.querit.api_key.clone(), config.search.querit.api_key.clone(),
None, None,
max_results, max_results,
@@ -729,7 +729,7 @@ fn handle_searxng_search(params: Map<String, Value>) -> ControllerFuture {
"[rpc][tools.searxng_search] start" "[rpc][tools.searxng_search] start"
); );
let tool = crate::openhuman::integrations::SearxngSearchTool::new( let tool = crate::openhuman::tools::SearxngSearchTool::new(
config.searxng.base_url.clone(), config.searxng.base_url.clone(),
config.searxng.max_results, config.searxng.max_results,
config.searxng.default_language.clone(), config.searxng.default_language.clone(),
@@ -737,7 +737,7 @@ fn handle_searxng_search(params: Map<String, Value>) -> ControllerFuture {
); );
let response = tool let response = tool
.search(crate::openhuman::integrations::SearxngSearchArgs { .search(crate::openhuman::tools::SearxngSearchArgs {
query, query,
categories, categories,
language, language,
+1
View File
@@ -10,6 +10,7 @@ mod execution;
mod ops; mod ops;
mod rpc; mod rpc;
mod schemas; mod schemas;
pub mod tools;
#[cfg(test)] #[cfg(test)]
pub(crate) mod test_support; pub(crate) mod test_support;
+1
View File
@@ -21,6 +21,7 @@ pub mod rpc;
mod schemas; mod schemas;
mod sqlite_retry; mod sqlite_retry;
pub mod store; pub mod store;
pub mod tools;
pub mod types; pub mod types;
pub use schemas::{ pub use schemas::{