mirror of
https://github.com/tinyhumansai/openhuman.git
synced 2026-07-27 21:08:00 +00:00
refactor(tools): move domain-owned tools into modules (#2977)
This commit is contained in:
@@ -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/` 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).
|
||||
- **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`.
|
||||
|
||||
@@ -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 |
|
||||
| ----- | ------------------------------------------ | ----- | ----------------------------------------------------------------------------------------------------------------- | ------ | ---------------------------------------------------------------------- |
|
||||
| 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.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.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.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/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 |
|
||||
|
||||
---
|
||||
@@ -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.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.4 Messaging Operations
|
||||
|
||||
@@ -17,7 +17,7 @@ The code path is split across several layers:
|
||||
- built-in agent definitions in `src/openhuman/agent/agents/`
|
||||
- harness data + task-local plumbing in `src/openhuman/agent/harness/`
|
||||
- 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`
|
||||
|
||||
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
|
||||
|
||||
- `src/openhuman/tools/impl/agent/spawn_subagent.rs`
|
||||
- `src/openhuman/agent/tools/spawn_subagent.rs`
|
||||
Runtime tool entrypoint for explicit subagent spawns.
|
||||
- `src/openhuman/agent/harness/fork_context.rs`
|
||||
Task-local parent and fork context.
|
||||
@@ -330,7 +330,7 @@ That history format is what the next iteration reasons from.
|
||||
|
||||
## 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:
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
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:**
|
||||
- `src/openhuman/cron/schemas.rs` — Add `"add"` controller with inputs: `name`, `schedule`, `prompt`, `session_target`, `model`, `agent_id`, `delivery`, `delete_after_run`
|
||||
|
||||
@@ -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:
|
||||
|
||||
- [`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.
|
||||
|
||||
## Why the orchestrator only lists three of these
|
||||
|
||||
@@ -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/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/memory/{store,forget}.rs` — sensitive-write tracking.
|
||||
- `src/openhuman/tools/impl/agent/delegate.rs` — sub-agent dispatch goes through the autonomy gate.
|
||||
- `src/openhuman/memory/tools/{store,forget}.rs` — sensitive-write tracking.
|
||||
- `src/openhuman/agent/tools/delegate.rs` — sub-agent dispatch goes through the autonomy gate.
|
||||
- `src/openhuman/credentials/` — uses `SecretStore` and `redact`.
|
||||
|
||||
## Tests
|
||||
|
||||
@@ -28,7 +28,7 @@ In-process pub/sub plus typed request/response. Owns the global `EventBus` singl
|
||||
## Called by
|
||||
|
||||
- ~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/channels/bus.rs` — `ChannelInboundSubscriber`.
|
||||
- `src/openhuman/cron/{bus,scheduler}.rs` — `CronDeliverySubscriber` + `CronJobTriggered` emission.
|
||||
|
||||
@@ -1092,7 +1092,7 @@ fn is_provider_user_state_message(lower: &str) -> bool {
|
||||
// personal Composio v3 tenant rejected with a 401 because the stored
|
||||
// API key is invalid / revoked / has the wrong prefix. The canonical
|
||||
// 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:
|
||||
//
|
||||
// `[composio-direct] list_connections failed: Composio v3
|
||||
|
||||
@@ -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/notifications/rpc.rs` — surfaces agent runs to the UI.
|
||||
- `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`.
|
||||
|
||||
## Tests
|
||||
|
||||
@@ -167,8 +167,8 @@ pub struct AgentDefinition {
|
||||
/// so that reading a TOML makes the distinction obvious: `tools` is
|
||||
/// "what I execute directly", `subagents` is "what I can delegate to".
|
||||
///
|
||||
/// [`ArchetypeDelegationTool`]: crate::openhuman::tools::impl::agent::ArchetypeDelegationTool
|
||||
/// [`SkillDelegationTool`]: crate::openhuman::tools::impl::agent::SkillDelegationTool
|
||||
/// [`ArchetypeDelegationTool`]: crate::openhuman::agent::tools::ArchetypeDelegationTool
|
||||
/// [`SkillDelegationTool`]: crate::openhuman::agent::tools::SkillDelegationTool
|
||||
#[serde(default)]
|
||||
pub subagents: Vec<SubagentEntry>,
|
||||
|
||||
|
||||
@@ -43,6 +43,7 @@ mod schemas;
|
||||
pub mod stop_hooks;
|
||||
pub mod task_board;
|
||||
pub mod tool_policy;
|
||||
pub mod tools;
|
||||
pub mod tree_loader;
|
||||
pub mod triage;
|
||||
pub use schemas::{
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
mod ops;
|
||||
mod schemas;
|
||||
pub mod tools;
|
||||
mod types;
|
||||
|
||||
pub use ops::{
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
pub mod index;
|
||||
pub mod search;
|
||||
pub mod store;
|
||||
pub mod tools;
|
||||
|
||||
pub use index::{
|
||||
code_tokens, count_code_files, current_ref, index_ref, structural_doc, IndexMode, IndexReport,
|
||||
|
||||
@@ -689,7 +689,7 @@ const MODE_DIRECT_PAT: &str = COMPOSIO_MODE_DIRECT;
|
||||
/// (calls `api.tinyhumans.ai/agent-integrations/composio/*`).
|
||||
///
|
||||
/// `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
|
||||
/// direct client does not currently cover every endpoint the
|
||||
/// backend-proxied path exposes (no per-toolkit allowlist, no
|
||||
@@ -801,7 +801,7 @@ pub fn create_composio_client(
|
||||
|
||||
// ── 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
|
||||
// reshape those v3 responses into the same envelopes the
|
||||
// backend-proxied [`ComposioClient`] returns, so callers in `ops.rs` /
|
||||
|
||||
@@ -45,6 +45,10 @@ use super::providers::{
|
||||
};
|
||||
use super::types::ComposioToolsResponse;
|
||||
|
||||
mod direct;
|
||||
|
||||
pub use direct::{ComposioAction, ComposioConnectedAccount, ComposioTool};
|
||||
|
||||
/// Decision returned by [`evaluate_tool_visibility`].
|
||||
enum ToolDecision {
|
||||
/// Action is curated for this toolkit and user scope allows it.
|
||||
|
||||
+1
-1
@@ -1091,5 +1091,5 @@ impl ComposioConnectedAccount {
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[path = "composio_tests.rs"]
|
||||
#[path = "direct_tests.rs"]
|
||||
mod tests;
|
||||
@@ -734,7 +734,7 @@ mod search_config_tests {
|
||||
/// (the async push surface that the backend currently mediates via
|
||||
/// 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
|
||||
/// 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_DIRECT: &str = "direct";
|
||||
|
||||
|
||||
@@ -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`.
|
||||
- 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).
|
||||
|
||||
@@ -4,6 +4,7 @@ mod schedule;
|
||||
mod schemas;
|
||||
pub mod seed;
|
||||
mod store;
|
||||
pub mod tools;
|
||||
mod types;
|
||||
|
||||
pub mod scheduler;
|
||||
|
||||
@@ -6,38 +6,11 @@
|
||||
//! endpoints directly when enabled; those callers must keep configured base URLs
|
||||
//! trusted because requests leave the local core process.
|
||||
|
||||
pub mod apify;
|
||||
pub mod brave;
|
||||
pub mod client;
|
||||
pub mod google_places;
|
||||
pub mod parallel;
|
||||
pub mod querit;
|
||||
pub mod searxng;
|
||||
pub mod seltz;
|
||||
pub mod stock_prices;
|
||||
pub mod tinyfish;
|
||||
pub mod twilio;
|
||||
pub mod tools;
|
||||
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 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::{
|
||||
BackendResponse, IntegrationPricing, IntegrationPricingEntry, PricingIntegrations, ToolScope,
|
||||
};
|
||||
|
||||
@@ -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.
|
||||
|
||||
use super::{IntegrationClient, ToolScope};
|
||||
use super::IntegrationClient;
|
||||
use crate::openhuman::integrations::ToolScope;
|
||||
use crate::openhuman::tools::traits::{PermissionLevel, Tool, ToolResult};
|
||||
use async_trait::async_trait;
|
||||
use serde::Deserialize;
|
||||
@@ -5,8 +5,8 @@ use crate::openhuman::agent::harness::AgentDefinitionRegistry;
|
||||
use crate::openhuman::agent::Agent;
|
||||
use crate::openhuman::config::rpc as config_rpc;
|
||||
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::tools::SEARXNG_MAX_RESULTS;
|
||||
|
||||
use super::write_dispatch;
|
||||
|
||||
@@ -737,7 +737,7 @@ fn build_rpc_params(
|
||||
let mut params = Map::new();
|
||||
params.insert("query".to_string(), Value::String(query));
|
||||
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()))?;
|
||||
params.insert("categories".to_string(), Value::from(categories));
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ pub mod read_rpc;
|
||||
pub mod remember;
|
||||
pub mod schema;
|
||||
pub mod sync;
|
||||
pub mod tools;
|
||||
pub mod util;
|
||||
|
||||
// Tree instances — policy and orchestration over the generic memory_tree engine.
|
||||
|
||||
@@ -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/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/memory/{store,forget}.rs` — sensitive-write tracking.
|
||||
- `src/openhuman/tools/impl/agent/delegate.rs` — sub-agent dispatch goes through autonomy gate.
|
||||
- `src/openhuman/memory/tools/{store,forget}.rs` — sensitive-write tracking.
|
||||
- `src/openhuman/agent/tools/delegate.rs` — sub-agent dispatch goes through autonomy gate.
|
||||
- `src/openhuman/credentials/` — uses `SecretStore` and `redact`.
|
||||
|
||||
## Tests
|
||||
|
||||
@@ -444,7 +444,7 @@ fn emit_progress(location: &BoardLocation, cards: &[TaskBoardCard]) {
|
||||
}
|
||||
|
||||
/// 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.
|
||||
#[cfg(test)]
|
||||
pub(crate) fn scratch_test_lock() -> std::sync::MutexGuard<'static, ()> {
|
||||
|
||||
@@ -1,25 +1,11 @@
|
||||
pub mod agent;
|
||||
pub mod audio;
|
||||
pub mod browser;
|
||||
pub mod codegraph;
|
||||
pub mod computer;
|
||||
pub mod cron;
|
||||
pub mod filesystem;
|
||||
pub mod memory;
|
||||
pub mod network;
|
||||
pub mod system;
|
||||
pub mod wallet;
|
||||
pub mod whatsapp_data;
|
||||
|
||||
pub use agent::*;
|
||||
pub use audio::*;
|
||||
pub use browser::*;
|
||||
pub use codegraph::*;
|
||||
pub use computer::*;
|
||||
pub use cron::*;
|
||||
pub use filesystem::*;
|
||||
pub use memory::*;
|
||||
pub use network::*;
|
||||
pub use system::*;
|
||||
pub use wallet::*;
|
||||
pub use whatsapp_data::*;
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
mod clob_auth;
|
||||
mod composio;
|
||||
mod curl;
|
||||
mod gitbooks;
|
||||
mod gmail_unsubscribe;
|
||||
@@ -12,7 +11,6 @@ mod url_guard;
|
||||
mod web_fetch;
|
||||
mod web_search;
|
||||
|
||||
pub use composio::{ComposioAction, ComposioConnectedAccount, ComposioTool};
|
||||
pub use curl::CurlTool;
|
||||
pub use gitbooks::{GitbooksGetPageTool, GitbooksSearchTool};
|
||||
pub use gmail_unsubscribe::GmailUnsubscribeTool;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use crate::openhuman::integrations::parallel::{SearchResponse, SearchResultItem};
|
||||
use crate::openhuman::integrations::{IntegrationClient, SeltzSearchTool};
|
||||
use crate::openhuman::integrations::IntegrationClient;
|
||||
use crate::openhuman::tools::traits::{Tool, ToolCallOptions, ToolResult};
|
||||
use crate::openhuman::tools::{SearchResponse, SearchResultItem, SeltzSearchTool};
|
||||
use async_trait::async_trait;
|
||||
use serde_json::{json, Value};
|
||||
use sha2::{Digest, Sha256};
|
||||
|
||||
@@ -11,6 +11,15 @@ pub(crate) mod user_filter;
|
||||
#[path = "impl/mod.rs"]
|
||||
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 ops::*;
|
||||
pub use policy::{DefaultToolPolicy, PolicyDecision, ToolPolicy};
|
||||
|
||||
+63
-79
@@ -388,34 +388,24 @@ pub fn all_tools_with_runtime(
|
||||
// pick it up once direct Parallel routing lands.
|
||||
let client = crate::openhuman::integrations::build_client(root_config);
|
||||
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(
|
||||
crate::openhuman::integrations::ParallelSearchTool::new(Arc::clone(
|
||||
&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,
|
||||
)),
|
||||
crate::openhuman::tools::ParallelResearchTool::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
|
||||
// agent's default research path keeps working.
|
||||
tools.push(Box::new(WebSearchTool::new(
|
||||
@@ -437,29 +427,25 @@ pub fn all_tools_with_runtime(
|
||||
SearchEngine::Brave => {
|
||||
tracing::debug!("[search] active engine = brave (BYO direct API)");
|
||||
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(
|
||||
crate::openhuman::integrations::BraveWebSearchTool::new(
|
||||
crate::openhuman::tools::BraveImageSearchTool::new(
|
||||
api_key.clone(),
|
||||
max_results,
|
||||
timeout_secs,
|
||||
),
|
||||
));
|
||||
tools.push(Box::new(
|
||||
crate::openhuman::integrations::BraveNewsSearchTool::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(
|
||||
crate::openhuman::tools::BraveVideoSearchTool::new(
|
||||
api_key,
|
||||
max_results,
|
||||
timeout_secs,
|
||||
@@ -469,21 +455,19 @@ pub fn all_tools_with_runtime(
|
||||
SearchEngine::Querit => {
|
||||
tracing::debug!("[search] active engine = querit (BYO direct API)");
|
||||
tools.push(Box::new(
|
||||
crate::openhuman::integrations::QueritSearchTool::new_web_search_tool(
|
||||
search.querit.api_key.clone(),
|
||||
None,
|
||||
max_results,
|
||||
timeout_secs,
|
||||
),
|
||||
));
|
||||
tools.push(Box::new(
|
||||
crate::openhuman::integrations::QueritSearchTool::new(
|
||||
crate::openhuman::tools::QueritSearchTool::new_web_search_tool(
|
||||
search.querit.api_key.clone(),
|
||||
None,
|
||||
max_results,
|
||||
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) {
|
||||
tracing::debug!("[integrations] client built successfully");
|
||||
if root_config.integrations.apify.is_active() {
|
||||
tools.push(Box::new(crate::openhuman::tools::ApifyRunActorTool::new(
|
||||
Arc::clone(&client),
|
||||
)));
|
||||
tools.push(Box::new(
|
||||
crate::openhuman::integrations::ApifyRunActorTool::new(Arc::clone(&client)),
|
||||
crate::openhuman::tools::ApifyGetRunStatusTool::new(Arc::clone(&client)),
|
||||
));
|
||||
tools.push(Box::new(
|
||||
crate::openhuman::integrations::ApifyGetRunStatusTool::new(Arc::clone(&client)),
|
||||
));
|
||||
tools.push(Box::new(
|
||||
crate::openhuman::integrations::ApifyGetRunResultsTool::new(Arc::clone(&client)),
|
||||
crate::openhuman::tools::ApifyGetRunResultsTool::new(Arc::clone(&client)),
|
||||
));
|
||||
tracing::debug!("[integrations] registered apify tools");
|
||||
} else {
|
||||
@@ -567,10 +551,10 @@ pub fn all_tools_with_runtime(
|
||||
}
|
||||
if root_config.integrations.google_places.is_active() {
|
||||
tools.push(Box::new(
|
||||
crate::openhuman::integrations::GooglePlacesSearchTool::new(Arc::clone(&client)),
|
||||
crate::openhuman::tools::GooglePlacesSearchTool::new(Arc::clone(&client)),
|
||||
));
|
||||
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");
|
||||
} else {
|
||||
@@ -586,43 +570,43 @@ pub fn all_tools_with_runtime(
|
||||
);
|
||||
}
|
||||
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(
|
||||
crate::openhuman::integrations::TinyFishSearchTool::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)),
|
||||
crate::openhuman::tools::TinyFishAgentRunTool::new(Arc::clone(&client)),
|
||||
));
|
||||
tracing::debug!("[integrations] registered tinyfish tools");
|
||||
} else {
|
||||
tracing::debug!("[integrations] tinyfish disabled — skipping");
|
||||
}
|
||||
if root_config.integrations.stock_prices.is_active() {
|
||||
tools.push(Box::new(crate::openhuman::tools::StockQuoteTool::new(
|
||||
Arc::clone(&client),
|
||||
)));
|
||||
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(
|
||||
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)),
|
||||
crate::openhuman::tools::StockCryptoSeriesTool::new(Arc::clone(&client)),
|
||||
));
|
||||
tools.push(Box::new(crate::openhuman::tools::StockCommodityTool::new(
|
||||
Arc::clone(&client),
|
||||
)));
|
||||
tracing::debug!("[integrations] registered stock_prices tools");
|
||||
} else {
|
||||
tracing::debug!("[integrations] stock_prices disabled — skipping");
|
||||
}
|
||||
if root_config.integrations.twilio.is_active() {
|
||||
tools.push(Box::new(
|
||||
crate::openhuman::integrations::TwilioCallTool::new(Arc::clone(&client)),
|
||||
));
|
||||
tools.push(Box::new(crate::openhuman::tools::TwilioCallTool::new(
|
||||
Arc::clone(&client),
|
||||
)));
|
||||
tracing::debug!("[integrations] registered twilio tools");
|
||||
} else {
|
||||
tracing::debug!("[integrations] twilio disabled — skipping");
|
||||
|
||||
@@ -11,8 +11,8 @@ use serde_json::{json, Map, Value};
|
||||
use crate::core::all::{ControllerFuture, RegisteredController};
|
||||
use crate::core::{ControllerSchema, FieldSchema, TypeSchema};
|
||||
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::SEARXNG_MAX_RESULTS;
|
||||
use crate::rpc::RpcOutcome;
|
||||
|
||||
pub fn all_controller_schemas() -> Vec<ControllerSchema> {
|
||||
@@ -517,7 +517,7 @@ fn handle_web_search(params: Map<String, Value>) -> ControllerFuture {
|
||||
});
|
||||
|
||||
let resp = client
|
||||
.post::<crate::openhuman::integrations::parallel::SearchResponse>(
|
||||
.post::<crate::openhuman::tools::SearchResponse>(
|
||||
"/agent-integrations/parallel/search",
|
||||
&body,
|
||||
)
|
||||
@@ -568,7 +568,7 @@ fn handle_seltz_search(params: Map<String, Value>) -> ControllerFuture {
|
||||
"[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_url.clone(),
|
||||
max_results,
|
||||
@@ -650,7 +650,7 @@ fn handle_querit_search(params: Map<String, Value>) -> ControllerFuture {
|
||||
"[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(),
|
||||
None,
|
||||
max_results,
|
||||
@@ -729,7 +729,7 @@ fn handle_searxng_search(params: Map<String, Value>) -> ControllerFuture {
|
||||
"[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.max_results,
|
||||
config.searxng.default_language.clone(),
|
||||
@@ -737,7 +737,7 @@ fn handle_searxng_search(params: Map<String, Value>) -> ControllerFuture {
|
||||
);
|
||||
|
||||
let response = tool
|
||||
.search(crate::openhuman::integrations::SearxngSearchArgs {
|
||||
.search(crate::openhuman::tools::SearxngSearchArgs {
|
||||
query,
|
||||
categories,
|
||||
language,
|
||||
|
||||
@@ -10,6 +10,7 @@ mod execution;
|
||||
mod ops;
|
||||
mod rpc;
|
||||
mod schemas;
|
||||
pub mod tools;
|
||||
|
||||
#[cfg(test)]
|
||||
pub(crate) mod test_support;
|
||||
|
||||
@@ -21,6 +21,7 @@ pub mod rpc;
|
||||
mod schemas;
|
||||
mod sqlite_retry;
|
||||
pub mod store;
|
||||
pub mod tools;
|
||||
pub mod types;
|
||||
|
||||
pub use schemas::{
|
||||
|
||||
Reference in New Issue
Block a user