From c685b2736982eb5c21969870813d075bf36a4ebd Mon Sep 17 00:00:00 2001 From: Mario Zechner Date: Tue, 19 May 2026 10:33:16 +0200 Subject: [PATCH] fix(coding-agent): mark retrying agent end events --- packages/coding-agent/CHANGELOG.md | 2 +- .../coding-agent/src/core/agent-session.ts | 24 +++++++++++++++++-- ...gent-session-auto-compaction-queue.test.ts | 7 +++--- .../suite/agent-session-retry-events.test.ts | 2 ++ 4 files changed, 28 insertions(+), 7 deletions(-) diff --git a/packages/coding-agent/CHANGELOG.md b/packages/coding-agent/CHANGELOG.md index 147b3b191..d4725a75f 100644 --- a/packages/coding-agent/CHANGELOG.md +++ b/packages/coding-agent/CHANGELOG.md @@ -4,7 +4,7 @@ ### Fixed -- Fixed AgentSession retry, compaction, and event settlement to use the awaited agent lifecycle instead of a separate event queue. +- Fixed AgentSession retry, compaction, and event settlement to use the awaited agent lifecycle instead of a separate event queue, and added `willRetry` to `agent_end` session events. - Fixed the subagent extension's parallel mode to return useful per-task output and failed-task diagnostics to the parent model instead of 100-character previews ([#4710](https://github.com/earendil-works/pi/issues/4710)). - Fixed Windows local bash execution to hide helper console windows when launched from background SDK processes ([#4699](https://github.com/earendil-works/pi/issues/4699)). diff --git a/packages/coding-agent/src/core/agent-session.ts b/packages/coding-agent/src/core/agent-session.ts index 2f5b805dd..c04791c27 100644 --- a/packages/coding-agent/src/core/agent-session.ts +++ b/packages/coding-agent/src/core/agent-session.ts @@ -120,7 +120,12 @@ export function parseSkillBlock(text: string): ParsedSkillBlock | null { /** Session-specific events that extend the core AgentEvent */ export type AgentSessionEvent = - | AgentEvent + | Exclude + | { + type: "agent_end"; + messages: AgentMessage[]; + willRetry: boolean; + } | { type: "queue_update"; steering: readonly string[]; @@ -485,7 +490,7 @@ export class AgentSession { await this._emitExtensionEvent(event); // Notify all listeners - this._emit(event); + this._emit(event.type === "agent_end" ? { ...event, willRetry: this._willRetryAfterAgentEnd(event) } : event); // Handle session persistence if (event.type === "message_end") { @@ -531,6 +536,21 @@ export class AgentSession { } }; + private _willRetryAfterAgentEnd(event: Extract): boolean { + const settings = this.settingsManager.getRetrySettings(); + if (!settings.enabled || this._retryAttempt >= settings.maxRetries) { + return false; + } + + for (let i = event.messages.length - 1; i >= 0; i--) { + const message = event.messages[i]; + if (message.role === "assistant") { + return this._isRetryableError(message as AssistantMessage); + } + } + return false; + } + /** Extract text content from a message */ private _getUserMessageText(message: Message): string { if (message.role !== "user") return ""; diff --git a/packages/coding-agent/test/agent-session-auto-compaction-queue.test.ts b/packages/coding-agent/test/agent-session-auto-compaction-queue.test.ts index f53431700..1dd01c9b4 100644 --- a/packages/coding-agent/test/agent-session-auto-compaction-queue.test.ts +++ b/packages/coding-agent/test/agent-session-auto-compaction-queue.test.ts @@ -113,14 +113,13 @@ describe("AgentSession auto-compaction queue resume", () => { const runAutoCompaction = ( session as unknown as { - _runAutoCompaction: (reason: "overflow" | "threshold", willRetry: boolean) => Promise; + _runAutoCompaction: (reason: "overflow" | "threshold", willRetry: boolean) => Promise; } )._runAutoCompaction.bind(session); - await runAutoCompaction("threshold", false); - await vi.advanceTimersByTimeAsync(100); + await expect(runAutoCompaction("threshold", false)).resolves.toBe(true); - expect(continueSpy).toHaveBeenCalledTimes(1); + expect(continueSpy).not.toHaveBeenCalled(); }); it("should not compact repeatedly after overflow recovery already attempted", async () => { diff --git a/packages/coding-agent/test/suite/agent-session-retry-events.test.ts b/packages/coding-agent/test/suite/agent-session-retry-events.test.ts index d10fe90c5..ff3e5e95a 100644 --- a/packages/coding-agent/test/suite/agent-session-retry-events.test.ts +++ b/packages/coding-agent/test/suite/agent-session-retry-events.test.ts @@ -47,6 +47,7 @@ describe("AgentSession retry and event characterization", () => { await harness.session.prompt("test"); expect(retryEvents).toEqual(["start:1", "end:true"]); + expect(harness.eventsOfType("agent_end").map((event) => event.willRetry)).toEqual([true, false]); expect(harness.faux.state.callCount).toBe(2); expect(harness.session.isRetrying).toBe(false); }); @@ -90,6 +91,7 @@ describe("AgentSession retry and event characterization", () => { await harness.session.prompt("test"); expect(retryEvents).toEqual(["start:1", "start:2", "end:false"]); + expect(harness.eventsOfType("agent_end").map((event) => event.willRetry)).toEqual([true, true, false]); expect(harness.faux.state.callCount).toBe(3); expect(harness.session.isRetrying).toBe(false); });