Skip to main content

oxios_kernel/tools/
kernel_bridge.rs

1//! KernelToolProvider bridge — plugs oxios kernel tools into oxi-sdk agent builder.
2//!
3//! Implements [`oxi_sdk::KernelToolProvider`] so that oxios kernel tools
4//! (exec, memory, browser, etc.) can be registered into the SDK's
5//! `AgentBuilder` via `.kernel_tools()`.
6
7use std::sync::Arc;
8
9use oxi_sdk::SearchCache;
10use oxi_sdk::ToolRegistry;
11use oxi_sdk::{
12    KernelToolContext as SdkKernelToolContext, KernelToolProvider as SdkKernelToolProvider,
13};
14
15use crate::tools::registration::register_always_on;
16use crate::KernelHandle;
17
18/// Bridges all oxios kernel tools into the oxi-sdk agent builder.
19pub struct OxiosKernelBridge {
20    kernel_handle: Arc<KernelHandle>,
21    search_cache: Arc<SearchCache>,
22}
23
24impl OxiosKernelBridge {
25    /// Create a new bridge with the given kernel handle.
26    pub fn new(kernel_handle: Arc<KernelHandle>) -> Self {
27        Self {
28            kernel_handle,
29            search_cache: Arc::new(SearchCache::new()),
30        }
31    }
32
33    /// Create a new bridge with a pre-built search cache.
34    pub fn with_cache(kernel_handle: Arc<KernelHandle>, search_cache: Arc<SearchCache>) -> Self {
35        Self {
36            kernel_handle,
37            search_cache,
38        }
39    }
40}
41
42impl SdkKernelToolProvider for OxiosKernelBridge {
43    fn tool_names(&self) -> Vec<&str> {
44        vec![
45            // Always-on file tools
46            "read",
47            "write",
48            "edit",
49            "grep",
50            "find",
51            "ls",
52            // Kernel domain
53            "exec",
54            "memory_read",
55            "memory_write",
56            "memory_search",
57            "space",
58            "agent",
59            "a2a_delegate",
60            "a2a_send",
61            "a2a_query",
62            "persona",
63            "program",
64            "cron",
65            "security",
66            "budget",
67            "resource",
68            "mcp",
69            "browser",
70        ]
71    }
72
73    fn register_tools(&self, registry: &ToolRegistry, context: &SdkKernelToolContext) {
74        // 1. Always-on file tools + web search
75        register_always_on(registry, Arc::clone(&self.search_cache));
76
77        // 2. Kernel domain tools via KernelHandle
78        crate::tools::kernel::register_all_kernel_tools(
79            registry,
80            &self.kernel_handle,
81            &context.agent_id,
82        );
83    }
84}
85
86#[cfg(test)]
87mod tests {
88    use super::*;
89
90    /// Verify that `tool_names()` returns the expected number of tool names.
91    #[tokio::test]
92    async fn test_tool_names_length() {
93        // Build a minimal KernelHandle for testing
94        let state_store = Arc::new(
95            crate::state_store::StateStore::new(std::path::PathBuf::from(
96                "/tmp/oxios-test-workspace",
97            ))
98            .unwrap(),
99        );
100
101        let kernel = Arc::new(crate::KernelHandle::new(
102            crate::StateApi::new(state_store.clone()),
103            crate::AgentApi::new(
104                Arc::new(crate::supervisor::NoOpSupervisor),
105                Arc::new(crate::budget::BudgetManager::new()),
106                Arc::new(crate::memory::MemoryManager::new(
107                    state_store.clone(),
108                )),
109                None,
110            ),
111            crate::SecurityApi::new(
112                Arc::new(parking_lot::Mutex::new(
113                    crate::auth::AuthManager::new(),
114                )),
115                Arc::new(crate::audit_trail::AuditTrail::new(100)),
116                Arc::new(parking_lot::Mutex::new(
117                    crate::access_manager::AccessManager::new(),
118                )),
119                state_store.clone(),
120            ),
121            crate::PersonaApi::new(Arc::new(
122                crate::persona_manager::PersonaManager::new(),
123            )),
124            crate::ExtensionApi::new(
125                Arc::new(crate::program::ProgramManager::new(
126                    std::path::PathBuf::from("/tmp/oxios-test/programs"),
127                )),
128                Arc::new(
129                    crate::skill::SkillStore::new(std::path::PathBuf::from(
130                        "/tmp/oxios-test/skills",
131                    ))
132                    .unwrap(),
133                ),
134                Arc::new(crate::host_tools::HostToolValidator::new(
135                    vec![],
136                    vec![],
137                )),
138            ),
139            crate::McpApi::new(Arc::new(crate::mcp::McpBridge::new())),
140            crate::InfraApi::new(
141                Arc::new(
142                    crate::git_layer::GitLayer::new(
143                        std::path::PathBuf::from("/tmp/oxios-test"),
144                        false,
145                    )
146                    .unwrap(),
147                ),
148                Arc::new(crate::scheduler::AgentScheduler::new(5, 60, 300)),
149                Arc::new(crate::cron::CronScheduler::new(
150                    state_store.clone(),
151                    60,
152                )),
153                Arc::new(crate::resource_monitor::ResourceMonitor::new(60, 60)),
154                crate::event_bus::EventBus::new(256),
155                crate::OxiosConfig::default(),
156                std::time::Instant::now(),
157            ),
158            crate::SpaceApi::new(
159                Arc::new(
160                    crate::space::SpaceManager::new(
161                        state_store.clone(),
162                        crate::event_bus::EventBus::new(256),
163                    )
164                    .await
165                    .unwrap(),
166                ),
167                crate::event_bus::EventBus::new(256),
168            ),
169            crate::ExecApi::new(
170                Arc::new(crate::config::ExecConfig::default()),
171                Arc::new(parking_lot::Mutex::new(
172                    crate::access_manager::AccessManager::new(),
173                )),
174            ),
175            crate::BrowserApi::default(),
176            crate::A2aApi::new(Arc::new(crate::a2a::A2AProtocol::new(
177                crate::event_bus::EventBus::new(256),
178            ))),
179        ));
180
181        let bridge = OxiosKernelBridge::new(kernel);
182
183        let names = bridge.tool_names();
184        // 6 always-on + 12 kernel domain = 18 tools
185        assert_eq!(names.len(), 23, "expected 23 tools, got {:?}", names);
186    }
187}