From da98a54393a7a023b81bd32ffa30d3b42f102e9f Mon Sep 17 00:00:00 2001 From: viettranx Date: Wed, 25 Mar 2026 16:03:40 +0700 Subject: [PATCH] fix(media): save browser screenshots and TTS audio to workspace instead of /tmp Screenshots saved to {workspace}/screenshots/, TTS audio to {workspace}/tts/. Agents can now access these files via read_file. Falls back to os.TempDir() when workspace is unavailable. --- internal/tools/tts.go | 13 ++++++++++--- pkg/browser/tool.go | 12 ++++++++++-- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/internal/tools/tts.go b/internal/tools/tts.go index 8669c903..fcdd0aab 100644 --- a/internal/tools/tts.go +++ b/internal/tools/tts.go @@ -101,9 +101,16 @@ func (t *TtsTool) Execute(ctx context.Context, args map[string]any) *Result { return &Result{ForLLM: fmt.Sprintf("error: tts failed: %s", err.Error()), IsError: true} } - // Write audio to temp file - tmpDir := os.TempDir() - audioPath := filepath.Join(tmpDir, fmt.Sprintf("tts-%d.%s", time.Now().UnixNano(), result.Extension)) + // Write audio to workspace/tts/ so the agent can access the file. + // Falls back to os.TempDir() if workspace is not available. + ttsDir := os.TempDir() + if ws := ToolWorkspaceFromCtx(ctx); ws != "" { + ttsDir = filepath.Join(ws, "tts") + } + if err := os.MkdirAll(ttsDir, 0755); err != nil { + return &Result{ForLLM: fmt.Sprintf("error: create tts directory: %s", err.Error()), IsError: true} + } + audioPath := filepath.Join(ttsDir, fmt.Sprintf("tts-%d.%s", time.Now().UnixNano(), result.Extension)) if err := os.WriteFile(audioPath, result.Audio, 0644); err != nil { return &Result{ForLLM: fmt.Sprintf("error: write tts audio: %s", err.Error()), IsError: true} } diff --git a/pkg/browser/tool.go b/pkg/browser/tool.go index cc48b80e..1d819d04 100644 --- a/pkg/browser/tool.go +++ b/pkg/browser/tool.go @@ -275,8 +275,16 @@ func (t *BrowserTool) handleScreenshot(ctx context.Context, args map[string]any) return tools.ErrorResult(fmt.Sprintf("screenshot failed: %v", err)) } - // Save to temp file so the media pipeline can deliver it (e.g. Telegram sendPhoto) - imagePath := filepath.Join(os.TempDir(), fmt.Sprintf("goclaw_screenshot_%d.png", time.Now().UnixNano())) + // Save to workspace/screenshots/ so the agent can access the file. + // Falls back to os.TempDir() if workspace is not available. + screenshotDir := filepath.Join(os.TempDir(), "goclaw_screenshots") + if ws := tools.ToolWorkspaceFromCtx(ctx); ws != "" { + screenshotDir = filepath.Join(ws, "screenshots") + } + if err := os.MkdirAll(screenshotDir, 0755); err != nil { + return tools.ErrorResult(fmt.Sprintf("failed to create screenshots directory: %v", err)) + } + imagePath := filepath.Join(screenshotDir, fmt.Sprintf("screenshot_%d.png", time.Now().UnixNano())) if err := os.WriteFile(imagePath, data, 0644); err != nil { return tools.ErrorResult(fmt.Sprintf("failed to save screenshot: %v", err)) }