swiftide_core/chat_completion/
traits.rs1use anyhow::Result;
2use async_trait::async_trait;
3use dyn_clone::DynClone;
4use std::{borrow::Cow, sync::Arc};
5
6use crate::{AgentContext, CommandOutput};
7
8use super::{
9 chat_completion_request::ChatCompletionRequest,
10 chat_completion_response::ChatCompletionResponse,
11 errors::{ChatCompletionError, ToolError},
12 ToolOutput, ToolSpec,
13};
14
15#[async_trait]
16pub trait ChatCompletion: Send + Sync + DynClone {
17 async fn complete(
18 &self,
19 request: &ChatCompletionRequest,
20 ) -> Result<ChatCompletionResponse, ChatCompletionError>;
21}
22
23#[async_trait]
24impl ChatCompletion for Box<dyn ChatCompletion> {
25 async fn complete(
26 &self,
27 request: &ChatCompletionRequest,
28 ) -> Result<ChatCompletionResponse, ChatCompletionError> {
29 (**self).complete(request).await
30 }
31}
32
33#[async_trait]
34impl ChatCompletion for &dyn ChatCompletion {
35 async fn complete(
36 &self,
37 request: &ChatCompletionRequest,
38 ) -> Result<ChatCompletionResponse, ChatCompletionError> {
39 (**self).complete(request).await
40 }
41}
42
43#[async_trait]
44impl<T> ChatCompletion for &T
45where
46 T: ChatCompletion + Clone + 'static,
47{
48 async fn complete(
49 &self,
50 request: &ChatCompletionRequest,
51 ) -> Result<ChatCompletionResponse, ChatCompletionError> {
52 (**self).complete(request).await
53 }
54}
55
56impl<LLM> From<&LLM> for Box<dyn ChatCompletion>
57where
58 LLM: ChatCompletion + Clone + 'static,
59{
60 fn from(llm: &LLM) -> Self {
61 Box::new(llm.clone()) as Box<dyn ChatCompletion>
62 }
63}
64
65dyn_clone::clone_trait_object!(ChatCompletion);
66
67impl From<CommandOutput> for ToolOutput {
68 fn from(value: CommandOutput) -> Self {
69 ToolOutput::Text(value.output)
70 }
71}
72
73#[async_trait]
82pub trait Tool: Send + Sync + DynClone {
83 async fn invoke(
85 &self,
86 agent_context: &dyn AgentContext,
87 raw_args: Option<&str>,
88 ) -> Result<ToolOutput, ToolError>;
89
90 fn name(&self) -> Cow<'_, str>;
91
92 fn tool_spec(&self) -> ToolSpec;
93
94 fn boxed<'a>(self) -> Box<dyn Tool + 'a>
95 where
96 Self: Sized + 'a,
97 {
98 Box::new(self) as Box<dyn Tool>
99 }
100}
101
102#[async_trait]
110pub trait ToolBox: Send + Sync + DynClone {
111 async fn available_tools(&self) -> Result<Vec<Box<dyn Tool>>>;
112
113 fn name(&self) -> Cow<'_, str> {
114 Cow::Borrowed("Unnamed ToolBox")
115 }
116
117 fn boxed<'a>(self) -> Box<dyn ToolBox + 'a>
118 where
119 Self: Sized + 'a,
120 {
121 Box::new(self) as Box<dyn ToolBox>
122 }
123}
124
125#[async_trait]
126impl ToolBox for Vec<Box<dyn Tool>> {
127 async fn available_tools(&self) -> Result<Vec<Box<dyn Tool>>> {
128 Ok(self.clone())
129 }
130}
131
132#[async_trait]
133impl ToolBox for Box<dyn ToolBox> {
134 async fn available_tools(&self) -> Result<Vec<Box<dyn Tool>>> {
135 (**self).available_tools().await
136 }
137}
138
139#[async_trait]
140impl ToolBox for Arc<dyn ToolBox> {
141 async fn available_tools(&self) -> Result<Vec<Box<dyn Tool>>> {
142 (**self).available_tools().await
143 }
144}
145
146#[async_trait]
147impl ToolBox for &dyn ToolBox {
148 async fn available_tools(&self) -> Result<Vec<Box<dyn Tool>>> {
149 (**self).available_tools().await
150 }
151}
152
153#[async_trait]
154impl ToolBox for &[Box<dyn Tool>] {
155 async fn available_tools(&self) -> Result<Vec<Box<dyn Tool>>> {
156 Ok(self.to_vec())
157 }
158}
159
160#[async_trait]
161impl ToolBox for [Box<dyn Tool>] {
162 async fn available_tools(&self) -> Result<Vec<Box<dyn Tool>>> {
163 Ok(self.to_vec())
164 }
165}
166
167dyn_clone::clone_trait_object!(ToolBox);
168
169#[async_trait]
170impl Tool for Box<dyn Tool> {
171 async fn invoke(
172 &self,
173 agent_context: &dyn AgentContext,
174 raw_args: Option<&str>,
175 ) -> Result<ToolOutput, ToolError> {
176 (**self).invoke(agent_context, raw_args).await
177 }
178 fn name(&self) -> Cow<'_, str> {
179 (**self).name()
180 }
181 fn tool_spec(&self) -> ToolSpec {
182 (**self).tool_spec()
183 }
184}
185
186dyn_clone::clone_trait_object!(Tool);
187
188impl PartialEq for Box<dyn Tool> {
191 fn eq(&self, other: &Self) -> bool {
192 self.name() == other.name()
193 }
194}
195impl Eq for Box<dyn Tool> {}
196impl std::hash::Hash for Box<dyn Tool> {
197 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
198 self.name().hash(state);
199 }
200}