Files
EJClaw/src/session-recovery.ts
2026-05-19 21:52:54 +09:00

90 lines
2.6 KiB
TypeScript

import { getAgentOutputText } from './agent-output.js';
import type { AgentOutput } from './agent-runner.js';
import { isCodexBadRequestText } from './codex-bad-request-signal.js';
const SESSION_RESET_PATTERNS = [
/An image in the conversation exceeds the dimension limit for many-image requests \(2000px\)\./i,
/Start a new session with fewer images\./i,
/No conversation found with session ID/i,
/400[^\n]*thinking/i,
/thinking[^\n]*block[^\n]*(?:invalid|error|signature)/i,
/invalid[^\n]*signature[^\n]*thinking/i,
];
const SESSION_RETRY_PATTERNS = [
/No conversation found with session ID/i,
/400[^\n]*thinking/i,
/thinking[^\n]*block[^\n]*(?:invalid|error|signature)/i,
/invalid[^\n]*signature[^\n]*thinking/i,
];
const CODEX_SESSION_RESET_PATTERNS = [
/Error running remote compact task/i,
/Codex ran out of room in the model's context window/i,
/Start a new thread or clear earlier history before retrying/i,
/prompt_cache_retention/i,
];
function toText(value: string | object | null | undefined): string[] {
if (!value) return [];
if (typeof value === 'string') return [value];
try {
return [JSON.stringify(value)];
} catch {
return [];
}
}
export function shouldResetSessionOnAgentFailure(
output: Pick<AgentOutput, 'result' | 'output' | 'error'>,
): boolean {
const texts = [
...toText(getAgentOutputText(output)),
...toText(output.error),
];
return texts.some((text) =>
SESSION_RESET_PATTERNS.some((pattern) => pattern.test(text)),
);
}
export function shouldRetryFreshSessionOnAgentFailure(
output: Pick<AgentOutput, 'result' | 'output' | 'error'>,
): boolean {
const texts = [
...toText(getAgentOutputText(output)),
...toText(output.error),
];
return texts.some((text) =>
SESSION_RETRY_PATTERNS.some((pattern) => pattern.test(text)),
);
}
export function shouldResetCodexSessionOnAgentFailure(
output: Pick<AgentOutput, 'result' | 'output' | 'error'>,
): boolean {
const texts = [
...toText(getAgentOutputText(output)),
...toText(output.error),
];
return texts.some((text) =>
CODEX_SESSION_RESET_PATTERNS.some((pattern) => pattern.test(text)),
);
}
export function shouldRetryFreshCodexSessionOnAgentFailure(
output: Pick<AgentOutput, 'result' | 'output' | 'error'>,
): boolean {
return shouldResetCodexSessionOnAgentFailure(output);
}
export function isCodexBadRequestSignal(
output: Pick<AgentOutput, 'result' | 'output' | 'error'>,
): boolean {
const texts = [
...toText(getAgentOutputText(output)),
...toText(output.error),
];
return texts.some((text) => isCodexBadRequestText(text));
}