From ef427d3eae77fca716c203dd8bd84939710c518a Mon Sep 17 00:00:00 2001 From: Adam Malczewski Date: Sat, 23 May 2026 04:37:56 +0900 Subject: feat: youtube_transcribe blocks with polling, interruptible with background retrieve - youtube_transcribe now polls until transcript is ready (waits estimated_seconds - 2s, min 2s) - Times out after 10 minutes of polling - When user interrupts, polling continues in background with youtube_transcribe_ job ID - BackgroundTranscriptStore holds polling jobs, retrieve tool resolves them - ToolCallDisplay shows 'interrupted' badge (blue) when result contains [USER INTERRUPT] - Applies to all interruptible tools: run_shell, youtube_transcribe, retrieve --- packages/api/src/agent-manager.ts | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) (limited to 'packages/api/src') diff --git a/packages/api/src/agent-manager.ts b/packages/api/src/agent-manager.ts index b0a2f56..3789b68 100644 --- a/packages/api/src/agent-manager.ts +++ b/packages/api/src/agent-manager.ts @@ -12,6 +12,7 @@ import { createRetrieveTool, createRunShellTool, BackgroundShellStore, + BackgroundTranscriptStore, createSkillsWatcher, createSummonTool, createTaskListTool, @@ -141,6 +142,8 @@ interface TabAgent { queueListeners: Array<() => void>; /** Store for shell commands backgrounded due to user interrupt. */ shellStore: BackgroundShellStore; + /** Store for transcript requests backgrounded due to user interrupt. */ + transcriptStore: BackgroundTranscriptStore; } export class AgentManager { @@ -277,6 +280,7 @@ export class AgentManager { messageQueue: [], queueListeners: [], shellStore: new BackgroundShellStore(), + transcriptStore: new BackgroundTranscriptStore(), }; this.tabAgents.set(tabId, tabAgent); } @@ -360,7 +364,7 @@ export class AgentManager { toolEntries.push({ name: "web_search", tool: createWebSearchTool() }); } if (allowed.has("youtube_transcribe")) { - toolEntries.push({ name: "youtube_transcribe", tool: createYoutubeTranscribeTool() }); + toolEntries.push({ name: "youtube_transcribe", tool: createYoutubeTranscribeTool(tabAgent.transcriptStore) }); } if (allowed.has("todo")) { toolEntries.push({ name: "todo", tool: createTaskListTool(tabAgent.taskList) }); @@ -388,7 +392,9 @@ export class AgentManager { getResult: (id) => tabAgent.shellStore.has(id) ? tabAgent.shellStore.getResult(id) - : this.getChildResult(id), + : tabAgent.transcriptStore.has(id) + ? tabAgent.transcriptStore.getResult(id) + : this.getChildResult(id), }), }); } @@ -405,7 +411,7 @@ export class AgentManager { toolEntries.push({ name: "run_shell", tool: createRunShellTool(workingDirectory, tabAgent.shellStore) }); } toolEntries.push({ name: "web_search", tool: createWebSearchTool() }); - toolEntries.push({ name: "youtube_transcribe", tool: createYoutubeTranscribeTool() }); + toolEntries.push({ name: "youtube_transcribe", tool: createYoutubeTranscribeTool(tabAgent.transcriptStore) }); toolEntries.push({ name: "todo", tool: createTaskListTool(tabAgent.taskList) }); if (permSummon) { // Capture parent's allowed tool names for child permission enforcement @@ -429,7 +435,9 @@ export class AgentManager { getResult: (id) => tabAgent.shellStore.has(id) ? tabAgent.shellStore.getResult(id) - : this.getChildResult(id), + : tabAgent.transcriptStore.has(id) + ? tabAgent.transcriptStore.getResult(id) + : this.getChildResult(id), }), }); } -- cgit v1.2.3