diff --git a/src/agents/subagent-announce.format.e2e.test.ts b/src/agents/subagent-announce.format.e2e.test.ts index 872f845e8e8..9f0d1687149 100644 --- a/src/agents/subagent-announce.format.e2e.test.ts +++ b/src/agents/subagent-announce.format.e2e.test.ts @@ -232,6 +232,36 @@ describe("subagent announce formatting", () => { expect(msg).toContain("tool output line 1"); }); + it("falls back to latest tool output when assistant reply is empty", async () => { + const { runSubagentAnnounceFlow } = await import("./subagent-announce.js"); + chatHistoryMock.mockResolvedValueOnce({ + messages: [ + { + role: "assistant", + content: [{ type: "text", text: "" }], + }, + { + role: "tool", + content: [{ type: "text", text: "tool output line 2" }], + }, + ], + }); + readLatestAssistantReplyMock.mockResolvedValue(""); + + await runSubagentAnnounceFlow({ + childSessionKey: "agent:main:subagent:worker", + childRunId: "run-tool-fallback-2", + requesterSessionKey: "agent:main:main", + requesterDisplayKey: "main", + ...defaultOutcomeAnnounce, + waitForCompletion: false, + }); + + const call = agentSpy.mock.calls[0]?.[0] as { params?: { message?: string } }; + const msg = call?.params?.message as string; + expect(msg).toContain("tool output line 2"); + }); + it("keeps full findings and includes compact stats", async () => { const { runSubagentAnnounceFlow } = await import("./subagent-announce.js"); sessionStore = { diff --git a/src/agents/subagent-announce.ts b/src/agents/subagent-announce.ts index 8bd2950bb91..894bc293fc2 100644 --- a/src/agents/subagent-announce.ts +++ b/src/agents/subagent-announce.ts @@ -37,6 +37,14 @@ type ToolResultMessage = { content?: unknown; }; +function isToolResultMessage(msg: unknown): boolean { + if (!msg || typeof msg !== "object") { + return false; + } + const role = (msg as { role?: unknown }).role; + return role === "toolResult" || role === "tool"; +} + function extractToolResultText(content: unknown): string { if (typeof content === "string") { return sanitizeTextContent(content); @@ -60,13 +68,10 @@ async function readLatestToolResult(sessionKey: string): Promise= 0; i -= 1) { const msg = messages[i]; - if (!msg || typeof msg !== "object") { + if (!isToolResultMessage(msg)) { continue; } const candidate = msg as ToolResultMessage; - if (candidate.role !== "toolResult") { - continue; - } const text = extractToolResultText(candidate.content); if (text) { return text; diff --git a/src/agents/tools/sessions-helpers.ts b/src/agents/tools/sessions-helpers.ts index f1a6b427e4c..c1e0babf5d4 100644 --- a/src/agents/tools/sessions-helpers.ts +++ b/src/agents/tools/sessions-helpers.ts @@ -127,7 +127,7 @@ export function stripToolMessages(messages: unknown[]): unknown[] { return true; } const role = (msg as { role?: unknown }).role; - return role !== "toolResult"; + return role !== "toolResult" && role !== "tool"; }); }