/** * Normalize Openference context-overflow errors so Pi auto-compacts. * Never rewrite 429 / rate-limit / overloaded — those stay on Retry-After. */ import { OPENFERENCE_PROVIDER } from "./constants.ts"; export interface OverflowProbeMessage { role?: string; stopReason?: string; errorMessage?: string; provider?: string; } /** Phrases that indicate context overflow (not rate limits). */ export const OVERFLOW_PATTERN = /context_length_exceeded|maximum context length|context window|input (?:token )?limit|prompt (?:is )?too long|input length too long|model_context_window_exceeded|上下文过长|输入内容过长/i; /** Must NOT be treated as overflow (Pi should retry / back off). */ export const RATE_LIMIT_PATTERN = /rate[_ ]?limit|too many requests|\b429\b|retry.after|overloaded|capacity|throttl/i; /** * Returns a rewritten errorMessage starting with context_length_exceeded, * or null when the message should be left alone. */ export function rewriteOverflowError( message: OverflowProbeMessage, providerFromModel?: string, ): string | null { if (message.role !== "assistant") return null; if (message.stopReason !== "error") return null; if ( message.provider !== OPENFERENCE_PROVIDER && providerFromModel !== OPENFERENCE_PROVIDER ) { return null; } const errorMessage = message.errorMessage ?? ""; if (!errorMessage) return null; if (errorMessage.startsWith("context_length_exceeded")) return null; if (RATE_LIMIT_PATTERN.test(errorMessage)) return null; if (!OVERFLOW_PATTERN.test(errorMessage)) return null; return `context_length_exceeded: ${errorMessage}`; }