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> {
354 fn into_prompt_result(self) -> PromptResult {
355 match self {
356 Ok(v) => v.into_prompt_result(),
357 Err(e) => PromptResult::user(format!("Error: {e}")),
358 }
359 }
360}
361
362impl<T: IntoPromptResult> IntoPromptResult for Option<T> {
363 fn into_prompt_result(self) -> PromptResult {
364 match self {
365 Some(v) => v.into_prompt_result(),
366 None => PromptResult::empty(),
367 }
368 }
369}
370
371#[cfg(test)]
372mod tests {
373 use super::*;
374
375 #[test]
376 fn test_string_into_tool_result() {
377 let result = "Hello".to_string().into_tool_result();
378 assert_eq!(result.first_text(), Some("Hello"));
379 assert!(!result.is_error());
380 }
381
382 #[test]
383 fn test_str_into_tool_result() {
384 let result = "Hello".into_tool_result();
385 assert_eq!(result.first_text(), Some("Hello"));
386 }
387
388 #[test]
389 fn test_i64_into_tool_result() {
390 let result = 42i64.into_tool_result();
391 assert_eq!(result.first_text(), Some("42"));
392 }
393
394 #[test]
395 fn test_bool_into_tool_result() {
396 let result = true.into_tool_result();
397 assert_eq!(result.first_text(), Some("true"));
398 }
399
400 #[test]
401 fn test_unit_into_tool_result() {
402 let result = ().into_tool_result();
403 assert!(result.content.is_empty());
404 }
405
406 #[test]
407 fn test_result_ok_into_tool_result() {
408 let r: Result<&str, &str> = Ok("success");
409 let result = r.into_tool_result();
410 assert_eq!(result.first_text(), Some("success"));
411 assert!(!result.is_error());
412 }
413
414 #[test]
415 fn test_result_err_into_tool_result() {
416 let r: Result<&str, &str> = Err("failed");
417 let result = r.into_tool_result();
418 assert_eq!(result.first_text(), Some("failed"));
419 assert!(result.is_error());
420 }
421
422 #[test]
423 fn test_option_some_into_tool_result() {
424 let r: Option<&str> = Some("value");
425 let result = r.into_tool_result();
426 assert_eq!(result.first_text(), Some("value"));
427 }
428
429 #[test]
430 fn test_option_none_into_tool_result() {
431 let r: Option<&str> = None;
432 let result = r.into_tool_result();
433 assert!(result.content.is_empty());
434 }
435
436 #[test]
437 fn test_vec_into_tool_result() {
438 let v = vec!["a", "b", "c"];
443 let result = v.into_tool_result();
444 assert_eq!(result.structured_content, None);
445 assert_eq!(
446 result.first_text(),
447 Some("[\n \"a\",\n \"b\",\n \"c\"\n]")
448 );
449 }
450
451 #[test]
452 fn test_object_into_tool_result_keeps_structured_content() {
453 let result = serde_json::json!({ "a": 1 }).into_tool_result();
454 assert_eq!(result.structured_content, Some(serde_json::json!({"a": 1})));
455 }
456
457 #[test]
458 fn test_string_into_resource_result() {
459 let result = "content".to_string().into_resource_result("file:///test");
460 assert_eq!(result.first_text(), Some("content"));
461 match &result.contents[0] {
462 crate::content::ResourceContents::Text(t) => assert_eq!(t.uri, "file:///test"),
463 _ => panic!("Expected text resource contents"),
464 }
465 }
466
467 #[test]
468 fn test_messages_into_prompt_result() {
469 let messages = vec![Message::user("Hello")];
470 let result = messages.into_prompt_result();
471 assert_eq!(result.len(), 1);
472 }
473}