use ai::error::{AiError, AiResult}; use ai::tool::tools::FunctionCall; use async_trait::async_trait; use serde_json::{Value, json}; use super::run::AppAgentContext; pub struct SetTitleTool; impl SetTitleTool { pub fn new() -> Self { Self } } impl Default for SetTitleTool { fn default() -> Self { Self::new() } } #[async_trait] impl FunctionCall for SetTitleTool { type Context = AppAgentContext; fn name(&self) -> &'static str { "set_conversation_title" } fn schema(&self) -> Value { json!({ "type": "object", "properties": { "title": { "type": "string", "description": "A concise, descriptive title for the conversation (max 100 characters)" } }, "required": ["title"] }) } async fn call( &self, context: &mut Self::Context, args: Value, ) -> AiResult { let title = args.get("title").and_then(|v| v.as_str()).ok_or_else(|| { AiError::Config("title parameter is required".to_string()) })?; let title = title.trim(); if title.is_empty() { return Err(AiError::Config("title cannot be empty".to_string())); } let title = if title.len() > 100 { &title[..100] } else { title }; context.pending_title = Some(title.to_string()); Ok(json!({ "success": true, "title": title })) } }