Skip to content

feat(models): qualify duplicate model names with provider prefix - #4516

Merged
diegosouzapw merged 1 commit into
cheaper-inference:release/v3.8.33from
Rahulsharma0810:fix/model-catalog-name-disambiguation
Jun 21, 2026
Merged

diegosouzapw merged 1 commit into
cheaper-inference:release/v3.8.33from
Rahulsharma0810:fix/model-catalog-name-disambiguation

Conversation

@Rahulsharma0810

@Rahulsharma0810 Rahulsharma0810 commented Jun 21, 2026 •

Copy link
Copy Markdown
Contributor

Problem

When multiple providers serve the same underlying model, the /v1/models catalog emits identical name fields for every entry.

Example — GPT-5.5 today:

{ "id": "gh/gpt-5.5",          "name": "GPT-5.5" }
{ "id": "cx/gpt-5.5",          "name": "GPT-5.5" }
{ "id": "opencode-zen/gpt-5.5", "name": "GPT-5.5" }
{ "id": "newapi.285743/gpt-5.5", "name": "GPT-5.5" }

Clients that render the name field for display — such as the opencode-omniroute-auth plugin (src/plugin.ts: name: model.name || model.id) — show an identical "GPT-5.5" label for every variant. The user sees the same text four times in their model picker with no way to distinguish which provider will handle the request.

This affects every model served by multiple providers: GPT-4o, Claude Sonnet, Gemini Flash, DeepSeek R1, and many more.

Fix

Add disambiguateCatalogModelNames() in src/lib/modelMetadataRegistry.ts. After the enrichment step, it makes a single O(n) pass over the catalog:

  1. Collect all display names and the set of provider prefixes using each name.
  2. For names that appear under 2 or more distinct provider prefixes, rewrite name to prefix/BaseName.
  3. Names that belong to a single provider are untouched — the clean display is preserved for the common case.

Example — GPT-5.5 after this PR:

{ "id": "gh/gpt-5.5",           "name": "gh/GPT-5.5" }
{ "id": "cx/gpt-5.5",           "name": "cx/GPT-5.5" }
{ "id": "opencode-zen/gpt-5.5",  "name": "opencode-zen/GPT-5.5" }
{ "id": "newapi.285743/gpt-5.5", "name": "newapi.285743/GPT-5.5" }

Single-provider models (e.g. DeepSeek Web-specific models only under ds-web/):

{ "id": "ds-web/deepseek-r1", "name": "DeepSeek R1" }   // unchanged

What is unchanged

  • Model IDs, routing, and request parsing are not affected.
  • The id, owned_by, root, and all capability fields are not affected.
  • Default behavior for single-provider models is identical.
  • The change is purely in the cosmetic name field used by display clients.

Why this matters for OpenCode users

