diff --git a/src/agents/pi-embedded-helpers.sanitize-session-messages-images.removes-empty-assistant-text-blocks-but-preserves.e2e.test.ts b/src/agents/pi-embedded-helpers.sanitize-session-messages-images.removes-empty-assistant-text-blocks-but-preserves.e2e.test.ts index 0a120aca5b..878b1199e7 100644 --- a/src/agents/pi-embedded-helpers.sanitize-session-messages-images.removes-empty-assistant-text-blocks-but-preserves.e2e.test.ts +++ b/src/agents/pi-embedded-helpers.sanitize-session-messages-images.removes-empty-assistant-text-blocks-but-preserves.e2e.test.ts @@ -83,7 +83,7 @@ describe("sanitizeSessionMessagesImages", () => { role: "assistant", content: [{ type: "toolCall", id: "call_1", name: "read" }], }, - ] satisfies AgentMessage[]; + ] as unknown as AgentMessage[]; const out = await sanitizeSessionMessagesImages(input, "test"); const assistant = out[0] as { content?: Array> }; @@ -102,7 +102,7 @@ describe("sanitizeSessionMessagesImages", () => { { type: "toolCall", id: "call_1", name: "read", arguments: {} }, ], }, - ] satisfies AgentMessage[]; + ] as unknown as AgentMessage[]; const out = await sanitizeSessionMessagesImages(input, "test"); @@ -130,7 +130,7 @@ describe("sanitizeSessionMessagesImages", () => { toolUseId: "call_abc|item:123", content: [{ type: "text", text: "ok" }], }, - ] satisfies AgentMessage[]; + ] as unknown as AgentMessage[]; const out = await sanitizeSessionMessagesImages(input, "test", { sanitizeToolCallIds: true, @@ -159,7 +159,7 @@ describe("sanitizeSessionMessagesImages", () => { content: [{ type: "text", text: "ok" }], isError: false, }, - ] satisfies AgentMessage[]; + ] as unknown as AgentMessage[]; const out = await sanitizeSessionMessagesImages(input, "test", { sanitizeMode: "images-only", @@ -183,7 +183,7 @@ describe("sanitizeSessionMessagesImages", () => { { type: "text", text: "ok" }, ], }, - ] satisfies AgentMessage[]; + ] as unknown as AgentMessage[]; const out = await sanitizeSessionMessagesImages(input, "test"); @@ -195,7 +195,7 @@ describe("sanitizeSessionMessagesImages", () => { const input = [ { role: "user", content: "hello" }, { role: "assistant", content: [{ type: "text", text: "" }] }, - ] satisfies AgentMessage[]; + ] as unknown as AgentMessage[]; const out = await sanitizeSessionMessagesImages(input, "test"); @@ -207,7 +207,7 @@ describe("sanitizeSessionMessagesImages", () => { { role: "user", content: "hello" }, { role: "assistant", stopReason: "error", content: [] }, { role: "assistant", stopReason: "error" }, - ] satisfies AgentMessage[]; + ] as unknown as AgentMessage[]; const out = await sanitizeSessionMessagesImages(input, "test"); @@ -224,7 +224,7 @@ describe("sanitizeSessionMessagesImages", () => { toolCallId: "tool-1", content: [{ type: "text", text: "result" }], }, - ] satisfies AgentMessage[]; + ] as unknown as AgentMessage[]; const out = await sanitizeSessionMessagesImages(input, "test"); @@ -247,7 +247,7 @@ describe("sanitizeSessionMessagesImages", () => { }, ], }, - ] satisfies AgentMessage[]; + ] as unknown as AgentMessage[]; const out = await sanitizeSessionMessagesImages(input, "test"); @@ -267,14 +267,14 @@ describe("sanitizeGoogleTurnOrdering", () => { role: "assistant", content: [{ type: "toolCall", id: "call_1", name: "exec", arguments: {} }], }, - ] satisfies AgentMessage[]; + ] as unknown as AgentMessage[]; const out = sanitizeGoogleTurnOrdering(input); expect(out[0]?.role).toBe("user"); expect(out[1]?.role).toBe("assistant"); }); it("is a no-op when history starts with user", () => { - const input = [{ role: "user", content: "hi" }] satisfies AgentMessage[]; + const input = [{ role: "user", content: "hi" }] as unknown as AgentMessage[]; const out = sanitizeGoogleTurnOrdering(input); expect(out).toBe(input); }); diff --git a/src/agents/pi-embedded-helpers.validate-turns.e2e.test.ts b/src/agents/pi-embedded-helpers.validate-turns.e2e.test.ts index 2e0b86287b..ae83ab8d4f 100644 --- a/src/agents/pi-embedded-helpers.validate-turns.e2e.test.ts +++ b/src/agents/pi-embedded-helpers.validate-turns.e2e.test.ts @@ -6,6 +6,10 @@ import { validateGeminiTurns, } from "./pi-embedded-helpers.js"; +function asMessages(messages: unknown[]): AgentMessage[] { + return messages as AgentMessage[]; +} + describe("validateGeminiTurns", () => { it("should return empty array unchanged", () => { const result = validateGeminiTurns([]); @@ -13,30 +17,30 @@ describe("validateGeminiTurns", () => { }); it("should return single message unchanged", () => { - const msgs: AgentMessage[] = [ + const msgs = asMessages([ { role: "user", content: "Hello", }, - ]; + ]); const result = validateGeminiTurns(msgs); expect(result).toEqual(msgs); }); it("should leave alternating user/assistant unchanged", () => { - const msgs: AgentMessage[] = [ + const msgs = asMessages([ { role: "user", content: "Hello" }, { role: "assistant", content: [{ type: "text", text: "Hi" }] }, { role: "user", content: "How are you?" }, { role: "assistant", content: [{ type: "text", text: "Good!" }] }, - ]; + ]); const result = validateGeminiTurns(msgs); expect(result).toHaveLength(4); expect(result).toEqual(msgs); }); it("should merge consecutive assistant messages", () => { - const msgs: AgentMessage[] = [ + const msgs = asMessages([ { role: "user", content: "Hello" }, { role: "assistant", @@ -49,19 +53,19 @@ describe("validateGeminiTurns", () => { stopReason: "end_turn", }, { role: "user", content: "How are you?" }, - ]; + ]); const result = validateGeminiTurns(msgs); expect(result).toHaveLength(3); expect(result[0]).toEqual({ role: "user", content: "Hello" }); expect(result[1].role).toBe("assistant"); - expect(result[1].content).toHaveLength(2); + expect((result[1] as { content?: unknown[] }).content).toHaveLength(2); expect(result[2]).toEqual({ role: "user", content: "How are you?" }); }); it("should preserve metadata from later message when merging", () => { - const msgs: AgentMessage[] = [ + const msgs = asMessages([ { role: "assistant", content: [{ type: "text", text: "Part 1" }], @@ -73,7 +77,7 @@ describe("validateGeminiTurns", () => { usage: { input: 10, output: 10 }, stopReason: "end_turn", }, - ]; + ]); const result = validateGeminiTurns(msgs); @@ -85,7 +89,7 @@ describe("validateGeminiTurns", () => { }); it("should handle toolResult messages without merging", () => { - const msgs: AgentMessage[] = [ + const msgs = asMessages([ { role: "user", content: "Use tool" }, { role: "assistant", @@ -105,7 +109,7 @@ describe("validateGeminiTurns", () => { content: [{ type: "text", text: "Extra thoughts" }], }, { role: "user", content: "Request 2" }, - ]; + ]); const result = validateGeminiTurns(msgs); @@ -125,31 +129,31 @@ describe("validateAnthropicTurns", () => { }); it("should return single message unchanged", () => { - const msgs: AgentMessage[] = [ + const msgs = asMessages([ { role: "user", content: [{ type: "text", text: "Hello" }], }, - ]; + ]); const result = validateAnthropicTurns(msgs); expect(result).toEqual(msgs); }); it("should return alternating user/assistant unchanged", () => { - const msgs: AgentMessage[] = [ + const msgs = asMessages([ { role: "user", content: [{ type: "text", text: "Question" }] }, { role: "assistant", content: [{ type: "text", text: "Answer" }], }, { role: "user", content: [{ type: "text", text: "Follow-up" }] }, - ]; + ]); const result = validateAnthropicTurns(msgs); expect(result).toEqual(msgs); }); it("should merge consecutive user messages", () => { - const msgs: AgentMessage[] = [ + const msgs = asMessages([ { role: "user", content: [{ type: "text", text: "First message" }], @@ -160,7 +164,7 @@ describe("validateAnthropicTurns", () => { content: [{ type: "text", text: "Second message" }], timestamp: 2000, }, - ]; + ]); const result = validateAnthropicTurns(msgs); @@ -175,11 +179,11 @@ describe("validateAnthropicTurns", () => { }); it("should merge three consecutive user messages", () => { - const msgs: AgentMessage[] = [ + const msgs = asMessages([ { role: "user", content: [{ type: "text", text: "One" }] }, { role: "user", content: [{ type: "text", text: "Two" }] }, { role: "user", content: [{ type: "text", text: "Three" }] }, - ]; + ]); const result = validateAnthropicTurns(msgs); @@ -189,7 +193,7 @@ describe("validateAnthropicTurns", () => { }); it("keeps newest metadata when merging consecutive users", () => { - const msgs: AgentMessage[] = [ + const msgs = asMessages([ { role: "user", content: [{ type: "text", text: "Old" }], @@ -203,7 +207,7 @@ describe("validateAnthropicTurns", () => { attachments: [{ type: "image", url: "new.png" }], someCustomField: "keep-me", } as AgentMessage, - ]; + ]); const result = validateAnthropicTurns(msgs) as Extract[]; @@ -221,7 +225,7 @@ describe("validateAnthropicTurns", () => { }); it("merges consecutive users with images and preserves order", () => { - const msgs: AgentMessage[] = [ + const msgs = asMessages([ { role: "user", content: [ @@ -236,7 +240,7 @@ describe("validateAnthropicTurns", () => { { type: "text", text: "second" }, ], }, - ]; + ]); const [merged] = validateAnthropicTurns(msgs) as Extract[]; expect(merged.content).toEqual([ @@ -248,7 +252,7 @@ describe("validateAnthropicTurns", () => { }); it("should not merge consecutive assistant messages", () => { - const msgs: AgentMessage[] = [ + const msgs = asMessages([ { role: "user", content: [{ type: "text", text: "Question" }] }, { role: "assistant", @@ -258,7 +262,7 @@ describe("validateAnthropicTurns", () => { role: "assistant", content: [{ type: "text", text: "Answer 2" }], }, - ]; + ]); const result = validateAnthropicTurns(msgs); @@ -268,7 +272,7 @@ describe("validateAnthropicTurns", () => { it("should handle mixed scenario with steering messages", () => { // Simulates: user asks -> assistant errors -> steering user message injected - const msgs: AgentMessage[] = [ + const msgs = asMessages([ { role: "user", content: [{ type: "text", text: "Original question" }] }, { role: "assistant", @@ -281,7 +285,7 @@ describe("validateAnthropicTurns", () => { content: [{ type: "text", text: "Steering: try again" }], }, { role: "user", content: [{ type: "text", text: "Another follow-up" }] }, - ]; + ]); const result = validateAnthropicTurns(msgs); @@ -297,19 +301,19 @@ describe("validateAnthropicTurns", () => { describe("mergeConsecutiveUserTurns", () => { it("keeps newest metadata while merging content", () => { - const previous: Extract = { + const previous = { role: "user", content: [{ type: "text", text: "before" }], timestamp: 1000, attachments: [{ type: "image", url: "old.png" }], - }; - const current: Extract = { + } as Extract; + const current = { role: "user", content: [{ type: "text", text: "after" }], timestamp: 2000, attachments: [{ type: "image", url: "new.png" }], someCustomField: "keep-me", - } as AgentMessage; + } as Extract; const merged = mergeConsecutiveUserTurns(previous, current); @@ -325,15 +329,15 @@ describe("mergeConsecutiveUserTurns", () => { }); it("backfills timestamp from earlier message when missing", () => { - const previous: Extract = { + const previous = { role: "user", content: [{ type: "text", text: "before" }], timestamp: 1000, - }; - const current: Extract = { + } as Extract; + const current = { role: "user", content: [{ type: "text", text: "after" }], - }; + } as Extract; const merged = mergeConsecutiveUserTurns(previous, current); diff --git a/src/agents/pi-embedded-runner.google-sanitize-thinking.e2e.test.ts b/src/agents/pi-embedded-runner.google-sanitize-thinking.e2e.test.ts index cca36413d0..249ca466c7 100644 --- a/src/agents/pi-embedded-runner.google-sanitize-thinking.e2e.test.ts +++ b/src/agents/pi-embedded-runner.google-sanitize-thinking.e2e.test.ts @@ -6,9 +6,13 @@ import { sanitizeSessionHistory } from "./pi-embedded-runner/google.js"; type AssistantThinking = { type?: string; thinking?: string; thinkingSignature?: string }; function getAssistantMessage(out: AgentMessage[]) { - return out.find((msg) => (msg as { role?: string }).role === "assistant") as + const assistant = out.find((msg) => (msg as { role?: string }).role === "assistant") as | { content?: AssistantThinking[] } | undefined; + if (!assistant) { + throw new Error("Expected assistant message in sanitized history"); + } + return assistant; } async function sanitizeGoogleAssistantWithContent(content: unknown[]) { @@ -22,7 +26,7 @@ async function sanitizeGoogleAssistantWithContent(content: unknown[]) { role: "assistant", content, }, - ] satisfies AgentMessage[]; + ] as unknown as AgentMessage[]; const out = await sanitizeSessionHistory({ messages: input, @@ -71,7 +75,7 @@ describe("sanitizeSessionHistory (google thinking)", () => { role: "assistant", content: [{ type: "thinking", thinking: "reasoning" }], }, - ] satisfies AgentMessage[]; + ] as unknown as AgentMessage[]; const out = await sanitizeSessionHistory({ messages: input, @@ -96,7 +100,7 @@ describe("sanitizeSessionHistory (google thinking)", () => { role: "assistant", content: [{ type: "thinking", thinking: "reasoning", signature: "c2ln" }], }, - ] satisfies AgentMessage[]; + ] as unknown as AgentMessage[]; const out = await sanitizeSessionHistory({ messages: input, @@ -129,7 +133,7 @@ describe("sanitizeSessionHistory (google thinking)", () => { { type: "text", text: "world" }, ], }, - ] satisfies AgentMessage[]; + ] as unknown as AgentMessage[]; const out = await sanitizeSessionHistory({ messages: input, @@ -173,7 +177,7 @@ describe("sanitizeSessionHistory (google thinking)", () => { }, ], }, - ] satisfies AgentMessage[]; + ] as unknown as AgentMessage[]; const out = await sanitizeSessionHistory({ messages: input, @@ -225,7 +229,7 @@ describe("sanitizeSessionHistory (google thinking)", () => { { type: "thinking", thinking: "unsigned" }, ], }, - ] satisfies AgentMessage[]; + ] as unknown as AgentMessage[]; const out = await sanitizeSessionHistory({ messages: input, @@ -253,7 +257,7 @@ describe("sanitizeSessionHistory (google thinking)", () => { role: "assistant", content: [{ type: "thinking", thinking: " " }], }, - ] satisfies AgentMessage[]; + ] as unknown as AgentMessage[]; const out = await sanitizeSessionHistory({ messages: input, @@ -279,7 +283,7 @@ describe("sanitizeSessionHistory (google thinking)", () => { role: "assistant", content: [{ type: "thinking", thinking: "reasoning" }], }, - ] satisfies AgentMessage[]; + ] as unknown as AgentMessage[]; const out = await sanitizeSessionHistory({ messages: input, @@ -308,7 +312,7 @@ describe("sanitizeSessionHistory (google thinking)", () => { toolName: "read", content: [{ type: "text", text: "ok" }], }, - ] satisfies AgentMessage[]; + ] as unknown as AgentMessage[]; const out = await sanitizeSessionHistory({ messages: input, diff --git a/src/agents/pi-embedded-utils.e2e.test.ts b/src/agents/pi-embedded-utils.e2e.test.ts index af23ca9b6a..fa8865abe1 100644 --- a/src/agents/pi-embedded-utils.e2e.test.ts +++ b/src/agents/pi-embedded-utils.e2e.test.ts @@ -6,9 +6,23 @@ import { stripDowngradedToolCallText, } from "./pi-embedded-utils.js"; +function makeAssistantMessage( + message: Omit & + Partial>, +): AssistantMessage { + return { + api: "responses", + provider: "openai", + model: "gpt-5", + usage: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, totalTokens: 0, cost: 0 }, + stopReason: "stop", + ...message, + }; +} + describe("extractAssistantText", () => { it("strips Minimax tool invocation XML from text", () => { - const msg: AssistantMessage = { + const msg = makeAssistantMessage({ role: "assistant", content: [ { @@ -20,14 +34,14 @@ describe("extractAssistantText", () => { }, ], timestamp: Date.now(), - }; + }); const result = extractAssistantText(msg); expect(result).toBe(""); }); it("strips multiple tool invocations", () => { - const msg: AssistantMessage = { + const msg = makeAssistantMessage({ role: "assistant", content: [ { @@ -39,14 +53,14 @@ describe("extractAssistantText", () => { }, ], timestamp: Date.now(), - }; + }); const result = extractAssistantText(msg); expect(result).toBe("Let me check that."); }); it("keeps invoke snippets without Minimax markers", () => { - const msg: AssistantMessage = { + const msg = makeAssistantMessage({ role: "assistant", content: [ { @@ -55,7 +69,7 @@ describe("extractAssistantText", () => { }, ], timestamp: Date.now(), - }; + }); const result = extractAssistantText(msg); expect(result).toBe( @@ -64,7 +78,7 @@ describe("extractAssistantText", () => { }); it("preserves normal text without tool invocations", () => { - const msg: AssistantMessage = { + const msg = makeAssistantMessage({ role: "assistant", content: [ { @@ -73,27 +87,27 @@ describe("extractAssistantText", () => { }, ], timestamp: Date.now(), - }; + }); const result = extractAssistantText(msg); expect(result).toBe("This is a normal response without any tool calls."); }); it("sanitizes HTTP-ish error text only when stopReason is error", () => { - const msg: AssistantMessage = { + const msg = makeAssistantMessage({ role: "assistant", stopReason: "error", errorMessage: "500 Internal Server Error", content: [{ type: "text", text: "500 Internal Server Error" }], timestamp: Date.now(), - }; + }); const result = extractAssistantText(msg); expect(result).toBe("HTTP 500: Internal Server Error"); }); it("does not rewrite normal text that references billing plans", () => { - const msg: AssistantMessage = { + const msg = makeAssistantMessage({ role: "assistant", content: [ { @@ -102,7 +116,7 @@ describe("extractAssistantText", () => { }, ], timestamp: Date.now(), - }; + }); const result = extractAssistantText(msg); expect(result).toBe( @@ -111,7 +125,7 @@ describe("extractAssistantText", () => { }); it("strips Minimax tool invocations with extra attributes", () => { - const msg: AssistantMessage = { + const msg = makeAssistantMessage({ role: "assistant", content: [ { @@ -120,14 +134,14 @@ describe("extractAssistantText", () => { }, ], timestamp: Date.now(), - }; + }); const result = extractAssistantText(msg); expect(result).toBe("Before\nAfter"); }); it("strips minimax tool_call open and close tags", () => { - const msg: AssistantMessage = { + const msg = makeAssistantMessage({ role: "assistant", content: [ { @@ -136,14 +150,14 @@ describe("extractAssistantText", () => { }, ], timestamp: Date.now(), - }; + }); const result = extractAssistantText(msg); expect(result).toBe("StartInnerEnd"); }); it("ignores invoke blocks without minimax markers", () => { - const msg: AssistantMessage = { + const msg = makeAssistantMessage({ role: "assistant", content: [ { @@ -152,14 +166,14 @@ describe("extractAssistantText", () => { }, ], timestamp: Date.now(), - }; + }); const result = extractAssistantText(msg); expect(result).toBe("BeforeKeepAfter"); }); it("strips invoke blocks when minimax markers are present elsewhere", () => { - const msg: AssistantMessage = { + const msg = makeAssistantMessage({ role: "assistant", content: [ { @@ -168,14 +182,14 @@ describe("extractAssistantText", () => { }, ], timestamp: Date.now(), - }; + }); const result = extractAssistantText(msg); expect(result).toBe("BeforeAfter"); }); it("strips invoke blocks with nested tags", () => { - const msg: AssistantMessage = { + const msg = makeAssistantMessage({ role: "assistant", content: [ { @@ -184,14 +198,14 @@ describe("extractAssistantText", () => { }, ], timestamp: Date.now(), - }; + }); const result = extractAssistantText(msg); expect(result).toBe("AB"); }); it("strips tool XML mixed with regular content", () => { - const msg: AssistantMessage = { + const msg = makeAssistantMessage({ role: "assistant", content: [ { @@ -203,14 +217,14 @@ describe("extractAssistantText", () => { }, ], timestamp: Date.now(), - }; + }); const result = extractAssistantText(msg); expect(result).toBe("I'll help you with that.\nHere are the results."); }); it("handles multiple invoke blocks in one message", () => { - const msg: AssistantMessage = { + const msg = makeAssistantMessage({ role: "assistant", content: [ { @@ -225,14 +239,14 @@ describe("extractAssistantText", () => { }, ], timestamp: Date.now(), - }; + }); const result = extractAssistantText(msg); expect(result).toBe("First check.\nSecond check.\nDone."); }); it("handles stray closing tags without opening tags", () => { - const msg: AssistantMessage = { + const msg = makeAssistantMessage({ role: "assistant", content: [ { @@ -241,14 +255,14 @@ describe("extractAssistantText", () => { }, ], timestamp: Date.now(), - }; + }); const result = extractAssistantText(msg); expect(result).toBe("Some text here.More text."); }); it("returns empty string when message is only tool invocations", () => { - const msg: AssistantMessage = { + const msg = makeAssistantMessage({ role: "assistant", content: [ { @@ -260,14 +274,14 @@ describe("extractAssistantText", () => { }, ], timestamp: Date.now(), - }; + }); const result = extractAssistantText(msg); expect(result).toBe(""); }); it("handles multiple text blocks", () => { - const msg: AssistantMessage = { + const msg = makeAssistantMessage({ role: "assistant", content: [ { @@ -287,14 +301,14 @@ describe("extractAssistantText", () => { }, ], timestamp: Date.now(), - }; + }); const result = extractAssistantText(msg); expect(result).toBe("First block.\nThird block."); }); it("strips downgraded Gemini tool call text representations", () => { - const msg: AssistantMessage = { + const msg = makeAssistantMessage({ role: "assistant", content: [ { @@ -304,14 +318,14 @@ Arguments: { "command": "git status", "timeout": 120000 }`, }, ], timestamp: Date.now(), - }; + }); const result = extractAssistantText(msg); expect(result).toBe(""); }); it("strips multiple downgraded tool calls", () => { - const msg: AssistantMessage = { + const msg = makeAssistantMessage({ role: "assistant", content: [ { @@ -323,14 +337,14 @@ Arguments: { "command": "ls -la" }`, }, ], timestamp: Date.now(), - }; + }); const result = extractAssistantText(msg); expect(result).toBe(""); }); it("strips tool results for downgraded calls", () => { - const msg: AssistantMessage = { + const msg = makeAssistantMessage({ role: "assistant", content: [ { @@ -340,14 +354,14 @@ Arguments: { "command": "ls -la" }`, }, ], timestamp: Date.now(), - }; + }); const result = extractAssistantText(msg); expect(result).toBe(""); }); it("preserves text around downgraded tool calls", () => { - const msg: AssistantMessage = { + const msg = makeAssistantMessage({ role: "assistant", content: [ { @@ -358,14 +372,14 @@ Arguments: { "action": "act", "request": "click button" }`, }, ], timestamp: Date.now(), - }; + }); const result = extractAssistantText(msg); expect(result).toBe("Let me check that for you."); }); it("preserves trailing text after downgraded tool call blocks", () => { - const msg: AssistantMessage = { + const msg = makeAssistantMessage({ role: "assistant", content: [ { @@ -379,14 +393,14 @@ Back to the user.`, }, ], timestamp: Date.now(), - }; + }); const result = extractAssistantText(msg); expect(result).toBe("Intro text.\nBack to the user."); }); it("handles multiple text blocks with tool calls and results", () => { - const msg: AssistantMessage = { + const msg = makeAssistantMessage({ role: "assistant", content: [ { @@ -409,14 +423,14 @@ File contents here`, }, ], timestamp: Date.now(), - }; + }); const result = extractAssistantText(msg); expect(result).toBe("Here's what I found:\nDone checking."); }); it("strips thinking tags from text content", () => { - const msg: AssistantMessage = { + const msg = makeAssistantMessage({ role: "assistant", content: [ { @@ -425,14 +439,14 @@ File contents here`, }, ], timestamp: Date.now(), - }; + }); const result = extractAssistantText(msg); expect(result).toBe("Aquí está tu respuesta."); }); it("strips thinking tags with attributes", () => { - const msg: AssistantMessage = { + const msg = makeAssistantMessage({ role: "assistant", content: [ { @@ -441,14 +455,14 @@ File contents here`, }, ], timestamp: Date.now(), - }; + }); const result = extractAssistantText(msg); expect(result).toBe("Visible"); }); it("strips thinking tags without closing tag", () => { - const msg: AssistantMessage = { + const msg = makeAssistantMessage({ role: "assistant", content: [ { @@ -457,14 +471,14 @@ File contents here`, }, ], timestamp: Date.now(), - }; + }); const result = extractAssistantText(msg); expect(result).toBe(""); }); it("strips thinking tags with various formats", () => { - const msg: AssistantMessage = { + const msg = makeAssistantMessage({ role: "assistant", content: [ { @@ -473,14 +487,14 @@ File contents here`, }, ], timestamp: Date.now(), - }; + }); const result = extractAssistantText(msg); expect(result).toBe("BeforeAfter"); }); it("strips antthinking tags", () => { - const msg: AssistantMessage = { + const msg = makeAssistantMessage({ role: "assistant", content: [ { @@ -489,14 +503,14 @@ File contents here`, }, ], timestamp: Date.now(), - }; + }); const result = extractAssistantText(msg); expect(result).toBe("The actual answer."); }); it("strips final tags while keeping content", () => { - const msg: AssistantMessage = { + const msg = makeAssistantMessage({ role: "assistant", content: [ { @@ -505,14 +519,14 @@ File contents here`, }, ], timestamp: Date.now(), - }; + }); const result = extractAssistantText(msg); expect(result).toBe("Answer"); }); it("strips thought tags", () => { - const msg: AssistantMessage = { + const msg = makeAssistantMessage({ role: "assistant", content: [ { @@ -521,14 +535,14 @@ File contents here`, }, ], timestamp: Date.now(), - }; + }); const result = extractAssistantText(msg); expect(result).toBe("Final response."); }); it("handles nested or multiple thinking blocks", () => { - const msg: AssistantMessage = { + const msg = makeAssistantMessage({ role: "assistant", content: [ { @@ -537,7 +551,7 @@ File contents here`, }, ], timestamp: Date.now(), - }; + }); const result = extractAssistantText(msg); expect(result).toBe("StartMiddleEnd"); diff --git a/src/agents/system-prompt.ts b/src/agents/system-prompt.ts index 04bff2d862..dcfce11fe3 100644 --- a/src/agents/system-prompt.ts +++ b/src/agents/system-prompt.ts @@ -1,9 +1,9 @@ import type { ReasoningLevel, ThinkLevel } from "../auto-reply/thinking.js"; +import { SILENT_REPLY_TOKEN } from "../auto-reply/tokens.js"; import type { MemoryCitationsMode } from "../config/types.memory.js"; +import { listDeliverableMessageChannels } from "../utils/message-channel.js"; import type { ResolvedTimeFormat } from "./date-time.js"; import type { EmbeddedContextFile } from "./pi-embedded-helpers.js"; -import { SILENT_REPLY_TOKEN } from "../auto-reply/tokens.js"; -import { listDeliverableMessageChannels } from "../utils/message-channel.js"; import { sanitizeForPromptLiteral } from "./sanitize-for-prompt.js"; /** diff --git a/src/auto-reply/reply/commands-export-session.ts b/src/auto-reply/reply/commands-export-session.ts index 23e30dff97..10d039741a 100644 --- a/src/auto-reply/reply/commands-export-session.ts +++ b/src/auto-reply/reply/commands-export-session.ts @@ -1,17 +1,17 @@ -import type { SessionEntry as PiSessionEntry, SessionHeader } from "@mariozechner/pi-coding-agent"; -import { SessionManager } from "@mariozechner/pi-coding-agent"; import fs from "node:fs"; import path from "node:path"; import { fileURLToPath } from "node:url"; -import type { SessionEntry } from "../../config/sessions/types.js"; -import type { ReplyPayload } from "../types.js"; -import type { HandleCommandsParams } from "./commands-types.js"; +import type { SessionEntry as PiSessionEntry, SessionHeader } from "@mariozechner/pi-coding-agent"; +import { SessionManager } from "@mariozechner/pi-coding-agent"; import { resolveDefaultSessionStorePath, resolveSessionFilePath, } from "../../config/sessions/paths.js"; import { loadSessionStore } from "../../config/sessions/store.js"; +import type { SessionEntry } from "../../config/sessions/types.js"; +import type { ReplyPayload } from "../types.js"; import { resolveCommandsSystemPromptBundle } from "./commands-system-prompt.js"; +import type { HandleCommandsParams } from "./commands-types.js"; // Export HTML templates are bundled with this module const EXPORT_HTML_DIR = path.join(path.dirname(fileURLToPath(import.meta.url)), "export-html");