Skip to content

Feature: latest-only default model preset per provider (stop exposing 400+ OpenRouter models and every Claude snapshot by default) #2465

Description

@lidge-jun

Area

Catalog / models

What are you trying to accomplish?

A curated "latest/core" default preset per provider, so that adding a high-volume provider exposes only its current flagship models instead of the entire catalog. Adding openrouter today exposes 400+ models to Codex's picker on day one; an Anthropic provider exposes every historical snapshot. The useful set is a handful of current flagships, and "everything" should be one click away — not the default.

What prevents this today?

  • The per-provider allowlist providers.<name>.selectedModels defaults to empty, which means ALL models ship to the catalog (src/types/provider.ts:262-268; PUT /api/selected-models with an empty list deletes the allowlist — src/server/management/model-routes.ts:557-558).
  • Nothing records whether a user ever edited the selection — absence is indistinguishable from "user chose all", so a preset system cannot reconcile upgrades without an explicit marker.
  • The burden is inverted: users must build the allowlist by hand from hundreds of rows.

What should OpenCodex do?

Full design: devlog/_plan/260824_model_ux_aliases_and_defaults/030_default_preset.md. Summary:

  1. Shipped preset registry: src/providers/model-presets.ts, keyed by provider id, values are versioned id-pattern rule lists (/^anthropic\/claude-(opus|sonnet)-[45]/ etc.) so vendor snapshot suffixes do not stale the preset between releases. Curated on the same release train as the provider registry.
  2. Marker object: providers.<name>.modelPreset = { mode: "preset"|"all"|"custom", appliedVersion, appliedAt }. The preset is a seed, not a lock: materialization evaluates rules against the current catalog and stores concrete ids in selectedModels (visibility hot path and older binaries stay byte-compatible).
  3. Divergence detection at the write path: any user edit through PUT /api/selected-models or /api/model-visibility while mode is "preset" flips it to "custom"; the proxy never touches a custom selection again. Auto-re-apply on upgrade happens only for never-diverged providers (version compare); custom providers get a non-blocking "preset updated" hint requiring explicit confirmation.
  4. "Latest" tracking: in preset mode, refresh-time re-materialization is additive — a new model matching the rules (e.g. the next opus snapshot) is added automatically; removals happen only on version bumps.
  5. Application policy: newly added providers with a registry preset default to preset mode (stated plainly in the add flow: "Showing the N current core models — switch to All to see everything"). Existing configured providers are untouched on upgrade (silently narrowing an existing catalog is a behavior break); a one-time dashboard hint nudges opt-in.
  6. Safety: a preset that matches zero models keeps the previous selection and warns — never write an empty allowlist from a preset, because empty means ALL.
  7. Surfaces: GET/PUT /api/model-presets (preview + apply), ocx models preset show|apply <provider> [--all], GUI segmented selector Preset / All / Custom per provider header ("9 of 412 shown — core preset v3").

Example usage or interface

ocx models preset show --provider openrouter
# openrouter: mode=all  available preset v3 (9 models of 412)
ocx models preset apply openrouter
# openrouter: preset v3 applied — selectedModels seeded with 9 core models
ocx models preset apply openrouter --all      # back to everything

GUI: provider header shows 프리셋 / 전체 / 커스텀; editing any toggle in preset mode flips to custom automatically.

Alternatives or workarounds

  • Hand-curating selectedModels per provider via the dashboard "모두 끄기" + re-enabling — hundreds of clicks for openrouter, repeated after every catalog change.
  • Global disabledModels blocklist — unbounded growth against a 400-model catalog and inverted semantics for this use case.

Additional context

Design doc: devlog/_plan/260824_model_ux_aliases_and_defaults/030_default_preset.md. Composes with the new-models-off proposal (preset providers keep a non-empty allowlist, so the new-model policy structurally never fires there) and the aliases proposal (preset-mode catalogs get near-complete built-in alias coverage). All three filed together.

Checks

  • I searched existing issues and documentation.
  • This request describes a concrete OpenCodex workflow rather than merely naming a desired technology.
  • I removed secrets and personal data.

