Repository navigation
[Feature]: config-level retainModels allow-list so operators keep configured models in the authoritative live catalog #1690
Description
Problem to solve
When a provider does live model discovery, the authoritative catalog drops configured models that the upstream does not (yet) return — even when the operator explicitly configured them and the wire mapping exists in code. Concretely:
google-antigravity(Cloud Code Assist) does not returngemini-3.7-flashfrom:fetchAvailableModelsfor accounts where the model is not yet provisioned, so the picker loses the model even though the operator configured it (see [Bug]: v2.15.1 drops gemini-3.7-flash from Antigravity live discovery on macOS #1683 for the user-facing symptom).- Today the only retention paths are: the hardcoded
CALLABLE_CONFIGURED_COMPATIBILITY_MODELSallow-list (kimi, xai), combo targets, and the Vertex default seed. There is no operator-facing, config-level way to say "keep this configured model in the catalog even if discovery omits it."
Operators who run proxies for their own account know their provider's roadmap (e.g. "gemini-3.7-flash is coming to my region; keep the row so it appears the moment the upstream enables it") and should not need a code change per model.
Proposed solution
-
Add a config-level retention list per provider:
providers.<name>.retainModels: string[].{ "providers": { "google-antigravity": { "retainModels": ["gemini-3.7-flash"], "modelCosts": { "gemini-3.7-flash": { "input": 0.75, "output": 3.75, "cacheRead": 0.15, "cacheWrite": 0 } } } } } -
In
mergeConfiguredModelsIntoLiveCatalog(src/codex/catalog/provider-fetch.ts), extend the retention condition:if ( seedVertexDefault === true || shouldRetainConfiguredProviderModel(name, candidate.id) + || (retainConfiguredModelIds?.has(candidate.id) === true) + || (providerRetainModels?.has(candidate.id) === true) || (retainComboTargets && retainConfiguredModelIds?.has(candidate.id) === true) ) { out.push(candidate); present.add(candidate.id); continue; }
-
When a retained model is invoked but the upstream returns 404/not-found, surface a clear diagnostic (log +
warnDroppedConfiguredIdsOnce-style one-shot warning) so a model that "exists in the picker but is not callable yet" is not silently hidden — the operator sees exactly why. -
Seed
CALLABLE_CONFIGURED_COMPATIBILITY_MODELSwithgoogle-antigravity: ["gemini-3.7-flash"]as the first entry, so the picker row exists out-of-the-box for antigravity users while the upstream catches up (mirrors the existing kimi/xai pattern).
Alternatives considered
- Keep the hardcoded allow-list only: works but requires a code change + release per model/per provider; does not scale to operator-specific account states.
- Make discovery "never drop configured models": would resurrect stale/broken models for everyone (the reason the authoritative catalog exists); the retention must be explicit and opt-in.
- Document "wait for upstream": not actionable for operators who know their model is coming; the row should exist with a clear "not callable yet" state.
Additional context
- Related open issue: [Bug]: v2.15.1 drops gemini-3.7-flash from Antigravity live discovery on macOS #1683 (gemini-3.7-flash dropped from Antigravity live discovery).
- Precedent for static + live coexistence: other gateways keep a static model list alongside live discovery (e.g. OmniRoute
QODER_STATIC_MODELS+ live--list-modelsfallback inopen-sse/services/qoderCli.ts). - The existing
warnDroppedConfiguredIdsOnceinfrastructure already logs dropped configured ids once per signature — the retention path should reuse it for the inverse case (retained-but-404) so logs stay quiet in steady state.
Acceptance criteria:
retainModelsentry absent from discovery → row present in catalog (visibilitylist).- Invoking a retained-but-unavailable model → 4xx from upstream is surfaced with a one-shot diagnostic log; the catalog row stays.
- Without
retainModels→ current behavior unchanged (no behavior change for existing users).
Activity
coderabbitai commentedon Aug 14, 2026
🔗 Related PRs
#354 - fix(models): surface discovery failure status when /v1/models returns 401 (
#329) [open]#652 - feat(providers): add bounded model discovery contract [merged]
#963 - fix(catalog): preserve provider capabilities on custom models [open]
#1331 - fix(catalog): keep failover combos when live discovery omits members [merged]
#1658 - fix(antigravity): discover live tiered models from CCA [merged]
📝 Issue Planner
Check the box below or use the
@coderabbitai plancommand to generate an implementation plan and prompts that you can use with your favorite coding assistant.🧪 Issue enrichment is currently in open beta.
To disable automatic issue enrichment, add the following to your
.coderabbit.yaml:💬 Have feedback or questions? Drop into our discord!
lidge-jun commentedon Aug 19, 2026
리뷰 · 우선순위 42 / 80
라이브 디스커버리가 아직 안 돌려주는 설정 모델을 운영자가 카탈로그에 남겨 두고 싶다는 요청입니다. google-antigravity의 gemini-3.7-flash처럼 계정에 아직 프로비저닝되지 않은 모델이 피커에서 사라지는 증상(#1683)이 배경입니다. 모든 설정 모델을 무조건 남기면 깨진 줄이 다시 살아나서, 명시적 허용 목록이 필요합니다.
현재 dev의 src/codex/catalog/provider-fetch.ts를 보면 CALLABLE_CONFIGURED_COMPATIBILITY_MODELS는 kimi와 xai만 들고 있습니다. shouldRetainConfiguredProviderModel()도 그 하드코드와 opencode-free 규칙만 봅니다. mergeConfiguredModelsIntoLiveCatalog()는 Vertex 시드, 위 함수, 콤보 타깃만 남기고 나머지는 droppedConfiguredIds로 보냅니다. providers.*.retainModels 필드는 이 조건에 없습니다.
이슈가 제안한 설정 형태는 운영자 허용 목록을 코드 변경 없이 넣는 것입니다. 유지된 모델을 호출했는데 업스트림이 404면, 피커에서 지우지 말고 warnDroppedConfiguredIdsOnce 같은 한 번만 찍는 진단이 필요합니다. 설정이 없으면 지금 동작을 바꾸면 안 됩니다.
해결방안: mergeConfiguredModelsIntoLiveCatalog 유지 조건에 설정 retainModels를 더하고, 404는 한 줄 진단으로 남기면 됩니다. antigravity 시드를 하드코드에 넣는 일은 제품 판단이지만, 설정 경로가 있으면 모델마다 릴리스할 필요는 없습니다. 디스커버리에서 무조건 설정 모델을 남기는 패치는 이 이슈와 맞지 않습니다.
이 댓글은 grok-bot이 작성했습니다
lidge-jun commentedon Aug 19, 2026
리뷰 · 우선순위 42 / 80 · 유지
라이브 디스커버리가 모델을 안 주면 피커에서 빠짐. 지금 남는 길은 하드코딩
CALLABLE_CONFIGURED_COMPATIBILITY_MODELS(kimi/xai), 콤보 타겟, Vertex 시드뿐임. 설정으로retainModels주고 남겨 달라는 요청. 증상은 #1683.유지함. 전부 남기면 죽은 모델이 다시 살아나서, opt-in만. 호출 404는 한 번만 경고하고 행은 유지.
해결방안:
providers.<name>.retainModels+mergeConfiguredModelsIntoLiveCatalog조건 추가. 기본 동작은 그대로.이 댓글은 grok-bot이 작성했습니다
fix(review): retained-model 404 diagnostic, cursor retention, whitesp…
feat(catalog): config-level retainModels allowlist for authoritative …
fix(review): retained-model 404 diagnostic, cursor retention, whitesp…
feat(catalog): config-level retainModels allowlist for authoritative …
fix(review): retained-model 404 diagnostic, cursor retention, whitesp…
fix(catalog): clear retained model diagnostic memos across generation…
fix(catalog): preserve retained diagnostics across multi-pass gathers…
fix(catalog): preserve retained diagnostics across multi-pass gathers…
feat(catalog): config-level retainModels allowlist for authoritative …
fix(review): retained-model 404 diagnostic, cursor retention, whitesp…
68 remaining items
fix(catalog): initialize cache generation before observed callback an…
fix(catalog): address review feedback on retainModels state preservat…
docs(types): align retainModels JSDoc with independent seeding contra…
feat(catalog): honor per-provider retainModels opt-in (closes lidge-j…
fix(catalog): recognize YYMMDD/MMDD/YYMM dated model id suffixes (lid…
fix(catalog): recognize YYMMDD/MMDD/YYMM dated model id suffixes (#3024)
test(catalog): guard the dated fold's direction at the merge loop, no…
fix(catalog): widen the dated-variant fold and guard its direction at…
feat(catalog): per-provider retainModels opt-in (#1690, carries #2860) (
lidge-jun commentedon Sep 1, 2026
Landed on
devvia #3206 (squash6a6efa928), carrying #2860's retention predicate and #2122's config/migration design.What shipped:
providers.<name>.retainModels: string[]keeps listed ids in the routed catalog when live discovery omits them. Ids do not need to be repeated inmodels; they get the same context/effort hints and surviveliveModels: false.null/empty clears); echoed in the provider DTO.ocx provider edit <name> --retain-models <id,id|->.Not included (deliberately): seeding
gemini-3.7-flashas an antigravity product default (with the config key available this no longer needs a release), a dashboard field (the PATCH contract is ready for one), and a 404-time warning.selectedModelsstill narrows what is visible, so an id must be in both lists when an allowlist is active.fix(catalog): widen the dated-variant fold and guard its direction at…
feat(catalog): per-provider retainModels opt-in (lidge-jun#1690, carr…
fix(catalog): widen the dated-variant fold and guard its direction at…
feat(catalog): per-provider retainModels opt-in (lidge-jun#1690, carr…