pub mod executor;
use crate::types::{Layer3Result, ToolMeta, ToolRequest, ToolResponse};
use async_trait::async_trait;
pub use executor::{DefaultToolExecutor, ExecutionRecord, JsonSchemaValidator};
#[async_trait]
pub trait ToolExecutor: Send + Sync {
async fn execute(&self, request: ToolRequest) -> Layer3Result<ToolResponse>;
async fn execute_batch(&self, requests: Vec<ToolRequest>) -> Layer3Result<Vec<ToolResponse>>;
fn is_available(&self, name: &str) -> bool;
fn get_meta(&self, name: &str) -> Option<ToolMeta>;
fn list_tools(&self) -> Vec<ToolMeta>;
}
pub trait ToolValidator: Send + Sync {
fn validate(&self, request: &ToolRequest) -> bool;
fn validate_with_reason(&self, request: &ToolRequest) -> Result<(), String>;
}
#[derive(Debug, Clone)]
pub struct ExecutionContext {
pub session_id: String,
pub working_dir: std::path::PathBuf,
pub user_id: Option<String>,
pub env_vars: std::collections::HashMap<String, String>,
pub timeout_secs: u64,
pub allow_dangerous: bool,
}
impl Default for ExecutionContext {
fn default() -> Self {
Self {
session_id: String::new(),
working_dir: std::path::PathBuf::from("."),
user_id: None,
env_vars: std::collections::HashMap::new(),
timeout_secs: 30,
allow_dangerous: false,
}
}
}
#[async_trait]
pub trait ContextualExecutor: ToolExecutor {
async fn execute_with_context(
&self,
request: ToolRequest,
context: ExecutionContext,
) -> Layer3Result<ToolResponse>;
async fn execute_batch_with_context(
&self,
requests: Vec<ToolRequest>,
context: ExecutionContext,
) -> Layer3Result<Vec<ToolResponse>>;
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_execution_context_default() {
let ctx = ExecutionContext::default();
assert_eq!(ctx.timeout_secs, 30);
assert!(!ctx.allow_dangerous);
}
}