send audio via send_audio/send_voice, format tool log as markdown, add gen_voice debug logging
This commit is contained in:
@@ -124,7 +124,12 @@ impl Output for TelegramOutput {
|
|||||||
// send tool call log as .md file if any
|
// send tool call log as .md file if any
|
||||||
if !self.tool_log.is_empty() {
|
if !self.tool_log.is_empty() {
|
||||||
let md = self.tool_log.join("\n");
|
let md = self.tool_log.join("\n");
|
||||||
let tmp = format!("/tmp/noc_tools_{}.md", std::process::id());
|
// extract tool names for filename
|
||||||
|
let names: Vec<&str> = self.tool_log.iter()
|
||||||
|
.filter_map(|s| s.strip_prefix('[')?.split('(').next())
|
||||||
|
.collect();
|
||||||
|
let label = if names.is_empty() { "tools".to_string() } else { names.join("_") };
|
||||||
|
let tmp = format!("/tmp/{label}.md");
|
||||||
if std::fs::write(&tmp, &md).is_ok() {
|
if std::fs::write(&tmp, &md).is_ok() {
|
||||||
let input_file = InputFile::file(std::path::Path::new(&tmp));
|
let input_file = InputFile::file(std::path::Path::new(&tmp));
|
||||||
let _ = self.bot.send_document(self.chat_id, input_file).await;
|
let _ = self.bot.send_document(self.chat_id, input_file).await;
|
||||||
@@ -141,12 +146,27 @@ impl Output for TelegramOutput {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fn send_file(&self, path: &Path, caption: &str) -> Result<bool> {
|
async fn send_file(&self, path: &Path, caption: &str) -> Result<bool> {
|
||||||
|
let ext = path.extension().and_then(|e| e.to_str()).unwrap_or("");
|
||||||
let input_file = InputFile::file(path);
|
let input_file = InputFile::file(path);
|
||||||
let mut req = self.bot.send_document(self.chat_id, input_file);
|
match ext {
|
||||||
if !caption.is_empty() {
|
"ogg" | "oga" => {
|
||||||
req = req.caption(caption);
|
self.bot.send_voice(self.chat_id, input_file).await?;
|
||||||
|
}
|
||||||
|
"wav" | "mp3" | "m4a" | "flac" => {
|
||||||
|
let mut req = self.bot.send_audio(self.chat_id, input_file);
|
||||||
|
if !caption.is_empty() {
|
||||||
|
req = req.caption(caption);
|
||||||
|
}
|
||||||
|
req.await?;
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
let mut req = self.bot.send_document(self.chat_id, input_file);
|
||||||
|
if !caption.is_empty() {
|
||||||
|
req = req.caption(caption);
|
||||||
|
}
|
||||||
|
req.await?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
req.await?;
|
|
||||||
Ok(true)
|
Ok(true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -193,14 +193,20 @@ pub async fn run_openai_with_tools(
|
|||||||
|
|
||||||
for tc in &tool_calls {
|
for tc in &tool_calls {
|
||||||
info!(tool = %tc.name, "executing tool call");
|
info!(tool = %tc.name, "executing tool call");
|
||||||
|
let args_preview = truncate_at_char_boundary(&tc.arguments, 200);
|
||||||
let _ = output
|
let _ = output
|
||||||
.status(&format!("[{}({})]", tc.name, truncate_at_char_boundary(&tc.arguments, 100)))
|
.status(&format!("### `{}`\n```json\n{args_preview}\n```", tc.name))
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
let result =
|
let result =
|
||||||
execute_tool(&tc.name, &tc.arguments, state, output, sid, config, chat_id)
|
execute_tool(&tc.name, &tc.arguments, state, output, sid, config, chat_id)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
|
let result_preview = truncate_at_char_boundary(&result, 500);
|
||||||
|
let _ = output
|
||||||
|
.status(&format!("**Result** ({} bytes)\n```\n{result_preview}\n```\n---", result.len()))
|
||||||
|
.await;
|
||||||
|
|
||||||
messages.push(serde_json::json!({
|
messages.push(serde_json::json!({
|
||||||
"role": "tool",
|
"role": "tool",
|
||||||
"tool_call_id": tc.id,
|
"tool_call_id": tc.id,
|
||||||
|
|||||||
@@ -583,6 +583,7 @@ pub async fn execute_tool(
|
|||||||
}
|
}
|
||||||
"gen_voice" => {
|
"gen_voice" => {
|
||||||
let text = args["text"].as_str().unwrap_or("");
|
let text = args["text"].as_str().unwrap_or("");
|
||||||
|
info!("gen_voice text={:?} args={}", text, truncate_at_char_boundary(arguments, 200));
|
||||||
if text.is_empty() {
|
if text.is_empty() {
|
||||||
return "Error: text is required".to_string();
|
return "Error: text is required".to_string();
|
||||||
}
|
}
|
||||||
@@ -611,9 +612,13 @@ pub async fn execute_tool(
|
|||||||
Ok(Ok(out)) => {
|
Ok(Ok(out)) => {
|
||||||
let stderr = String::from_utf8_lossy(&out.stderr);
|
let stderr = String::from_utf8_lossy(&out.stderr);
|
||||||
let stdout = String::from_utf8_lossy(&out.stdout);
|
let stdout = String::from_utf8_lossy(&out.stdout);
|
||||||
|
warn!("gen_voice failed (exit={}): stdout={stdout} stderr={stderr}", out.status.code().unwrap_or(-1));
|
||||||
format!("gen_voice failed: {stdout} {stderr}")
|
format!("gen_voice failed: {stdout} {stderr}")
|
||||||
}
|
}
|
||||||
Ok(Err(e)) => format!("gen_voice exec error: {e}"),
|
Ok(Err(e)) => {
|
||||||
|
warn!("gen_voice exec error: {e}");
|
||||||
|
format!("gen_voice exec error: {e}")
|
||||||
|
}
|
||||||
Err(_) => "gen_voice timeout (120s)".to_string(),
|
Err(_) => "gen_voice timeout (120s)".to_string(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user