fix(suggest-compact): recognize large-window model families without a [1m] marker (#2468)

* fix(suggest-compact): recognize large-window model families without a [1m] marker

resolveContextWindowTokens() only detected a 1M window via the env
override, the [1m] model-id marker, or observed tokens already above
200k. Large-window models whose ids carry none of these (e.g.
claude-fable-5) were misclassified as 200k windows, overstating
context usage ~5x in the compact suggestion.

Add a known-model-family substring table (claude-fable-5,
claude-mythos-5) checked after the env override and [1m] marker and
before the token-count heuristic. Env overrides still win, and unknown
model ids still fall back to the 200k default.

Closes #2461

* fix(suggest-compact): anchor known-model-family match at a token boundary

Unanchored substring matching would misclassify a hypothetical smaller
tier sharing a known family prefix (e.g. claude-fable-5-mini) as a 1M
window. Require the family id to end at a token boundary: end of id, a
delimiter, or a dated/versioned suffix (-20260115). Alphanumeric
continuations and letter suffixes no longer match.

Addresses CodeRabbit/Greptile review on #2468
This commit is contained in:
Girish Kanjiyani
2026-07-22 12:17:11 -04:00
committed by GitHub
parent e7b3ba07bb
commit cd39df154c
2 changed files with 69 additions and 3 deletions
+39 -3
View File
@@ -28,6 +28,32 @@ const DEFAULT_TRANSCRIPT_TAIL_BYTES = 256 * 1024;
const MAX_TOKEN_SETTING = 10000000;
const LARGE_WINDOW_MODEL_MARKER = '[1m]';
// Known large-window model families whose ids carry no `[1m]` marker (#2461).
// Matched boundary-aware against the model id — covers dated/region-prefixed
// variants (e.g. `us.anthropic.claude-fable-5-20260115-v1:0`) without matching
// hypothetical smaller tiers sharing the prefix (e.g. `claude-fable-5-mini`).
// Checked in order, first match wins. Best-effort and expected to lag new
// releases; the env override remains the escape hatch for unlisted models.
const KNOWN_MODEL_WINDOW_TOKENS = [
['claude-fable-5', LARGE_CONTEXT_WINDOW_TOKENS],
['claude-mythos-5', LARGE_CONTEXT_WINDOW_TOKENS]
];
/**
* True when `model` contains `familyId` ending at a token boundary: end of id,
* a delimiter (`[`, `:`, `.`), or a dated/versioned suffix (`-20260115`).
* Alphanumeric continuations and letter suffixes (`-mini`) are different
* models, possibly with smaller windows, and must not match.
*/
function isKnownModelFamilyMatch(model, familyId) {
const start = model.indexOf(familyId);
if (start === -1) {
return false;
}
const rest = model.slice(start + familyId.length);
return !/^[A-Za-z0-9]/.test(rest) && !/^-[A-Za-z]/.test(rest);
}
/**
* Read the trailing `tailBytes` of a file as UTF-8.
* Returns null when the file is missing or unreadable.
@@ -132,9 +158,10 @@ function readLatestContextTokens(transcriptPath, options = {}) {
/**
* Detect the context window size for a turn.
* 1M when the model id carries the `[1m]` marker, or when the observed token
* count already exceeds the standard 200k window (covers logs that drop the
* suffix); otherwise the standard 200k window.
* 1M when the model id carries the `[1m]` marker, matches a known large-window
* model family, or when the observed token count already exceeds the standard
* 200k window (covers logs that drop the suffix); otherwise the standard 200k
* window.
*/
function resolveContextWindowTokens(tokens, model) {
// Explicit window override wins: 400k models (e.g. Opus 4.x) match neither the
@@ -150,6 +177,15 @@ function resolveContextWindowTokens(tokens, model) {
return LARGE_CONTEXT_WINDOW_TOKENS;
}
// Large-window model families without a [1m] marker fall through the checks
// above and would be misreported against the 200k default (#2461).
if (typeof model === 'string') {
const known = KNOWN_MODEL_WINDOW_TOKENS.find(([familyId]) => isKnownModelFamilyMatch(model, familyId));
if (known) {
return known[1];
}
}
if (Number.isFinite(tokens) && tokens > STANDARD_CONTEXT_WINDOW_TOKENS) {
return LARGE_CONTEXT_WINDOW_TOKENS;
}