diff --git a/packages/pi-coding-agent/src/core/chat-controller-ordering.test.ts b/packages/pi-coding-agent/src/core/chat-controller-ordering.test.ts index 8d0cdaa49..a7a826975 100644 --- a/packages/pi-coding-agent/src/core/chat-controller-ordering.test.ts +++ b/packages/pi-coding-agent/src/core/chat-controller-ordering.test.ts @@ -338,6 +338,54 @@ test("chat-controller clears pinned zone when a new assistant message starts", a assert.equal(host.pinnedMessageContainer.children.length, 0, "pinned zone should clear on new assistant message"); }); +test("chat-controller clears pinned zone when the agent turn ends", async () => { + (globalThis as any)[Symbol.for("@gsd/pi-coding-agent:theme")] = { + fg: (_key: string, text: string) => text, + bg: (_key: string, text: string) => text, + bold: (text: string) => text, + italic: (text: string) => text, + truncate: (text: string) => text, + }; + + const host = createHost(); + const toolCall = { + type: "toolCall", + id: "tool-clear-on-end-1", + name: "exec_command", + arguments: { cmd: "echo hi" }, + }; + + await handleAgentEvent(host, { type: "message_start", message: makeAssistant([]) } as any); + + host.getMarkdownThemeWithSettings = () => ({}); + await handleAgentEvent( + host, + { + type: "message_update", + message: makeAssistant([{ type: "text", text: "Working on it." }, toolCall]), + assistantMessageEvent: { + type: "toolcall_end", + contentIndex: 1, + toolCall: { + ...toolCall, + externalResult: { + content: [{ type: "text", text: "ok" }], + details: {}, + isError: false, + }, + }, + partial: makeAssistant([{ type: "text", text: "Working on it." }, toolCall]), + }, + } as any, + ); + + assert.ok(host.pinnedMessageContainer.children.length > 0, "pinned zone should be populated before agent_end"); + + await handleAgentEvent(host, { type: "agent_end" } as any); + + assert.equal(host.pinnedMessageContainer.children.length, 0, "pinned zone should clear on agent_end"); +}); + test("chat-controller does not pin when there are no tool calls", async () => { (globalThis as any)[Symbol.for("@gsd/pi-coding-agent:theme")] = { fg: (_key: string, text: string) => text, diff --git a/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts b/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts index c7a7daf8b..634f8d28f 100644 --- a/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +++ b/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts @@ -432,12 +432,12 @@ export async function handleAgentEvent(host: InteractiveModeStateHost & { host.streamingMessage = undefined; } host.pendingTools.clear(); - // Stop spinner on pinned border and switch label from "Working ยท Latest Output" to "Latest Output" + // Pinned output is only useful while work is actively streaming. + // Keep chat history as the single source after completion. if (pinnedBorder) { pinnedBorder.stopSpinner(); - pinnedBorder.setLabel("Latest Output"); } - // Keep pinned message visible until the next assistant turn starts. + host.pinnedMessageContainer.clear(); lastPinnedText = ""; hasToolsInTurn = false; pinnedBorder = undefined;