Skip to content

🤖 feat: validated make update-models refresh + full catalog in Treat as - #3930

Merged
ibetitsmike merged 12 commits into
mainfrom
mike/fix-3727-models-json-refresh
Aug 23, 2026
Merged

🤖 feat: validated make update-models refresh + full catalog in Treat as#3930
ibetitsmike merged 12 commits into
mainfrom
mike/fix-3727-models-json-refresh

Conversation

@ibetitsmike

@ibetitsmike ibetitsmike commented Aug 23, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds a validated, idempotent make update-models flow that refreshes the vendored LiteLLM model catalog, and expands the custom-model "Treat as" dropdown to offer the full models.json catalog instead of only the ~21 curated KNOWN_MODELS.

Fixes #3727

Background

src/common/utils/tokens/models.json is a pruned vendor copy of LiteLLM's model_prices_and_context_window.json, but scripts/update_models.ts was manual-only and unwired, so the data had gone stale (last real refresh around #1103). Meanwhile the "Treat as" mapping (mappedToModel) is persisted as a plain string and resolved through resolveModelForMetadata -> getModelStats, which can already resolve any catalog entry, so restricting the dropdown to curated models was purely a UI limitation. Per the maintainer suggestion on the issue, the refresh is a make-process flag that fetches, validates pricing, and updates only when needed.

Implementation

Freshness:

  • scripts/update_models.ts is now a thin CLI over pure logic in src/common/utils/tokens/updateModelsData.ts (covered by bun test src): prune to retained fields, drop entries whose present cost fields are not finite non-negative numbers, then validate before writing (>= 500 chat entries as a truncation guard, <= 5% invalid-pricing drops, and every KNOWN_MODELS entry still resolvable via models.json plus models-extra). Validation also bounds shrinkage to 10% below the vendored catalog's chat-model count, curated coverage requires usable token limits (same bar as getModelStats) rather than key presence, and serialization sorts keys so upstream reordering never diffs. It writes only when the serialized content changed, so reruns are no-ops.
  • make update-models runs it; make build UPDATE_MODELS=1 makes the refresh a prerequisite of every catalog-consuming bundle, ordering it under parallel make and forcing those bundles stale (plain make build stays network-free).
  • .github/workflows/update-models.yml runs weekly (plus dispatch) and opens/updates a bot/update-models PR only when the data changed, reusing the auto-cleanup GitHub App token pattern so the bot PR triggers CI; the checkout is pinned to main and the job goes through make update-models.
  • knownModels.test.ts now reuses the same findMissingKnownModels coverage check instead of duplicating the key logic.
  • models.json refreshed in its own commit via the new target (2456 -> 3176 entries). Upstream deleted max_pdf_size_mb wholesale, so the capability test for that field now exercises the exported extraction function with injected metadata instead of a retired Gemini 1.5 fixture.

Treat as:

  • New listModelCatalogIds() (src/common/utils/tokens/modelCatalog.ts) returns canonical provider:model ids for every chat/responses catalog entry that resolves through getModelStats, unioned with the curated ids (~2300 ids on the refreshed data), normalized via normalizeToCanonical and deduped so gateway keys with direct-provider origins collapse into the canonical id whose metadata resolution actually uses. ModelsSection feeds it to the dropdown.
  • SearchableModelSelect caps rendering at 200 rows with a "+N more, keep typing to filter" footer so the popover stays responsive with the full catalog.

Validation

  • make update-models run twice: first refreshes, second prints "already up to date" with a clean tree.
  • Remote dogfood UAT (Coder Agents) on this exact head passed: full catalog + cap footer verified in the UI, non-curated mapping (openai:gpt-4o-mini) saves and inherits 128k context, "None (use own metadata)" clears it, curated Claude mappings still load; make update-models idempotency re-verified in the workspace; no console errors. Search latency measured at 4-31 ms per keystroke.
  • make lint-actions (actionlint + zizmor) clean for the new workflow.

Risks

  • The models.json refresh changes pricing/limits metadata app-wide (costs, context windows, capability gates). Curated models are pinned by models-extra overrides and the coverage validation, and bun test src passes on the refreshed data; the main residual risk is upstream metadata quality for non-curated models, which the pricing sanitization bounds.
  • The scheduled workflow only opens a PR (never pushes to main) and skips gracefully when app secrets are absent.