The opencode-omniroute-auth plugin (https://github.com/Alph4d0g/opencode-omniroute-auth) renders model names from OmniRoute's catalog name field directly. With 28 providers and 868 total model entries, many models appear under 3–5 different provider prefixes — each showing the same label. There is no way for a user to know which provider they selected from the UI. This PR makes the model picker unambiguous for every affected model.

Files changed

File Change
src/lib/modelMetadataRegistry.ts +51 lines: disambiguateCatalogModelNames() helper
src/app/api/v1/models/catalog.ts 2-line wiring (import + pipe enrichedModels through helper)
tests/unit/model-catalog-name-disambiguation.test.ts 6 new unit tests (pure function, no DB)

Tests

node --import tsx/esm --test tests/unit/model-catalog-name-disambiguation.test.ts
# 6/6 pass (pure function tests, no DB needed)

node --import tsx/esm --test tests/unit/models-catalog-route.test.ts tests/unit/models-catalog-low-noise-flag.test.ts tests/unit/model-catalog-name-disambiguation.test.ts
# 52/52 pass

npm run check:file-size
# PASS — catalog.ts stays at frozen baseline 1478

Related

When multiple providers serve the same model (e.g. gh/gpt-5.5, cx/gpt-5.5,
opencode-zen/gpt-5.5), the /v1/models catalog emits identical name fields
("GPT-5.5") for every entry. Clients that render the name field -- such as
opencode-omniroute-auth plugin (src/plugin.ts: name: model.name || model.id)
-- show the same display name for all variants, giving users no way to know
which provider they selected. This is a known pain point for OpenCode users.

Fix: add disambiguateCatalogModelNames() to modelMetadataRegistry.ts.
After enrichment, it scans the catalog for display-name collisions across
two or more distinct provider prefixes. For each ambiguous name it rewrites
the name to prefix/BaseName (e.g. "gh/GPT-5.5", "cx/GPT-5.5"). Unique names
are untouched -- the clean display is preserved for the common case.

The change is purely cosmetic: only the catalog name field is affected.
Model IDs, routing, and request parsing are unchanged.

Tests: 6 new unit tests for disambiguateCatalogModelNames (pure function,
no DB needed). All 48 existing catalog + low-noise tests pass.
@gemini-code-assist

Copy link
Copy Markdown
Contributor

Warning

You have reached your daily quota limit. Please wait up to 24 hours and I will start processing your requests again!

@diegosouzapw
diegosouzapw changed the base branch from main to release/v3.8.33 June 21, 2026 14:54
@diegosouzapw
diegosouzapw merged commit 296b72d into cheaper-inference:release/v3.8.33 Jun 21, 2026
3 checks passed
@diegosouzapw diegosouzapw mentioned this pull request Jun 22, 2026
Alph4d0g pushed a commit to Rahulsharma0810/opencode-omniroute-auth that referenced this pull request Jun 25, 2026
Adds a new `modelNameDisplay` option to `OmniRouteConfig`:
- `"name"` (default): use the human-readable `name` field from
  `/v1/models`, unchanged from previous behaviour
- `"id"`: use the model `id` as the display name

Multiple OmniRoute providers can serve the same base model under
different IDs — for example `gh/gpt-5.5`, `cx/gpt-5.5`,
`opencode-zen/gpt-5.5`, and `newapi.285743/gpt-5.5` all expose
`name: "GPT-5.5"`.  The picker currently shows them as identical
"GPT-5.5" entries and the user cannot tell which provider they
selected.

Two complementary fixes are possible:

1. **Server-side** (OmniRoute PR #4516): `disambiguateCatalogModelNames()`
   — qualify ambiguous names server-side (e.g. `"gh/GPT-5.5"`)
2. **Client-side** (this PR): `modelNameDisplay: "id"` — always show
   the model ID, which is guaranteed to be unique

The client-side option is useful when:
- the OmniRoute instance is older than v3.8.32 and PR #4516 is not
  deployed yet
- the user prefers seeing provider-prefixed IDs regardless of whether
  disambiguation is enabled on the server
- models.dev enrichment overwrites the server-supplied name with a
  different value

```js
// opencode.js
import OmniRouteAuthPlugin from 'opencode-omniroute-auth';

export default {
  plugins: [OmniRouteAuthPlugin],
  provider: {
    omniroute: {
      options: {
        baseURL: 'http://localhost:20128/v1',
        modelNameDisplay: 'id',   // show gh/gpt-5.5 instead of GPT-5.5
      },
    },
  },
};
```

- `OmniRouteConfig.modelNameDisplay?: "name" | "id"` in `types.ts`
- `getModelNameDisplay()` helper validates and extracts the option
- `toProviderModel()` uses `model.id` as `name` when `modelNameDisplay === "id"`
- All four call sites of `toProviderModels()` pass the option through
- 3 new tests (modelNameDisplay=id, default, invalid)

Related: cheaper-inference/OmniRoute#4516
tkgo11 pushed a commit to tkgo11/OmniRoute that referenced this pull request Sep 23, 2026
…aper-inference#4516)

Disambiguates display names when the same model name appears across distinct provider prefixes. Pure, non-mutating; complementary to id-dedupe.

Integrated into release/v3.8.33.
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.

feat: qualify ambiguous model names with provider prefix in /v1/models

2 participants