fix: avoid context-window-too-small misclassification (#1266, thanks @humanwritten)
Co-authored-by: humanwritten <humanwritten@users.noreply.github.com>
This commit is contained in:
@@ -13,6 +13,7 @@ Docs: https://docs.clawd.bot
|
|||||||
- TUI: keep thinking blocks ordered before content during streaming and isolate per-run assembly. (#1202) — thanks @aaronveklabs.
|
- TUI: keep thinking blocks ordered before content during streaming and isolate per-run assembly. (#1202) — thanks @aaronveklabs.
|
||||||
- CLI: avoid duplicating --profile/--dev flags when formatting commands.
|
- CLI: avoid duplicating --profile/--dev flags when formatting commands.
|
||||||
- Auth: dedupe codex-cli profiles when tokens match custom openai-codex entries. (#1264) — thanks @odrobnik.
|
- Auth: dedupe codex-cli profiles when tokens match custom openai-codex entries. (#1264) — thanks @odrobnik.
|
||||||
|
- Agents: avoid misclassifying context-window-too-small errors as context overflow. (#1266) — thanks @humanwritten.
|
||||||
|
|
||||||
## 2026.1.19-3
|
## 2026.1.19-3
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,34 @@
|
|||||||
|
import { describe, expect, it } from "vitest";
|
||||||
|
import { isLikelyContextOverflowError } from "./pi-embedded-helpers.js";
|
||||||
|
import { DEFAULT_AGENTS_FILENAME } from "./workspace.js";
|
||||||
|
|
||||||
|
const _makeFile = (overrides: Partial<WorkspaceBootstrapFile>): WorkspaceBootstrapFile => ({
|
||||||
|
name: DEFAULT_AGENTS_FILENAME,
|
||||||
|
path: "/tmp/AGENTS.md",
|
||||||
|
content: "",
|
||||||
|
missing: false,
|
||||||
|
...overrides,
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("isLikelyContextOverflowError", () => {
|
||||||
|
it("matches context overflow hints", () => {
|
||||||
|
const samples = [
|
||||||
|
"Model context window is 128k tokens, you requested 256k tokens",
|
||||||
|
"Context window exceeded: requested 12000 tokens",
|
||||||
|
"Prompt too large for this model",
|
||||||
|
];
|
||||||
|
for (const sample of samples) {
|
||||||
|
expect(isLikelyContextOverflowError(sample)).toBe(true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it("excludes context window too small errors", () => {
|
||||||
|
const samples = [
|
||||||
|
"Model context window too small (minimum is 128k tokens)",
|
||||||
|
"Context window too small: minimum is 1000 tokens",
|
||||||
|
];
|
||||||
|
for (const sample of samples) {
|
||||||
|
expect(isLikelyContextOverflowError(sample)).toBe(false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -19,6 +19,7 @@ export {
|
|||||||
isCloudCodeAssistFormatError,
|
isCloudCodeAssistFormatError,
|
||||||
isCompactionFailureError,
|
isCompactionFailureError,
|
||||||
isContextOverflowError,
|
isContextOverflowError,
|
||||||
|
isLikelyContextOverflowError,
|
||||||
isFailoverAssistantError,
|
isFailoverAssistantError,
|
||||||
isFailoverErrorMessage,
|
isFailoverErrorMessage,
|
||||||
isImageDimensionErrorMessage,
|
isImageDimensionErrorMessage,
|
||||||
|
|||||||
@@ -18,6 +18,17 @@ export function isContextOverflowError(errorMessage?: string): boolean {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const CONTEXT_WINDOW_TOO_SMALL_RE = /context window.*(too small|minimum is)/i;
|
||||||
|
const CONTEXT_OVERFLOW_HINT_RE =
|
||||||
|
/context.*overflow|context window.*(too (?:large|long)|exceed|over|limit|max(?:imum)?|requested|sent|tokens)|(?:prompt|request|input).*(too (?:large|long)|exceed|over|limit|max(?:imum)?)/i;
|
||||||
|
|
||||||
|
export function isLikelyContextOverflowError(errorMessage?: string): boolean {
|
||||||
|
if (!errorMessage) return false;
|
||||||
|
if (CONTEXT_WINDOW_TOO_SMALL_RE.test(errorMessage)) return false;
|
||||||
|
if (isContextOverflowError(errorMessage)) return true;
|
||||||
|
return CONTEXT_OVERFLOW_HINT_RE.test(errorMessage);
|
||||||
|
}
|
||||||
|
|
||||||
export function isCompactionFailureError(errorMessage?: string): boolean {
|
export function isCompactionFailureError(errorMessage?: string): boolean {
|
||||||
if (!errorMessage) return false;
|
if (!errorMessage) return false;
|
||||||
if (!isContextOverflowError(errorMessage)) return false;
|
if (!isContextOverflowError(errorMessage)) return false;
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import { runEmbeddedPiAgent } from "../../agents/pi-embedded.js";
|
|||||||
import {
|
import {
|
||||||
isCompactionFailureError,
|
isCompactionFailureError,
|
||||||
isContextOverflowError,
|
isContextOverflowError,
|
||||||
|
isLikelyContextOverflowError,
|
||||||
sanitizeUserFacingText,
|
sanitizeUserFacingText,
|
||||||
} from "../../agents/pi-embedded-helpers.js";
|
} from "../../agents/pi-embedded-helpers.js";
|
||||||
import {
|
import {
|
||||||
@@ -419,10 +420,7 @@ export async function runAgentTurnWithFallback(params: {
|
|||||||
break;
|
break;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
const message = err instanceof Error ? err.message : String(err);
|
const message = err instanceof Error ? err.message : String(err);
|
||||||
const isContextOverflow =
|
const isContextOverflow = isLikelyContextOverflowError(message);
|
||||||
isContextOverflowError(message) ||
|
|
||||||
(/context.*overflow|too large|context window/i.test(message) &&
|
|
||||||
!/too small|minimum is/i.test(message));
|
|
||||||
const isCompactionFailure = isCompactionFailureError(message);
|
const isCompactionFailure = isCompactionFailureError(message);
|
||||||
const isSessionCorruption = /function call turn comes immediately after/i.test(message);
|
const isSessionCorruption = /function call turn comes immediately after/i.test(message);
|
||||||
const isRoleOrderingError = /incorrect role information|roles must alternate/i.test(message);
|
const isRoleOrderingError = /incorrect role information|roles must alternate/i.test(message);
|
||||||
|
|||||||
Reference in New Issue
Block a user