Activity

  1. lidge-jun commented on Aug 24, 2026

    @lidge-jun
    OwnerAuthor

    리뷰 · 우선순위 45 / 80

    설명: 이 이슈는 제공자마다 최신 핵심 모델만 기본으로 보여 주자는 것이다. 오픈라우터를 넣으면 피커에 사백 개가 넘는다. 앤트로픽을 넣으면 예전 스냅샷까지 다 나온다. 쓸모 있는 것은 지금 플래그십 몇 개다. 전부 보기는 한 번에 켤 수 있으면 되고, 기본은 아니어야 한다. 지난 시간 2465 조사는 없는 번호였다. 이번 시간에 열렸다. 지금 CURRENT dev HEAD 는 35a89903c 이다. 이번 시간에 origin/dev 는 그대로다. 새 머지는 없다. package.json 은 2.27.0 이다. src/config.ts 는 3238줄이다. src/runtime 폴더는 지금 HEAD 에 없다.

    하려는 일은 이렇다. 제공자 아이디로 고른 규칙 목록을 실어 보낸다. 스냅샷 접미사가 바뀌어도 규칙이 살아 있게 한다. 제공자에 모드 표시를 남긴다. 프리셋은 잠금이 아니라 씨앗이다. 규칙을 지금 카탈로그에 적용해 구체 아이디를 허용 목록에 넣는다. 예전 바이너리도 그 허용 목록만 보면 된다. 사용자가 허용 목록을 고치면 커스텀이 되고 프록시가 다시 손대지 않는다. 프리셋 모드에서 새로고침은 규칙에 맞는 새 아이디만 더한다. 이미 설정된 제공자는 업그레이드 때 건드리지 않는다. 새로 넣는 제공자만 프리셋이 기본이다. 규칙이 0개를 맞추면 이전 선택을 지키고 경고한다. 빈 허용 목록은 전부라는 뜻이라서, 프리셋이 빈 목록을 쓰면 안 된다.

    지금 HEAD 를 열었다. src/types/provider.ts 262줄 빈 허용 목록은 전부 공개다. src/server/management/model-routes.ts 557줄 빈 저장은 허용 목록을 지워서 다시 전부다. 이슈가 경고한 0개 맞춤 구멍이 맞다. src/providers 폴더에 model-presets.ts 가 없다. src/cli/registry.ts 168줄 ocx models 에 list live add enable disable selected 는 있다. preset 하위 명령은 없다. src/cli/provider.ts 436줄 presets 는 GUI 제공자 프리셋 목록이다. 모델 최신 프리셋이 아니다. 새 명령은 ocx models preset 으로 두고, 기존 ocx provider presets 를 덮어쓰지 말 것. 이슈가 가리키는 설계 문서 폴더는 지금 origin/dev HEAD 에 없다. 본문만 있다.

    2464 새 모델 끄기는 허용 목록이 있는 제공자에서는 일이 없다. 프리셋이 허용 목록을 채우면 그 정책은 구조적으로 쉬게 된다. 같이 설계됐다. 카탈로그 기차에서는 이 프리셋을 앞칸으로 두는 편이 맞다. 2463 별칭은 요청 길이다. 한 기차에 섞지 말 것. 1690 과 초안 2122 는 산 목록에서 빠진 설정을 남기는 길이다. 이번 씨앗과 다르다. 닫지 말 것. 이미 설정된 제공자를 업그레이드 때 조용히 좁히지 말 것. 이슈 본문도 그렇게 적었다. 2459 와 2460 과 2462 와 한 기차에 섞지 말 것. 2210 과 1049 과 2221 을 닫지 말 것.

    사용자 길이로는 피커가 사백 개로 불어 고르기 어려워서 45. 이미 쓰는 제공자의 목록은 그대로다. 새로 넣는 제공자만 기본이 바뀐다. 지금 요청이 502 로 죽지는 않는다. 카탈로그 팁은 Ox Alpha x-preview-f-free + deepseek-v4-flash-vision-exp. Cursor 정적 카탈로그는 opus-4-8-fast / opus-5-fast. 2334 CursorCredentialRouter 는 여전히 src/providers/cursor-pool.ts 모듈+테스트만 있고 어댑터에 연결되지 않았다. 2332 H2 는 discovery 전용. 2320 overflow + 2342 는 이미 dev. 2188 사이드카는 이미 dev. 2361 __omit__ 는 이미 HEAD 다. combo-stream-preflight.ts 는 지금 HEAD 에 있다. src/lib/bounded-body.ts 128줄 취소 없는 던짐과 2426 나가는 크기 가드는 그대로다. 2451 wait 허용 목록은 아직 하이픈이다. 이번 프리셋은 그 구멍들이 아니다.

    src/types/provider.ts 라인 262 - 빈 허용 목록은 전부 공개다
    src/server/management/model-routes.ts 라인 557 - 빈 저장은 허용 목록을 지운다. 0개 맞춤이면 전부가 된다
    src/cli/provider.ts 라인 436 - presets 는 GUI 제공자 프리셋 목록이다. 모델 최신 프리셋이 아니다
    src/cli/registry.ts 라인 168 - ocx models 에 preset 하위 명령은 없다
    src/providers - model-presets.ts 가 지금 HEAD 에 없다
    이슈 1690 / PR 2122 - 남기기 허용 목록이다. 이번 씨앗과 섞지 말 것. 닫지 말 것
    설계 문서 폴더 - 지금 origin/dev HEAD 에 없다. 본문만 명세다

    메인테이너의 판단이 필요한 지점

    • 설계 문서를 같은 기차에 먼저 넣을지. 넣는 편이 맞다
    • 기존 ocx provider presets 이름을 재사용할지. 재사용하지 말 것. GUI 제공자 프리셋과 겹친다
    • 이미 설정된 제공자를 업그레이드 때 좁힐지. 좁히지 말 것. 이슈 본문대로 새 제공자만 기본이다
    • 2464 끄기를 같은 카탈로그 기차의 뒷칸으로 둘지. 두는 편이 맞다
    • 2463 별칭과 한 기차에 섞을지. 섞지 말 것

    너의 추천
    이슈는 열어 둔다. 설계 문서를 origin/dev 에 먼저 넣는다. 0개 맞춤에서 빈 허용 목록을 쓰지 않는 씨앗만 좁게 본다. 명령 이름은 ocx models preset 이다. 1690 과 2122 와 2463 과 2451 은 닫지 않는다. 호출 길을 넓히지 말 것. 라벨은 그대로 둔다. 프리뷰 배포가 아니다.

    이 댓글은 grok-bot이 작성했습니다

  2. lidge-jun commented on Aug 25, 2026

    @lidge-jun
    OwnerAuthor

    Shipped on dev across #2603 (backend) and #2604 (GUI), following the design in 030_default_preset.md.

    MODEL_PRESETS keys providers to versioned id patterns rather than literal lists, so a vendor snapshot suffix does not stale the preset between releases. Materialization stores concrete ids in selectedModels, which keeps the visibility hot path and older binaries working against a plain allowlist — downgrade stays lossless as the design intended.

    Divergence is detected at the write path exactly as specified: any edit through PUT /api/selected-models while in preset mode flips the marker to custom, so upgrade reconciliation is a version compare instead of a three-way merge.

    The edge case that needed the most care is the one your design called out: a preset matching zero models never writes an empty allowlist, because empty means ALL and would silently un-curate the provider it was asked to curate. It keeps the previous selection, falls back to all, and records the fallback so a later convergence retries.

    Surfaces: GET/PUT /api/model-presets, ocx models preset show|apply <provider> [--all], and a Preset / All segmented control on the provider header reusing the existing .models-segmented language. Custom renders as a disabled segment since it is a state that activates on edit, not a mode you pick.

    Verified by rendering the built GUI in a browser across all three states — the first attempt failed on a bad API stub, which is a useful reminder that a component can typecheck and still not render. 256 pass across the preset/catalog/CLI suites, 10 GUI tests, lint and typecheck clean.

    Two things deliberately deferred from your spec: the add-provider flow defaulting new providers to preset mode, and the one-time dashboard nudge for existing providers. Both change onboarding behaviour rather than the preset mechanism, so they are better as their own change than folded in here.

  3. added a commit that references this issue on Aug 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    catalogModel catalog, slugs, visibility, routed entriesenhancementNew feature or request

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions