Files
2026-07-13 13:39:12 +08:00

330 lines
10 KiB
TypeScript

import test from "node:test";
import assert from "node:assert/strict";
import fs from "node:fs";
import os from "node:os";
import path from "node:path";
const TEST_DATA_DIR = fs.mkdtempSync(path.join(os.tmpdir(), "omniroute-db-models-"));
process.env.DATA_DIR = TEST_DATA_DIR;
const core = await import("../../src/lib/db/core.ts");
const modelsDb = await import("../../src/lib/db/models.ts");
async function resetStorage() {
core.resetDbInstance();
for (let attempt = 0; attempt < 10; attempt++) {
try {
if (fs.existsSync(TEST_DATA_DIR)) {
fs.rmSync(TEST_DATA_DIR, { recursive: true, force: true });
}
break;
} catch (error: any) {
if ((error?.code === "EBUSY" || error?.code === "EPERM") && attempt < 9) {
await new Promise((resolve) => setTimeout(resolve, 50 * (attempt + 1)));
} else {
throw error;
}
}
}
fs.mkdirSync(TEST_DATA_DIR, { recursive: true });
}
test.beforeEach(async () => {
await resetStorage();
});
test.after(async () => {
core.resetDbInstance();
fs.rmSync(TEST_DATA_DIR, { recursive: true, force: true });
});
test("model aliases can be created, listed and deleted", async () => {
await modelsDb.setModelAlias("fast-default", { provider: "openai", model: "gpt-4.1-mini" });
await modelsDb.setModelAlias("reasoning", { provider: "anthropic", model: "claude-3-7-sonnet" });
const aliases = await modelsDb.getModelAliases();
assert.deepEqual(aliases["fast-default"], {
provider: "openai",
model: "gpt-4.1-mini",
});
assert.deepEqual(aliases.reasoning, {
provider: "anthropic",
model: "claude-3-7-sonnet",
});
await modelsDb.deleteModelAlias("fast-default");
assert.equal((await modelsDb.getModelAliases())["fast-default"], undefined);
});
test("MITM aliases support per-tool lookup and aggregated reads", async () => {
await modelsDb.setMitmAliasAll("cursor", {
"gpt-4.1": "cursor/gpt-4.1",
});
await modelsDb.setMitmAliasAll("codex", {
"gpt-4.1-mini": "codex/gpt-4.1-mini",
});
assert.deepEqual(await modelsDb.getMitmAlias("cursor"), {
"gpt-4.1": "cursor/gpt-4.1",
});
assert.deepEqual(await modelsDb.getMitmAlias(), {
cursor: { "gpt-4.1": "cursor/gpt-4.1" },
codex: { "gpt-4.1-mini": "codex/gpt-4.1-mini" },
});
});
test("custom models can be added once and queried by provider", async () => {
const created = await modelsDb.addCustomModel(
"openrouter",
"anthropic/claude-3.7-sonnet",
"Claude 3.7 Sonnet",
"manual",
"responses",
["chat", "responses"]
);
const duplicate = await modelsDb.addCustomModel(
"openrouter",
"anthropic/claude-3.7-sonnet",
"Claude 3.7 Sonnet"
);
const providerModels = await modelsDb.getCustomModels("openrouter");
const allModels = await modelsDb.getAllCustomModels();
assert.equal(duplicate.id, created.id);
assert.equal(providerModels.length, 1);
assert.deepEqual(providerModels[0], created);
assert.equal((allModels.openrouter as any).length, 1);
});
test("replaceCustomModels preserves compat fields and respects the empty-list guard", async () => {
await modelsDb.addCustomModel("openai", "gpt-4.1", "GPT-4.1");
await modelsDb.updateCustomModel("openai", "gpt-4.1", {
normalizeToolCallId: true,
preserveOpenAIDeveloperRole: false,
upstreamHeaders: {
"X-Test": " enabled ",
Host: "should-be-removed",
},
});
const replaced = await modelsDb.replaceCustomModels("openai", [
{
id: "gpt-4.1",
name: "GPT-4.1 Refreshed",
source: "imported",
supportsThinking: true,
},
]);
const guarded = await modelsDb.replaceCustomModels("openai", []);
assert.equal(replaced[0].normalizeToolCallId, true);
assert.equal(replaced[0].preserveOpenAIDeveloperRole, false);
assert.deepEqual(replaced[0].upstreamHeaders, { "X-Test": "enabled" });
assert.equal(replaced[0].supportsThinking, true);
assert.equal(guarded.length, 1);
await modelsDb.replaceCustomModels("openai", [], { allowEmpty: true });
assert.deepEqual(await modelsDb.getCustomModels("openai"), []);
});
test("removing a custom model also removes its compat override", async () => {
await modelsDb.addCustomModel("anthropic", "claude-3-haiku", "Claude 3 Haiku");
modelsDb.mergeModelCompatOverride("anthropic", "claude-3-haiku", {
normalizeToolCallId: true,
isHidden: true,
});
assert.equal(await modelsDb.removeCustomModel("anthropic", "claude-3-haiku"), true);
assert.equal(await modelsDb.removeCustomModel("anthropic", "claude-3-haiku"), false);
assert.deepEqual(await modelsDb.getCustomModels("anthropic"), []);
assert.deepEqual(modelsDb.getModelCompatOverrides("anthropic"), []);
});
test("synced available models are unioned across connections and cleaned per connection", async () => {
await modelsDb.replaceSyncedAvailableModelsForConnection("openai", "conn-a", [
{ id: "gpt-4.1", name: "GPT-4.1", source: "imported" },
{ id: "gpt-4.1-mini", name: "GPT-4.1 Mini", source: "imported" },
]);
const union = await modelsDb.replaceSyncedAvailableModelsForConnection("openai", "conn-b", [
{ id: "gpt-4.1-mini", name: "GPT-4.1 Mini", source: "imported" },
{ id: "o3-mini", name: "o3-mini", source: "imported" },
]);
const remaining = await modelsDb.deleteSyncedAvailableModelsForConnection("openai", "conn-a");
const allProviders = await modelsDb.getAllSyncedAvailableModels();
assert.deepEqual(union.map((model) => model.id).sort(), ["gpt-4.1", "gpt-4.1-mini", "o3-mini"]);
assert.deepEqual(remaining.map((model) => model.id).sort(), ["gpt-4.1-mini", "o3-mini"]);
assert.deepEqual(allProviders.openai.map((model) => model.id).sort(), [
"gpt-4.1-mini",
"o3-mini",
]);
});
test("compat overrides expose per-protocol getters and removable extra headers", async () => {
modelsDb.mergeModelCompatOverride("openai", "gpt-4.1", {
normalizeToolCallId: true,
preserveOpenAIDeveloperRole: false,
isHidden: true,
upstreamHeaders: {
"X-Top": "1",
"bad header": "skip",
},
compatByProtocol: {
openai: {
normalizeToolCallId: false,
preserveOpenAIDeveloperRole: true,
upstreamHeaders: {
"X-Proto": "yes",
},
},
},
});
assert.equal(modelsDb.getModelNormalizeToolCallId("openai", "gpt-4.1"), true);
assert.equal(modelsDb.getModelNormalizeToolCallId("openai", "gpt-4.1", "openai"), false);
assert.equal(modelsDb.getModelPreserveOpenAIDeveloperRole("openai", "gpt-4.1"), false);
assert.equal(modelsDb.getModelPreserveOpenAIDeveloperRole("openai", "gpt-4.1", "openai"), true);
assert.equal(modelsDb.getModelIsHidden("openai", "gpt-4.1"), true);
assert.deepEqual(modelsDb.getModelUpstreamExtraHeaders("openai", "gpt-4.1", "openai"), {
"X-Top": "1",
"X-Proto": "yes",
});
modelsDb.removeModelCompatOverride("openai", "gpt-4.1");
assert.equal(modelsDb.getModelNormalizeToolCallId("openai", "gpt-4.1"), false);
assert.deepEqual(modelsDb.getModelCompatOverrides("openai"), []);
});
test("sanitizeUpstreamHeadersMap keeps only safe trimmed headers", () => {
const sanitized = modelsDb.sanitizeUpstreamHeadersMap({
"X-First": " one ",
Host: "blocked",
"Bad Header": "blocked",
"X-Newline": "bad\nvalue",
"X-Second": 42,
});
assert.deepEqual(sanitized, {
"X-First": "one",
"X-Second": "42",
});
});
test("compat overrides ignore invalid protocol keys and can be fully removed again", () => {
modelsDb.mergeModelCompatOverride("openai", "gpt-4.1-mini", {
normalizeToolCallId: true,
preserveOpenAIDeveloperRole: true,
isHidden: true,
upstreamHeaders: {
"X-Test": "enabled",
Host: "blocked",
},
compatByProtocol: {
openai: {
normalizeToolCallId: false,
},
invalid: {
normalizeToolCallId: true,
},
},
});
let overrides = modelsDb.getModelCompatOverrides("openai");
assert.equal(overrides.length, 1);
assert.equal(overrides[0].compatByProtocol.invalid, undefined);
assert.deepEqual(overrides[0].upstreamHeaders, { "X-Test": "enabled" });
modelsDb.mergeModelCompatOverride("openai", "gpt-4.1-mini", {
normalizeToolCallId: false,
preserveOpenAIDeveloperRole: null,
isHidden: null,
upstreamHeaders: null,
compatByProtocol: {
openai: {
upstreamHeaders: {},
},
},
});
overrides = modelsDb.getModelCompatOverrides("openai");
assert.deepEqual(overrides, [
{
id: "gpt-4.1-mini",
compatByProtocol: {
openai: {
normalizeToolCallId: false,
},
},
},
]);
});
test("compat getters fall back to override rows when custom model storage is malformed", async () => {
await modelsDb.addCustomModel("anthropic", "claude-edge", "Claude Edge");
await modelsDb.updateCustomModel("anthropic", "claude-edge", {
normalizeToolCallId: true,
preserveOpenAIDeveloperRole: false,
upstreamHeaders: {
"X-Custom": "top",
},
compatByProtocol: {
openai: {
normalizeToolCallId: false,
preserveOpenAIDeveloperRole: true,
upstreamHeaders: {
"X-Proto": "proto",
},
},
},
});
modelsDb.mergeModelCompatOverride("anthropic", "claude-edge", {
normalizeToolCallId: true,
preserveOpenAIDeveloperRole: false,
isHidden: true,
upstreamHeaders: {
"X-Compat": "fallback",
},
compatByProtocol: {
openai: {
normalizeToolCallId: false,
preserveOpenAIDeveloperRole: true,
upstreamHeaders: {
"X-Compat-Proto": "fallback-proto",
},
},
},
});
const db = core.getDbInstance();
db.prepare("UPDATE key_value SET value = ? WHERE namespace = 'customModels' AND key = ?").run(
"{not-json",
"anthropic"
);
assert.equal(modelsDb.getModelNormalizeToolCallId("anthropic", "claude-edge", "openai"), false);
assert.equal(
modelsDb.getModelPreserveOpenAIDeveloperRole("anthropic", "claude-edge", "openai"),
true
);
assert.equal(modelsDb.getModelIsHidden("anthropic", "claude-edge"), true);
assert.deepEqual(modelsDb.getModelUpstreamExtraHeaders("anthropic", "claude-edge", "openai"), {
"X-Compat": "fallback",
"X-Compat-Proto": "fallback-proto",
});
});
test("missing alias helpers return empty results for unknown tools and providers", async () => {
assert.deepEqual(await modelsDb.getMitmAlias("missing-tool"), {});
assert.deepEqual(await modelsDb.getCustomModels("missing-provider"), []);
assert.deepEqual(await modelsDb.getAllSyncedAvailableModels(), {});
});