diff --git a/packages/server/src/server/agent/providers/pi/agent.test.ts b/packages/server/src/server/agent/providers/pi/agent.test.ts index 039d3eaf22..9ca6c821b8 100644 --- a/packages/server/src/server/agent/providers/pi/agent.test.ts +++ b/packages/server/src/server/agent/providers/pi/agent.test.ts @@ -2194,6 +2194,33 @@ describe("PiRpcAgentSession", () => { }); }); + test.each([false, true])( + "rejects new turns with Reload guidance after the Pi process exits (active: %s)", + async (active) => { + const { pi, session, events } = await createSession(); + try { + if (active) { + await session.startTurn("before crash"); + } + const runtime = pi.latestSession(); + runtime.emit({ type: "process_exit", error: "Pi exited" }); + if (active) { + await expect(events.nextTurnFailure()).resolves.toMatchObject({ error: "Pi exited" }); + } + const promptCount = runtime.prompts.length; + + for (let attempt = 0; attempt < 2; attempt += 1) { + await expect(session.startTurn("after crash")).rejects.toThrow( + "Pi process exited. Reload agent before sending another message.", + ); + } + expect(runtime.prompts).toHaveLength(promptCount); + } finally { + await session.close(); + } + }, + ); + test("fails an autonomous turn when the Pi process exits before settlement", async () => { const { pi, events } = await createSession(); const fakeSession = pi.latestSession(); diff --git a/packages/server/src/server/agent/providers/pi/agent.ts b/packages/server/src/server/agent/providers/pi/agent.ts index 198d596c9b..513f9b62e9 100644 --- a/packages/server/src/server/agent/providers/pi/agent.ts +++ b/packages/server/src/server/agent/providers/pi/agent.ts @@ -1223,6 +1223,7 @@ export class PiRpcAgentSession implements AgentSession { private readonly logger: Logger; private readonly usagePoller: PiUsagePoller; private closed = false; + private runtimeDead = false; private readonly closeController = new AbortController(); private readonly pendingExtensionHydrations = new Set>(); private pendingOutput: Promise | null = null; @@ -1305,6 +1306,9 @@ export class PiRpcAgentSession implements AgentSession { } async startTurn(prompt: AgentPromptInput, options?: AgentRunOptions): Promise { + if (this.runtimeDead) { + throw new Error("Pi process exited. Reload agent before sending another message."); + } if (this.activeTurnId) { throw new Error("A Pi turn is already active"); } @@ -2190,6 +2194,7 @@ export class PiRpcAgentSession implements AgentSession { } private handleProcessExit(error: string): void { + this.runtimeDead = true; this.rejectAllExtensionResults(new Error(error)); this.interruptingTurn = null; if (!this.activeTurnId && !this.activeTurnStarted) {