use serde::{Deserialize, Serialize};
use serde_json::json;
use crate::completion::ToolDefinition;
use crate::tool::Tool;
#[derive(Deserialize)]
pub struct ThinkArgs {
pub thought: String,
}
#[derive(Debug, thiserror::Error)]
#[error("Think tool error: {0}")]
pub struct ThinkError(String);
#[derive(Deserialize, Serialize)]
pub struct ThinkTool;
impl Tool for ThinkTool {
const NAME: &'static str = "think";
type Error = ThinkError;
type Args = ThinkArgs;
type Output = String;
async fn definition(&self, _prompt: String) -> ToolDefinition {
ToolDefinition {
name: "think".to_string(),
description: "Use the tool to think about something. It will not obtain new information
or change the database, but just append the thought to the log. Use it when complex
reasoning or some cache memory is needed."
.to_string(),
parameters: json!({
"type": "object",
"properties": {
"thought": {
"type": "string",
"description": "A thought to think about."
}
},
"required": ["thought"]
}),
}
}
async fn call(&self, args: Self::Args) -> Result<Self::Output, Self::Error> {
Ok(args.thought)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[tokio::test]
async fn test_think_tool_definition() {
let tool = ThinkTool;
let definition = tool.definition("".to_string()).await;
assert_eq!(definition.name, "think");
assert!(
definition
.description
.contains("Use the tool to think about something")
);
}
#[tokio::test]
async fn test_think_tool_call() {
let tool = ThinkTool;
let args = ThinkArgs {
thought: "I need to verify the user's identity before proceeding".to_string(),
};
let result = tool.call(args).await.unwrap();
assert_eq!(
result,
"I need to verify the user's identity before proceeding"
);
}
}