From 0d1b6ebe2ccaaddd5864fabb4eae03fe389366f5 Mon Sep 17 00:00:00 2001 From: GyuminJack Date: Fri, 13 Feb 2026 14:53:22 +0900 Subject: [PATCH] fix: resolve empty response when custom agents end with tool calls When a custom agent's last assistant message contains only tool calls (no text/reasoning parts), the sync result fetcher returned empty content. Walk assistant messages newest-first to find the first one with actual text content. --- src/tools/delegate-task/sync-result-fetcher.ts | 13 +++++++++++-- src/tools/delegate-task/unstable-agent-task.ts | 11 +++++++++-- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/src/tools/delegate-task/sync-result-fetcher.ts b/src/tools/delegate-task/sync-result-fetcher.ts index 64d1a278..e072ac40 100644 --- a/src/tools/delegate-task/sync-result-fetcher.ts +++ b/src/tools/delegate-task/sync-result-fetcher.ts @@ -41,8 +41,17 @@ export async function fetchSyncResult( return { ok: false, error: `No assistant response found.\n\nSession ID: ${sessionID}` } } - const textParts = lastMessage?.parts?.filter((p) => p.type === "text" || p.type === "reasoning") ?? [] - const textContent = textParts.map((p) => p.text ?? "").filter(Boolean).join("\n") + // Search assistant messages (newest first) for one with text/reasoning content. + // The last assistant message may only contain tool calls with no text. + let textContent = "" + for (const msg of assistantMessages) { + const textParts = msg.parts?.filter((p) => p.type === "text" || p.type === "reasoning") ?? [] + const content = textParts.map((p) => p.text ?? "").filter(Boolean).join("\n") + if (content) { + textContent = content + break + } + } return { ok: true, textContent } } diff --git a/src/tools/delegate-task/unstable-agent-task.ts b/src/tools/delegate-task/unstable-agent-task.ts index ae97153b..35eea1d5 100644 --- a/src/tools/delegate-task/unstable-agent-task.ts +++ b/src/tools/delegate-task/unstable-agent-task.ts @@ -120,8 +120,15 @@ export async function executeUnstableAgentTask( return `No assistant response found (task ran in background mode).\n\nSession ID: ${sessionID}` } - const textParts = lastMessage?.parts?.filter((p) => p.type === "text" || p.type === "reasoning") ?? [] - const textContent = textParts.map((p) => p.text ?? "").filter(Boolean).join("\n") + let textContent = "" + for (const msg of assistantMessages) { + const textParts = msg.parts?.filter((p) => p.type === "text" || p.type === "reasoning") ?? [] + const content = textParts.map((p) => p.text ?? "").filter(Boolean).join("\n") + if (content) { + textContent = content + break + } + } const duration = formatDuration(startTime) return `SUPERVISED TASK COMPLETED SUCCESSFULLY