1use core::fmt::Display;
19
20use serde::Serialize;
21
22#[cfg(not(feature = "std"))]
23use alloc::{
24 format,
25 string::{String, ToString},
26 vec,
27 vec::Vec,
28};
29
30use crate::content::Message;
31use crate::results::{PromptResult, ResourceResult, ToolResult};
32
33pub trait IntoToolResult {
72 fn into_tool_result(self) -> ToolResult;
74}
75
76impl IntoToolResult for String {
78 fn into_tool_result(self) -> ToolResult {
79 ToolResult::text(self)
80 }
81}
82
83impl IntoToolResult for &str {
84 fn into_tool_result(self) -> ToolResult {
85 ToolResult::text(self)
86 }
87}
88
89impl IntoToolResult for &String {
90 fn into_tool_result(self) -> ToolResult {
91 ToolResult::text(self.clone())
92 }
93}
94
95impl IntoToolResult for i8 {
97 fn into_tool_result(self) -> ToolResult {
98 ToolResult::text(self.to_string())
99 }
100}
101
102impl IntoToolResult for i16 {
103 fn into_tool_result(self) -> ToolResult {
104 ToolResult::text(self.to_string())
105 }
106}
107
108impl IntoToolResult for i32 {
109 fn into_tool_result(self) -> ToolResult {
110 ToolResult::text(self.to_string())
111 }
112}
113
114impl IntoToolResult for i64 {
115 fn into_tool_result(self) -> ToolResult {
116 ToolResult::text(self.to_string())
117 }
118}
119
120impl IntoToolResult for i128 {
121 fn into_tool_result(self) -> ToolResult {
122 ToolResult::text(self.to_string())
123 }
124}
125
126impl IntoToolResult for isize {
127 fn into_tool_result(self) -> ToolResult {
128 ToolResult::text(self.to_string())
129 }
130}
131
132impl IntoToolResult for u8 {
133 fn into_tool_result(self) -> ToolResult {
134 ToolResult::text(self.to_string())
135 }
136}
137
138impl IntoToolResult for u16 {
139 fn into_tool_result(self) -> ToolResult {
140 ToolResult::text(self.to_string())
141 }
142}
143
144impl IntoToolResult for u32 {
145 fn into_tool_result(self) -> ToolResult {
146 ToolResult::text(self.to_string())
147 }
148}
149
150impl IntoToolResult for u64 {
151 fn into_tool_result(self) -> ToolResult {
152 ToolResult::text(self.to_string())
153 }
154}
155
156impl IntoToolResult for u128 {
157 fn into_tool_result(self) -> ToolResult {
158 ToolResult::text(self.to_string())
159 }
160}
161
162impl IntoToolResult for usize {
163 fn into_tool_result(self) -> ToolResult {
164 ToolResult::text(self.to_string())
165 }
166}
167
168impl IntoToolResult for f32 {
169 fn into_tool_result(self) -> ToolResult {
170 ToolResult::text(self.to_string())
171 }
172}
173
174impl IntoToolResult for f64 {
175 fn into_tool_result(self) -> ToolResult {
176 ToolResult::text(self.to_string())
177 }
178}
179
180impl IntoToolResult for bool {
182 fn into_tool_result(self) -> ToolResult {
183 ToolResult::text(self.to_string())
184 }
185}
186
187impl IntoToolResult for () {
189 fn into_tool_result(self) -> ToolResult {
190 ToolResult::empty()
191 }
192}
193
194impl IntoToolResult for ToolResult {
196 fn into_tool_result(self) -> ToolResult {
197 self
198 }
199}
200
201impl<T: IntoToolResult, E: Display> IntoToolResult for Result<T, E> {
203 fn into_tool_result(self) -> ToolResult {
204 match self {
205 Ok(v) => v.into_tool_result(),
206 Err(e) => ToolResult::error(e.to_string()),
207 }
208 }
209}
210
211impl<T: IntoToolResult> IntoToolResult for Option<T> {
213 fn into_tool_result(self) -> ToolResult {
214 match self {
215 Some(v) => v.into_tool_result(),
216 None => ToolResult::empty(),
217 }
218 }
219}
220
221impl<T: Serialize> IntoToolResult for Vec<T> {
223 fn into_tool_result(self) -> ToolResult {
224 ToolResult::json(&self).unwrap_or_else(|e| ToolResult::error(e.to_string()))
225 }
226}
227
228impl IntoToolResult for serde_json::Value {
230 fn into_tool_result(self) -> ToolResult {
231 ToolResult::json(&self).unwrap_or_else(|e| ToolResult::error(e.to_string()))
232 }
233}
234
235pub trait IntoResourceResult {
250 fn into_resource_result(self, uri: &str) -> ResourceResult;
254}
255
256impl IntoResourceResult for String {
257 fn into_resource_result(self, uri: &str) -> ResourceResult {
258 ResourceResult::text(uri, self)
259 }
260}
261
262impl IntoResourceResult for &str {
263 fn into_resource_result(self, uri: &str) -> ResourceResult {
264 ResourceResult::text(uri, self)
265 }
266}
267
268impl IntoResourceResult for ResourceResult {
269 fn into_resource_result(self, _uri: &str) -> ResourceResult {
270 self
271 }
272}
273
274impl<T: IntoResourceResult, E: Display> IntoResourceResult for Result<T, E> {
275 fn into_resource_result(self, uri: &str) -> ResourceResult {
276 match self {
277 Ok(v) => v.into_resource_result(uri),
278 Err(e) => ResourceResult::text(uri, format!("Error: {e}")),
279 }
280 }
281}
282
283impl<T: IntoResourceResult> IntoResourceResult for Option<T> {
284 fn into_resource_result(self, uri: &str) -> ResourceResult {
285 match self {
286 Some(v) => v.into_resource_result(uri),
287 None => ResourceResult::empty(),
288 }
289 }
290}
291
292pub trait IntoPromptResult {
308 fn into_prompt_result(self) -> PromptResult;
310}
311
312impl IntoPromptResult for Vec<Message> {
313 fn into_prompt_result(self) -> PromptResult {
314 PromptResult::new(self)
315 }
316}
317
318impl IntoPromptResult for PromptResult {
319 fn into_prompt_result(self) -> PromptResult {
320 self
321 }
322}
323
324impl IntoPromptResult for Message {
325 fn into_prompt_result(self) -> PromptResult {
326 PromptResult::new(vec![self])
327 }
328}
329
330impl IntoPromptResult for String {
331 fn into_prompt_result(self) -> PromptResult {
332 PromptResult::user(self)
333 }
334}
335
336impl IntoPromptResult for &str {
337 fn into_prompt_result(self) -> PromptResult {
338 PromptResult::user(self)
339 }
340}
341
342impl<T: IntoPromptResult, E: Display> IntoPromptResult for Result<T, E> {
343 fn into_prompt_result(self) -> PromptResult {
344 match self {
345 Ok(v) => v.into_prompt_result(),
346 Err(e) => PromptResult::user(format!("Error: {e}")),
349 }
350 }
351}
352
353impl<T: IntoPromptResult> IntoPromptResult for Option<T> {
354 fn into_prompt_result(self) -> PromptResult {
355 match self {
356 Some(v) => v.into_prompt_result(),
357 None => PromptResult::empty(),
358 }
359 }
360}
361
362#[cfg(test)]
363mod tests {
364 use super::*;
365
366 #[test]
367 fn test_string_into_tool_result() {
368 let result = "Hello".to_string().into_tool_result();
369 assert_eq!(result.first_text(), Some("Hello"));
370 assert!(!result.is_error());
371 }
372
373 #[test]
374 fn test_str_into_tool_result() {
375 let result = "Hello".into_tool_result();
376 assert_eq!(result.first_text(), Some("Hello"));
377 }
378
379 #[test]
380 fn test_i64_into_tool_result() {
381 let result = 42i64.into_tool_result();
382 assert_eq!(result.first_text(), Some("42"));
383 }
384
385 #[test]
386 fn test_bool_into_tool_result() {
387 let result = true.into_tool_result();
388 assert_eq!(result.first_text(), Some("true"));
389 }
390
391 #[test]
392 fn test_unit_into_tool_result() {
393 let result = ().into_tool_result();
394 assert!(result.content.is_empty());
395 }
396
397 #[test]
398 fn test_result_ok_into_tool_result() {
399 let r: Result<&str, &str> = Ok("success");
400 let result = r.into_tool_result();
401 assert_eq!(result.first_text(), Some("success"));
402 assert!(!result.is_error());
403 }
404
405 #[test]
406 fn test_result_err_into_tool_result() {
407 let r: Result<&str, &str> = Err("failed");
408 let result = r.into_tool_result();
409 assert_eq!(result.first_text(), Some("failed"));
410 assert!(result.is_error());
411 }
412
413 #[test]
414 fn test_option_some_into_tool_result() {
415 let r: Option<&str> = Some("value");
416 let result = r.into_tool_result();
417 assert_eq!(result.first_text(), Some("value"));
418 }
419
420 #[test]
421 fn test_option_none_into_tool_result() {
422 let r: Option<&str> = None;
423 let result = r.into_tool_result();
424 assert!(result.content.is_empty());
425 }
426
427 #[test]
428 fn test_vec_into_tool_result() {
429 let v = vec!["a", "b", "c"];
430 let result = v.into_tool_result();
431 assert!(result.structured_content.is_some());
432 }
433
434 #[test]
435 fn test_string_into_resource_result() {
436 let result = "content".to_string().into_resource_result("file:///test");
437 assert_eq!(result.first_text(), Some("content"));
438 match &result.contents[0] {
439 crate::content::ResourceContents::Text(t) => assert_eq!(t.uri, "file:///test"),
440 _ => panic!("Expected text resource contents"),
441 }
442 }
443
444 #[test]
445 fn test_messages_into_prompt_result() {
446 let messages = vec![Message::user("Hello")];
447 let result = messages.into_prompt_result();
448 assert_eq!(result.len(), 1);
449 }
450}