Skip to content

fix(combos): show embedding/rerank models and disambiguate duplicate names in builder options (#6975, #6957) - #6991

Merged
diegosouzapw merged 1 commit into
release/v3.8.47from
fix/6975-6957-combo-builder-models
Jul 12, 2026
Merged

diegosouzapw merged 1 commit into
release/v3.8.47from
fix/6975-6957-combo-builder-models

Conversation

@diegosouzapw

Copy link
Copy Markdown
Owner

Closes #6975
Closes #6957

Root cause

#6975: addModelOption() in src/lib/combos/builderOptions.ts called isChatCapable(input.supportedEndpoints) and silently dropped any model whose supportedEndpoints didn't include "chat" — a leftover chat-only gate from before combo routing supported embeddings/rerank. The backend already fully supports embedding/rerank combos (dimension-conflict guard, handleComboChat()), so this was purely a listing bug hiding embeddings-only (JinaAI, Gemini auto-imported, OpenRouter custom) and rerank-only models from GET /api/combos/builder/options.

#6957: no literal model.id collision exists anywhere in the merge pipeline (verified against the reporter's real payload — all 64 ids unique). The actual bug is that ComboBuilderModelOption.name is copied straight from the upstream-synced model.name with no cross-entry uniqueness check, and providers like Mistral assign the same canonical name to multiple distinct ids (e.g. codestral-2508, codestral-latest, mistral-code-fim-latest, mistral-code-latest all render as "codestral-2508 · imported"), making distinct models look duplicated and hiding -latest aliases behind their base model's label.

Fix

  • Removed the isChatCapable() gate (and the now-unused function itself, since it had no other callers) from addModelOption().
  • Added a disambiguateCollidingModelNames() pass at the end of buildModelOptions(), run after all 4 merge loops (synced/built-in/custom/fallback) finish populating the map: any name shared by 2+ distinct ids falls back to the model's own id as the display label. Display-only — id/qualifiedModel used for routing are untouched.

Evidence (TDD, Hard Rule #18)

Both fixes were proven with failing-then-passing repro tests reusing the plan-file reproductions:

$ node --import tsx/esm --test tests/unit/repro-6975.test.ts   # BEFORE fix
✖ #6975 embeddings-only custom model must appear in the combo builder output
✖ #6975 rerank-only custom model must appear in the combo builder output
ℹ fail 2

$ node --import tsx/esm --test tests/unit/repro-6957.test.ts   # BEFORE fix
✖ #6957 native Mistral provider with 2 connections: ... ambiguous/colliding display names
ℹ fail 1

# AFTER fix — both files + the whole combo-builder test area:
$ node --import tsx/esm --test tests/unit/repro-6975.test.ts tests/unit/repro-6957.test.ts \
    tests/unit/combo-fingerprint-pin-6696.test.ts tests/unit/combo-builder-model-source-5477.test.ts \
    tests/unit/provider-alias-transitive-5918.test.ts tests/unit/combo-builder-fingerprint-expansion.test.ts \
    tests/unit/combo-builder-options-route.test.ts tests/unit/combo-builder-opencode-prefix.test.ts
ℹ tests 25
ℹ pass 25
ℹ fail 0

tests/unit/combo-builder-options-route.test.ts had a case (text-embedding-hidden) that explicitly encoded the removed chat-only gate as expected behavior — renamed to text-embedding-visible and flipped the assertion to true, since embeddings-only models are now intentionally listed (#6975).

Gates run

  • npm run typecheck:core — clean
  • npx eslint --suppressions-location config/quality/eslint-suppressions.json <changed files> — 0 errors on every touched file (pre-existing warnings only, unrelated to this change)
  • node scripts/check/check-file-size.mjs — no violation on touched files (2 pre-existing base-red violations on unrelated files)
  • node scripts/check/check-complexity.mjs / check-cognitive-complexity.mjs — both OK at baseline (2056 / 890 violations, unchanged)
  • node scripts/check/check-changelog-integrity.mjs — OK

…names in builder options (#6975, #6957)

Removes the leftover chat-only isChatCapable gate from addModelOption() (#6975) and adds a name-disambiguation pass at the end of buildModelOptions() so distinct model ids sharing the same upstream display name fall back to their id (#6957). Both proven with TDD repro tests (RED->GREEN).
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@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 merged commit 9b43a00 into release/v3.8.47 Jul 12, 2026
3 checks passed
@diegosouzapw
diegosouzapw deleted the fix/6975-6957-combo-builder-models branch July 19, 2026 21:01
HouMinXi pushed a commit to HouMinXi/OmniRoute that referenced this pull request Aug 2, 2026
…names in builder options (diegosouzapw#6975, diegosouzapw#6957) (diegosouzapw#6991)

Removes the leftover chat-only isChatCapable gate from addModelOption() (diegosouzapw#6975) and adds a name-disambiguation pass at the end of buildModelOptions() so distinct model ids sharing the same upstream display name fall back to their id (diegosouzapw#6957). Both proven with TDD repro tests (RED->GREEN).
muhamadgalihsaputra pushed a commit to niyatna/NiyatnaRoute that referenced this pull request Sep 27, 2026
…names in builder options (diegosouzapw#6975, diegosouzapw#6957) (diegosouzapw#6991)

Removes the leftover chat-only isChatCapable gate from addModelOption() (diegosouzapw#6975) and adds a name-disambiguation pass at the end of buildModelOptions() so distinct model ids sharing the same upstream display name fall back to their id (diegosouzapw#6957). Both proven with TDD repro tests (RED->GREEN).
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.

1 participant