Skip to content

fix(providers): make upstream model sync opt-in and preserve manual overrides - #10603

Merged
diegosouzapw merged 4 commits into
cheaper-inference:release/v3.8.50from
InkshadeWoods:release/v3.8.50
Aug 18, 2026
Merged

diegosouzapw merged 4 commits into
cheaper-inference:release/v3.8.50from
InkshadeWoods:release/v3.8.50

Conversation

@InkshadeWoods

Copy link
Copy Markdown
Contributor

Summary

  • Add an “Auto-fetch upstream models” control to provider detail pages and keep it disabled by default.
  • Prevent automatic upstream model synchronization unless the provider explicitly enables it.
  • Preserve same-ID manual models as user-configurable overrides of synced upstream models, including capabilities such as vision support and API format.
  • Add an action to restore a model’s upstream defaults, plus English source strings and regression coverage.

Related Issues

  • Closes #
  • Related to #

Validation

Choose the change type and focused loop from the
Contribution Golden Path. The full unit suite,
Vitest, the 60% coverage gate, and the production build all run in CI on this PR (#8329):

  • Change type: provider / UI / i18n
  • Focused tests and category gates from the golden path
    • node --import tsx/esm --test tests/unit/managed-model-import.test.ts — 9 passed
    • node --import tsx/esm --test --test-name-pattern "keeps upstream discovery off until autoFetchModels is explicitly enabled" tests/unit/provider-models-route.test.ts — 1 passed
    • Focused Vitest provider UI/hook tests — 14 passed
    • Focused ESLint for changed test files — passed
  • npm run lint — the full command reports pre-existing unrelated lint errors in the current release base; the changed test files pass focused ESLint.
  • Reconciled with the current active release base; focused checks rerun afterward
  • Production-code changes include a new or updated automated test in this PR
  • SonarQube is temporarily opt-in while the private project has no quota; it is not a PR gate.

Tests Added Or Updated

  • tests/unit/managed-model-import.test.ts
  • tests/unit/provider-models-route.test.ts
  • tests/unit/ui/use-provider-models-auto-fetch.test.tsx
  • src/app/(dashboard)/dashboard/providers/[id]/__tests__/useModelImportHandlers.test.tsx
  • src/app/(dashboard)/dashboard/providers/[id]/__tests__/providerModelsSectionVisibilityKey.test.tsx

Coverage Notes

  • The provider-model route test covers the default-off behavior.
  • The managed-model import test covers same-ID manual model metadata preservation.
  • The UI/hook tests cover the detail-page toggle and ensure synchronization occurs only when autoFetchModels === true.

Reviewer Notes

  • No migration or Docker/build workflow change is included.
  • Existing providers and custom providers both default to disabled automatic upstream model fetching.
  • Users can enable the behavior from the provider detail UI and can restore an overridden model to upstream defaults when needed.

@diegosouzapw

Copy link
Copy Markdown
Collaborator

This is a nice, well-scoped feature — the default-off opt-in for upstream auto-fetch plus the same-id manual-override/reset flow is exactly the right design, and your own new tests (24) all pass for me locally.

However the CI run shows the default flip breaks two pre-existing tests that assumed auto-fetch reached the network by default:

  • tests/unit/provider-models-route-lan-guard.test.ts (the SSRF-guard test for LAN model-list fetches) now short-circuits before reaching the guarded fetch, because its connection fixtures don't set autoFetchModels: true.
  • tests/unit/openrouter-embeddings-catalog-6976.test.ts (live-vs-curated dedup) has the same issue.

Could you add autoFetchModels: true to those fixtures' providerSpecificData so they keep exercising the paths they were written to test?

Also, the 11 new i18n keys (providers.autoFetchModels*, overridesUpstreamModel*, resetToUpstreamDefaults*) only made it into en.json and zh-CN.json — the i18n-completeness CI gate is failing for the other locales, so a sync pass is needed there too.

Separately, I saw a 'Kimi Coding' model-list assertion fail in CI — that looks like it's from catalog data drift unrelated to your diff (the current release/v3.8.50 tip's test still expects the same fixture your CI run expected), so a rebase should clear it up; flagging just in case.

