Repository navigation
[Feature] configurable human-readable display names for discovered provider models #2201
Description
Area
Catalog / models
What are you trying to accomplish?
Make provider/model names readable in the dashboard, model picker, /v1/models, ocx models --json, usage views, and client exports without changing the canonical identifier used for routing.
What prevents this today?
The catalog currently conflates the machine-facing routed slug with the human-facing display name for automatically discovered provider models. In the local v2.28.0 catalog snapshot, NVIDIA NIM is exposed as:
| Field | Current value |
|---|---|
| Provider | nvidia |
| Routed slug | nvidia/deepseek-ai-deepseek-v4-flash-0731 |
| Display name | nvidia/deepseek-ai-deepseek-v4-flash-0731 |
That is technically unambiguous but poor for scanning. The same problem appears in the discovered NVIDIA rows nvidia/moonshotai-kimi-k3, nvidia/nvidia-nemotron-3.5-lightning-30b-a3b, and nvidia/z-ai-glm-5.2: the provider namespace and vendor path are repeated in the visible label.
The code already has a useful precedent: customModels[].displayName is display-only and is carried into the catalog without changing routedSlug(provider, modelId). That field does not provide an operator-facing override for ordinary live-discovery rows, which are the rows producing the unreadable labels.
What should OpenCodex do?
Add explicit, validated display metadata for discovered provider models while keeping identity and routing separate. At minimum, support:
- Canonical provider name / provider id — immutable routing key, for example nvidia.
- Native model id — the provider wire identifier, for example deepseek-ai/deepseek-v4-flash-0731.
- Routed slug — the stable public selector, for example nvidia/deepseek-ai-deepseek-v4-flash-0731.
- Configurable model display name — a short human-readable label, for example DeepSeek V4 Flash.
- Optional provider display name — for example NVIDIA NIM, so the UI can show DeepSeek V4 Flash (NVIDIA NIM) without embedding provider text in the model name.
- Optional description or vendor field — useful for tooltips/details, but never used as an identifier.
- Display-name source/precedence — explicit operator override, provider metadata, upstream marketing name, then the current slug fallback.
- Clear/reset semantics — removing an override must restore the derived name deterministically.
- Scope controls — allow a per-provider map for discovered models and a per-model override for exceptions.
- Migration compatibility — existing customModels[].displayName values and existing slugs must continue to work unchanged.
The override should be usable from config.json, the Management API, and the dashboard. A possible configuration shape is:
{
"providers": {
"nvidia": {
"displayName": "NVIDIA NIM",
"modelDisplayNames": {
"deepseek-ai/deepseek-v4-flash-0731": "DeepSeek V4 Flash",
"moonshotai/kimi-k3": "Kimi K3"
}
}
}
}
The exact field names are open for design; the important contract is that display metadata is separate from the provider id, native model id, routed slug, pricing key, disabled-model key, fallback key, and wire request model.
Example usage or interface
Before:
nvidia/deepseek-ai-deepseek-v4-flash-0731
nvidia/moonshotai-kimi-k3
nvidia/nvidia-nemotron-3.5-lightning-30b-a3b
After applying the overrides above:
DeepSeek V4 Flash (NVIDIA NIM)
Kimi K3 (NVIDIA NIM)
Nemotron 3.5 Lightning 30B (NVIDIA NIM)
The client must still send the original routed slug, and the proxy must still resolve the original provider/model pair. Renaming a display value must not create a second catalog row, alter cost matching, invalidate a saved selection, or change a Claude/Codex alias.
Alternatives or workarounds
Today an operator can create a separate custom model entry with a displayName, but that duplicates a live-discovered model and is not a good solution for a provider catalog that changes over time. Editing generated cache files is also non-persistent and is overwritten by discovery/sync. A client-side label map would need to be repeated independently in every consuming application.
Additional context
Evidence was checked against the v2.28.0 migration stack and the local generated catalog. Relevant implementation precedent:
- src/server/management/model-routes.ts already accepts and validates displayName for custom models.
- src/codex/catalog/provider-fetch.ts already propagates custom display names as display-only metadata.
- src/codex/catalog/effort.ts documents that display names must not affect routing slug, alias collision, provider behavior, or native identity.
- src/codex/catalog/parsing.ts carries CatalogModel.displayName as a display-only field.
This request is therefore an extension of an existing separation contract to ordinary live-discovery rows, not a request to rename wire models. Related catalog issues include #1690 (retain configured models), #1649 (picker ordering), and #1760 (context metadata import), but none of them provides configurable human-readable names for discovered rows.
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
Ingwannu commentedon Aug 20, 2026
This is a valid catalog enhancement, and the important invariant is exactly the one described here: display metadata must never become routing identity.
I would keep the first implementation deliberately below the GUI boundary:
The dashboard editor and wider presentation changes should be a follow-up after that core contract is reviewed. That keeps this from becoming one large catalog/API/GUI rewrite, and it respects the current maintainer preference to review GUI/text changes separately.
So I am leaving this open as a real enhancement, but I would not accept a broad all-surfaces PR as the first cut. A focused core metadata/config PR against
dev, followed by a separately reviewed GUI PR, is the safer path.lidge-jun commentedon Aug 20, 2026
리뷰 · 우선순위 48 / 80
디스플레이 이름이 라우팅 슬러그랑 붙어 있는 거 맞음. 발견 모델은
nvidia/deepseek-ai-deepseek-v4-flash-0731이 라벨로 그대로 나감. 피커/대시보드/usage가 그 문자열을 그대로 보여줌.이미 선례 있음.
customModels[].displayName은 표시만 바꾸고 라우팅은 안 건드림 (src/types/config.ts:190,src/codex/catalog/effort.ts:118-124). 콤보도aggregation.ts:175에서 displayName을 실음. 라이브 디스커버리 줄만 그 필드가 없음.라우팅 키를 바꾸면 사고남.
routedSlug/ native id / provider id는 그대로 두고 라벨만 분리해야 함. 프로바이더 표시명(NVIDIA NIM)이랑 모델 표시명(DeepSeek V4 Flash)을 한 필드에 섞지 말 것.types.ts/config.ts에 필드 추가가 필요함. 스플릿 캠페인 겹치면 이 이슈 기준으로 새로 짜고 리베이스하지 말 것. 2.28 블로커 아님. 닫을 중복 아님.
해결방안: 디스커버리 줄에 display-only 오버라이드를 넣음. 슬러그/id는 불변. GUI/
ocx models --json//v1/models는 라벨만 갈아끼움. 기본값은 지금처럼 슬러그. 빈 문자열/슬래시 거절은 customModels랑 같은 검증을 재사용.이 댓글은 grok-bot이 작성했습니다
feat(catalog): declare modelDisplayNames, and keep custom-model labels
feat(catalog): declare modelDisplayNames, and keep custom-model labels
feat(catalog): declare modelDisplayNames, and keep custom-model labels
zigzag-007 commentedon Aug 26, 2026
I can reproduce the practical impact of this on Windows with OpenCodex 2.31.0 and Codex Desktop.
My provider models are discovered models rather than custom duplicate rows. The dashboard available in my setup did not show an option to assign a display name to an existing discovered model. I therefore used a local display-name mapping and catalog patching workaround. The readable labels later returned to raw namespaced slugs such as
provider/model-idafterocx sync, an OpenCodex update, catalog regeneration, and a Windows or Codex restart. The routes still worked, but a large model picker became difficult to read.A local script that rewrites
opencodex-catalog.jsoncan restore the labels, but it is fragile because the catalog is generated state. Running that script automatically at login also creates startup ordering problems with Codex Desktop and the OpenCodex proxy.The core proposal in this issue would solve the problem cleanly if operator labels for discovered models can be entered through config and the dashboard, stored as user-owned configuration, and reapplied during every catalog rebuild. For the Windows case, it would be useful to add regression coverage for this sequence:
provider/modelrow.ocx syncand rebuild the Codex catalog.Clear and reset behavior, validation, and import and export of this label map would also make Windows reinstall and migration much safer. No startup helper should be required just to preserve labels.
feat(catalog): declare modelDisplayNames, and keep custom-model labels
feat(catalog): declare modelDisplayNames, and keep custom-model labels
fix(catalog): label models at one post-gather boundary, not just conv…
feat(catalog): durable display names for discovered models (#2201, ca…
lidge-jun commentedon Sep 1, 2026
Landed on
devvia #3212 (d975feaa4), carrying @zigzag-007's #2715. Providers now acceptmodelDisplayNames(exact upstream model id → label), edited throughPUT /api/providers/:name/model-display-names(nullresets one id) or the provider config, with precedence operator override → discovery metadata → routed slug. The label reaches the management catalog,/api/providers, and the OpenCode export; routing ids, pricing keys, disabled/selected lists, aliases, and the wire model are untouched. The dashboard editor (#2716) is the separately reviewed follow-up.feat(catalog): durable display names for discovered models (lidge-jun…
feat(catalog): durable display names for discovered models (lidge-jun…