1use std::collections::HashMap;
2use std::sync::Arc;
3
4use async_trait::async_trait;
5use serde_json::{json, Value};
6use tokio::sync::mpsc;
7
8use crate::llm::LlmClient;
9use crate::types::{AgentResult, AgentError, SessionId, UserEvent};
10use crate::engine::SessionStore;
11
12pub mod auto_continue;
13pub mod policy;
14pub mod subagent;
15pub mod update_plan;
16
17pub use auto_continue::AutoContinueTool;
18pub use subagent::{SubAgentSessionPolicy, SubAgentTool};
19pub use update_plan::UpdatePlanTool;
20
21pub use policy::ToolPolicy;
22
23#[derive(Clone, Debug, Default)]
24pub struct ToolOutput {
25 pub summary: String,
26 pub raw: Option<Value>,
27 pub control_flow: ToolControlFlow,
28 pub truncation: Option<TruncationInfo>,
29}
30
31#[derive(Clone, Debug)]
32pub struct TruncationInfo {
33 pub original_summary_len: usize,
34 pub original_raw_len: Option<usize>,
35 pub max_allowed_chars: usize,
36}
37
38#[derive(Clone, Debug, Default)]
39pub enum ToolControlFlow {
40 #[default]
41 Break,
42 Continue,
43}
44
45#[derive(Clone)]
46pub struct ToolContext {
47 pub session_id: SessionId,
48 pub user_event_tx: mpsc::UnboundedSender<UserEvent>,
51 pub llm_client: Option<Arc<dyn LlmClient>>,
52 pub session_store: Option<Arc<dyn SessionStore>>,
53 pub language: crate::types::Language,
56 pub cancel_token: tokio_util::sync::CancellationToken,
58}
59
60impl ToolContext {
61 pub fn emit_user_event(&self, event: UserEvent) {
63 let _ = self.user_event_tx.send(event);
64 }
65
66 pub fn emit_progress(&self, text: impl Into<String>) {
68 self.emit_user_event(UserEvent::Progress { text: text.into() });
69 }
70}
71
72#[async_trait]
73pub trait Tool: Send + Sync {
74 fn name(&self) -> &'static str;
75 fn definition(&self) -> Value;
76 async fn call(&self, args: &Value, ctx: &ToolContext) -> AgentResult<ToolOutput>;
77
78 #[allow(private_interfaces)]
82 fn as_framework_tool(&self) -> Option<&dyn FrameworkTool> { None }
83}
84
85pub(crate) trait FrameworkTool: Tool {
93 fn set_event_bus(&self, _event_bus: crate::engine::EventBus) {}
95}
96
97#[async_trait]
98pub trait TypedTool: Send + Sync {
99 type Args: serde::de::DeserializeOwned;
100 type Output: serde::Serialize;
101
102 fn name(&self) -> &'static str;
103 fn description(&self) -> &'static str;
104 fn parameters_schema(&self) -> Value;
105 async fn call_typed(&self, args: Self::Args, ctx: &ToolContext) -> AgentResult<Self::Output>;
106
107 fn control_flow() -> ToolControlFlow
108 where
109 Self: Sized,
110 {
111 ToolControlFlow::Break
112 }
113
114 fn format_output(&self, output: Self::Output) -> String {
115 serde_json::to_string(&output).unwrap_or_default()
116 }
117}
118
119#[async_trait]
120impl<T: TypedTool + Send + Sync + 'static> Tool for T {
121 fn name(&self) -> &'static str {
122 TypedTool::name(self)
123 }
124
125 fn definition(&self) -> Value {
126 json!({
127 "type": "function",
128 "function": {
129 "name": self.name(),
130 "description": self.description(),
131 "parameters": self.parameters_schema(),
132 }
133 })
134 }
135
136 async fn call(&self, args: &Value, ctx: &ToolContext) -> AgentResult<ToolOutput> {
137 let typed_args: T::Args = serde_json::from_value(args.clone())
138 .map_err(|_| AgentError::ToolArgsInvalid {
139 name: self.name().to_string(),
140 raw: args.to_string(),
141 })?;
142 let output = self.call_typed(typed_args, ctx).await?;
143 let output_json = serde_json::to_value(&output).ok();
144 let summary = self.format_output(output);
145 Ok(ToolOutput {
146 summary,
147 raw: output_json,
148 control_flow: T::control_flow(),
149 truncation: None,
150 })
151 }
152}
153
154pub(crate) type ToolRef = Arc<dyn Tool>;
155
156#[derive(Clone, Default)]
157pub struct ToolRegistry {
158 tools: HashMap<String, ToolRef>,
159}
160
161impl ToolRegistry {
162 pub fn register(&mut self, tool: impl Tool + 'static) {
163 self.tools.insert(tool.name().to_string(), Arc::new(tool));
164 }
165
166 pub fn register_arc(&mut self, tool: Arc<dyn Tool>) {
167 self.tools.insert(tool.name().to_string(), tool);
168 }
169
170 pub fn update(&mut self, tool: impl Tool + 'static) {
171 self.tools.insert(tool.name().to_string(), Arc::new(tool));
172 }
173
174 pub fn remove(&mut self, name: &str) {
176 self.tools.remove(name);
177 }
178
179 pub fn get(&self, name: &str) -> Option<ToolRef> {
180 self.tools.get(name).cloned()
181 }
182
183 pub fn definitions(&self) -> Vec<Value> {
184 self.tools.values().map(|tool| tool.definition()).collect()
185 }
186
187 pub fn len(&self) -> usize {
188 self.tools.len()
189 }
190
191 pub fn is_empty(&self) -> bool {
192 self.tools.is_empty()
193 }
194
195 pub fn inject_event_bus(&self, event_bus: &crate::engine::EventBus) {
197 for tool in self.tools.values() {
198 if let Some(fw) = tool.as_framework_tool() {
199 fw.set_event_bus(event_bus.clone());
200 }
201 }
202 }
203}