fix(routing): fall through to compatible node when built-in alias has no credentials
This commit is contained in:
@@ -11,10 +11,12 @@ async function setupDb() {
|
||||
vi.resetModules();
|
||||
|
||||
const { createProviderNode } = await import("@/models/index.js");
|
||||
const { createProviderConnection } = await import("@/models/index.js");
|
||||
const { getModelInfo } = await import("@/sse/services/model.js");
|
||||
|
||||
return {
|
||||
createProviderNode,
|
||||
createProviderConnection,
|
||||
getModelInfo,
|
||||
cleanup() {
|
||||
fs.rmSync(tempDir, { recursive: true, force: true });
|
||||
@@ -38,10 +40,18 @@ describe("model routing", () => {
|
||||
else process.env.DATA_DIR = originalDataDir;
|
||||
});
|
||||
|
||||
it("keeps built-in provider aliases ahead of compatible node prefixes", async () => {
|
||||
it("keeps built-in provider aliases ahead of compatible node prefixes when built-in has credentials", async () => {
|
||||
const ctx = await setupDb();
|
||||
cleanup = ctx.cleanup;
|
||||
|
||||
await ctx.createProviderConnection({
|
||||
provider: "cloudflare-ai",
|
||||
authType: "apikey",
|
||||
name: "CF Key",
|
||||
apiKey: "cf-test-key",
|
||||
isActive: true,
|
||||
});
|
||||
|
||||
await ctx.createProviderNode({
|
||||
id: "openai-compatible-chat-test",
|
||||
type: "openai-compatible",
|
||||
@@ -58,6 +68,55 @@ describe("model routing", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("routes reserved alias prefix to compatible node when built-in has no credentials", async () => {
|
||||
const ctx = await setupDb();
|
||||
cleanup = ctx.cleanup;
|
||||
|
||||
await ctx.createProviderNode({
|
||||
id: "openai-compatible-chat-test",
|
||||
type: "openai-compatible",
|
||||
name: "Compatible TR Collision",
|
||||
prefix: "tr",
|
||||
apiType: "chat",
|
||||
baseUrl: "https://api.tokenrouter.com/v1",
|
||||
});
|
||||
|
||||
// No tokenrouter connection → custom node wins instead of 404.
|
||||
await expect(ctx.getModelInfo("tr/qwen/qwen3.8-max-free"))
|
||||
.resolves.toEqual({
|
||||
provider: "openai-compatible-chat-test",
|
||||
model: "qwen/qwen3.8-max-free",
|
||||
});
|
||||
});
|
||||
|
||||
it("keeps built-in route when both built-in credentials and reserved-prefix compatible node exist", async () => {
|
||||
const ctx = await setupDb();
|
||||
cleanup = ctx.cleanup;
|
||||
|
||||
await ctx.createProviderConnection({
|
||||
provider: "tokenrouter",
|
||||
authType: "apikey",
|
||||
name: "TR Key",
|
||||
apiKey: "tr-test-key",
|
||||
isActive: true,
|
||||
});
|
||||
|
||||
await ctx.createProviderNode({
|
||||
id: "openai-compatible-chat-test",
|
||||
type: "openai-compatible",
|
||||
name: "Compatible TR Collision",
|
||||
prefix: "tr",
|
||||
apiType: "chat",
|
||||
baseUrl: "https://api.tokenrouter.com/v1",
|
||||
});
|
||||
|
||||
await expect(ctx.getModelInfo("tr/qwen/qwen3.8-max-free"))
|
||||
.resolves.toEqual({
|
||||
provider: "tokenrouter",
|
||||
model: "qwen/qwen3.8-max-free",
|
||||
});
|
||||
});
|
||||
|
||||
it("still routes non-reserved compatible node prefixes", async () => {
|
||||
const ctx = await setupDb();
|
||||
cleanup = ctx.cleanup;
|
||||
|
||||
@@ -32,6 +32,7 @@ vi.mock("@/lib/localDb", () => ({
|
||||
getComboByName: vi.fn(async () => null),
|
||||
getModelAliases: vi.fn(async () => ({})),
|
||||
getProviderNodes: vi.fn(async () => []),
|
||||
getProviderConnections: vi.fn(async () => []),
|
||||
}));
|
||||
vi.mock("@/sse/utils/logger.js", () => ({ info: vi.fn(), warn: vi.fn(), error: vi.fn(), debug: vi.fn() }));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user