use core::fmt::Display;
use serde::Serialize;
use crate::content::Message;
use crate::results::{PromptResult, ResourceResult, ToolResult};
pub trait IntoToolResult {
fn into_tool_result(self) -> ToolResult;
}
impl IntoToolResult for String {
fn into_tool_result(self) -> ToolResult {
ToolResult::text(self)
}
}
impl IntoToolResult for &str {
fn into_tool_result(self) -> ToolResult {
ToolResult::text(self)
}
}
impl IntoToolResult for &String {
fn into_tool_result(self) -> ToolResult {
ToolResult::text(self.clone())
}
}
impl IntoToolResult for i8 {
fn into_tool_result(self) -> ToolResult {
ToolResult::text(self.to_string())
}
}
impl IntoToolResult for i16 {
fn into_tool_result(self) -> ToolResult {
ToolResult::text(self.to_string())
}
}
impl IntoToolResult for i32 {
fn into_tool_result(self) -> ToolResult {
ToolResult::text(self.to_string())
}
}
impl IntoToolResult for i64 {
fn into_tool_result(self) -> ToolResult {
ToolResult::text(self.to_string())
}
}
impl IntoToolResult for i128 {
fn into_tool_result(self) -> ToolResult {
ToolResult::text(self.to_string())
}
}
impl IntoToolResult for isize {
fn into_tool_result(self) -> ToolResult {
ToolResult::text(self.to_string())
}
}
impl IntoToolResult for u8 {
fn into_tool_result(self) -> ToolResult {
ToolResult::text(self.to_string())
}
}
impl IntoToolResult for u16 {
fn into_tool_result(self) -> ToolResult {
ToolResult::text(self.to_string())
}
}
impl IntoToolResult for u32 {
fn into_tool_result(self) -> ToolResult {
ToolResult::text(self.to_string())
}
}
impl IntoToolResult for u64 {
fn into_tool_result(self) -> ToolResult {
ToolResult::text(self.to_string())
}
}
impl IntoToolResult for u128 {
fn into_tool_result(self) -> ToolResult {
ToolResult::text(self.to_string())
}
}
impl IntoToolResult for usize {
fn into_tool_result(self) -> ToolResult {
ToolResult::text(self.to_string())
}
}
impl IntoToolResult for f32 {
fn into_tool_result(self) -> ToolResult {
ToolResult::text(self.to_string())
}
}
impl IntoToolResult for f64 {
fn into_tool_result(self) -> ToolResult {
ToolResult::text(self.to_string())
}
}
impl IntoToolResult for bool {
fn into_tool_result(self) -> ToolResult {
ToolResult::text(self.to_string())
}
}
impl IntoToolResult for () {
fn into_tool_result(self) -> ToolResult {
ToolResult::empty()
}
}
impl IntoToolResult for ToolResult {
fn into_tool_result(self) -> ToolResult {
self
}
}
impl<T: IntoToolResult, E: Display> IntoToolResult for Result<T, E> {
fn into_tool_result(self) -> ToolResult {
match self {
Ok(v) => v.into_tool_result(),
Err(e) => ToolResult::error(e.to_string()),
}
}
}
impl<T: IntoToolResult> IntoToolResult for Option<T> {
fn into_tool_result(self) -> ToolResult {
match self {
Some(v) => v.into_tool_result(),
None => ToolResult::empty(),
}
}
}
impl<T: Serialize> IntoToolResult for Vec<T> {
fn into_tool_result(self) -> ToolResult {
ToolResult::json(&self).unwrap_or_else(|e| ToolResult::error(e.to_string()))
}
}
impl IntoToolResult for serde_json::Value {
fn into_tool_result(self) -> ToolResult {
ToolResult::json(&self).unwrap_or_else(|e| ToolResult::error(e.to_string()))
}
}
pub trait IntoResourceResult {
fn into_resource_result(self, uri: &str) -> ResourceResult;
}
impl IntoResourceResult for String {
fn into_resource_result(self, uri: &str) -> ResourceResult {
ResourceResult::text(uri, self)
}
}
impl IntoResourceResult for &str {
fn into_resource_result(self, uri: &str) -> ResourceResult {
ResourceResult::text(uri, self)
}
}
impl IntoResourceResult for ResourceResult {
fn into_resource_result(self, _uri: &str) -> ResourceResult {
self
}
}
impl<T: IntoResourceResult, E: Display> IntoResourceResult for Result<T, E> {
fn into_resource_result(self, uri: &str) -> ResourceResult {
match self {
Ok(v) => v.into_resource_result(uri),
Err(e) => ResourceResult::text(uri, format!("Error: {}", e)),
}
}
}
impl<T: IntoResourceResult> IntoResourceResult for Option<T> {
fn into_resource_result(self, uri: &str) -> ResourceResult {
match self {
Some(v) => v.into_resource_result(uri),
None => ResourceResult::empty(),
}
}
}
pub trait IntoPromptResult {
fn into_prompt_result(self) -> PromptResult;
}
impl IntoPromptResult for Vec<Message> {
fn into_prompt_result(self) -> PromptResult {
PromptResult::new(self)
}
}
impl IntoPromptResult for PromptResult {
fn into_prompt_result(self) -> PromptResult {
self
}
}
impl IntoPromptResult for Message {
fn into_prompt_result(self) -> PromptResult {
PromptResult::new(vec![self])
}
}
impl IntoPromptResult for String {
fn into_prompt_result(self) -> PromptResult {
PromptResult::user(self)
}
}
impl IntoPromptResult for &str {
fn into_prompt_result(self) -> PromptResult {
PromptResult::user(self)
}
}
impl<T: IntoPromptResult, E: Display> IntoPromptResult for Result<T, E> {
fn into_prompt_result(self) -> PromptResult {
match self {
Ok(v) => v.into_prompt_result(),
Err(e) => PromptResult::user(format!("Error: {}", e)),
}
}
}
impl<T: IntoPromptResult> IntoPromptResult for Option<T> {
fn into_prompt_result(self) -> PromptResult {
match self {
Some(v) => v.into_prompt_result(),
None => PromptResult::empty(),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_string_into_tool_result() {
let result = "Hello".to_string().into_tool_result();
assert_eq!(result.first_text(), Some("Hello"));
assert!(!result.is_error());
}
#[test]
fn test_str_into_tool_result() {
let result = "Hello".into_tool_result();
assert_eq!(result.first_text(), Some("Hello"));
}
#[test]
fn test_i64_into_tool_result() {
let result = 42i64.into_tool_result();
assert_eq!(result.first_text(), Some("42"));
}
#[test]
fn test_bool_into_tool_result() {
let result = true.into_tool_result();
assert_eq!(result.first_text(), Some("true"));
}
#[test]
fn test_unit_into_tool_result() {
let result = ().into_tool_result();
assert!(result.content.is_empty());
}
#[test]
fn test_result_ok_into_tool_result() {
let r: Result<&str, &str> = Ok("success");
let result = r.into_tool_result();
assert_eq!(result.first_text(), Some("success"));
assert!(!result.is_error());
}
#[test]
fn test_result_err_into_tool_result() {
let r: Result<&str, &str> = Err("failed");
let result = r.into_tool_result();
assert_eq!(result.first_text(), Some("failed"));
assert!(result.is_error());
}
#[test]
fn test_option_some_into_tool_result() {
let r: Option<&str> = Some("value");
let result = r.into_tool_result();
assert_eq!(result.first_text(), Some("value"));
}
#[test]
fn test_option_none_into_tool_result() {
let r: Option<&str> = None;
let result = r.into_tool_result();
assert!(result.content.is_empty());
}
#[test]
fn test_vec_into_tool_result() {
let v = vec!["a", "b", "c"];
let result = v.into_tool_result();
assert!(result.structured_content.is_some());
}
#[test]
fn test_string_into_resource_result() {
let result = "content".to_string().into_resource_result("file:///test");
assert_eq!(result.first_text(), Some("content"));
match &result.contents[0] {
crate::content::ResourceContents::Text(t) => assert_eq!(t.uri, "file:///test"),
_ => panic!("Expected text resource contents"),
}
}
#[test]
fn test_messages_into_prompt_result() {
let messages = vec![Message::user("Hello")];
let result = messages.into_prompt_result();
assert_eq!(result.len(), 1);
}
}