Skip to content

fix(models): context window controls for metadata-poor providers (#1073) - #1223

Merged
lidge-jun merged 5 commits into
devfrom
codex/260807-context-window-controls
Aug 7, 2026
Merged

fix(models): context window controls for metadata-poor providers (#1073)#1223
lidge-jun merged 5 commits into
devfrom
codex/260807-context-window-controls

Conversation

@lidge-jun

Copy link
Copy Markdown
Owner

Summary

A provider whose /models returns nothing but ids leaves the routed catalog on its conservative 128K fallback. The backend already honors providers.<id>.contextWindow and modelContextWindowsconfiguredContextWindow reads them and the value is materialized when upstream metadata is absent — but GET /api/providers never returned those fields and the PATCH mask never accepted them, so the Models page had nowhere to save. Hand-editing config.json worked; the dashboard did not.

Adopts #1203 by @estelledc — the first three commits are theirs, cherry-picked with authorship intact. The approach was right: expose the existing contract at the management and UI layers without touching catalog derivation, and leave providerContextCaps as the separate ceiling it already is.

Models context window controls

Four corrections, all from independent audit

Only the selected model was saved. The drafts map held edits for every model, but the PATCH was keyed on the current picker selection. A value typed into model A and then abandoned by switching to B vanished with no error and no warning. The PR's own test pinned that as correct behaviour.

"Every model that differs" would have been wrong the other way. The 10s poll can refresh a field while the modal is open; diffing drafts against live state would call an untouched field dirty and revert someone else's change. Two conditions are now required — the user touched it, and the value differs from what the modal opened with. Both apply to the provider default too, which was previously sent unconditionally.

The snapshot holds canonical numbers rather than raw text, so retyping 64000 as 64,000 is not an edit. When nothing survives the comparison, no PATCH is sent and the feedback says so instead of claiming an update.

Number.isInteger(1e100) is true. Both the validator and the form accepted it; it would persist and serialize into the catalog as an enormous number that can make Codex reject the file. Both now require a safe integer. The default is validated only when touched, so a value inherited from a hand-edited config cannot block an unrelated per-model save.

An override for a model that left live discovery was unreachable — present in the drafts map, absent from the picker, impossible to inspect or clear.

Verification

  • bun run typecheck, bun run lint:gui, bun run doctor:gui, bun run privacy:scan — all clean.
  • bun run test — 9761 pass, 8 skip, 0 fail across 607 files.
  • The exact Models GUI cannot define a fallback context window for metadata-poor third-party providers #1073 reproduction is split in two, because a single case setting modelContextWindows keeps passing with the provider-wide fallback deleted — the per-model value is chosen first, so one test cannot defend both branches.
  • Ablations driven red in their real defect shape rather than as artificially strong mutants. The sharpest: keeping the touched guard while comparing against live groups is only visible when a field is edited, reverted, and changed server-side, which the suite now covers explicitly.

Docs

Translated provider docs (ko/ja/ru/zh-cn) described both fields as caps only, which reads as the opposite of the fix for non-English users. Synced with the English source.

Checklist

  • Scope stays focused and avoids unrelated cleanup.
  • Docs or release notes were updated when needed.
  • Security-sensitive changes were reviewed for secrets, auth, and unsafe defaults.

Stacked on #1220. Replaces #1203.

Closes #1073

@coderabbitai

coderabbitai Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

🗂️ Base branches to auto review (2)
  • ^dev$
  • ^preview$

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: f1fec2c2-ddd4-4571-aff7-12d836bfd781

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Deterministic PR hygiene checks passed.

@github-actions github-actions Bot added the bug Something isn't working label Aug 7, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 5b01de549c

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread gui/src/pages/Models.tsx
<span className="muted mono text-label">{t("models.active", { active: activeCount, total: rows.length })}</span>
</button>
<div className="row models-provider-actions">
{!isNative && (

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Hide context controls for canonical OpenAI groups

When a valid custom model is assigned to the openai provider, /api/models combines that non-native row with the native OpenAI rows, causing every(row.native) to classify the group as non-native and render this new button. Any Apply then PATCHes context fields onto canonical openai, but providerManagementConfigError requires that provider to remain equal to its canonical seed and returns 400, so the dashboard exposes a control that can never save. Gate the control on the provider's forward auth mode or identity rather than aggregate row nativeness.

AGENTS.md reference: gui/AGENTS.md:L10-L10

Useful? React with 👍 / 👎.

Comment thread gui/src/pages/Models.tsx

const openContextSettings = (group: ProviderModelGroup<ModelRow>) => {
const modelIds = [...new Set([
...group.rows.map(model => model.id),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Exclude custom-only models from the provider override picker

When a provider has a custom model, this adds that row to the per-model context picker even though catalog assembly deliberately skips applyProviderConfigHints for custom rows. For a custom-only model—or any custom model with its own context window—the PATCH succeeds and persists modelContextWindows[id], but the generated catalog continues using the custom model's separate customModels[].contextWindow, so the UI reports success for an ineffective change. Exclude custom rows that cannot inherit provider hints, or route their edits through the existing custom-model editor.

AGENTS.md reference: gui/AGENTS.md:L10-L10

Useful? React with 👍 / 👎.

@lidge-jun
lidge-jun force-pushed the codex/260807-loopback-listener branch from 03bc98d to 9d95125 Compare August 7, 2026 16:47
@lidge-jun
lidge-jun force-pushed the codex/260807-context-window-controls branch from 5b01de5 to 39962e2 Compare August 7, 2026 16:47
@github-actions github-actions Bot changed the title fix(models): context window controls for metadata-poor providers (#1073) [WRONG BRANCH] fix(models): context window controls for metadata-poor providers (#1073) Aug 7, 2026
@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

✅ READY

  • all PR quality gates passed.

@github-actions
github-actions Bot marked this pull request as draft August 7, 2026 16:47
@github-actions github-actions Bot changed the title [WRONG BRANCH] fix(models): context window controls for metadata-poor providers (#1073) fix(models): context window controls for metadata-poor providers (#1073) Aug 7, 2026
@github-actions
github-actions Bot marked this pull request as ready for review August 7, 2026 16:50
@lidge-jun
lidge-jun force-pushed the codex/260807-context-window-controls branch from 39962e2 to 67790a5 Compare August 7, 2026 16:53

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 39962e2049

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread gui/src/pages/Models.tsx
<span className="muted mono text-label">{t("models.active", { active: activeCount, total: rows.length })}</span>
</button>
<div className="row models-provider-actions">
{!isNative && (

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Hide context settings for synthetic combo groups

When the catalog includes combo aliases and there is no real provider named combo, those rows are grouped under the synthetic combo provider, but PATCH /api/providers?name=combo returns 404 because the management route requires hasOwnProvider(config.providers, name). Showing this new button for every non-native group therefore exposes a dialog whose Apply can never save for normal combo groups; gate it on a configured provider summary rather than !isNative alone.

AGENTS.md reference: gui/AGENTS.md:L10-L10

Useful? React with 👍 / 👎.

estelledc and others added 5 commits August 8, 2026 02:09
…reverting concurrent changes

Adopts #1203 by @estelledc — the first three commits are theirs, cherry-picked
with authorship intact. The approach was right: expose the existing
`providers.<id>.contextWindow` / `modelContextWindows` contract at the
management and UI layers without touching catalog derivation, which already
materializes those values when upstream metadata is absent.

Four corrections, all found by independent audit.

**Only the selected model was saved.** The drafts map held edits for every
model but the PATCH was keyed on `contextModelId`, so a value typed into
model A and then abandoned by switching to B vanished — no error, no warning.
The PR's own test pinned that as correct. It now sends every model the user
typed into.

**But "every model that differs" would have been wrong the other way.** The
10s poll can refresh a field while the modal is open; diffing drafts against
live state would then call an untouched field dirty and revert someone else's
change. Two conditions are required: the user touched it, AND the value
differs from what the modal opened with. Both apply to the provider default
too, which was previously sent unconditionally and would stamp a stale number
over a concurrent update.

The snapshot holds canonical numbers, not the raw text. Retyping 64000 as
"64,000" is not an edit, and treating it as one would resurrect the same
stale-write. When nothing survives the comparison, no PATCH is sent at all
and the feedback says so rather than claiming an update.

**`Number.isInteger(1e100)` is true.** Both the management validator and the
form accepted it; it would persist and serialize into the catalog as an
enormous number that can make Codex reject the file. Both now require a safe
integer. The default is only validated when touched, so a value inherited
from a hand-edited config cannot block an unrelated per-model save.

**An override for a model that left live discovery was unreachable.** It sat
in the drafts map, absent from the picker, impossible to inspect or clear.

Tests: the exact #1073 reproduction is split in two, because a single case
setting `modelContextWindows` keeps passing with the provider-wide fallback
deleted. Ablations were driven red in their real defect shape rather than as
artificially strong mutants — notably, comparing against live `groups` while
keeping the touched guard is only visible when a field is edited, reverted,
and changed server-side, which the suite now covers.

Translated provider docs (ko/ja/ru/zh-cn) described both fields as caps only,
which reads as the opposite of the fix for non-English users.

Co-authored-by: zhouxun <zhouxun.13@bytedance.com>
Closes #1073
react-doctor's prefer-module-scope-pure-function, and it is right: the
function closes over nothing, so rebuilding it on every render is wasted
work. The prepush doctor gate rejected the push over it.
@lidge-jun
lidge-jun force-pushed the codex/260807-context-window-controls branch from 67790a5 to b07a582 Compare August 7, 2026 17:15
@lidge-jun
lidge-jun force-pushed the codex/260807-loopback-listener branch from 0d7e0ca to 912cb99 Compare August 7, 2026 17:15
@lidge-jun
lidge-jun changed the base branch from codex/260807-loopback-listener to dev August 7, 2026 17:59
@lidge-jun
lidge-jun merged commit 5609faf into dev Aug 7, 2026
28 of 46 checks passed
@lidge-jun
lidge-jun deleted the codex/260807-context-window-controls branch August 8, 2026 00:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants