ceylon_core/
action.rs

1use crate::agent::AgentContext;
2use crate::error::{Error, Result};
3use async_trait::async_trait;
4use serde::{Deserialize, Serialize};
5use serde_json::Value;
6use std::collections::HashMap;
7
8/// Metadata describing an action
9#[derive(Debug, Clone, Serialize, Deserialize)]
10pub struct ActionMetadata {
11    /// Action name (unique within an agent)
12    pub name: String,
13
14    /// Human-readable description
15    pub description: String,
16
17    /// JSON Schema for input validation
18    pub input_schema: Value,
19
20    /// JSON Schema for output (optional)
21    pub output_schema: Option<Value>,
22}
23
24/// Trait for invoking actions with context
25#[async_trait]
26pub trait ActionInvoker: Send + Sync {
27    /// Execute the action with given context and inputs
28    async fn execute(&self, ctx: &mut AgentContext, inputs: Value) -> Result<Value>;
29
30    /// Get action metadata
31    fn metadata(&self) -> &ActionMetadata;
32}
33
34/// Manages action registration and execution for an agent
35pub struct ToolInvoker {
36    actions: HashMap<String, Box<dyn ActionInvoker>>,
37}
38
39impl ToolInvoker {
40    /// Create a new ToolInvoker
41    pub fn new() -> Self {
42        Self {
43            actions: HashMap::new(),
44        }
45    }
46
47    /// Register an action
48    pub fn register(&mut self, action: Box<dyn ActionInvoker>) {
49        let name = action.metadata().name.clone();
50        self.actions.insert(name, action);
51    }
52
53    /// List all registered actions
54    pub fn list_actions(&self) -> Vec<ActionMetadata> {
55        self.actions
56            .values()
57            .map(|a| a.metadata().clone())
58            .collect()
59    }
60
61    /// Invoke an action by name
62    pub async fn invoke(&self, name: &str, ctx: &mut AgentContext, inputs: Value) -> Result<Value> {
63        let action = self
64            .actions
65            .get(name)
66            .ok_or_else(|| Error::ActionNotFound(name.to_string()))?;
67
68        action.execute(ctx, inputs).await
69    }
70}
71
72impl Default for ToolInvoker {
73    fn default() -> Self {
74        Self::new()
75    }
76}