InkshadeWoods and others added 4 commits August 17, 2026 22:35
…sync i18n keys

The upstream model auto-fetch opt-in default flip made 3 pre-existing tests
short-circuit before reaching the paths they exercise, because their
connection fixtures never set providerSpecificData.autoFetchModels: true:

- tests/unit/provider-models-route-lan-guard.test.ts (cheaper-inference#6939 SSRF-guard tests)
- tests/unit/openrouter-embeddings-catalog-6976.test.ts (live discovery merge/dedup)
- tests/unit/provider-models-route.test.ts (Kimi Coding auth-header test —
  this was mislabeled as base/catalog drift during review, but is the same
  root cause: without autoFetchModels the mocked fetch is never reached and
  the route falls back to local catalog data instead)

Also syncs the 11 new providers.autoFetchModels*/overridesUpstreamModel*/
resetToUpstreamDefaults* i18n keys from en.json/zh-CN.json to the remaining
40 locale files via a narrowly-scoped ad-hoc translation script (only these
11 keys — leaves each locale's pre-existing, unrelated missing-key backlog
untouched).

Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
…el sync

Rebase surfaced that the 'Kimi Coding' CI failure flagged as possible base
drift during review was actually the same root cause as the lan-guard and
openrouter-embeddings fixes: 29 pre-existing tests in
tests/unit/provider-models-route.test.ts (of 59 total) short-circuit under
the new autoFetchModels opt-in default because their connection fixtures
never set providerSpecificData.autoFetchModels: true, so they never reach
the live-fetch/validation paths they were written to exercise (fetch mocks
never called, base-URL validation never reached, live models never merged).

Adds providerSpecificData.autoFetchModels: true to each affected fixture.
No production code or test assertions changed — same TEST-fixture-only
pattern as the lan-guard and openrouter-embeddings fixes. All 59 tests in
the file now pass (was 30/59).

Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
@diegosouzapw
diegosouzapw merged commit fd76271 into cheaper-inference:release/v3.8.50 Aug 18, 2026
5 checks passed
diegosouzapw added a commit that referenced this pull request Aug 19, 2026
…10749)

* fix(ci): route the Gemini Web b64_json download error through sanitizeErrorMessage()

