diff --git a/open-sse/services/model.ts b/open-sse/services/model.ts index 91ad9495c1..ec0f40d351 100644 --- a/open-sse/services/model.ts +++ b/open-sse/services/model.ts @@ -105,12 +105,13 @@ export function parseModel(modelStr) { extendedContext = true; cleanStr = cleanStr.slice(0, -4); } + cleanStr = cleanStr.trim(); // Check if standard format: provider/model or alias/model if (cleanStr.includes("/")) { const firstSlash = cleanStr.indexOf("/"); - const providerOrAlias = cleanStr.slice(0, firstSlash); - const model = cleanStr.slice(firstSlash + 1); + const providerOrAlias = cleanStr.slice(0, firstSlash).trim(); + const model = cleanStr.slice(firstSlash + 1).trim(); const provider = resolveProviderAlias(providerOrAlias); return { provider, model, isAlias: false, providerAlias: providerOrAlias, extendedContext }; } diff --git a/src/sse/services/auth.ts b/src/sse/services/auth.ts index 8f28073265..06d15f29f6 100644 --- a/src/sse/services/auth.ts +++ b/src/sse/services/auth.ts @@ -23,6 +23,7 @@ import { } from "@omniroute/open-sse/config/providerRegistry.ts"; import { COOLDOWN_MS } from "@omniroute/open-sse/config/constants.ts"; import { getCodexModelScope } from "@omniroute/open-sse/executors/codex.ts"; +import { getProviderAlias, resolveProviderId } from "@/shared/constants/providers"; import * as log from "../utils/logger"; import { fisherYatesShuffle, getNextFromDeckSync } from "@/shared/utils/shuffleDeck"; @@ -316,13 +317,17 @@ export { fisherYatesShuffle, getNextFromDeckSync as getNextFromDeck }; * Resolve provider aliases (e.g., nvidia -> nvidia_nim) for DB lookup */ function getProviderSearchPool(provider: string): string[] { + const canonicalProvider = resolveProviderId(provider); + const canonicalAlias = getProviderAlias(canonicalProvider); + if (provider === "nvidia") { return ["nvidia", "nvidia_nim"]; } if (provider === "nvidia_nim") { return ["nvidia_nim", "nvidia"]; } - return [provider]; + + return Array.from(new Set([provider, canonicalProvider, canonicalAlias].filter(Boolean))); } /** diff --git a/tests/unit/auth-clear-account-error.test.mjs b/tests/unit/auth-clear-account-error.test.mjs index 7f957a1ccd..4a9b45a6b1 100644 --- a/tests/unit/auth-clear-account-error.test.mjs +++ b/tests/unit/auth-clear-account-error.test.mjs @@ -56,3 +56,19 @@ test("clearAccountError clears stale provider error metadata after recovery", as assert.equal(updated.rateLimitedUntil, undefined); assert.equal(updated.backoffLevel, 0); }); + +test("getProviderCredentials resolves provider aliases to canonical DB records", async () => { + await resetStorage(); + + const created = await providersDb.createProviderConnection({ + provider: "codex", + authType: "oauth", + email: "alias@example.com", + accessToken: "access", + refreshToken: "refresh", + testStatus: "active", + }); + + const credentials = await auth.getProviderCredentials("cx"); + assert.equal(credentials.connectionId, created.id); +}); diff --git a/tests/unit/model-parse.test.mjs b/tests/unit/model-parse.test.mjs index 39d539bfdc..e85e91f59f 100644 --- a/tests/unit/model-parse.test.mjs +++ b/tests/unit/model-parse.test.mjs @@ -20,3 +20,10 @@ test("[1m] suffix: works with provider prefix", () => { assert.strictEqual(result.model, "claude-sonnet-4-6"); assert.strictEqual(result.extendedContext, true); }); + +test("parseModel trims provider prefix and model id", () => { + const result = parseModel(" cx / gpt-5.4 "); + assert.strictEqual(result.providerAlias, "cx"); + assert.strictEqual(result.provider, "codex"); + assert.strictEqual(result.model, "gpt-5.4"); +});