import fs from "node:fs"; import os from "node:os"; import path from "node:path"; import { describe, it, expect, beforeEach, afterEach, vi } from "vitest"; const originalDataDir = process.env.DATA_DIR; async function setupDb() { const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "9router-model-routing-")); process.env.DATA_DIR = tempDir; 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 }); }, }; } describe("model routing", () => { let cleanup = () => {}; beforeEach(() => { vi.clearAllMocks(); }); afterEach(() => { vi.resetModules(); vi.clearAllMocks(); cleanup(); cleanup = () => {}; if (originalDataDir === undefined) delete process.env.DATA_DIR; else process.env.DATA_DIR = originalDataDir; }); 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", name: "Compatible CF Collision", prefix: "cf", apiType: "chat", baseUrl: "https://compatible.test/v1", }); await expect(ctx.getModelInfo("cf/@cf/black-forest-labs/flux-2-klein-9b")) .resolves.toEqual({ provider: "cloudflare-ai", model: "@cf/black-forest-labs/flux-2-klein-9b", }); }); 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; await ctx.createProviderNode({ id: "openai-compatible-chat-test", type: "openai-compatible", name: "Compatible OCT", prefix: "oct", apiType: "chat", baseUrl: "https://compatible.test/v1", }); await expect(ctx.getModelInfo("oct/gpt-image-1")) .resolves.toEqual({ provider: "openai-compatible-chat-test", model: "gpt-image-1", }); }); });