diff --git a/src/agents/pi-embedded-runner/session-manager-init.ts b/src/agents/pi-embedded-runner/session-manager-init.ts index 95c699947bd..b6b635004b5 100644 --- a/src/agents/pi-embedded-runner/session-manager-init.ts +++ b/src/agents/pi-embedded-runner/session-manager-init.ts @@ -12,6 +12,11 @@ type SessionMessageEntry = { type: "message"; message?: { role?: string } }; * * This normalizes the file/session state so the first user prompt is persisted before the first * assistant entry, even for pre-created session files. + * + * NOTE: We only reset when there are no user messages yet (truly empty pre-created session). + * If user messages already exist, the session has real conversation history — an API error + * (e.g. 400/503) may have left the transcript without an assistant reply, but we must NOT + * wipe the history. The orphaned-user-message repair in attempt.ts handles that case instead. */ export async function prepareSessionManagerForRun(params: { sessionManager: unknown; @@ -33,6 +38,11 @@ export async function prepareSessionManagerForRun(params: { const hasAssistant = sm.fileEntries.some( (e) => e.type === "message" && (e as SessionMessageEntry).message?.role === "assistant", ); + // A session with existing user messages has real conversation history (e.g. a prior turn that + // hit an API error). Do not reset it — the orphaned-user-message repair handles recovery. + const hasUser = sm.fileEntries.some( + (e) => e.type === "message" && (e as SessionMessageEntry).message?.role === "user", + ); if (!params.hadSessionFile && header) { header.id = params.sessionId; @@ -41,8 +51,9 @@ export async function prepareSessionManagerForRun(params: { return; } - if (params.hadSessionFile && header && !hasAssistant) { + if (params.hadSessionFile && header && !hasAssistant && !hasUser) { // Reset file so the first assistant flush includes header+user+assistant in order. + // Only applies to truly empty pre-created session files (no messages at all). await fs.writeFile(params.sessionFile, "", "utf-8"); sm.fileEntries = [header]; sm.byId?.clear?.();