From 8fb0300914e8d3c8997a5e4684a60e9bfe9276b9 Mon Sep 17 00:00:00 2001 From: viettranx Date: Sat, 18 Apr 2026 15:34:46 +0700 Subject: [PATCH] fix(tts): set Result.Media so provider bridges forward attachments TTS relied solely on ForLLM "MEDIA:" parsing. claude_cli's MCP bridge reshapes ForLLM before the agent sees it, so rs.mediaResults stayed empty and mp3s never attached to outbound messages. Populate Result.Media alongside the legacy ForLLM prefix (matching create_audio.go). The agent loop prefers explicit Result.Media over the ForLLM fallback. Closes #806 --- internal/tools/tts.go | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/internal/tools/tts.go b/internal/tools/tts.go index d53a1452..e756de57 100644 --- a/internal/tools/tts.go +++ b/internal/tools/tts.go @@ -12,6 +12,7 @@ import ( "github.com/google/uuid" + "github.com/nextlevelbuilder/goclaw/internal/bus" "github.com/nextlevelbuilder/goclaw/internal/store" "github.com/nextlevelbuilder/goclaw/internal/tts" ) @@ -238,7 +239,16 @@ func (t *TtsTool) Execute(ctx context.Context, args map[string]any) *Result { } forLLM := fmt.Sprintf("%sMEDIA:%s", voiceTag, audioPath) - r := &Result{ForLLM: forLLM} + // Set Result.Media explicitly (matching create_audio) so the agent loop's + // media collector uses the authoritative path even when the ForLLM + // MEDIA: prefix is reshaped by a provider bridge (e.g. claude_cli MCP). + r := &Result{ + ForLLM: forLLM, + Media: []bus.MediaFile{{ + Path: audioPath, + MimeType: "audio/" + result.Extension, + }}, + } r.Deliverable = fmt.Sprintf("[Generated audio: %s]\nText: %s", filepath.Base(audioPath), text) if t.vaultIntc != nil { mimeType := "audio/" + result.Extension