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            "knowledge",
71        ]
72    }
73
74    fn register_tools(&self, registry: &ToolRegistry, context: &SdkKernelToolContext) {
75        // 1. Always-on file tools + web search
76        register_always_on(registry, Arc::clone(&self.search_cache));
77
78        // 2. Kernel domain tools via KernelHandle
79        crate::tools::kernel::register_all_kernel_tools(
80            registry,
81            &self.kernel_handle,
82            &context.agent_id,
83        );
84    }
85}
86
87#[cfg(test)]
88mod tests {
89    use super::*;
90
91    /// Verify that `tool_names()` returns the expected number of tool names.
92    #[tokio::test]
93    async fn test_tool_names_length() {
94        // Build a minimal KernelHandle for testing
95        let state_store = Arc::new(
96            crate::state_store::StateStore::new(std::path::PathBuf::from(
97                "/tmp/oxios-test-workspace",
98            ))
99            .unwrap(),
100        );
101
102        let kernel = Arc::new(crate::KernelHandle::new(
103            crate::StateApi::new(state_store.clone()),
104            crate::AgentApi::new(
105                Arc::new(crate::supervisor::NoOpSupervisor),
106                Arc::new(crate::budget::BudgetManager::new()),
107                Arc::new(crate::memory::MemoryManager::new(state_store.clone())),
108                None,
109            ),
110            crate::SecurityApi::new(
111                Arc::new(parking_lot::Mutex::new(crate::auth::AuthManager::new())),
112                Arc::new(crate::audit_trail::AuditTrail::new(100)),
113                Arc::new(parking_lot::Mutex::new(
114                    crate::access_manager::AccessManager::new(),
115                )),
116                state_store.clone(),
117            ),
118            crate::PersonaApi::new(Arc::new(crate::persona_manager::PersonaManager::new())),
119            crate::ExtensionApi::new(
120                Arc::new(crate::program::ProgramManager::new(
121                    std::path::PathBuf::from("/tmp/oxios-test/programs"),
122                )),
123                Arc::new(
124                    crate::skill::SkillStore::new(std::path::PathBuf::from(
125                        "/tmp/oxios-test/skills",
126                    ))
127                    .unwrap(),
128                ),
129                Arc::new(crate::host_tools::HostToolValidator::new(vec![], vec![])),
130            ),
131            crate::McpApi::new(Arc::new(crate::mcp::McpBridge::new())),
132            crate::InfraApi::new(
133                Arc::new(
134                    crate::git_layer::GitLayer::new(
135                        std::path::PathBuf::from("/tmp/oxios-test"),
136                        false,
137                    )
138                    .unwrap(),
139                ),
140                Arc::new(crate::scheduler::AgentScheduler::new(5, 60, 300)),
141                Arc::new(crate::cron::CronScheduler::new(state_store.clone(), 60)),
142                Arc::new(crate::resource_monitor::ResourceMonitor::new(60, 60)),
143                crate::event_bus::EventBus::new(256),
144                crate::OxiosConfig::default(),
145                std::time::Instant::now(),
146            ),
147            crate::SpaceApi::new(
148                Arc::new(
149                    crate::space::SpaceManager::new(
150                        state_store.clone(),
151                        crate::event_bus::EventBus::new(256),
152                    )
153                    .await
154                    .unwrap(),
155                ),
156                crate::event_bus::EventBus::new(256),
157            ),
158            crate::ExecApi::new(
159                Arc::new(crate::config::ExecConfig::default()),
160                Arc::new(parking_lot::Mutex::new(
161                    crate::access_manager::AccessManager::new(),
162                )),
163            ),
164            crate::BrowserApi::default(),
165            crate::A2aApi::new(Arc::new(crate::a2a::A2AProtocol::new(
166                crate::event_bus::EventBus::new(256),
167            ))),
168            Arc::new(
169                oxios_markdown::KnowledgeBase::new(std::path::PathBuf::from(
170                    "/tmp/oxios-test/knowledge",
171                ))
172                .unwrap(),
173            ),
174            Arc::new(
175                crate::kernel_handle::KnowledgeLens::new(
176                    Arc::new(
177                        oxios_markdown::KnowledgeBase::new(std::path::PathBuf::from(
178                            "/tmp/oxios-test/knowledge",
179                        ))
180                        .unwrap(),
181                    ),
182                    Arc::new(crate::memory::MemoryManager::new(state_store.clone())),
183                )
184                .unwrap(),
185            ),
186        ));
187
188        let bridge = OxiosKernelBridge::new(kernel);
189
190        let names = bridge.tool_names();
191        // 6 always-on + 17 kernel domain = 23 ... plus knowledge = 24
192        assert_eq!(names.len(), 24, "expected 24 tools, got {:?}", names);
193    }
194}