mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-07-26 09:52:11 +03:00
* fix(providers): give v0-vercel-web its own alias so credentials are detected (#6343) * test(6343): type casts to satisfy no-explicit-any gate * test(6343): register v0-web + cliproxyapi tests in stryker tap.testFiles The two unit tests added on this branch cover mutated modules (src/sse/services/auth.ts, comboContextCache.ts) but were missing from stryker.conf.json tap.testFiles, tripping check:mutation-test-coverage --strict. Co-authored-by: diegosouzapw <diegosouza.pw@gmail.com>
This commit is contained in:
committed by
GitHub
parent
0834bb2c70
commit
8c4364a597
1
changelog.d/fixes/6343-6343-v0web-creds.md
Normal file
1
changelog.d/fixes/6343-6343-v0web-creds.md
Normal file
@@ -0,0 +1 @@
|
||||
- fix(providers): give v0-vercel-web its own alias so its credentials are detected (#6343)
|
||||
@@ -242,7 +242,13 @@ export const WEB_COOKIE_PROVIDERS = {
|
||||
},
|
||||
"v0-vercel-web": {
|
||||
id: "v0-vercel-web",
|
||||
alias: "v0",
|
||||
// #6343: was "v0", colliding with the unrelated "v0-vercel" API-key provider's
|
||||
// alias. Aliases resolve 1:1 to a provider id, so the dashboard's model-string
|
||||
// routing always picked v0-vercel, silently hiding this provider's own
|
||||
// credentials. Follows the established secondary-web-variant convention (see
|
||||
// kimi-web / qwen-web / huggingchat in tests/unit/provider-alias-uniqueness.test.ts):
|
||||
// the web/secondary variant uses its own id as alias instead of a short prefix.
|
||||
alias: "v0-vercel-web",
|
||||
name: "v0 Vercel Web (Code Gen)",
|
||||
icon: "auto_awesome",
|
||||
color: "#000000",
|
||||
|
||||
@@ -179,6 +179,7 @@
|
||||
"tests/unit/headroom-codex-quota-snapshot-6379.test.ts",
|
||||
"tests/unit/headroom-proxy-lifecycle.test.ts",
|
||||
"tests/unit/idempotency-fusion-collision.test.ts",
|
||||
"tests/unit/issue-6343-v0-web-alias-collision.test.ts",
|
||||
"tests/unit/issue-6638-ollama-quota.test.ts",
|
||||
"tests/unit/issue-6686-quota-preflight-coverage.test.ts",
|
||||
"tests/unit/livews-forward-backoff-4604.test.ts",
|
||||
|
||||
90
tests/unit/issue-6343-v0-web-alias-collision.test.ts
Normal file
90
tests/unit/issue-6343-v0-web-alias-collision.test.ts
Normal file
@@ -0,0 +1,90 @@
|
||||
// Regression test for #6343: "v0 Web cannot detect added credentials".
|
||||
//
|
||||
// Root cause: 'v0 Vercel Web (Code Gen)' (id v0-vercel-web, cookie auth) and the
|
||||
// unrelated 'v0 (Vercel)' API-key provider (id v0-vercel) both declared alias
|
||||
// "v0". The dashboard's per-model Test button builds the test model string from
|
||||
// the provider's ALIAS (not its canonical id), and open-sse's alias->id map is
|
||||
// necessarily 1:1, so "v0/<model>" always resolved to v0-vercel (which the user
|
||||
// has no credentials for) instead of v0-vercel-web (the provider they actually
|
||||
// configured). See _tasks/pipeline/bugs/2-implementing/6343-*.plan.md.
|
||||
import { describe, it, after } from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import fs from "node:fs";
|
||||
|
||||
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "omniroute-6343-"));
|
||||
process.env.DATA_DIR = tmpDir;
|
||||
process.env.JWT_SECRET = "test-jwt-secret-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
|
||||
process.env.API_KEY_SECRET = "0123456789abcdef0123456789abcdef";
|
||||
|
||||
describe("#6343: v0-vercel-web credential detection (alias collision)", () => {
|
||||
after(async () => {
|
||||
try {
|
||||
const { resetDbInstance } = await import("../../src/lib/db/core.ts");
|
||||
resetDbInstance();
|
||||
} catch {
|
||||
// best-effort cleanup
|
||||
}
|
||||
fs.rmSync(tmpDir, { recursive: true, force: true });
|
||||
});
|
||||
|
||||
it("v0-vercel and v0-vercel-web no longer share an alias", async () => {
|
||||
const { getProviderAlias } = await import("../../src/shared/constants/providers.ts");
|
||||
const apiKeyAlias = getProviderAlias("v0-vercel");
|
||||
const webAlias = getProviderAlias("v0-vercel-web");
|
||||
assert.notEqual(
|
||||
webAlias,
|
||||
apiKeyAlias,
|
||||
"v0-vercel and v0-vercel-web must have distinct aliases so alias->id resolution is unambiguous"
|
||||
);
|
||||
});
|
||||
|
||||
it("a saved v0-vercel-web connection is found by getProviderCredentials", async () => {
|
||||
const { createProviderConnection } = await import("../../src/lib/db/providers.ts");
|
||||
const { getProviderCredentials } = await import("../../src/sse/services/auth.ts");
|
||||
const conn = await createProviderConnection({
|
||||
provider: "v0-vercel-web",
|
||||
authType: "cookie",
|
||||
name: "test-v0-web",
|
||||
apiKey: "__vercel_session=faketoken123",
|
||||
priority: 1,
|
||||
isActive: true,
|
||||
testStatus: "active",
|
||||
});
|
||||
const creds = await getProviderCredentials("v0-vercel-web", null, null, "v0-fable-5");
|
||||
assert.ok(creds);
|
||||
assert.equal((creds as { connectionId?: string }).connectionId, conn.id);
|
||||
});
|
||||
|
||||
it("dashboard 'Test Model' fullModel (built from provider ALIAS) resolves back to v0-vercel-web and finds the real credential", async () => {
|
||||
const { getProviderAlias } = await import("../../src/shared/constants/providers.ts");
|
||||
const { parseModel } = await import("../../open-sse/services/model.ts");
|
||||
const { getProviderCredentials } = await import("../../src/sse/services/auth.ts");
|
||||
|
||||
const providerId = "v0-vercel-web";
|
||||
// Mirrors ProviderDetailPageClient.tsx:266 for a non-"compatible" provider.
|
||||
const providerDisplayAlias = getProviderAlias(providerId);
|
||||
// Mirrors ProviderModelsSection.tsx:461.
|
||||
const fullModelFromUi = `${providerDisplayAlias}/v0-fable-5`;
|
||||
|
||||
const parsed = parseModel(fullModelFromUi);
|
||||
assert.equal(parsed.provider, providerId);
|
||||
|
||||
const creds = await getProviderCredentials(String(parsed.provider), null, null, parsed.model);
|
||||
assert.ok(creds);
|
||||
});
|
||||
|
||||
it("v0-vercel and v0-vercel-web are the only two AI_PROVIDERS entries with alias 'v0'", async () => {
|
||||
// Guards against a future re-introduction of the exact collision this bug fixed
|
||||
// (see AI_PROVIDERS scan in the plan-file / triage). Deliberately scoped to the
|
||||
// "v0" alias only — other pre-existing alias collisions (e.g. poe / poe-web) are
|
||||
// out of scope for #6343 and are not asserted here.
|
||||
const { AI_PROVIDERS } = await import("../../src/shared/constants/providers.ts");
|
||||
const idsWithV0Alias = Object.values(AI_PROVIDERS)
|
||||
.filter((p: { alias?: string; id: string }) => p.alias === "v0")
|
||||
.map((p: { alias?: string; id: string }) => p.id)
|
||||
.sort();
|
||||
assert.deepEqual(idsWithV0Alias, ["v0-vercel"]);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user