fix(agent): recover blank streamed replies from final answer

This commit is contained in:
Sanjay Santhanam
2026-04-25 00:35:03 -07:00
committed by Peter Steinberger
parent bc2d53dacd
commit 1f06dbd04c
2 changed files with 29 additions and 4 deletions

View File

@@ -65,6 +65,29 @@ describe("buildEmbeddedRunPayloads tool-error warnings", () => {
expectSinglePayloadText(payloads, "Done.");
});
it("falls back to final-answer assistant text when streamed text only contains blanks", () => {
const payloads = buildPayloads({
assistantTexts: [" "],
lastAssistant: {
role: "assistant",
stopReason: "stop",
content: [
{
type: "text",
text: "Fixed.",
textSignature: JSON.stringify({
v: 1,
id: "item_final",
phase: "final_answer",
}),
},
],
} as AssistantMessage,
});
expectSinglePayloadText(payloads, "Fixed.");
});
it("suppresses exec tool errors when verbose mode is off", () => {
expectNoPayloads({
lastToolError: { toolName: "exec", error: "command failed" },

View File

@@ -293,20 +293,22 @@ export function buildEmbeddedRunPayloads(params: {
const parsed = parseReplyDirectives(text);
return (parsed.mediaUrls?.length ?? 0) > 0 || parsed.audioAsVoice;
});
const normalizedAssistantTexts = normalizeTextForComparison(params.assistantTexts.join("\n\n"));
const nonEmptyAssistantTexts = params.assistantTexts.filter((text) => text.trim().length > 0);
const normalizedAssistantTexts = normalizeTextForComparison(nonEmptyAssistantTexts.join("\n\n"));
const normalizedRawAnswerText = normalizeTextForComparison(rawAnswerDirectiveState?.text ?? "");
const shouldPreferRawAnswerText =
rawAnswerHasMedia &&
(!params.assistantTexts.length ||
(!nonEmptyAssistantTexts.length ||
(!assistantTextsHaveMedia &&
normalizedAssistantTexts.length > 0 &&
normalizedAssistantTexts === normalizedRawAnswerText));
const hasAssistantTextPayload = nonEmptyAssistantTexts.length > 0;
const answerTexts = suppressAssistantArtifacts
? []
: (shouldPreferRawAnswerText && fallbackRawAnswerText
? [fallbackRawAnswerText]
: params.assistantTexts.length
? params.assistantTexts
: hasAssistantTextPayload
? nonEmptyAssistantTexts
: fallbackAnswerText
? [fallbackAnswerText]
: []