use serde::{Deserialize, Serialize};
use serde_json::{json, Value};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ToolSuccess<T = Value> {
#[serde(flatten)]
pub data: T,
#[serde(skip_serializing_if = "Option::is_none")]
pub message: Option<String>,
}
impl<T> ToolSuccess<T> {
pub fn new(data: T) -> Self {
Self {
data,
message: None,
}
}
pub fn with_message(mut self, message: impl Into<String>) -> Self {
self.message = Some(message.into());
self
}
}
impl ToolSuccess<Value> {
pub fn empty() -> Self {
Self {
data: json!({}),
message: None,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ToolStatus {
pub success: bool,
pub message: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub details: Option<Value>,
}
impl ToolStatus {
pub fn success(message: impl Into<String>) -> Self {
Self {
success: true,
message: message.into(),
details: None,
}
}
pub fn error(message: impl Into<String>) -> Self {
Self {
success: false,
message: message.into(),
details: None,
}
}
pub fn with_details(mut self, details: Value) -> Self {
self.details = Some(details);
self
}
}
pub fn tool_success<T: Serialize>(data: T) -> Result<Value, crate::error::ToolError> {
serde_json::to_value(data)
.map_err(|e| crate::error::ToolError::internal(format!("Serialization failed: {}", e)))
}
pub fn tool_ok(message: impl Into<String>) -> Result<Value, crate::error::ToolError> {
Ok(json!({
"success": true,
"message": message.into()
}))
}
#[cfg(test)]
mod tests {
use super::*;
use serde_json::json;
#[test]
fn test_tool_success_new() {
let data = json!({"count": 42});
let success = ToolSuccess::new(data.clone());
assert_eq!(success.data, data);
assert_eq!(success.message, None);
}
#[test]
fn test_tool_success_with_message() {
let data = json!({"result": "ok"});
let success = ToolSuccess::new(data.clone()).with_message("Operation completed");
assert_eq!(success.data, data);
assert_eq!(success.message, Some("Operation completed".to_string()));
}
#[test]
fn test_tool_success_empty() {
let success = ToolSuccess::empty();
assert_eq!(success.data, json!({}));
assert_eq!(success.message, None);
}
#[test]
fn test_tool_success_serialization() {
let success = ToolSuccess::new(json!({"value": 100})).with_message("Done");
let serialized = serde_json::to_value(&success).unwrap();
assert_eq!(serialized["value"], 100);
assert_eq!(serialized["message"], "Done");
}
#[test]
fn test_tool_success_no_message_serialization() {
let success = ToolSuccess::new(json!({"key": "value"}));
let serialized = serde_json::to_value(&success).unwrap();
assert_eq!(serialized["key"], "value");
assert!(!serialized.as_object().unwrap().contains_key("message"));
}
#[test]
fn test_tool_status_success() {
let status = ToolStatus::success("All good");
assert!(status.success);
assert_eq!(status.message, "All good");
assert_eq!(status.details, None);
}
#[test]
fn test_tool_status_error() {
let status = ToolStatus::error("Something went wrong");
assert!(!status.success);
assert_eq!(status.message, "Something went wrong");
assert_eq!(status.details, None);
}
#[test]
fn test_tool_status_with_details() {
let details = json!({"code": 404, "reason": "not found"});
let status = ToolStatus::error("Failed").with_details(details.clone());
assert!(!status.success);
assert_eq!(status.message, "Failed");
assert_eq!(status.details, Some(details));
}
#[test]
fn test_tool_status_serialization() {
let status = ToolStatus::success("Complete").with_details(json!({"items": 5}));
let serialized = serde_json::to_value(&status).unwrap();
assert_eq!(serialized["success"], true);
assert_eq!(serialized["message"], "Complete");
assert_eq!(serialized["details"]["items"], 5);
}
#[test]
fn test_tool_success_helper() {
#[derive(Serialize)]
struct TestData {
name: String,
age: u32,
}
let data = TestData {
name: "Alice".to_string(),
age: 30,
};
let result = tool_success(data).unwrap();
assert_eq!(result["name"], "Alice");
assert_eq!(result["age"], 30);
}
#[test]
fn test_tool_ok_helper() {
let result = tool_ok("Task completed").unwrap();
assert_eq!(result["success"], true);
assert_eq!(result["message"], "Task completed");
}
#[test]
fn test_tool_success_with_struct() {
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
struct CustomData {
id: u64,
value: String,
}
let data = CustomData {
id: 123,
value: "test".to_string(),
};
let success = ToolSuccess::new(data.clone());
let serialized = serde_json::to_string(&success).unwrap();
let deserialized: ToolSuccess<CustomData> = serde_json::from_str(&serialized).unwrap();
assert_eq!(deserialized.data, data);
}
}