test_tools.rs

  1use super::*;
  2use anyhow::Result;
  3use gpui::{App, SharedString, Task};
  4use std::future;
  5
  6/// A tool that echoes its input
  7#[derive(JsonSchema, Serialize, Deserialize)]
  8pub struct EchoToolInput {
  9    /// The text to echo.
 10    pub text: String,
 11}
 12
 13pub struct EchoTool;
 14
 15impl AgentTool for EchoTool {
 16    type Input = EchoToolInput;
 17    type Output = String;
 18
 19    fn name() -> &'static str {
 20        "echo"
 21    }
 22
 23    fn kind() -> acp::ToolKind {
 24        acp::ToolKind::Other
 25    }
 26
 27    fn initial_title(&self, _input: Result<Self::Input, serde_json::Value>) -> SharedString {
 28        "Echo".into()
 29    }
 30
 31    fn run(
 32        self: Arc<Self>,
 33        input: Self::Input,
 34        _event_stream: ToolCallEventStream,
 35        _cx: &mut App,
 36    ) -> Task<Result<String>> {
 37        Task::ready(Ok(input.text))
 38    }
 39}
 40
 41/// A tool that waits for a specified delay
 42#[derive(JsonSchema, Serialize, Deserialize)]
 43pub struct DelayToolInput {
 44    /// The delay in milliseconds.
 45    ms: u64,
 46}
 47
 48pub struct DelayTool;
 49
 50impl AgentTool for DelayTool {
 51    type Input = DelayToolInput;
 52    type Output = String;
 53
 54    fn name() -> &'static str {
 55        "delay"
 56    }
 57
 58    fn initial_title(&self, input: Result<Self::Input, serde_json::Value>) -> SharedString {
 59        if let Ok(input) = input {
 60            format!("Delay {}ms", input.ms).into()
 61        } else {
 62            "Delay".into()
 63        }
 64    }
 65
 66    fn kind() -> acp::ToolKind {
 67        acp::ToolKind::Other
 68    }
 69
 70    fn run(
 71        self: Arc<Self>,
 72        input: Self::Input,
 73        _event_stream: ToolCallEventStream,
 74        cx: &mut App,
 75    ) -> Task<Result<String>>
 76    where
 77        Self: Sized,
 78    {
 79        cx.foreground_executor().spawn(async move {
 80            smol::Timer::after(Duration::from_millis(input.ms)).await;
 81            Ok("Ding".to_string())
 82        })
 83    }
 84}
 85
 86#[derive(JsonSchema, Serialize, Deserialize)]
 87pub struct ToolRequiringPermissionInput {}
 88
 89pub struct ToolRequiringPermission;
 90
 91impl AgentTool for ToolRequiringPermission {
 92    type Input = ToolRequiringPermissionInput;
 93    type Output = String;
 94
 95    fn name() -> &'static str {
 96        "tool_requiring_permission"
 97    }
 98
 99    fn kind() -> acp::ToolKind {
100        acp::ToolKind::Other
101    }
102
103    fn initial_title(&self, _input: Result<Self::Input, serde_json::Value>) -> SharedString {
104        "This tool requires permission".into()
105    }
106
107    fn run(
108        self: Arc<Self>,
109        _input: Self::Input,
110        event_stream: ToolCallEventStream,
111        cx: &mut App,
112    ) -> Task<Result<String>> {
113        let authorize = event_stream.authorize("Authorize?", cx);
114        cx.foreground_executor().spawn(async move {
115            authorize.await?;
116            Ok("Allowed".to_string())
117        })
118    }
119}
120
121#[derive(JsonSchema, Serialize, Deserialize)]
122pub struct InfiniteToolInput {}
123
124pub struct InfiniteTool;
125
126impl AgentTool for InfiniteTool {
127    type Input = InfiniteToolInput;
128    type Output = String;
129
130    fn name() -> &'static str {
131        "infinite"
132    }
133
134    fn kind() -> acp::ToolKind {
135        acp::ToolKind::Other
136    }
137
138    fn initial_title(&self, _input: Result<Self::Input, serde_json::Value>) -> SharedString {
139        "Infinite Tool".into()
140    }
141
142    fn run(
143        self: Arc<Self>,
144        _input: Self::Input,
145        _event_stream: ToolCallEventStream,
146        cx: &mut App,
147    ) -> Task<Result<String>> {
148        cx.foreground_executor().spawn(async move {
149            future::pending::<()>().await;
150            unreachable!()
151        })
152    }
153}
154
155/// A tool that takes an object with map from letters to random words starting with that letter.
156/// All fiealds are required! Pass a word for every letter!
157#[derive(JsonSchema, Serialize, Deserialize)]
158pub struct WordListInput {
159    /// Provide a random word that starts with A.
160    a: Option<String>,
161    /// Provide a random word that starts with B.
162    b: Option<String>,
163    /// Provide a random word that starts with C.
164    c: Option<String>,
165    /// Provide a random word that starts with D.
166    d: Option<String>,
167    /// Provide a random word that starts with E.
168    e: Option<String>,
169    /// Provide a random word that starts with F.
170    f: Option<String>,
171    /// Provide a random word that starts with G.
172    g: Option<String>,
173}
174
175pub struct WordListTool;
176
177impl AgentTool for WordListTool {
178    type Input = WordListInput;
179    type Output = String;
180
181    fn name() -> &'static str {
182        "word_list"
183    }
184
185    fn kind() -> acp::ToolKind {
186        acp::ToolKind::Other
187    }
188
189    fn initial_title(&self, _input: Result<Self::Input, serde_json::Value>) -> SharedString {
190        "List of random words".into()
191    }
192
193    fn run(
194        self: Arc<Self>,
195        _input: Self::Input,
196        _event_stream: ToolCallEventStream,
197        _cx: &mut App,
198    ) -> Task<Result<String>> {
199        Task::ready(Ok("ok".to_string()))
200    }
201}