1use std::sync::Arc;
4
5use async_trait::async_trait;
6use serde_json::Value;
7
8use crate::traits::{TtsProvider, TtsRequest};
9
10pub struct SpeakTool {
14 tts: Arc<dyn TtsProvider>,
15 default_voice: String,
16}
17
18impl SpeakTool {
19 pub fn new(tts: Arc<dyn TtsProvider>, default_voice: impl Into<String>) -> Self {
21 Self { tts, default_voice: default_voice.into() }
22 }
23}
24
25#[async_trait]
26impl adk_core::Tool for SpeakTool {
27 fn name(&self) -> &str {
28 "speak"
29 }
30
31 fn description(&self) -> &str {
32 "Synthesize text to speech audio"
33 }
34
35 fn parameters_schema(&self) -> Option<Value> {
36 Some(serde_json::json!({
37 "type": "object",
38 "properties": {
39 "text": { "type": "string", "description": "Text to speak" },
40 "voice": { "type": "string", "description": "Voice ID (optional)" },
41 "emotion": { "type": "string", "enum": ["neutral","happy","sad","angry","whisper","excited","calm"] }
42 },
43 "required": ["text"]
44 }))
45 }
46
47 async fn execute(
48 &self,
49 _ctx: Arc<dyn adk_core::ToolContext>,
50 args: Value,
51 ) -> adk_core::Result<Value> {
52 let text = args["text"].as_str().unwrap_or_default();
53 let voice = args["voice"].as_str().unwrap_or(&self.default_voice).to_string();
54 let request = TtsRequest { text: text.into(), voice, ..Default::default() };
55 let frame = self
56 .tts
57 .synthesize(&request)
58 .await
59 .map_err(|e| adk_core::AdkError::tool(format!("speak: {e}")))?;
60 Ok(serde_json::json!({
61 "duration_ms": frame.duration_ms,
62 "sample_rate": frame.sample_rate
63 }))
64 }
65}