use std::sync::Arc;
use oxi_sdk::SearchCache;
use oxi_sdk::ToolRegistry;
use oxi_sdk::{
KernelToolContext as SdkKernelToolContext, KernelToolProvider as SdkKernelToolProvider,
};
use crate::tools::registration::register_always_on;
use crate::KernelHandle;
pub struct OxiosKernelBridge {
kernel_handle: Arc<KernelHandle>,
search_cache: Arc<SearchCache>,
}
impl OxiosKernelBridge {
pub fn new(kernel_handle: Arc<KernelHandle>) -> Self {
Self {
kernel_handle,
search_cache: Arc::new(SearchCache::new()),
}
}
pub fn with_cache(kernel_handle: Arc<KernelHandle>, search_cache: Arc<SearchCache>) -> Self {
Self {
kernel_handle,
search_cache,
}
}
}
impl SdkKernelToolProvider for OxiosKernelBridge {
fn tool_names(&self) -> Vec<&str> {
vec![
"read",
"write",
"edit",
"grep",
"find",
"ls",
"exec",
"memory_read",
"memory_write",
"memory_search",
"space",
"agent",
"a2a_delegate",
"a2a_send",
"a2a_query",
"persona",
"program",
"cron",
"security",
"budget",
"resource",
"mcp",
"browser",
"knowledge",
]
}
fn register_tools(&self, registry: &ToolRegistry, context: &SdkKernelToolContext) {
register_always_on(registry, Arc::clone(&self.search_cache));
crate::tools::kernel::register_all_kernel_tools(
registry,
&self.kernel_handle,
&context.agent_id,
);
}
}
#[cfg(test)]
mod tests {
use super::*;
#[tokio::test]
async fn test_tool_names_length() {
let tmp = tempfile::tempdir().unwrap();
let base = tmp.path().to_path_buf();
let state_store = Arc::new(
crate::state_store::StateStore::new(base.join("workspace")).unwrap(),
);
let kernel = Arc::new(crate::KernelHandle::new(
crate::StateApi::new(state_store.clone()),
crate::AgentApi::new(
Arc::new(crate::supervisor::NoOpSupervisor),
Arc::new(crate::budget::BudgetManager::new()),
Arc::new(crate::memory::MemoryManager::new(state_store.clone())),
None,
),
crate::SecurityApi::new(
Arc::new(parking_lot::Mutex::new(crate::auth::AuthManager::new())),
Arc::new(crate::audit_trail::AuditTrail::new(100)),
Arc::new(parking_lot::Mutex::new(
crate::access_manager::AccessManager::new(),
)),
state_store.clone(),
),
crate::PersonaApi::new(Arc::new(crate::persona_manager::PersonaManager::new())),
crate::ExtensionApi::new(
Arc::new(crate::program::ProgramManager::new(
base.join("programs"),
)),
Arc::new(
crate::skill::SkillStore::new(base.join("skills"))
.unwrap(),
),
Arc::new(crate::host_tools::HostToolValidator::new(vec![], vec![])),
),
crate::McpApi::new(Arc::new(crate::mcp::McpBridge::new())),
crate::InfraApi::new(
Arc::new(
crate::git_layer::GitLayer::new(base.join("git"), false).unwrap(),
),
Arc::new(crate::scheduler::AgentScheduler::new(5, 60, 300)),
Arc::new(crate::cron::CronScheduler::new(state_store.clone(), 60)),
Arc::new(crate::resource_monitor::ResourceMonitor::new(60, 60)),
crate::event_bus::EventBus::new(256),
crate::OxiosConfig::default(),
std::time::Instant::now(),
),
crate::SpaceApi::new(
Arc::new(
crate::space::SpaceManager::new(
state_store.clone(),
crate::event_bus::EventBus::new(256),
)
.await
.unwrap(),
),
crate::event_bus::EventBus::new(256),
),
crate::ExecApi::new(
Arc::new(crate::config::ExecConfig::default()),
Arc::new(parking_lot::Mutex::new(
crate::access_manager::AccessManager::new(),
)),
),
crate::BrowserApi::default(),
crate::A2aApi::new(Arc::new(crate::a2a::A2AProtocol::new(
crate::event_bus::EventBus::new(256),
))),
Arc::new(
oxios_markdown::KnowledgeBase::new(base.join("knowledge"))
.unwrap(),
),
Arc::new(
crate::kernel_handle::KnowledgeLens::new(
Arc::new(
oxios_markdown::KnowledgeBase::new(base.join("knowledge_lens"))
.unwrap(),
),
Arc::new(crate::memory::MemoryManager::new(state_store.clone())),
)
.unwrap(),
),
));
let bridge = OxiosKernelBridge::new(kernel);
let names = bridge.tool_names();
assert_eq!(names.len(), 24, "expected 24 tools, got {:?}", names);
}
}