Skip to content

[Feature] configurable human-readable display names for discovered provider models #2201

Description

@brunoflma

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:

  1. Canonical provider name / provider id — immutable routing key, for example nvidia.
  2. Native model id — the provider wire identifier, for example deepseek-ai/deepseek-v4-flash-0731.
  3. Routed slug — the stable public selector, for example nvidia/deepseek-ai-deepseek-v4-flash-0731.
  4. Configurable model display name — a short human-readable label, for example DeepSeek V4 Flash.
  5. 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.
  6. Optional description or vendor field — useful for tooltips/details, but never used as an identifier.
  7. Display-name source/precedence — explicit operator override, provider metadata, upstream marketing name, then the current slug fallback.
  8. Clear/reset semantics — removing an override must restore the derived name deterministically.
  9. Scope controls — allow a per-provider map for discovered models and a per-model override for exceptions.
  10. 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

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 requestproxyHTTP proxy, routing, reverse-proxy / management auth

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions