swiftide_agents/tools/
control.rs1use anyhow::Result;
3use async_trait::async_trait;
4use std::borrow::Cow;
5use swiftide_core::{
6 AgentContext, ToolFeedback,
7 chat_completion::{Tool, ToolCall, ToolOutput, ToolSpec, errors::ToolError},
8};
9
10#[derive(Clone, Debug, Default)]
12pub struct Stop {}
13
14#[async_trait]
15impl Tool for Stop {
16 async fn invoke(
17 &self,
18 _agent_context: &dyn AgentContext,
19 _tool_call: &ToolCall,
20 ) -> Result<ToolOutput, ToolError> {
21 Ok(ToolOutput::Stop)
22 }
23
24 fn name(&self) -> Cow<'_, str> {
25 "stop".into()
26 }
27
28 fn tool_spec(&self) -> ToolSpec {
29 ToolSpec::builder()
30 .name("stop")
31 .description("When you have completed, or cannot complete, your task, call this")
32 .build()
33 .unwrap()
34 }
35}
36
37impl From<Stop> for Box<dyn Tool> {
38 fn from(val: Stop) -> Self {
39 Box::new(val)
40 }
41}
42
43#[derive(Clone)]
44pub struct ApprovalRequired(pub Box<dyn Tool>);
46
47impl ApprovalRequired {
48 pub fn new(tool: impl Tool + 'static) -> Self {
50 Self(Box::new(tool))
51 }
52}
53
54#[async_trait]
55impl Tool for ApprovalRequired {
56 async fn invoke(
57 &self,
58 context: &dyn AgentContext,
59 tool_call: &ToolCall,
60 ) -> Result<ToolOutput, ToolError> {
61 if let Some(feedback) = context.has_received_feedback(tool_call).await {
62 match feedback {
63 ToolFeedback::Approved { .. } => return self.0.invoke(context, tool_call).await,
64 ToolFeedback::Refused { .. } => {
65 return Ok(ToolOutput::text("This tool call was refused"));
66 }
67 }
68 }
69
70 Ok(ToolOutput::FeedbackRequired(None))
71 }
72
73 fn name(&self) -> Cow<'_, str> {
74 self.0.name()
75 }
76
77 fn tool_spec(&self) -> ToolSpec {
78 self.0.tool_spec()
79 }
80}
81
82impl From<ApprovalRequired> for Box<dyn Tool> {
83 fn from(val: ApprovalRequired) -> Self {
84 Box::new(val)
85 }
86}