Generated with xum • Model: anthropic:claude-fable-5 • Thinking: xhigh

Upstream dropped max_pdf_size_mb entirely, so the capability inference test
now exercises the extraction branch with injected metadata.
@ibetitsmike

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector

This comment has been minimized.

@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: e84d314ea1

ℹ️ 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 Makefile
Comment thread .github/workflows/update-models.yml
Comment thread src/common/utils/tokens/updateModelsData.ts Outdated
Comment thread src/common/utils/tokens/modelCatalog.ts Outdated
Comment thread .github/workflows/update-models.yml Outdated
Comment thread src/common/utils/tokens/updateModelsData.ts Outdated
Comment thread src/common/utils/ai/modelCapabilities.test.ts
Comment thread src/common/utils/tokens/updateModelsData.ts Outdated
- validate curated coverage by usable metadata, not key presence
- bound catalog shrink against the vendored baseline
- sort serialized keys to avoid reorder-only churn
- normalize gateway catalog ids so rows match resolved metadata
- order UPDATE_MODELS=1 refresh before catalog-consuming bundles
- pin scheduled workflow checkout to main and route it via make
@ibetitsmike

Copy link
Copy Markdown
Contributor Author

@codex review

Addressed all 8 findings in dda73bb (7 code fixes; the max_pdf_size_mb thread explains why we don't vendor the upstream-deleted values). Please take another look.

@chatgpt-codex-connector

This comment has been minimized.

@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: dda73bb7b9

ℹ️ 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 src/common/utils/tokens/modelCatalog.ts Outdated
Comment thread Makefile
Comment thread .github/workflows/update-models.yml Outdated
…fallback

- capabilities now resolve with getModelStats' shared key preference so
  provider-scoped entries win in both lookups
- models.json is a prerequisite of the main bundle so catalog-only
  refreshes rebuild it
- update-models workflow references only canonical XUM_APP_* secrets
@ibetitsmike

Copy link
Copy Markdown
Contributor Author

@codex review

Addressed all 3 round-2 findings in aa5110e: capabilities share getModelStats' lookup keys, models.json is a prerequisite of the main bundle, and the workflow uses only canonical XUM_APP_* secrets. Please take another look.

@chatgpt-codex-connector

This comment has been minimized.

@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: aa5110ee78

ℹ️ 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 src/common/utils/ai/modelCapabilities.ts
Comment thread src/common/utils/tokens/updateModelsData.ts
- catalog rows must resolve stats from their own entry (resolveRawModelEntry),
  excluding provider-scoped duplicates shadowed by models-extra overrides
- validation compares priced chat-model coverage against the vendored
  baseline so an upstream pricing-field rename cannot zero-price the catalog
@ibetitsmike

Copy link
Copy Markdown
Contributor Author

@codex review

Addressed both round-3 findings in 4e04f5c: catalog rows must round-trip stats resolution to their own entry, and validation guards priced chat-model coverage against the vendored baseline. Please take another look.

@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: 4e04f5cd7f

ℹ️ 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 src/common/utils/tokens/updateModelsData.ts Outdated
Comment thread src/common/utils/tokens/updateModelsData.ts Outdated
- shrinkage measured over usable chat/responses entries (getModelStats bar),
  so token-limit loss and responses-mode loss both register
- input- and output-priced chat coverage compared independently so renaming
  one cost field cannot hide behind the other
@ibetitsmike

Copy link
Copy Markdown
Contributor Author

@codex review

Addressed both round-4 findings in 07dd882: usable chat/responses coverage (getModelStats' usability bar) drives the shrink guard, and input/output pricing coverage are tracked independently. Please take another look.

@chatgpt-codex-connector

This comment has been minimized.

@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: 07dd882b64

ℹ️ 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 src/common/utils/tokens/updateModelsData.ts Outdated
@ibetitsmike

Copy link
Copy Markdown
Contributor Author

@codex review

Addressed the round-5 finding in 673c0d8: priced coverage now spans chat and responses modes. Please take another look.

@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: 673c0d8c8d

ℹ️ 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 src/common/utils/tokens/updateModelsData.ts Outdated
Comment thread src/common/utils/tokens/updateModelsData.ts Outdated
Comment thread src/common/utils/tokens/updateModelsData.ts Outdated

@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 Security Review

Here are some automated security review suggestions for this pull request.

Reviewed commit: 673c0d8c8d

View security finding report

Only the user who started this review can view the report in Codex.

ℹ️ About Codex security reviews in GitHub

This is an experimental Codex feature. Security reviews are triggered when:

  • You comment "@codex security review"
  • A regular code review gets triggered (for example, "@codex review" or when a PR is opened), and you’re opted in so security review runs alongside code review

Once complete, Codex will leave suggestions, or a comment if no findings are found.

Comment thread src/common/utils/tokens/updateModelsData.ts Outdated
- summarizeCatalog tracks usable/input-priced/output-priced coverage per
  mode plus total entries; every baseline mode is compared independently,
  closing pricing/mode-slice regressions the aggregate counters hid
- baselines below a noise floor (20) skip relative checks so tiny modes
  cannot block refreshes forever
- curated coverage reuses generateModelLookupKeys instead of the
  xai/moonshot special case
@ibetitsmike

Copy link
Copy Markdown
Contributor Author

@codex review

Addressed all 3 round-6 findings in 430c0fb: per-mode coverage baselines (usable + per-field pricing, every mode plus total entries), and curated coverage via the shared runtime lookup keys. Please take another look.

Median input/output cost across mappable entries must stay within 100x of
the vendored baseline, so a poisoned upstream cannot keep every field while
scaling rates toward zero.
@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Swish!

Reviewed commit: 430c0fb9ef

ℹ️ 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".

@ibetitsmike

Copy link
Copy Markdown
Contributor Author

@codex review

Addressed the security finding in 70578c3 (median price-magnitude guard vs the vendored baseline). Please review the current head.

@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: 70578c3110

ℹ️ 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 src/common/utils/tokens/updateModelsData.ts Outdated
Comment thread src/common/utils/tokens/updateModelsData.ts Outdated
Comment thread src/common/utils/tokens/updateModelsData.ts
Comment thread src/common/utils/tokens/updateModelsData.ts

@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 Security Review

Here are some automated security review suggestions for this pull request.

Reviewed commit: 70578c3110

View security finding report

Only the user who started this review can view the report in Codex.

ℹ️ About Codex security reviews in GitHub

This is an experimental Codex feature. Security reviews are triggered when:

  • You comment "@codex security review"
  • A regular code review gets triggered (for example, "@codex review" or when a PR is opened), and you’re opted in so security review runs alongside code review

Once complete, Codex will leave suggestions, or a comment if no findings are found.

Comment thread src/common/utils/tokens/updateModelsData.ts Outdated
…ic magnitude baselines

Replaces the bespoke inputPriced/outputPriced counters and cost-only medians
with generic guards over the whole retained-field surface:
- per-mode coverage counts for every retained field (pricing incl. image/cache/
  tiered rates, token limits, capability flags; booleans count only when true)
- positive-sample counts and medians for every numeric field across mappable
  modes, rejecting >100x median shifts including collapses to zero
- per-mode entry counts so whole-mode omissions are caught directly
Catalog-wide counts and medians cannot see a targeted repricing of a single
surviving row. validateModelData now takes the baseline catalog itself
(simplifying callers) and rejects any surviving entry whose positive numeric
field shifts more than 100x or vanishes.
@ibetitsmike

Copy link
Copy Markdown
Contributor Author

@codex review

Addressed all 5 round-7 findings (4 review + 1 security) by generalizing the guards instead of adding more bespoke counters:

  • 382ca0e: per-mode coverage baselines now span every retained field (all cost fields incl. image/cache/tiered rates, token limits, capability flags; booleans count only when true, so mass flips register as removal), and numeric magnitude medians span every numeric field (catching token-limit rescaling and zero-collapsed prices; the zero endpoint is no longer bypassed).
  • 67ccf59: per-entry bounds against the vendored baseline catch targeted single-row shifts (scaling or deletion of a surviving row's positive numeric field beyond 100x fails validation).

Please review the current head 67ccf59.

@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: 67ccf596a1

ℹ️ 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 src/common/utils/tokens/updateModelsData.ts Outdated
Comment thread src/common/utils/tokens/updateModelsData.ts
Comment thread src/common/utils/tokens/updateModelsData.ts Outdated
Comment thread .github/workflows/update-models.yml Outdated

@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 Security Review

Here are some automated security review suggestions for this pull request.

Reviewed commit: 67ccf596a1

View security finding report

Only the user who started this review can view the report in Codex.

ℹ️ About Codex security reviews in GitHub

This is an experimental Codex feature. Security reviews are triggered when:

  • You comment "@codex security review"
  • A regular code review gets triggered (for example, "@codex review" or when a PR is opened), and you’re opted in so security review runs alongside code review

Once complete, Codex will leave suggestions, or a comment if no findings are found.

Comment thread src/common/utils/tokens/updateModelsData.ts Outdated
…tion commits

Raw-key per-entry comparison missed alias shadowing: a poisoned catalog can add
or substitute a higher-precedence lookup key that hijacks runtime resolution
while all counts and medians stay intact. Validation now compares, for every
model id either catalog can serve, the entry each side resolves through
getModelStats' own lookup preference, using runtime parseNum semantics (numeric
strings compare by value, not as collapses) and requiring baseline-true
capability flags to stay true per identity.

Also adds the sanctioned automation attribution footer to the weekly bot
commit/PR and documents the convention in the pull-requests skill.
@ibetitsmike

Copy link
Copy Markdown
Contributor Author

@codex review

Addressed all 5 round-8 findings in c95ee88 by moving per-entry comparison from raw keys to runtime identities: for every model id either catalog can serve, both sides resolve their entry through getModelStats' own lookup preference and the resolved entries are compared. This covers alias-shadow additions and removed-key+alias substitutions with one mechanism, adds per-identity baseline-true capability-flag checks, and uses runtime parseNum semantics so numeric-string representation changes compare by value. The weekly bot commit/PR now carries the automation attribution footer, with the convention documented in the pull-requests skill.

Verified against live upstream: make update-models passes validation with the identity comparison enabled.

Please review the current head c95ee88.

@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 Security Review

Here are some automated security review suggestions for this pull request.

Reviewed commit: c95ee88162

View security finding report

Only the user who started this review can view the report in Codex.

ℹ️ About Codex security reviews in GitHub

This is an experimental Codex feature. Security reviews are triggered when:

  • You comment "@codex security review"
  • A regular code review gets triggered (for example, "@codex review" or when a PR is opened), and you’re opted in so security review runs alongside code review

Once complete, Codex will leave suggestions, or a comment if no findings are found.

Comment thread src/common/utils/tokens/updateModelsData.ts
@ibetitsmike

Copy link
Copy Markdown
Contributor Author

@codex review

Re-requesting: the security review for head c95ee88 arrived, but the code review verdict for this head never landed. No code changes since the last request. The round-9 security finding (mode-flip repricing) was resolved with an explicit maintainer scope decision: the human-reviewed weekly bot PR is the trust boundary against a poisoned upstream; in-repo validation remains a best-effort sanity gate.

Please review the current head c95ee88.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Keep it up!

Reviewed commit: c95ee88162

ℹ️ 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".

@chatgpt-codex-connector

This comment has been minimized.

@ibetitsmike
ibetitsmike added this pull request to the merge queue Aug 23, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Aug 23, 2026
@ibetitsmike
ibetitsmike added this pull request to the merge queue Aug 23, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Aug 23, 2026
@ibetitsmike
ibetitsmike added this pull request to the merge queue Aug 23, 2026
Merged via the queue into main with commit f61d319 Aug 23, 2026
35 of 38 checks passed
@ibetitsmike
ibetitsmike deleted the mike/fix-3727-models-json-refresh branch August 23, 2026 15:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Feature Request: update models.json automatically each release and show all of it in Treat as field for custom model

1 participant