1use 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
18pub struct OxiosKernelBridge {
20 kernel_handle: Arc<KernelHandle>,
21 search_cache: Arc<SearchCache>,
22}
23
24impl OxiosKernelBridge {
25 pub fn new(kernel_handle: Arc<KernelHandle>) -> Self {
27 Self {
28 kernel_handle,
29 search_cache: Arc::new(SearchCache::new()),
30 }
31 }
32
33 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 "read",
47 "write",
48 "edit",
49 "grep",
50 "find",
51 "ls",
52 "exec",
54 "memory_read",
55 "memory_write",
56 "memory_search",
57 "project",
58 "agent",
59 "a2a_delegate",
60 "a2a_send",
61 "a2a_query",
62 "persona",
63 "cron",
64 "security",
65 "budget",
66 "resource",
67 "mcp",
68 "browser",
69 "knowledge",
70 "marketplace",
72 "calendar",
74 "send_email",
76 ]
77 }
78
79 fn register_tools(&self, registry: &ToolRegistry, context: &SdkKernelToolContext) {
80 register_always_on(registry, Arc::clone(&self.search_cache));
82
83 crate::tools::builtin::register_all_kernel_tools(
85 registry,
86 &self.kernel_handle,
87 &context.agent_id,
88 );
89 }
90}
91
92#[cfg(test)]
93mod tests {
94 use super::*;
95
96 #[tokio::test]
98 async fn test_tool_names_length() {
99 let tmp = tempfile::tempdir().unwrap();
100 let base = tmp.path().to_path_buf();
101
102 let state_store =
104 Arc::new(crate::state_store::StateStore::new(base.join("workspace")).unwrap());
105
106 let kernel = Arc::new(crate::KernelHandle::new(
107 crate::StateApi::new(state_store.clone()),
108 crate::AgentApi::new(
109 Arc::new(crate::supervisor::NoOpSupervisor),
110 Arc::new(crate::budget::BudgetManager::new()),
111 Arc::new(crate::memory::MemoryManager::new(state_store.clone())),
112 None,
113 ),
114 crate::SecurityApi::new(
115 Arc::new(parking_lot::Mutex::new(crate::auth::AuthManager::new())),
116 Arc::new(oxi_sdk::observability::AuditTrail::new(100)),
117 Arc::new(parking_lot::Mutex::new(
118 crate::access_manager::AccessManager::new(),
119 )),
120 state_store.clone(),
121 ),
122 crate::PersonaApi::new(Arc::new(crate::persona::PersonaManager::new())),
123 crate::ExtensionApi::new(Arc::new(crate::skill::SkillManager::new(
124 base.join("skills"),
125 base.join("share/skills"),
126 ))),
127 crate::McpApi::new(Arc::new(crate::mcp::McpBridge::new())),
128 crate::InfraApi::new(
129 Arc::new(crate::git_layer::GitLayer::new(base.join("git"), false).unwrap()),
130 Arc::new(crate::scheduler::AgentScheduler::new(5, 60, 300)),
131 Arc::new(crate::cron::CronScheduler::new(state_store.clone(), 60)),
132 Arc::new(crate::resource_monitor::ResourceMonitor::new(60, 60)),
133 crate::event_bus::EventBus::new(256),
134 crate::OxiosConfig::default(),
135 std::time::Instant::now(),
136 ),
137 None,
138 crate::ExecApi::new(
139 Arc::new(parking_lot::RwLock::new(
140 crate::config::ExecConfig::default(),
141 )),
142 Arc::new(parking_lot::Mutex::new(
143 crate::access_manager::AccessManager::new(),
144 )),
145 ),
146 crate::A2aApi::new(Arc::new(crate::a2a::A2AProtocol::new(
147 crate::event_bus::EventBus::new(256),
148 ))),
149 crate::EngineApi::new(
150 Arc::new(parking_lot::RwLock::new(crate::OxiosConfig::default())),
151 base.join("config.toml"),
152 Arc::new(crate::RoutingStats::new()),
153 Arc::new(crate::engine::EngineHandle::new(Arc::new(
154 crate::OxiosEngine::new("anthropic/claude-sonnet-4-20250514"),
155 ))),
156 ),
157 Arc::new(oxios_markdown::KnowledgeBase::new(base.join("knowledge")).unwrap()),
158 Arc::new(
159 crate::kernel_handle::KnowledgeLens::new(
160 Arc::new(
161 oxios_markdown::KnowledgeBase::new(base.join("knowledge_lens")).unwrap(),
162 ),
163 Arc::new(crate::memory::MemoryManager::new(state_store.clone())),
164 )
165 .unwrap(),
166 ),
167 crate::MarketplaceApi::new(
168 Arc::new(crate::skill::clawhub::ClawHubInstaller::new(
169 base.join("skills"),
170 base.join("workspace"),
171 None,
172 )),
173 Arc::new(
174 crate::skill::clawhub::ClawHubClient::new(None).expect("valid ClawHub client"),
175 ),
176 Arc::new(crate::skill::skills_sh::SkillsShInstaller::new(
177 base.join("skills"),
178 None,
179 None,
180 )),
181 Arc::new(
182 crate::skill::skills_sh::SkillsShClient::new(None, None)
183 .expect("valid Skills.sh client"),
184 ),
185 ),
186 None, None, ));
189
190 let bridge = OxiosKernelBridge::new(kernel);
191
192 let names = bridge.tool_names();
193 assert_eq!(names.len(), 26, "expected 26 tools, got {:?}", names);
196 }
197}