sh_layer3/tool_executor/
mod.rs1pub mod executor;
6
7use crate::types::{Layer3Result, ToolMeta, ToolRequest, ToolResponse};
8use async_trait::async_trait;
9
10pub use executor::{DefaultToolExecutor, ExecutionRecord, JsonSchemaValidator};
12
13#[async_trait]
21pub trait ToolExecutor: Send + Sync {
22 async fn execute(&self, request: ToolRequest) -> Layer3Result<ToolResponse>;
30
31 async fn execute_batch(&self, requests: Vec<ToolRequest>) -> Layer3Result<Vec<ToolResponse>>;
39
40 fn is_available(&self, name: &str) -> bool;
45
46 fn get_meta(&self, name: &str) -> Option<ToolMeta>;
51
52 fn list_tools(&self) -> Vec<ToolMeta>;
54}
55
56pub trait ToolValidator: Send + Sync {
60 fn validate(&self, request: &ToolRequest) -> bool;
68
69 fn validate_with_reason(&self, request: &ToolRequest) -> Result<(), String>;
74}
75
76#[derive(Debug, Clone)]
80pub struct ExecutionContext {
81 pub session_id: String,
83 pub working_dir: std::path::PathBuf,
85 pub user_id: Option<String>,
87 pub env_vars: std::collections::HashMap<String, String>,
89 pub timeout_secs: u64,
91 pub allow_dangerous: bool,
93}
94
95impl Default for ExecutionContext {
96 fn default() -> Self {
97 Self {
98 session_id: String::new(),
99 working_dir: std::path::PathBuf::from("."),
100 user_id: None,
101 env_vars: std::collections::HashMap::new(),
102 timeout_secs: 30,
103 allow_dangerous: false,
104 }
105 }
106}
107
108#[async_trait]
112pub trait ContextualExecutor: ToolExecutor {
113 async fn execute_with_context(
119 &self,
120 request: ToolRequest,
121 context: ExecutionContext,
122 ) -> Layer3Result<ToolResponse>;
123
124 async fn execute_batch_with_context(
126 &self,
127 requests: Vec<ToolRequest>,
128 context: ExecutionContext,
129 ) -> Layer3Result<Vec<ToolResponse>>;
130}
131
132#[cfg(test)]
133mod tests {
134 use super::*;
135
136 #[test]
137 fn test_execution_context_default() {
138 let ctx = ExecutionContext::default();
139 assert_eq!(ctx.timeout_secs, 30);
140 assert!(!ctx.allow_dangerous);
141 }
142}