diff --git a/src/agents/pi-embedded-runner.sanitize-session-history.test.ts b/src/agents/pi-embedded-runner.sanitize-session-history.test.ts index 438b46bb971..39b8a5e907b 100644 --- a/src/agents/pi-embedded-runner.sanitize-session-history.test.ts +++ b/src/agents/pi-embedded-runner.sanitize-session-history.test.ts @@ -53,6 +53,20 @@ describe("sanitizeSessionHistory", () => { sessionId: TEST_SESSION_ID, }); + const sanitizeQianfanHistory = async (params: { + messages: AgentMessage[]; + modelApi?: string; + modelId?: string; + }) => + sanitizeSessionHistory({ + messages: params.messages, + modelApi: params.modelApi ?? "openai-completions", + provider: "qianfan", + modelId: params.modelId ?? "baiduqianfancodingplan/qianfan-code-latest", + sessionManager: makeMockSessionManager(), + sessionId: TEST_SESSION_ID, + }); + const sanitizeAnthropicHistory = async (params: { messages: AgentMessage[]; provider?: string; @@ -781,6 +795,29 @@ describe("sanitizeSessionHistory", () => { expect(types).not.toContain("thinking"); }); + it("drops assistant thinking blocks for qianfan code tool-call replay", async () => { + setNonGoogleModelApi(); + + const messages: AgentMessage[] = [ + makeUserMessage("read a file"), + makeAssistantMessage([ + { + type: "thinking", + thinking: "I should use the read tool", + thinkingSignature: "reasoning_content", + }, + { type: "toolCall", id: "tool_123", name: "read", arguments: { path: "/tmp/test" } }, + { type: "text", text: "Let me read that file." }, + ]), + ]; + + const result = await sanitizeQianfanHistory({ messages }); + const types = getAssistantContentTypes(result); + expect(types).toContain("toolCall"); + expect(types).toContain("text"); + expect(types).not.toContain("thinking"); + }); + it("drops assistant thinking blocks for anthropic replay", async () => { setNonGoogleModelApi(); @@ -816,4 +853,14 @@ describe("sanitizeSessionHistory", () => { const types = getAssistantContentTypes(result); expect(types).toContain("thinking"); }); + + it("does not drop thinking blocks for non-qianfan-code qianfan models", async () => { + setNonGoogleModelApi(); + + const messages = makeThinkingAndTextAssistantMessages("reasoning_content"); + + const result = await sanitizeQianfanHistory({ messages, modelId: "deepseek-v3.2" }); + const types = getAssistantContentTypes(result); + expect(types).toContain("thinking"); + }); }); diff --git a/src/agents/provider-capabilities.test.ts b/src/agents/provider-capabilities.test.ts index 09f19468776..83d8f70da87 100644 --- a/src/agents/provider-capabilities.test.ts +++ b/src/agents/provider-capabilities.test.ts @@ -174,6 +174,12 @@ describe("resolveProviderCapabilities", () => { modelId: "claude-3.7-sonnet", }), ).toBe(true); + expect( + shouldDropThinkingBlocksForModel({ + provider: "qianfan", + modelId: "baiduqianfancodingplan/qianfan-code-latest", + }), + ).toBe(true); }); it("forwards config and workspace context to plugin capability lookup", () => { diff --git a/src/agents/provider-capabilities.ts b/src/agents/provider-capabilities.ts index c52be686387..7c2738ef713 100644 --- a/src/agents/provider-capabilities.ts +++ b/src/agents/provider-capabilities.ts @@ -75,6 +75,9 @@ const PLUGIN_CAPABILITIES_FALLBACKS: Record