fix(agents): strip [Historical context: ...] and tool call text from streaming path (#13453)

- Add [Historical context: ...] marker pattern to stripDowngradedToolCallText
- Apply stripDowngradedToolCallText in emitBlockChunk streaming path
- Previously only stripBlockTags ran during streaming, leaking [Tool Call: ...] markers to users
- Add 7 test cases for the new pattern stripping
This commit is contained in:
Cklee
2026-02-11 05:04:52 +09:00
committed by GitHub
parent 67d25c6533
commit 22458f57f2
3 changed files with 48 additions and 4 deletions

View File

@@ -1,6 +1,10 @@
import type { AssistantMessage } from "@mariozechner/pi-ai";
import { describe, expect, it } from "vitest";
import { extractAssistantText, formatReasoningMessage } from "./pi-embedded-utils.js";
import {
extractAssistantText,
formatReasoningMessage,
stripDowngradedToolCallText,
} from "./pi-embedded-utils.js";
describe("extractAssistantText", () => {
it("strips Minimax tool invocation XML from text", () => {
@@ -559,3 +563,39 @@ describe("formatReasoningMessage", () => {
);
});
});
describe("stripDowngradedToolCallText", () => {
it("strips [Historical context: ...] blocks", () => {
const text = `[Historical context: a different model called tool "exec" with arguments {"command":"git status"}]`;
expect(stripDowngradedToolCallText(text)).toBe("");
});
it("preserves text before [Historical context: ...] blocks", () => {
const text = `Here is the answer.\n[Historical context: a different model called tool "read"]`;
expect(stripDowngradedToolCallText(text)).toBe("Here is the answer.");
});
it("preserves text around [Historical context: ...] blocks", () => {
const text = `Before.\n[Historical context: tool call info]\nAfter.`;
expect(stripDowngradedToolCallText(text)).toBe("Before.\nAfter.");
});
it("strips multiple [Historical context: ...] blocks", () => {
const text = `[Historical context: first tool call]\n[Historical context: second tool call]`;
expect(stripDowngradedToolCallText(text)).toBe("");
});
it("strips mixed [Tool Call: ...] and [Historical context: ...] blocks", () => {
const text = `Intro.\n[Tool Call: exec (ID: toolu_1)]\nArguments: { "command": "ls" }\n[Historical context: a different model called tool "read"]`;
expect(stripDowngradedToolCallText(text)).toBe("Intro.");
});
it("returns text unchanged when no markers are present", () => {
const text = "Just a normal response with no markers.";
expect(stripDowngradedToolCallText(text)).toBe("Just a normal response with no markers.");
});
it("returns empty string for empty input", () => {
expect(stripDowngradedToolCallText("")).toBe("");
});
});