oxicode_sdk/
kernel_bridge.rs1use oxicode_agent::ToolRegistry;
7use std::collections::HashMap;
8use std::path::PathBuf;
9
10#[derive(Debug, Clone)]
19pub struct KernelToolContext {
20 pub workspace_dir: PathBuf,
22 pub agent_id: String,
24 pub session_id: Option<String>,
26 pub permissions: Vec<String>,
28 pub metadata: HashMap<String, serde_json::Value>,
34}
35
36impl KernelToolContext {
37 pub fn new(workspace_dir: impl Into<PathBuf>, agent_id: impl Into<String>) -> Self {
39 Self {
40 workspace_dir: workspace_dir.into(),
41 agent_id: agent_id.into(),
42 session_id: None,
43 permissions: Vec::new(),
44 metadata: HashMap::new(),
45 }
46 }
47
48 pub fn with_session(mut self, session_id: impl Into<String>) -> Self {
50 self.session_id = Some(session_id.into());
51 self
52 }
53
54 pub fn with_permissions(mut self, permissions: Vec<String>) -> Self {
56 self.permissions = permissions;
57 self
58 }
59
60 pub fn with_meta(mut self, key: impl Into<String>, value: serde_json::Value) -> Self {
72 self.metadata.insert(key.into(), value);
73 self
74 }
75
76 pub fn get_meta(&self, key: &str) -> Option<&serde_json::Value> {
78 self.metadata.get(key)
79 }
80
81 pub fn get_meta_str(&self, key: &str) -> Option<&str> {
83 self.metadata.get(key).and_then(|v| v.as_str())
84 }
85}
86
87pub trait KernelToolProvider: Send + Sync {
112 fn tool_names(&self) -> Vec<&str>;
114
115 fn register_tools(&self, registry: &ToolRegistry, context: &KernelToolContext);
120}
121
122#[cfg(test)]
123mod tests {
124 use super::*;
125 use async_trait::async_trait;
126 use oxicode_agent::{AgentTool, AgentToolResult, ToolContext, ToolError};
127 use serde_json::Value;
128
129 struct MockKernelTool {
130 name: String,
131 }
132
133 #[async_trait]
134 impl AgentTool for MockKernelTool {
135 fn name(&self) -> &str {
136 &self.name
137 }
138 fn label(&self) -> &str {
139 "mock"
140 }
141 fn description(&self) -> &str {
142 "A mock kernel tool"
143 }
144 fn parameters_schema(&self) -> Value {
145 serde_json::json!({"type": "object", "properties": {}})
146 }
147
148 async fn execute(
149 &self,
150 _tool_call_id: &str,
151 _params: Value,
152 _signal: Option<tokio::sync::oneshot::Receiver<()>>,
153 _ctx: &ToolContext,
154 ) -> Result<AgentToolResult, ToolError> {
155 Ok(AgentToolResult::success("mock result"))
156 }
157 }
158
159 struct MockKernelBridge;
160
161 impl KernelToolProvider for MockKernelBridge {
162 fn tool_names(&self) -> Vec<&str> {
163 vec!["exec", "memory"]
164 }
165
166 fn register_tools(&self, registry: &ToolRegistry, ctx: &KernelToolContext) {
167 registry.register(MockKernelTool {
168 name: format!("exec_{}", ctx.agent_id),
169 });
170 registry.register(MockKernelTool {
171 name: format!("memory_{}", ctx.agent_id),
172 });
173 }
174 }
175
176 #[test]
177 fn test_kernel_tool_context_builder() {
178 let ctx = KernelToolContext::new("/workspace", "agent-001")
179 .with_session("sess-123")
180 .with_permissions(vec!["read".into(), "write".into()]);
181
182 assert_eq!(ctx.workspace_dir, PathBuf::from("/workspace"));
183 assert_eq!(ctx.agent_id, "agent-001");
184 assert_eq!(ctx.session_id, Some("sess-123".to_string()));
185 assert_eq!(ctx.permissions, vec!["read", "write"]);
186 }
187
188 #[test]
189 fn test_kernel_bridge_registers_tools() {
190 let bridge = MockKernelBridge;
191 let registry = ToolRegistry::new();
192 let ctx = KernelToolContext::new("/workspace", "agent-001");
193
194 bridge.register_tools(®istry, &ctx);
195
196 let names = registry.names();
197 assert!(names.contains(&"exec_agent-001".to_string()));
198 assert!(names.contains(&"memory_agent-001".to_string()));
199 }
200}