Conversation
…er publishes none A model whose provider publishes no context window was given clodex's invented 200,000 and persisted as if the server had said so. `clodex models --context <model>=1m --save` then could not raise it: the stop was clamped back to the guess, because an absent ceiling fell back to the stored window. Saving a stop now works for these models, and `clodex patch` bakes it in. Three tiers sit behind a window: the curated models.dev cache, the id heuristics, and a flat 200,000 default when nothing matches. Only the third is invention, so only it stops being persisted; `lookupKnownContextWindow` reports it as absent instead. An absent window is no longer treated as a ceiling, while every real one still clamps — a provider-declared window, the account ceiling, the curated tier, the heuristic tier, and a 200,000 an older clodex already stored. Reachable through `providers add` for any OpenAI-compatible server whose model list omits the field, a custom Anthropic endpoint, or an OpenCode Go endpoint added under a non-canonical provider id. The retained `opencode-go` provider is not affected: its template is allowlist-only and every shipped entry declares a window. o1, o3 and o1-mini declared no window and matched no rule, so they were being persisted at the invented default. They now carry their real windows and keep a correct ceiling. Existing installs keep the stored guess until `clodex providers refresh-models <provider>`, which replaces the cache wholesale and lets an already-saved stop take effect. The patch config hash is unchanged for every install except those that have saved a stop above the default on such a model — `buildPatchModelConfig` treats an absent window and an explicit 200,000 identically, and a comment there records that this equality is what keeps upgrades from marking installs stale.
Open
7 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
A model whose provider publishes no context window was given clodex's invented 200,000 and
persisted as if the server had said so. The user could not raise it:
With no
maxContextWindow, the ceiling collapsed onto the guess, soclodex models --context <model>=1m --savesaved an inert preference and silently resolved back to200,000. Measured on a real provider: a model stored at 200,000 against a real 1,048,576 — 848,576
tokens the user could not reach.
What changed
Three tiers sit behind a window: the curated models.dev cache, the id heuristics, and a flat
200,000 when nothing matches. Only the third is invention. A new
lookupKnownContextWindowreportsit as absent rather than inventing a number, and the write sites stop persisting it.
resolveContextWindowandlookupContextWindowkeep their exact signatures and answers, so no readsite changed.
An absent window is no longer treated as a ceiling. Every real one still clamps.
o1,o3ando1-minideclared no window and matched no heuristic rule, so they were persistingat the invented default; they now carry their real windows (200,000 / 200,000 / 128,000) and keep a
correct ceiling from data rather than from invention.
Clamps preserved — measured, not argued
Base vs head through the real
buildDesiredPatchConfig, same fixtures both sides:maxThe only ceiling removed is the flat default standing in for a model nothing declares.
Upgrade safety
The patch config hash does not move for any install that has not already saved a stop above the
default on such a model — verified by computing it at base and head over nine fixtures, with
PATCH_TRANSFORMS_VERSIONpinned so only the model config could move the digest. Seven arebyte-identical; the two that move are exactly the population this fix exists for.
That result rests on
buildPatchModelConfigtreating an absent window and an explicit 200,000identically — both omit
context. A comment now records that, because a future changedistinguishing them would mark every patched install stale.
Existing installs keep their stored guess until
clodex providers refresh-models <provider>, whichreplaces the cache wholesale; an already-saved stop then takes effect with no further action. The
README says so.
Tests
19 mutants, all killed in full-file runs; feature deletion reds 18 tests, and the ones that stay
green are exactly the under-scope guards pinning preserved behaviour. Suite run in normal and
shuffled order (files and tests,
--no-file-parallelism, private Vite cache): 423/423 both, so noorder dependence despite the module-scope memoization in
context-window.tsandcontext-modes.ts.pnpm typecheckclean · 2943 passed, 20 skipped (2963) ·pnpm buildsuccess.Known, and deliberate
unlike the flat default it is a claim about that model, and it stops a user baking a window the
server will reject. Revisit only with an endpoint proven to accept more.
clodex patchstill emits no warning for a model that is in the catalog with no publishedwindow;
unknownWindowsonly fires for a favorite whose model or provider has left the registry.Making it fire needs provenance carried through
PatchModelMeta— filed separately rather thanwidened here.