Skip to content

fix(api): honor model-hidden overrides across provider key variants (#11300) - #11308

Closed
jonlwheat2-gif wants to merge 2 commits into
diegosouzapw:release/v3.8.50from
jonlwheat2-gif:fix/11300-hidden-models-catalog
Closed

jonlwheat2-gif wants to merge 2 commits into
diegosouzapw:release/v3.8.50from
jonlwheat2-gif:fix/11300-hidden-models-catalog

Conversation

@jonlwheat2-gif

Copy link
Copy Markdown
Contributor

Fixes #11300

Summary

Models toggled Hidden on provider pages kept appearing in GET /v1/models whenever the storage key differed from the key a catalog loop queried. Root cause verified line-by-line at base 527da6565: the write path persists {isHidden:true} under whatever provider key the dashboard route carried — node UUID (openai-compatible-chat-<uuid>), route alias (cc/gh/cx/xao), or canonical id (claude/github/xai) — while every read path used exactly one key.

Before → After (precise)

Site Before (base) After (this branch)
Bulk-map closure, catalog.ts single-key exact lookup, :267-271 delegates to multi-key helper, :275-279, extras [providerIdToAlias[key], providerIdToPrefix[key]]; all 16 call sites unchanged
Codex-native loop, catalog.ts hardcoded "codex" only, :1020-1021 also consults the openai family page, :1030-1031
getModelIsHidden, db/models.ts exact-key reads only, :961-968 equivalence-set walk across both namespaces, :966-981
New: providerKeysToCheck() — models.ts:990-1009: [key, canonical=resolveProviderId(key), getProviderAlias(canonical), …getProviderConnectionFamilyIds(canonical), …extras] — family ids cover xai ↔ xao/xai-oauth, magnific ↔ freepik
New: isModelHiddenInBulkMap() — models.ts:1016-1033: O(1)-per-model bulk check, preserves the #9147 one-query-per-build guarantee
Re-export, localDb.ts — lines 68-69

Loop-key mismatch table being fixed (base line numbers): static loop queried canonical (:958) missing alias/UUID-stored hides; synced loop queried raw connection id (:1082); custom loop canonical (:1501/:1685/:1759); media loops model.provider (:1336-1455). Secondary blast radius closed: per-key public filtering (apiKeys.ts:1541) uses getModelIsHidden.

TDD evidence (hard rule #18)

New suite tests/unit/model-hide-multikey-11300.test.ts:

RED against unfixed base — pass 4 / fail 3:

✖ hide saved under xAI alias xao is honored when querying xai   (family aliases never resolved)
✖ bulk map helper resolves alias/canonical/prefix variants       (catalog seam missing entirely)
✖ providerKeysToCheck dedupes and keeps unknown ids intact       (helper did not exist)

Honest note: two cases passed pre-fix because readCompatList() internally resolves some aliases via open-sse's resolveProviderAlias — but the customModels namespace, connection-family aliases (xao), and the entire catalog bulk map did not. That patchwork is why existing tests (which only cover same-key hides) never caught it.

GREEN post-fix: 7/7.

Regression sweep — issue-named tests + full /v1/models family (synced-model-hide-persist-3782, model-catalog-policy-invalidation-8728, aliases-included, auth-leak-9320, catalog-generation-race, catalog-ttl, concurrent-6408, discovery-conformance): 39 pass / 0 fail; re-run green after rebase onto current tip. Independently reproduced in a detached clean worktree (no caches): same results.

Gates: npm run typecheck:core clean. ⚠️ Inherited: repo-wide lint reports 34 pre-existing errors in files this PR does not touch (present at base; tracked by the base-red cluster #9985).

Scope boundary (matches the reporter's own proposal)

Cross-family bridging with no alias/family/prefix relationship (e.g. bare UUID vs unrelated canonical) would require a reverse node-family index; every combination reachable via canonical resolution, registered aliases, connection-family ids, and node prefixes — i.e., all four cases enumerated in the issue — is covered.

Diff: 4 files changed, +191/−10.

…iegosouzapw#11300)

Visibility overrides are persisted under whatever provider key the dashboard
route carried (node UUID, route alias like cc/gh/xao, or canonical id), but
catalog lookups queried a single exact key, so hidden models kept leaking
into GET /v1/models. Add a shared equivalence-set resolver (key + canonical +
alias + connection-family ids + caller extras such as node prefixes) and wire
it into getModelIsHidden and the catalog's bulk isModelHiddenBulk path; the
codex-native loop now also consults the openai family page.
@diegosouzapw

Copy link
Copy Markdown
Owner

Closing as already covered: #11309 (merged before this PR was opened) fixed the same underlying issue #11300 — a hidden-model override written under a dashboard route key (alias/canonical/node UUID) not being honored by a catalog loop that only checked one key shape. I verified against the pristine release/v3.8.50 tip: tests/unit/hidden-models-leak-v1-models-11300.test.ts (3/3, from #11309) already covers alias↔canonical resolution, xai/xao aliasing, and the codex/openai shared-connection case that this PR's own new test (model-hide-multikey-11300.test.ts) targets. The diagnosis in both PRs is correct and matches; #11309 simply landed the fix first with a slightly different internal shape (resolveCanonicalProviderId + inline key-set walk vs this PR's providerKeysToCheck/isModelHiddenInBulkMap helpers). No behavioral gap remains — I ran this PR's own regression test against the current tip and confirmed the scenarios it probes are handled. Thank you @jonlwheat2-gif for catching and diagnosing #11300 independently — the root-cause analysis here is exactly right, it just arrived after #11309 already shipped the same fix.

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.

Bug: Models toggled to 'Hidden' on Provider pages are still listed in GET /v1/models

2 participants