open-sse/handlers/imageGeneration/providers/geminiWeb.ts embedded a raw
err.message in the b64_json download-failure response, tripping
check:error-helper (Hard Rule #12) on release/v3.8.50.

Refs #9985.

* fix(tests): drain test-drift base-reds left by #10603/#10537 and a stale qwen-web catalog id

Several base-reds on release/v3.8.50 (#9985) share one root cause: a legitimate
product change landed without updating the test asserting the old behavior.

- tests/unit/glm-provider-model-import-route.test.ts (12 tests) and
  tests/unit/model-sync-route.test.ts (2 tests) predate #10603, which made
  upstream model sync opt-in (isAutoFetchModelsEnabled() now requires
  providerSpecificData.autoFetchModels === true) and made manual custom-model
  overrides survive a sync instead of being demoted. Updated both files to
  opt in / assert the new preserve-manual-overrides behavior, with a comment
  citing #10603.
- tests/unit/antigravity-model-aliases.test.ts predates #10537, which retired
  the collapsed 'gemini-3.7-flash' alias (upstream 'gemini-3.7-flash-tiered')
  in favor of the three directly-callable tiered ids. Dropped the retired id
  from EXPECTED_FLASH_TIERS.
- open-sse/config/freeModelCatalog.data.ts: the qwen-web free-catalog entry
  still listed the retired 'qwen3.8-max-preview' id instead of the current
  'qwen3.8-max' (open-sse/config/providers/registry/qwen/web/index.ts and the
  executor's compat alias both confirm 'qwen3.8-max' is canonical). Real data
  drift, not test drift.
- src/i18n/messages/zh-TW.json: providers.autoFetchModelsTooltip (added by
  #10603) used the mainland term 緩存 instead of the zh-TW glossary-canonical
  快取, tripping the i18n-glossary-consistency-check base-red.
- src/lib/oauth/providers/zed-hosted.ts: removed an unused default export
  (the named export already covers every consumer) — shaves one symbol off
  the check:dead-code ratchet (419 -> 418; baseline 415, 3 still outstanding).

Refs #9985.

---------

Co-authored-by: Markus Hartung <mail@hartmark.se>
diegosouzapw pushed a commit that referenced this pull request Aug 25, 2026
…ive the test

Vitest went red on 'synchronizes upstream models only when autoFetchModels is
explicitly true' with new URL throwing inside a fetch dispatched from
Timeout._onTimeout (useProviderModels.ts:69). It is intermittent: green in the two
previous CI runs, green every time in isolation, red only under the ui suite's 20
parallel workers.

The hook schedules its auto-sync in a setTimeout whose callback only checks the
 flag on entry — and that flag stays false while the component is
mounted. Both tests asserted first and unmounted last, so under contention the
timer escaped the test window, fired after afterEach had already run
vi.unstubAllGlobals(), and reached the REAL fetch with a relative URL.

Unmounting before the assertions closes the window: cleanup flips , the
callback returns early, and the calls already recorded on fetchMock are still there
to assert against. No assertion changed.

Not a regression from this cycle — the file's last change is fd76271 (#10603).
Fixed rather than tracked because an intermittent red in a blocking job is worse
than a permanent one: it teaches people to re-run instead of to look.

Refs #10692
muhamadgalihsaputra pushed a commit to niyatna/NiyatnaRoute that referenced this pull request Sep 27, 2026
…verrides (cheaper-inference#10603)

* fix(providers): make upstream model sync opt-in and preserve manual overrides

(cherry picked from commit 0a84f54)

* test(providers): cover upstream model sync controls

* fix(providers): fix pre-existing tests broken by opt-in model sync + sync i18n keys

The upstream model auto-fetch opt-in default flip made 3 pre-existing tests
short-circuit before reaching the paths they exercise, because their
connection fixtures never set providerSpecificData.autoFetchModels: true:

- tests/unit/provider-models-route-lan-guard.test.ts (cheaper-inference#6939 SSRF-guard tests)
- tests/unit/openrouter-embeddings-catalog-6976.test.ts (live discovery merge/dedup)
- tests/unit/provider-models-route.test.ts (Kimi Coding auth-header test —
  this was mislabeled as base/catalog drift during review, but is the same
  root cause: without autoFetchModels the mocked fetch is never reached and
  the route falls back to local catalog data instead)

Also syncs the 11 new providers.autoFetchModels*/overridesUpstreamModel*/
resetToUpstreamDefaults* i18n keys from en.json/zh-CN.json to the remaining
40 locale files via a narrowly-scoped ad-hoc translation script (only these
11 keys — leaves each locale's pre-existing, unrelated missing-key backlog
untouched).

Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>

* fix(providers): fix remaining pre-existing tests broken by opt-in model sync

Rebase surfaced that the 'Kimi Coding' CI failure flagged as possible base
drift during review was actually the same root cause as the lan-guard and
openrouter-embeddings fixes: 29 pre-existing tests in
tests/unit/provider-models-route.test.ts (of 59 total) short-circuit under
the new autoFetchModels opt-in default because their connection fixtures
never set providerSpecificData.autoFetchModels: true, so they never reach
the live-fetch/validation paths they were written to exercise (fetch mocks
never called, base-URL validation never reached, live models never merged).

Adds providerSpecificData.autoFetchModels: true to each affected fixture.
No production code or test assertions changed — same TEST-fixture-only
pattern as the lan-guard and openrouter-embeddings fixes. All 59 tests in
the file now pass (was 30/59).

Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>

---------

Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
muhamadgalihsaputra pushed a commit to niyatna/NiyatnaRoute that referenced this pull request Sep 27, 2026
…nference#9985) (cheaper-inference#10749)

* fix(ci): route the Gemini Web b64_json download error through sanitizeErrorMessage()

open-sse/handlers/imageGeneration/providers/geminiWeb.ts embedded a raw
err.message in the b64_json download-failure response, tripping
check:error-helper (Hard Rule cheaper-inference#12) on release/v3.8.50.

Refs cheaper-inference#9985.

* fix(tests): drain test-drift base-reds left by cheaper-inference#10603/cheaper-inference#10537 and a stale qwen-web catalog id

Several base-reds on release/v3.8.50 (cheaper-inference#9985) share one root cause: a legitimate
product change landed without updating the test asserting the old behavior.

- tests/unit/glm-provider-model-import-route.test.ts (12 tests) and
  tests/unit/model-sync-route.test.ts (2 tests) predate cheaper-inference#10603, which made
  upstream model sync opt-in (isAutoFetchModelsEnabled() now requires
  providerSpecificData.autoFetchModels === true) and made manual custom-model
  overrides survive a sync instead of being demoted. Updated both files to
  opt in / assert the new preserve-manual-overrides behavior, with a comment
  citing cheaper-inference#10603.
- tests/unit/antigravity-model-aliases.test.ts predates cheaper-inference#10537, which retired
  the collapsed 'gemini-3.7-flash' alias (upstream 'gemini-3.7-flash-tiered')
  in favor of the three directly-callable tiered ids. Dropped the retired id
  from EXPECTED_FLASH_TIERS.
- open-sse/config/freeModelCatalog.data.ts: the qwen-web free-catalog entry
  still listed the retired 'qwen3.8-max-preview' id instead of the current
  'qwen3.8-max' (open-sse/config/providers/registry/qwen/web/index.ts and the
  executor's compat alias both confirm 'qwen3.8-max' is canonical). Real data
  drift, not test drift.
- src/i18n/messages/zh-TW.json: providers.autoFetchModelsTooltip (added by
  cheaper-inference#10603) used the mainland term 緩存 instead of the zh-TW glossary-canonical
  快取, tripping the i18n-glossary-consistency-check base-red.
- src/lib/oauth/providers/zed-hosted.ts: removed an unused default export
  (the named export already covers every consumer) — shaves one symbol off
  the check:dead-code ratchet (419 -> 418; baseline 415, 3 still outstanding).

Refs cheaper-inference#9985.

---------

Co-authored-by: Markus Hartung <mail@hartmark.se>
muhamadgalihsaputra pushed a commit to niyatna/NiyatnaRoute that referenced this pull request Sep 27, 2026
…ive the test

Vitest went red on 'synchronizes upstream models only when autoFetchModels is
explicitly true' with new URL throwing inside a fetch dispatched from
Timeout._onTimeout (useProviderModels.ts:69). It is intermittent: green in the two
previous CI runs, green every time in isolation, red only under the ui suite's 20
parallel workers.

The hook schedules its auto-sync in a setTimeout whose callback only checks the
 flag on entry — and that flag stays false while the component is
mounted. Both tests asserted first and unmounted last, so under contention the
timer escaped the test window, fired after afterEach had already run
vi.unstubAllGlobals(), and reached the REAL fetch with a relative URL.

Unmounting before the assertions closes the window: cleanup flips , the
callback returns early, and the calls already recorded on fetchMock are still there
to assert against. No assertion changed.

Not a regression from this cycle — the file's last change is 51653a6 (cheaper-inference#10603).
Fixed rather than tracked because an intermittent red in a blocking job is worse
than a permanent one: it teaches people to re-run instead of to look.

Refs cheaper-inference#10692
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.

2 participants