feat: expose an explicit tier override for any provider connection (#7818) - #7838
Merged
Merged
Conversation
…nnection (#7818) classifyTier() already honored a DB-backed providerOverrides list keyed by an arbitrary provider-id string (built-in or custom), but nothing exposed it through the UI or API. Adds GET/PUT /api/settings/tier-config, a generic Advanced Settings tier selector wired into EditConnectionModal, and makes TierCoverageWidget consult the same override before falling back to registry-membership classification. Owner decision: scope is the 3 real ProviderTier machine values (free/cheap/premium) — the enum is not extended to 4.
Contributor
|
Warning You have reached your daily quota limit. Please wait up to 24 hours and I will start processing your requests again! |
Owner
Author
|
Reviewed and verified this against a clean worktree off
Good use of the existing |
Owner
Author
|
Validated in local merge-train on tomni-proxmox-113 @ 19bcf534352e24cdd2448cdfdfd64d5bd9695c74 (FAST gates green: static + changed tests + vitest) |
diegosouzapw
added a commit
that referenced
this pull request
Jul 20, 2026
…llision + stryker 7806 registration (1) #7838 added providerTierField.ts next to ProviderTierField.tsx in the same directory — a case-only collision that breaks webpack on case-insensitive filesystems; the #6584 guard fails Unit shard 4/4 on every fresh PR run. Rename the helper to providerTierFieldApi.ts (import + test path adjusted). (2) check:mutation-test-coverage --strict fails on the tip because merged #7806's combo-skip-conn-disable-plugin-block test was never registered in stryker tap.testFiles. Register it.
diegosouzapw
added a commit
that referenced
this pull request
Jul 20, 2026
…base-red) #7838 added six providers.tierOverride* keys to en.json without the Vietnamese counterparts; i18n-vi-completeness (key parity + both ICU checks) fails on the release tip for every fresh PR run. Translated using the locale's existing tier vocabulary and inserted at the mirrored position.
diegosouzapw
added a commit
to backryun/OmniRoute
that referenced
this pull request
Jul 20, 2026
release/v3.8.49 tip took slot 129 via diegosouzapw#7843 (usage_history_codex_strong_identity, itself renumbered from 128 during the diegosouzapw#7838/diegosouzapw#7840 base-red cleanup) after this branch forked; renumber remove_unregistered_qwen_data to 130. Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
diegosouzapw
added a commit
that referenced
this pull request
Jul 20, 2026
…rovider (#7866) * refactor(cli): remove legacy Qwen Code integration * refactor(qwen): remove deprecated Qwen OAuth provider * feat(cli): rebuild Qwen Code integration for upstream V4 * fix(qwen): clear stale CLI auth on reset * test(qwen): align retired provider coverage * fix(db): renumber qwen-cleanup migration 129 -> 130 release/v3.8.49 tip took slot 129 via #7843 (usage_history_codex_strong_identity, itself renumbered from 128 during the #7838/#7840 base-red cleanup) after this branch forked; renumber remove_unregistered_qwen_data to 130. Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com> --------- Co-authored-by: Diego Rodrigues de Sa e Souza <8016841+diegosouzapw@users.noreply.github.com>
HouMinXi
pushed a commit
to HouMinXi/OmniRoute
that referenced
this pull request
Aug 2, 2026
…nnection (diegosouzapw#7818) (diegosouzapw#7838) classifyTier() already honored a DB-backed providerOverrides list keyed by an arbitrary provider-id string (built-in or custom), but nothing exposed it through the UI or API. Adds GET/PUT /api/settings/tier-config, a generic Advanced Settings tier selector wired into EditConnectionModal, and makes TierCoverageWidget consult the same override before falling back to registry-membership classification. Owner decision: scope is the 3 real ProviderTier machine values (free/cheap/premium) — the enum is not extended to 4.
HouMinXi
pushed a commit
to HouMinXi/OmniRoute
that referenced
this pull request
Aug 2, 2026
…llision + stryker 7806 registration (1) diegosouzapw#7838 added providerTierField.ts next to ProviderTierField.tsx in the same directory — a case-only collision that breaks webpack on case-insensitive filesystems; the diegosouzapw#6584 guard fails Unit shard 4/4 on every fresh PR run. Rename the helper to providerTierFieldApi.ts (import + test path adjusted). (2) check:mutation-test-coverage --strict fails on the tip because merged diegosouzapw#7806's combo-skip-conn-disable-plugin-block test was never registered in stryker tap.testFiles. Register it.
HouMinXi
pushed a commit
to HouMinXi/OmniRoute
that referenced
this pull request
Aug 2, 2026
…ouzapw#7838 base-red) diegosouzapw#7838 added six providers.tierOverride* keys to en.json without the Vietnamese counterparts; i18n-vi-completeness (key parity + both ICU checks) fails on the release tip for every fresh PR run. Translated using the locale's existing tier vocabulary and inserted at the mirrored position.
HouMinXi
pushed a commit
to HouMinXi/OmniRoute
that referenced
this pull request
Aug 2, 2026
…rovider (diegosouzapw#7866) * refactor(cli): remove legacy Qwen Code integration * refactor(qwen): remove deprecated Qwen OAuth provider * feat(cli): rebuild Qwen Code integration for upstream V4 * fix(qwen): clear stale CLI auth on reset * test(qwen): align retired provider coverage * fix(db): renumber qwen-cleanup migration 129 -> 130 release/v3.8.49 tip took slot 129 via diegosouzapw#7843 (usage_history_codex_strong_identity, itself renumbered from 128 during the diegosouzapw#7838/diegosouzapw#7840 base-red cleanup) after this branch forked; renumber remove_unregistered_qwen_data to 130. Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com> --------- Co-authored-by: Diego Rodrigues de Sa e Souza <8016841+diegosouzapw@users.noreply.github.com>
muhamadgalihsaputra
pushed a commit
to niyatna/NiyatnaRoute
that referenced
this pull request
Sep 27, 2026
…nnection (diegosouzapw#7818) (diegosouzapw#7838) classifyTier() already honored a DB-backed providerOverrides list keyed by an arbitrary provider-id string (built-in or custom), but nothing exposed it through the UI or API. Adds GET/PUT /api/settings/tier-config, a generic Advanced Settings tier selector wired into EditConnectionModal, and makes TierCoverageWidget consult the same override before falling back to registry-membership classification. Owner decision: scope is the 3 real ProviderTier machine values (free/cheap/premium) — the enum is not extended to 4.
muhamadgalihsaputra
pushed a commit
to niyatna/NiyatnaRoute
that referenced
this pull request
Sep 27, 2026
…llision + stryker 7806 registration (1) diegosouzapw#7838 added providerTierField.ts next to ProviderTierField.tsx in the same directory — a case-only collision that breaks webpack on case-insensitive filesystems; the diegosouzapw#6584 guard fails Unit shard 4/4 on every fresh PR run. Rename the helper to providerTierFieldApi.ts (import + test path adjusted). (2) check:mutation-test-coverage --strict fails on the tip because merged diegosouzapw#7806's combo-skip-conn-disable-plugin-block test was never registered in stryker tap.testFiles. Register it.
muhamadgalihsaputra
pushed a commit
to niyatna/NiyatnaRoute
that referenced
this pull request
Sep 27, 2026
…ouzapw#7838 base-red) diegosouzapw#7838 added six providers.tierOverride* keys to en.json without the Vietnamese counterparts; i18n-vi-completeness (key parity + both ICU checks) fails on the release tip for every fresh PR run. Translated using the locale's existing tier vocabulary and inserted at the mirrored position.
muhamadgalihsaputra
pushed a commit
to niyatna/NiyatnaRoute
that referenced
this pull request
Sep 27, 2026
…rovider (diegosouzapw#7866) * refactor(cli): remove legacy Qwen Code integration * refactor(qwen): remove deprecated Qwen OAuth provider * feat(cli): rebuild Qwen Code integration for upstream V4 * fix(qwen): clear stale CLI auth on reset * test(qwen): align retired provider coverage * fix(db): renumber qwen-cleanup migration 129 -> 130 release/v3.8.49 tip took slot 129 via diegosouzapw#7843 (usage_history_codex_strong_identity, itself renumbered from 128 during the diegosouzapw#7838/diegosouzapw#7840 base-red cleanup) after this branch forked; renumber remove_unregistered_qwen_data to 130. Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com> --------- Co-authored-by: Diego Rodrigues de Sa e Souza <8016841+diegosouzapw@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Closes the actual gap behind #7818/#7763:
classifyTier()(open-sse/services/tierResolver.ts) already honored a DB-backedproviderOverrideslist keyed by an arbitrary provider-id string — it worked identically for a built-in or custom provider — but nothing exposed that mechanism through any UI or API route, for any provider. This PR is that missing surface.GET/PUT /api/settings/tier-configroute: reads/writes a single provider's tier override in the existingtier_configtable (loadTierConfig()/saveTierConfig()), validated with az.enum(["free","cheap","premium"])schema, and busts the in-process routing cache viasetTierConfig()so a change applies immediately.<Select>wired intoEditConnectionModal.tsx's Advanced Settings section (ProviderTierField.tsx+providerTierField.tshelpers, mirroring the existingm365Tier.tspattern in the same directory) — applies uniformly to every connection, built-in or custom, no capability gate.TierCoverageWidget.tsx::classifyConnection()now consults the same override before falling back to its existing registry-membership check, so a tiered custom provider shows up in the correct bucket instead of always landing in "Cheap".en.json+pt-BR.jsonunder theprovidersnamespace (tierOverride*).No database migration —
tier_configalready exists via migration059_manifest_routing.sql; verified viagrep -rln "loadTierConfig\|saveTierConfig" src/app/api/returning empty before this PR.Scope decision (owner-confirmed): the original report says "4 tiers", but the actual
ProviderTiermachine enum (open-sse/services/tierTypes.ts) has exactly 3 values (free/cheap/premium) — the "4" isREADME.mdmarketing copy conflating two separate 3-bucket classifiers. This PR implements the override for the 3 real machine values and does not extend the enum. Nothing else is deferred; the feature is complete against the amended (3-tier) scope, so this closes the issue.How validated (Hard Rule #18 — TDD, proved red before green)
Added 4 new top-level test files (26 assertions across 14 test cases):
tests/unit/tier-config-provider-override-route.test.ts— exercises the route'sGET/PUTagainst a real isolated SQLite test DB (DATA_DIRtemp dir +resetDbInstance()inbeforeEach/after). Covers: set override for a custom (non-registry) provider id, clear viatier: nullwithout touching other providers, reject an invalid tier with 400 (and assert the error body doesn't leak a stack trace), reject an empty provider string, and round-trip cleanly against an already-populatedtier_configrow (no-migration scenario).tests/unit/tier-resolver-provider-override.test.ts— proves thesetTierConfig()cache-bust actually matters: callsclassifyTier()directly before and after aPUT, asserting the routing side picks up the override on the very next call (using a fresh model key so a stale per-key cache entry can't fake the result).tests/unit/tier-coverage-widget-provider-override.test.ts—classifyConnection()unit tests (override-before-registry precedence, case-insensitive lookup, fallback to registry membership).tests/unit/provider-tier-field-helpers.test.ts—fetchProviderTierOverride/saveProviderTierOverride/normalizeTierValueagainst a stubbedglobal.fetch.Proved the red (not a placebo): deleted
src/app/api/settings/tier-config/entirely (backed up first, restored after) and re-ran the route + resolver test files — both failed withERR_MODULE_NOT_FOUND(the route genuinely didn't exist before this PR). Also revertedclassifyConnection()to drop the override lookup and re-ran the widget test — it failed with'tier2' !== 'tier1'/'tier2' !== 'tier3'assertion errors, proving that test isn't a DOM-less placebo either. Restored both files and reran green afterward.Gates run (all green)
node scripts/check/check-test-discovery.mjsnpm run typecheck:core— cleannpm run typecheck:noimplicit:core— pre-existing errors only inopen-sse/services/combo.ts,open-sse/utils/usageTracking.ts,src/shared/services/cliRuntime.ts(confirmed identical againstorigin/release/v3.8.49, untouched by this diff)npx eslint --suppressions-location config/quality/eslint-suppressions.json <changed files>— cleannpm run check:complexity-ratchets— cyclomatic 2076 (baseline 2130), cognitive 901 (baseline 950), both OKnode scripts/check/check-file-size.mjs— OK;EditConnectionModal.tsxfrozen baseline bumped 1286→1288 (net +2 lines: one import + one<ProviderTierField .../>render call, justified inconfig/quality/file-size-baseline.json's new_rebaseline_2026_07_20_7818_provider_tier_fieldentry, mirroring the existingm365Tier.ts/AgentRouter precedents)npm run check:mutation-test-coverage— no drift (tierResolver.ts/tierConfig.ts/the new route are not in Stryker'smutateset, confirmed before writing tests, so notap.testFilesregistration was needed)node scripts/check/check-dashboard-typecheck.mjs— 2 pre-existing failures (AgentEmoji.tsx,GheConfigStep.tsx), confirmed viagit diff --stat origin/release/v3.8.49...HEADto be untouched by this PRnpm run check:cycles— no new cyclesnpm run test:coverageintentionally not run locally (heaviest gate, shared box) — CI runs it authoritatively.What was deferred
Nothing from the confirmed (3-tier) scope. The only thing explicitly out of scope is extending
ProviderTierto a 4th machine value (subscription vs. API-key), which the plan's Open Question flagged as a materially larger, separately-scoped change — the owner confirmed the 3-value scope for this issue.Closes #7818