fix(worker): don't double-append streamed answer when completed event carries content

This commit is contained in:
Gabriel Brown
2026-07-11 11:47:11 -04:00
parent 2311679802
commit 432e3b501e
3 changed files with 52 additions and 3 deletions
@@ -42,3 +42,19 @@ export const resolveTurnOutcome = (args: {
}
return { text };
};
// Pure decision for whether the `content` on an `assistant_completed` event
// should be folded into the accumulated assistant text.
//
// Some runtimes (Claude `-p --output-format stream-json`, OpenCode) emit the
// final answer TWICE: once as streamed `assistant_delta` chunks and again as
// the `content` on the terminal `assistant_completed`/`result` event. Appending
// both yields a doubled "<answer><answer>". So only fold in the completed
// content when nothing has streamed yet (a runtime that emits only a final
// result). When deltas already carried the answer, skip it. The truly-empty
// case is still covered by resolveTurnOutcome's recoveredText/finalMessage
// fallback, so nothing is lost.
export const shouldAppendCompletedContent = (
currentText: string,
completedContent?: string,
): boolean => Boolean(completedContent) && !currentText.trim();
+5 -2
View File
@@ -18,7 +18,10 @@ import type { AdapterWorkspace, Claim } from './runtime/provider';
import type { BoxHandle } from './user-container';
import type { AgentRuntimeName } from './runtime/agent-runtime';
import { getAdapter } from './runtime/agent-runtime';
import { resolveTurnOutcome } from './runtime/turn-outcome';
import {
resolveTurnOutcome,
shouldAppendCompletedContent,
} from './runtime/turn-outcome';
import './runtime/register';
import { env } from './env';
import {
@@ -344,7 +347,7 @@ const handleAgentEvent = async (args: {
workspace.agentTurnActive = false;
workspace.resolveTurn?.();
workspace.resolveTurn = undefined;
if (event.content) {
if (shouldAppendCompletedContent(assistantContent.value, event.content)) {
assistantContent.value = truncate(
`${assistantContent.value}${event.content}`,
40_000,