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