fix: auto-recover from Gemini session corruption
Detect the Gemini API error 'function call turn comes immediately after a user turn or after a function response turn' which indicates corrupted session history. When detected: - Delete the corrupted transcript file - Remove the session entry from the store - Return a user-friendly message asking them to retry This prevents the error loop where every subsequent message fails with the same error until manual intervention. Fixes #296
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import crypto from "node:crypto";
|
||||
import fs from "node:fs";
|
||||
import { lookupContextTokens } from "../../agents/context.js";
|
||||
import { DEFAULT_CONTEXT_TOKENS } from "../../agents/defaults.js";
|
||||
import { runWithModelFallback } from "../../agents/model-fallback.js";
|
||||
@@ -8,6 +9,7 @@ import {
|
||||
} from "../../agents/pi-embedded.js";
|
||||
import {
|
||||
loadSessionStore,
|
||||
resolveSessionTranscriptPath,
|
||||
type SessionEntry,
|
||||
saveSessionStore,
|
||||
} from "../../config/sessions.js";
|
||||
@@ -346,6 +348,37 @@ export async function runReplyAgent(params: {
|
||||
const message = err instanceof Error ? err.message : String(err);
|
||||
const isContextOverflow =
|
||||
/context.*overflow|too large|context window/i.test(message);
|
||||
const isSessionCorruption =
|
||||
/function call turn comes immediately after|INVALID_ARGUMENT.*function/i.test(
|
||||
message,
|
||||
);
|
||||
|
||||
// Auto-recover from Gemini session corruption by resetting the session
|
||||
if (isSessionCorruption && sessionKey && sessionStore && storePath) {
|
||||
const corruptedSessionId = sessionEntry?.sessionId;
|
||||
defaultRuntime.error(
|
||||
`Session history corrupted (Gemini function call ordering). Resetting session: ${sessionKey}`,
|
||||
);
|
||||
|
||||
// Delete transcript file if it exists
|
||||
if (corruptedSessionId) {
|
||||
const transcriptPath = resolveSessionTranscriptPath(corruptedSessionId);
|
||||
try {
|
||||
fs.unlinkSync(transcriptPath);
|
||||
} catch {
|
||||
// Ignore if file doesn't exist
|
||||
}
|
||||
}
|
||||
|
||||
// Remove session entry from store
|
||||
delete sessionStore[sessionKey];
|
||||
await saveSessionStore(storePath, sessionStore);
|
||||
|
||||
return finalizeWithFollowup({
|
||||
text: "⚠️ Session history was corrupted. I've reset the conversation - please try again!",
|
||||
});
|
||||
}
|
||||
|
||||
defaultRuntime.error(`Embedded agent failed before reply: ${message}`);
|
||||
return finalizeWithFollowup({
|
||||
text: isContextOverflow
|
||||
|
||||
Reference in New Issue
Block a user