fix(usage): guard GLM region lookup and stabilize test runs

Only use provider apiRegion values when they are strings before resolving
the GLM quota endpoint, preventing invalid metadata from affecting usage
requests.

Run unit tests with single-test concurrency to avoid shared-state flakes
and expand coverage for auth-protected routes, provider node validation,
proxy and stream handling, model sync, token refresh, and protobuf
parsing.
This commit is contained in:
diegosouzapw
2026-04-06 11:15:44 -03:00
parent 7b75476c4a
commit f1e30dfba2
16 changed files with 1560 additions and 22 deletions
+4 -1
View File
@@ -107,7 +107,10 @@ const GLM_QUOTA_URLS: Record<string, string> = {
};
async function getGlmUsage(apiKey: string, providerSpecificData?: Record<string, unknown>) {
const region = providerSpecificData?.apiRegion || "international";
const region =
typeof providerSpecificData?.apiRegion === "string"
? providerSpecificData.apiRegion
: "international";
const quotaUrl = GLM_QUOTA_URLS[region] || GLM_QUOTA_URLS.international;
const res = await fetch(quotaUrl, {
+3 -3
View File
@@ -56,8 +56,8 @@
"electron:build:win": "npm run build && cd electron && npm run build:win",
"electron:build:mac": "npm run build && cd electron && npm run build:mac",
"electron:build:linux": "npm run build && cd electron && npm run build:linux",
"test": "cross-env DISABLE_SQLITE_AUTO_BACKUP=true node --import tsx/esm --test tests/unit/*.test.mjs",
"test:unit": "cross-env DISABLE_SQLITE_AUTO_BACKUP=true node --import tsx/esm --test tests/unit/*.test.mjs",
"test": "cross-env DISABLE_SQLITE_AUTO_BACKUP=true node --import tsx/esm --test --test-concurrency=1 tests/unit/*.test.mjs",
"test:unit": "cross-env DISABLE_SQLITE_AUTO_BACKUP=true node --import tsx/esm --test --test-concurrency=1 tests/unit/*.test.mjs",
"test:plan3": "cross-env DISABLE_SQLITE_AUTO_BACKUP=true node --import tsx/esm --test tests/unit/plan3-p0.test.mjs",
"test:fixes": "cross-env DISABLE_SQLITE_AUTO_BACKUP=true node --import tsx/esm --test tests/unit/fixes-p1.test.mjs",
"test:security": "cross-env DISABLE_SQLITE_AUTO_BACKUP=true node --import tsx/esm --test tests/unit/security-fase01.test.mjs",
@@ -72,7 +72,7 @@
"test:protocols:e2e": "node scripts/run-protocol-clients-tests.mjs",
"test:vitest": "vitest run --config vitest.mcp.config.ts",
"test:ecosystem": "node scripts/run-ecosystem-tests.mjs",
"test:coverage": "c8 --output-dir coverage --exclude=tests/** --exclude=**/*.test.* --reporter=text-summary --reporter=html --reporter=json-summary --reporter=lcov --check-coverage --statements 60 --lines 60 --functions 60 --branches 60 node --import tsx/esm --test tests/unit/*.test.mjs",
"test:coverage": "c8 --output-dir coverage --exclude=tests/** --exclude=**/*.test.* --reporter=text-summary --reporter=html --reporter=json-summary --reporter=lcov --check-coverage --statements 60 --lines 60 --functions 60 --branches 60 node --import tsx/esm --test --test-concurrency=1 tests/unit/*.test.mjs",
"test:coverage:legacy": "c8 --output-dir coverage --exclude=open-sse --check-coverage --lines 50 --functions 50 --branches 50 node --import tsx/esm --test tests/unit/*.test.mjs",
"coverage:report": "c8 report --output-dir coverage --exclude=tests/** --exclude=**/*.test.* --reporter=text --reporter=text-summary --reporter=html --reporter=json-summary --reporter=lcov",
"coverage:summary": "node scripts/test-report-summary.mjs --input coverage/coverage-summary.json --output coverage/coverage-report.md --threshold 60",
+83
View File
@@ -81,6 +81,32 @@ test("API keys routes require management auth when login protection is enabled",
assert.equal(invalidTokenBody.error.message, "Invalid management token");
});
test("API keys POST also requires management auth when login protection is enabled", async () => {
await enableManagementAuth();
const unauthenticated = await listRoute.POST(
makeRequest("http://localhost/api/keys", {
method: "POST",
body: { name: "Blocked Create" },
})
);
const invalidToken = await listRoute.POST(
makeRequest("http://localhost/api/keys", {
method: "POST",
token: "sk-invalid",
body: { name: "Blocked Create" },
})
);
const unauthenticatedBody = await unauthenticated.json();
const invalidTokenBody = await invalidToken.json();
assert.equal(unauthenticated.status, 401);
assert.equal(unauthenticatedBody.error.message, "Authentication required");
assert.equal(invalidToken.status, 403);
assert.equal(invalidTokenBody.error.message, "Invalid management token");
});
test("POST /api/keys creates a key, preserves special characters, and persists noLog", async () => {
await enableManagementAuth();
const authKey = await createManagementKey();
@@ -196,6 +222,31 @@ test("GET /api/keys falls back to default pagination for invalid query params",
assert.equal(body.keys[0].name, "management");
});
test("GET /api/keys uses default pagination when query params are absent and reports reveal support", async () => {
await enableManagementAuth();
process.env.ALLOW_API_KEY_REVEAL = "true";
const authKey = await createManagementKey();
const createdA = await apiKeysDb.createApiKey("Alpha", MACHINE_ID);
const createdB = await apiKeysDb.createApiKey("Beta", MACHINE_ID);
const response = await listRoute.GET(
makeRequest("http://localhost/api/keys", {
token: authKey.key,
})
);
const body = await response.json();
assert.equal(response.status, 200);
assert.equal(body.total, 3);
assert.equal(body.allowKeyReveal, true);
assert.equal(body.keys.length, 3);
assert.deepEqual(
body.keys.map((entry) => entry.id).sort(),
[authKey.id, createdA.id, createdB.id].sort()
);
assert.ok(body.keys.every((entry) => entry.key !== undefined && entry.key !== ""));
});
test("POST /api/keys triggers cloud sync when cloud mode is enabled", async () => {
await enableManagementAuth();
await localDb.updateSettings({ cloudEnabled: true });
@@ -229,6 +280,38 @@ test("POST /api/keys triggers cloud sync when cloud mode is enabled", async () =
}
});
test("POST /api/keys still succeeds when cloud sync fails after creation", async () => {
await enableManagementAuth();
await localDb.updateSettings({ cloudEnabled: true });
const authKey = await createManagementKey();
const originalFetch = globalThis.fetch;
let syncAttempts = 0;
globalThis.fetch = async () => {
syncAttempts += 1;
throw new Error("cloud sync offline");
};
try {
const response = await listRoute.POST(
makeRequest("http://localhost/api/keys", {
method: "POST",
token: authKey.key,
body: { name: "Cloud Failure Tolerated" },
})
);
const body = await response.json();
const stored = await apiKeysDb.getApiKeyById(body.id);
assert.equal(response.status, 201);
assert.equal(body.name, "Cloud Failure Tolerated");
assert.equal(syncAttempts, 1);
assert.equal(stored?.name, "Cloud Failure Tolerated");
} finally {
globalThis.fetch = originalFetch;
}
});
test("GET /api/keys/[id] returns 404 for an unknown key and reveal is gated by the feature flag", async () => {
await enableManagementAuth();
const authKey = await createManagementKey();
@@ -261,6 +261,70 @@ test("critical routes: v1 management proxies validates create payloads and clamp
assert.equal(missingDeleteBody.error.message, "Proxy not found");
});
test("critical routes: v1 management proxies requires auth on mutating routes", async () => {
await enableManagementAuth();
const unauthenticatedPost = await proxiesRoute.POST(
makeRequest("http://localhost/api/v1/management/proxies", {
method: "POST",
body: {
name: "Denied Proxy",
type: "http",
host: "denied.local",
port: 8080,
},
})
);
const invalidPost = await proxiesRoute.POST(
makeRequest("http://localhost/api/v1/management/proxies", {
method: "POST",
token: "sk-invalid",
body: {
name: "Denied Proxy",
type: "http",
host: "denied.local",
port: 8080,
},
})
);
const unauthenticatedPatch = await proxiesRoute.PATCH(
makeRequest("http://localhost/api/v1/management/proxies", {
method: "PATCH",
body: { id: "proxy-1", host: "patched.local" },
})
);
const invalidPatch = await proxiesRoute.PATCH(
makeRequest("http://localhost/api/v1/management/proxies", {
method: "PATCH",
token: "sk-invalid",
body: { id: "proxy-1", host: "patched.local" },
})
);
const unauthenticatedDelete = await proxiesRoute.DELETE(
makeRequest("http://localhost/api/v1/management/proxies?id=proxy-1", {
method: "DELETE",
})
);
const invalidDelete = await proxiesRoute.DELETE(
makeRequest("http://localhost/api/v1/management/proxies?id=proxy-1", {
method: "DELETE",
token: "sk-invalid",
})
);
for (const response of [unauthenticatedPost, unauthenticatedPatch, unauthenticatedDelete]) {
const body = await response.json();
assert.equal(response.status, 401);
assert.equal(body.error.message, "Authentication required");
}
for (const response of [invalidPost, invalidPatch, invalidDelete]) {
const body = await response.json();
assert.equal(response.status, 403);
assert.equal(body.error.message, "Invalid management token");
}
});
test("critical routes: settings proxy resolves config, validates payloads, and deletes scoped entries", async () => {
const connection = await localDb.createProviderConnection({
provider: "openai",
@@ -12,6 +12,25 @@ const providersDb = await import("../../src/lib/db/providers.ts");
const moderationRoute = await import("../../src/app/api/v1/moderations/route.ts");
const embeddingsRoute = await import("../../src/app/api/v1/embeddings/route.ts");
async function withEnv(name, value, fn) {
const previous = process.env[name];
if (value === undefined) {
delete process.env[name];
} else {
process.env[name] = value;
}
try {
return await fn();
} finally {
if (previous === undefined) {
delete process.env[name];
} else {
process.env[name] = previous;
}
}
}
async function resetStorage() {
core.resetDbInstance();
fs.rmSync(TEST_DATA_DIR, { recursive: true, force: true });
@@ -76,6 +95,74 @@ test("moderations route clears stale provider error metadata on success", async
}
});
test("moderations route covers CORS, API key auth, validation, and missing credential branches", async () => {
await resetStorage();
const optionsResponse = await moderationRoute.OPTIONS();
assert.equal(optionsResponse.status, 200);
assert.equal(optionsResponse.headers.get("Access-Control-Allow-Methods"), "POST, OPTIONS");
await withEnv("REQUIRE_API_KEY", "true", async () => {
const missingKeyResponse = await moderationRoute.POST(
new Request("http://localhost/v1/moderations", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ input: "hello" }),
})
);
assert.equal(missingKeyResponse.status, 401);
assert.match(await missingKeyResponse.text(), /Missing API key/i);
const invalidKeyResponse = await moderationRoute.POST(
new Request("http://localhost/v1/moderations", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: "Bearer invalid-test-key",
},
body: JSON.stringify({ input: "hello" }),
})
);
assert.equal(invalidKeyResponse.status, 401);
assert.match(await invalidKeyResponse.text(), /Invalid API key/i);
});
const invalidJsonResponse = await moderationRoute.POST(
new Request("http://localhost/v1/moderations", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: "{",
})
);
assert.equal(invalidJsonResponse.status, 400);
assert.match(await invalidJsonResponse.text(), /Invalid JSON body/i);
const invalidBodyResponse = await moderationRoute.POST(
new Request("http://localhost/v1/moderations", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({}),
})
);
assert.equal(invalidBodyResponse.status, 400);
assert.match(await invalidBodyResponse.text(), /Invalid request/i);
const noCredentialsResponse = await moderationRoute.POST(
new Request("http://localhost/v1/moderations", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
input: "hello",
model: "anthropic/omni-moderation-latest",
}),
})
);
assert.equal(noCredentialsResponse.status, 400);
assert.match(await noCredentialsResponse.text(), /No credentials for provider: openai/i);
});
test("embeddings route clears stale provider error metadata on success", async () => {
await resetStorage();
const created = await seedOpenAIConnection("embeddings@example.com");
+154
View File
@@ -725,6 +725,160 @@ test("provider-nodes validate route rejects CC mode when feature flag is disable
assert.equal(response.status, 403);
});
test("provider-nodes validate route rejects invalid JSON and schema errors", async () => {
const invalidJsonResponse = await providerNodesValidateRoute.POST(
new Request("http://localhost/api/provider-nodes/validate", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: "{",
})
);
assert.equal(invalidJsonResponse.status, 400);
assert.deepEqual(await invalidJsonResponse.json(), {
error: {
message: "Invalid request",
details: [{ field: "body", message: "Invalid JSON body" }],
},
});
const invalidBodyResponse = await providerNodesValidateRoute.POST(
new Request("http://localhost/api/provider-nodes/validate", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
baseUrl: "",
apiKey: "",
}),
})
);
assert.equal(invalidBodyResponse.status, 400);
const invalidBodyPayload = await invalidBodyResponse.json();
assert.equal(invalidBodyPayload.error.message, "Invalid request");
assert.equal(invalidBodyPayload.error.details.length >= 2, true);
});
test("provider-nodes validate route validates anthropic compatible providers against the models endpoint", async () => {
const calls = [];
globalThis.fetch = async (url, init = {}) => {
calls.push({ url, init });
return new Response(JSON.stringify({ data: [] }), {
status: 200,
headers: { "content-type": "application/json" },
});
};
const response = await providerNodesValidateRoute.POST(
new Request("http://localhost/api/provider-nodes/validate", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
baseUrl: "https://proxy.example.com/v1/messages?beta=true",
apiKey: "sk-anthropic-test",
type: "anthropic-compatible",
modelsPath: "/catalog",
}),
})
);
assert.equal(response.status, 200);
assert.deepEqual(await response.json(), {
valid: true,
error: null,
});
assert.equal(calls.length, 1);
assert.equal(calls[0].url, "https://proxy.example.com/v1/catalog");
assert.equal(calls[0].init.method, "GET");
assert.equal(calls[0].init.headers["x-api-key"], "sk-anthropic-test");
assert.equal(calls[0].init.headers["anthropic-version"], "2023-06-01");
assert.equal(calls[0].init.headers.Authorization, "Bearer sk-anthropic-test");
});
test("provider-nodes validate route supports enabled CC validation and OpenAI-style failures", async () => {
process.env.ENABLE_CC_COMPATIBLE_PROVIDER = "true";
const calls = [];
globalThis.fetch = async (url, init = {}) => {
calls.push({ url, init });
if (calls.length === 1) {
return new Response(JSON.stringify({ data: [] }), {
status: 200,
headers: { "content-type": "application/json" },
});
}
return new Response(JSON.stringify({ error: "Unauthorized" }), {
status: 401,
headers: { "content-type": "application/json" },
});
};
const ccResponse = await providerNodesValidateRoute.POST(
new Request("http://localhost/api/provider-nodes/validate", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
baseUrl: "https://proxy.example.com/v1/messages?beta=true",
apiKey: "sk-cc-test",
type: "anthropic-compatible",
compatMode: "cc",
chatPath: CLAUDE_CODE_COMPATIBLE_DEFAULT_CHAT_PATH,
}),
})
);
assert.equal(ccResponse.status, 200);
assert.deepEqual(await ccResponse.json(), {
valid: true,
error: null,
warning: null,
method: "models_endpoint",
});
assert.equal(String(calls[0].url).includes("/v1/messages"), false);
assert.equal(calls[0].init.method, "GET");
const openAiResponse = await providerNodesValidateRoute.POST(
new Request("http://localhost/api/provider-nodes/validate", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
baseUrl: "https://proxy.example.com/",
apiKey: "sk-openai-test",
}),
})
);
assert.equal(openAiResponse.status, 200);
assert.deepEqual(await openAiResponse.json(), {
valid: false,
error: "Invalid API key",
});
assert.equal(calls[1].url, "https://proxy.example.com/models");
assert.equal(calls[1].init.headers.Authorization, "Bearer sk-openai-test");
});
test("provider-nodes validate route reports unexpected upstream failures", async () => {
globalThis.fetch = async () => {
throw new Error("boom");
};
const response = await providerNodesValidateRoute.POST(
new Request("http://localhost/api/provider-nodes/validate", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
baseUrl: "https://proxy.example.com",
apiKey: "sk-openai-test",
}),
})
);
assert.equal(response.status, 500);
assert.deepEqual(await response.json(), {
error: "Validation failed",
});
});
test("provider-nodes list route exposes CC flag state from server env", async () => {
process.env.ENABLE_CC_COMPATIBLE_PROVIDER = "true";
+15 -17
View File
@@ -10,24 +10,20 @@ process.env.DATA_DIR = TEST_DATA_DIR;
const core = await import("../../src/lib/db/core.ts");
const providersDb = await import("../../src/lib/db/providers.ts");
const chatRoute = await import("../../src/app/api/v1/chat/completions/route.ts");
const {
generateSignature,
invalidateBySignature,
setCachedResponse,
} = await import("../../src/lib/semanticCache.ts");
const {
clearModelUnavailability,
resetAllAvailability,
setModelUnavailable,
} = await import("../../src/domain/modelAvailability.ts");
const {
getCircuitBreaker,
resetAllCircuitBreakers,
STATE,
} = await import("../../src/shared/utils/circuitBreaker.ts");
const { generateSignature, invalidateBySignature, setCachedResponse } =
await import("../../src/lib/semanticCache.ts");
const { clearModelUnavailability, resetAllAvailability, setModelUnavailable } =
await import("../../src/domain/modelAvailability.ts");
const { getCircuitBreaker, resetAllCircuitBreakers, STATE } =
await import("../../src/shared/utils/circuitBreaker.ts");
const originalFetch = globalThis.fetch;
async function flushBackgroundWork() {
await new Promise((resolve) => setTimeout(resolve, 50));
await new Promise((resolve) => setImmediate(resolve));
}
async function resetStorage() {
core.resetDbInstance();
fs.rmSync(TEST_DATA_DIR, { recursive: true, force: true });
@@ -80,13 +76,15 @@ test.beforeEach(async () => {
await resetStorage();
});
test.afterEach(() => {
test.afterEach(async () => {
await flushBackgroundWork();
globalThis.fetch = originalFetch;
resetAllAvailability();
resetAllCircuitBreakers();
});
test.after(() => {
test.after(async () => {
await flushBackgroundWork();
globalThis.fetch = originalFetch;
resetAllAvailability();
resetAllCircuitBreakers();
+66
View File
@@ -52,3 +52,69 @@ test("console log API normalizes numeric pino levels correctly", async () => {
["info", "warn"]
);
});
test("console log API filters by component, time window, and result limit", async () => {
fs.writeFileSync(
TEST_LOG_PATH,
[
JSON.stringify({
time: new Date(Date.now() - 2 * 60 * 60 * 1000).toISOString(),
level: "warn",
component: "router",
msg: "too old",
}),
"not-json",
JSON.stringify({
time: new Date().toISOString(),
level: "debug",
component: "router",
msg: "below level",
}),
JSON.stringify({
time: new Date().toISOString(),
level: "error",
component: "router-core",
msg: "match one",
}),
JSON.stringify({
timestamp: new Date().toISOString(),
level: "fatal",
module: "router-worker",
msg: "match two",
}),
].join("\n") + "\n",
"utf8"
);
const response = await route.GET(
new Request("http://localhost/api/logs/console?level=warn&component=router&limit=1")
);
const body = await response.json();
assert.equal(response.status, 200);
assert.equal(body.length, 1);
assert.equal(body[0].level, "fatal");
assert.equal(body[0].timestamp !== undefined, true);
});
test("console log API returns an empty list for a missing file and surfaces read errors", async () => {
fs.rmSync(TEST_LOG_PATH, { force: true });
const missingResponse = await route.GET(new Request("http://localhost/api/logs/console"));
assert.equal(missingResponse.status, 200);
assert.deepEqual(await missingResponse.json(), []);
const brokenPath = path.join(TEST_LOG_DIR, "dir-log");
fs.mkdirSync(brokenPath, { recursive: true });
process.env.APP_LOG_FILE_PATH = brokenPath;
try {
const brokenResponse = await route.GET(new Request("http://localhost/api/logs/console"));
assert.equal(brokenResponse.status, 500);
const payload = await brokenResponse.json();
assert.equal(typeof payload.error, "string");
assert.equal(payload.error.length > 0, true);
} finally {
process.env.APP_LOG_FILE_PATH = TEST_LOG_PATH;
}
});
+156
View File
@@ -2,8 +2,11 @@ import test from "node:test";
import assert from "node:assert/strict";
import {
buildChatRequest,
decodeMessage,
decodeField,
encodeField,
encodeMcpTool,
extractTextFromResponse,
generateCursorBody,
parseConnectRPCFrame,
@@ -59,6 +62,54 @@ test("parseConnectRPCFrame returns null for truncated frames", () => {
assert.equal(parseConnectRPCFrame(frame.slice(0, frame.length - 1)), null);
});
test("parseConnectRPCFrame keeps the raw payload when a compressed frame is not valid gzip", () => {
const payload = textEncoder.encode("not-gzip");
const frame = new Uint8Array(5 + payload.length);
frame[0] = 0x01;
frame[1] = (payload.length >> 24) & 0xff;
frame[2] = (payload.length >> 16) & 0xff;
frame[3] = (payload.length >> 8) & 0xff;
frame[4] = payload.length & 0xff;
frame.set(payload, 5);
const parsed = parseConnectRPCFrame(frame);
assert.equal(parsed.flags, 0x01);
assert.equal(parsed.consumed, frame.length);
assert.equal(textDecoder.decode(parsed.payload), "not-gzip");
});
test("decodeField handles fixed-width wire types and past-end offsets", () => {
const buffer = Uint8Array.from([
(1 << 3) | 1,
1,
2,
3,
4,
5,
6,
7,
8,
(2 << 3) | 5,
9,
10,
11,
12,
]);
const [field1, wire1, value1, pos1] = decodeField(buffer, 0);
const [field2, wire2, value2, pos2] = decodeField(buffer, pos1);
const pastEnd = decodeField(buffer, pos2);
assert.equal(field1, 1);
assert.equal(wire1, 1);
assert.deepEqual([...value1], [1, 2, 3, 4, 5, 6, 7, 8]);
assert.equal(field2, 2);
assert.equal(wire2, 5);
assert.deepEqual([...value2], [9, 10, 11, 12]);
assert.deepEqual(pastEnd, [null, null, null, pos2]);
});
test("extractTextFromResponse reads MCP nested tool metadata and alternate last-tool flag", () => {
const toolCallPayload = encodeField(
TOP_LEVEL_TOOL_CALL,
@@ -91,6 +142,40 @@ test("extractTextFromResponse reads MCP nested tool metadata and alternate last-
assert.equal(extracted.toolCall.isLast, true);
});
test("extractTextFromResponse falls back to raw args when MCP metadata is absent", () => {
const toolCallPayload = encodeField(
TOP_LEVEL_TOOL_CALL,
LEN,
concatArrays(
encodeField(TOOL_ID, LEN, "call_fallback"),
encodeField(TOOL_NAME, LEN, "read_file"),
encodeField(TOOL_RAW_ARGS, LEN, '{"path":"/tmp/fallback"}')
)
);
const extracted = extractTextFromResponse(toolCallPayload);
assert.equal(extracted.toolCall.id, "call_fallback");
assert.equal(extracted.toolCall.function.name, "read_file");
assert.equal(extracted.toolCall.function.arguments, '{"path":"/tmp/fallback"}');
assert.equal(extracted.toolCall.isLast, false);
});
test("extractTextFromResponse ignores incomplete tool call payloads", () => {
const toolCallPayload = encodeField(
TOP_LEVEL_TOOL_CALL,
LEN,
encodeField(TOOL_NAME, LEN, "read_file")
);
assert.deepEqual(extractTextFromResponse(toolCallPayload), {
text: null,
error: null,
toolCall: null,
thinking: null,
});
});
test("extractTextFromResponse returns text and thinking blocks from response payloads", () => {
const responsePayload = encodeField(
TOP_LEVEL_RESPONSE,
@@ -160,3 +245,74 @@ test("generateCursorBody encodes tool metadata, message ids and high reasoning m
assert.equal(request.get(30).length >= 2, true);
assert.equal(request.get(49)[0].value, 2);
});
test("buildChatRequest normalizes mixed assistant tool payloads without duplicating matching tool-result messages", () => {
const requestFrame = buildChatRequest(
[
{ role: "user", content: "Hello" },
{
role: "assistant",
content: "",
tool_calls: [
{
id: "call_1",
type: "function",
function: {
name: "mcp__repo__read_file",
arguments: '{"path":"/tmp/a"}',
},
},
],
tool_results: [
{
tool_call_id: "call_1\nmc_model_1",
name: "mcp__repo__read_file",
index: 1,
raw_args: '{"path":"/tmp/a"}',
result: "file contents",
},
],
},
{
role: "assistant",
content: "",
tool_results: [
{
tool_call_id: "call_1\nmc_model_1",
name: "mcp__repo__read_file",
index: 1,
raw_args: '{"path":"/tmp/a"}',
result: "file contents",
},
],
},
],
"cursor-small",
[
{
name: "read_file",
description: "Read a file",
},
],
"medium"
);
const topLevel = decodeMessage(requestFrame);
const request = decodeMessage(topLevel.get(1)[0].value);
assert.equal(request.get(1).length, 3);
assert.equal(request.get(27)[0].value, 1);
assert.equal(request.get(48)[0].value, 0);
assert.equal(request.get(49)[0].value, 1);
assert.equal(request.has(29), true);
assert.equal(request.has(34), true);
});
test("encodeMcpTool keeps the custom server field even when name and schema are missing", () => {
const encoded = encodeMcpTool({ description: "" });
const decoded = decodeMessage(encoded);
assert.equal(decoded.has(1), false);
assert.equal(decoded.has(2), false);
assert.equal(decoded.has(3), false);
assert.equal(textDecoder.decode(decoded.get(4)[0].value), "custom");
});
+185
View File
@@ -8,23 +8,33 @@ const TEST_DATA_DIR = fs.mkdtempSync(path.join(os.tmpdir(), "omniroute-model-syn
process.env.DATA_DIR = TEST_DATA_DIR;
const core = await import("../../src/lib/db/core.ts");
const localDb = await import("../../src/lib/localDb.ts");
const providersDb = await import("../../src/lib/db/providers.ts");
const modelsDb = await import("../../src/lib/db/models.ts");
const callLogs = await import("../../src/lib/usage/callLogs.ts");
const modelSyncRoute = await import("../../src/app/api/providers/[id]/sync-models/route.ts");
const scheduler = await import("../../src/shared/services/modelSyncScheduler.ts");
const originalFetch = globalThis.fetch;
async function resetStorage() {
delete process.env.INITIAL_PASSWORD;
globalThis.fetch = originalFetch;
core.resetDbInstance();
fs.rmSync(TEST_DATA_DIR, { recursive: true, force: true });
fs.mkdirSync(TEST_DATA_DIR, { recursive: true });
}
test.after(() => {
globalThis.fetch = originalFetch;
core.resetDbInstance();
fs.rmSync(TEST_DATA_DIR, { recursive: true, force: true });
});
async function enableAuth() {
process.env.INITIAL_PASSWORD = "bootstrap-password";
await localDb.updateSettings({ requireLogin: true, password: "" });
}
test("model sync route skips success log when fetched models do not change stored models", async () => {
await resetStorage();
@@ -116,3 +126,178 @@ test("model sync route stores the real provider while keeping the account label"
globalThis.fetch = originalFetch;
}
});
test("model sync route requires authentication for external requests when auth is enabled", async () => {
await resetStorage();
await enableAuth();
const connection = await providersDb.createProviderConnection({
provider: "openrouter",
authType: "apikey",
name: "Protected Connection",
apiKey: "test-key",
});
const response = await modelSyncRoute.POST(
new Request(`http://localhost/api/providers/${connection.id}/sync-models`, {
method: "POST",
}),
{ params: { id: connection.id } }
);
const body = await response.json();
assert.equal(response.status, 401);
assert.equal(body.error.message, "Authentication required");
assert.equal(body.error.type, "invalid_api_key");
});
test("model sync route returns 404 for unknown connections after internal auth passes", async () => {
await resetStorage();
const response = await modelSyncRoute.POST(
new Request("http://localhost/api/providers/missing/sync-models", {
method: "POST",
headers: scheduler.buildModelSyncInternalHeaders(),
}),
{ params: { id: "missing" } }
);
assert.equal(response.status, 404);
assert.deepEqual(await response.json(), { error: "Connection not found" });
});
test("model sync route propagates upstream failures and records an error log entry", async () => {
await resetStorage();
const connection = await providersDb.createProviderConnection({
provider: "openrouter",
authType: "apikey",
name: "Error Branch",
apiKey: "test-key",
});
globalThis.fetch = async (url) => {
assert.equal(String(url), `http://localhost/api/providers/${connection.id}/models`);
return Response.json({ error: "Provider upstream unavailable" }, { status: 502 });
};
const response = await modelSyncRoute.POST(
new Request(`http://localhost/api/providers/${connection.id}/sync-models`, {
method: "POST",
headers: scheduler.buildModelSyncInternalHeaders(),
}),
{ params: { id: connection.id } }
);
const body = await response.json();
const logs = await callLogs.getCallLogs({ model: "model-sync", limit: 10 });
assert.equal(response.status, 502);
assert.equal(body.error, "Provider upstream unavailable");
assert.equal(logs.length, 1);
assert.equal(logs[0].status, 502);
assert.equal(logs[0].provider, "openrouter");
assert.equal(logs[0].path, `/api/providers/${connection.id}/models`);
});
test("model sync route writes synced available models for Gemini connections", async () => {
await resetStorage();
const connection = await providersDb.createProviderConnection({
provider: "gemini",
authType: "apikey",
name: "Gemini Sync",
apiKey: "gm-key",
});
globalThis.fetch = async (url) => {
assert.equal(String(url), `http://localhost/api/providers/${connection.id}/models`);
return Response.json({
models: [
{
id: "gemini-custom-preview",
name: "Gemini Custom Preview",
supportedEndpoints: ["chat", "embeddings"],
inputTokenLimit: 32768,
outputTokenLimit: 8192,
description: "Custom Gemini preview model",
supportsThinking: true,
},
],
});
};
const response = await modelSyncRoute.POST(
new Request(`http://localhost/api/providers/${connection.id}/sync-models`, {
method: "POST",
headers: scheduler.buildModelSyncInternalHeaders(),
}),
{ params: { id: connection.id } }
);
const body = await response.json();
const synced = await modelsDb.getSyncedAvailableModels("gemini");
const logs = await callLogs.getCallLogs({ model: "model-sync", limit: 10 });
assert.equal(response.status, 200);
assert.equal(body.provider, "gemini");
assert.equal(body.syncedModels, 1);
assert.equal(body.logged, true);
assert.deepEqual(body.modelChanges, { added: 1, removed: 0, updated: 0, total: 1 });
assert.deepEqual(body.models, [
{
id: "gemini-custom-preview",
name: "Gemini Custom Preview",
source: "auto-sync",
apiFormat: "chat-completions",
supportedEndpoints: ["chat", "embeddings"],
inputTokenLimit: 32768,
outputTokenLimit: 8192,
description: "Custom Gemini preview model",
supportsThinking: true,
},
]);
assert.deepEqual(synced, [
{
id: "gemini-custom-preview",
name: "Gemini Custom Preview",
source: "api-sync",
supportedEndpoints: ["chat", "embeddings"],
inputTokenLimit: 32768,
outputTokenLimit: 8192,
description: "Custom Gemini preview model",
supportsThinking: true,
},
]);
assert.equal(logs.length, 1);
assert.equal(logs[0].status, 200);
});
test("model sync route returns 500 and records a failure when the internal models fetch throws", async () => {
await resetStorage();
const connection = await providersDb.createProviderConnection({
provider: "openrouter",
authType: "apikey",
name: "Exploding Sync",
apiKey: "test-key",
});
globalThis.fetch = async () => {
throw new Error("network exploded");
};
const response = await modelSyncRoute.POST(
new Request(`http://localhost/api/providers/${connection.id}/sync-models`, {
method: "POST",
headers: scheduler.buildModelSyncInternalHeaders(),
}),
{ params: { id: connection.id } }
);
const body = await response.json();
const logs = await callLogs.getCallLogs({ model: "model-sync", limit: 10 });
assert.equal(response.status, 500);
assert.equal(body.error, "network exploded");
assert.equal(logs.length, 1);
assert.equal(logs[0].status, 500);
assert.equal(logs[0].provider, "openrouter");
});
+174
View File
@@ -0,0 +1,174 @@
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-provider-nodes-route-"));
process.env.DATA_DIR = TEST_DATA_DIR;
const core = await import("../../src/lib/db/core.ts");
const providersDb = await import("../../src/lib/db/providers.ts");
const providerNodesRoute = await import("../../src/app/api/provider-nodes/route.ts");
const { OPENAI_COMPATIBLE_PREFIX, ANTHROPIC_COMPATIBLE_PREFIX, CLAUDE_CODE_COMPATIBLE_PREFIX } =
await import("../../src/shared/constants/providers.ts");
async function resetStorage() {
delete process.env.ENABLE_CC_COMPATIBLE_PROVIDER;
core.resetDbInstance();
fs.rmSync(TEST_DATA_DIR, { recursive: true, force: true });
fs.mkdirSync(TEST_DATA_DIR, { recursive: true });
}
function makeRequest(body) {
return new Request("http://localhost/api/provider-nodes", {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify(body),
});
}
test.beforeEach(async () => {
await resetStorage();
});
test.after(async () => {
await resetStorage();
fs.rmSync(TEST_DATA_DIR, { recursive: true, force: true });
});
test("provider nodes route lists stored nodes and exposes the CC feature flag", async () => {
await providersDb.createProviderNode({
id: "openai-compatible-chat-seeded",
name: "Seeded Node",
prefix: "seed",
type: "openai-compatible",
apiType: "chat",
baseUrl: "https://seed.example.com/v1",
});
process.env.ENABLE_CC_COMPATIBLE_PROVIDER = "true";
const response = await providerNodesRoute.GET();
const body = await response.json();
assert.equal(response.status, 200);
assert.equal(body.ccCompatibleProviderEnabled, true);
assert.equal(body.nodes.length, 1);
assert.equal(body.nodes[0].name, "Seeded Node");
});
test("provider nodes route rejects malformed JSON and schema validation failures", async () => {
const malformed = await providerNodesRoute.POST(
new Request("http://localhost/api/provider-nodes", {
method: "POST",
headers: { "content-type": "application/json" },
body: "{",
})
);
const invalid = await providerNodesRoute.POST(
makeRequest({
name: "Missing API Type",
prefix: "missing-api-type",
})
);
const malformedBody = await malformed.json();
const invalidBody = await invalid.json();
assert.equal(malformed.status, 400);
assert.equal(malformedBody.error.message, "Invalid request");
assert.deepEqual(malformedBody.error.details, [{ field: "body", message: "Invalid JSON body" }]);
assert.equal(invalid.status, 400);
assert.equal(invalidBody.error.message, "Invalid request");
assert.match(
invalidBody.error.details.find((detail) => detail.field === "apiType")?.message || "",
/Invalid OpenAI compatible API type/
);
});
test("provider nodes route creates OpenAI-compatible nodes with normalized defaults", async () => {
const response = await providerNodesRoute.POST(
makeRequest({
name: " OpenAI Proxy ",
prefix: " openlike ",
apiType: "chat",
baseUrl: " https://proxy.example.com/v1 ",
chatPath: "",
modelsPath: "",
})
);
const body = await response.json();
assert.equal(response.status, 201);
assert.match(body.node.id, new RegExp(`^${OPENAI_COMPATIBLE_PREFIX}chat-`));
assert.equal(body.node.type, "openai-compatible");
assert.equal(body.node.name, "OpenAI Proxy");
assert.equal(body.node.prefix, "openlike");
assert.equal(body.node.baseUrl, "https://proxy.example.com/v1");
assert.equal(body.node.chatPath, null);
assert.equal(body.node.modelsPath, null);
});
test("provider nodes route creates Anthropics-compatible nodes and sanitizes messages URLs", async () => {
const response = await providerNodesRoute.POST(
makeRequest({
type: "anthropic-compatible",
name: " Anthropic Gateway ",
prefix: " anthropicx ",
baseUrl: " https://anthropic.example.com/v1/messages?beta=1 ",
modelsPath: "/models",
})
);
const body = await response.json();
assert.equal(response.status, 201);
assert.match(body.node.id, new RegExp(`^${ANTHROPIC_COMPATIBLE_PREFIX}`));
assert.equal(body.node.type, "anthropic-compatible");
assert.equal(body.node.name, "Anthropic Gateway");
assert.equal(body.node.prefix, "anthropicx");
assert.equal(body.node.baseUrl, "https://anthropic.example.com/v1");
assert.equal(body.node.modelsPath, "/models");
});
test("provider nodes route blocks CC-compatible nodes when the feature flag is disabled", async () => {
const response = await providerNodesRoute.POST(
makeRequest({
type: "anthropic-compatible",
compatMode: "cc",
name: "Claude Code Disabled",
prefix: "cc-disabled",
baseUrl: "https://cc.example.com/v1/messages?beta=1",
})
);
const body = await response.json();
assert.equal(response.status, 403);
assert.equal(body.error, "CC Compatible provider is disabled");
});
test("provider nodes route creates CC-compatible nodes with CC-specific URL normalization", async () => {
process.env.ENABLE_CC_COMPATIBLE_PROVIDER = "true";
const response = await providerNodesRoute.POST(
makeRequest({
type: "anthropic-compatible",
compatMode: "cc",
name: " Claude Code Gateway ",
prefix: " cc-gateway ",
baseUrl: " https://cc.example.com/v1/messages?beta=1 ",
chatPath: "/chat",
modelsPath: "/models",
})
);
const body = await response.json();
assert.equal(response.status, 201);
assert.match(body.node.id, new RegExp(`^${CLAUDE_CODE_COMPATIBLE_PREFIX}`));
assert.equal(body.node.type, "anthropic-compatible");
assert.equal(body.node.name, "Claude Code Gateway");
assert.equal(body.node.prefix, "cc-gateway");
assert.equal(body.node.baseUrl, "https://cc.example.com");
assert.equal(body.node.chatPath, "/chat");
assert.equal(body.node.modelsPath, null);
});
+140
View File
@@ -7,6 +7,8 @@ import proxyFetch, {
runWithTlsTracking,
isTlsFingerprintActive,
} from "../../open-sse/utils/proxyFetch.ts";
import { getDefaultDispatcher } from "../../open-sse/utils/proxyDispatcher.ts";
import tlsClient from "../../open-sse/utils/tlsClient.ts";
async function withEnv(overrides, fn) {
const previous = new Map();
@@ -56,6 +58,14 @@ async function withHttpServer(handler, fn) {
}
}
const originalTlsAvailable = tlsClient.available;
const originalTlsFetch = tlsClient.fetch.bind(tlsClient);
test.afterEach(() => {
tlsClient.available = originalTlsAvailable;
tlsClient.fetch = originalTlsFetch;
});
test("proxy fetch bypasses environment proxy when NO_PROXY matches the target host", async () => {
await withHttpServer(
(_req, res) => {
@@ -81,6 +91,33 @@ test("proxy fetch bypasses environment proxy when NO_PROXY matches the target ho
);
});
test("proxy fetch honors suffix-and-port NO_PROXY patterns", async () => {
await withHttpServer(
(_req, res) => {
res.writeHead(200, { "Content-Type": "text/plain" });
res.end("suffix-bypassed");
},
async (url) => {
const parsed = new URL(url);
await withEnv(
{
HTTP_PROXY: "http://127.0.0.1:9",
HTTPS_PROXY: undefined,
ALL_PROXY: undefined,
NO_PROXY: `.0.0.1:${parsed.port}`,
},
async () => {
const response = await proxyFetch(url);
assert.equal(response.status, 200);
assert.equal(await response.text(), "suffix-bypassed");
}
);
}
);
});
test("proxy fetch fails closed when an invalid environment proxy is configured", async () => {
await withHttpServer(
(_req, res) => {
@@ -110,6 +147,28 @@ test("runWithProxyContext requires a callback function", async () => {
);
});
test("proxy fetch respects an explicit dispatcher override", async () => {
await withHttpServer(
(req, res) => {
assert.equal(req.method, "POST");
res.writeHead(200, { "Content-Type": "text/plain" });
res.end("dispatcher");
},
async (url) => {
const response = await proxyFetch(
new Request(url, {
method: "POST",
body: "payload",
}),
{ dispatcher: getDefaultDispatcher() }
);
assert.equal(response.status, 200);
assert.equal(await response.text(), "dispatcher");
}
);
});
test("runWithTlsTracking reports direct executions without TLS fingerprint usage", async () => {
await withEnv({ ENABLE_TLS_FINGERPRINT: undefined }, async () => {
const tracked = await runWithTlsTracking(async () => "ok");
@@ -121,3 +180,84 @@ test("runWithTlsTracking reports direct executions without TLS fingerprint usage
assert.equal(isTlsFingerprintActive(), false);
});
});
test("proxy fetch uses TLS fingerprint transport when enabled and available", async () => {
await withEnv(
{
ENABLE_TLS_FINGERPRINT: "true",
HTTP_PROXY: undefined,
HTTPS_PROXY: undefined,
ALL_PROXY: undefined,
NO_PROXY: undefined,
},
async () => {
tlsClient.available = true;
tlsClient.fetch = async (url, options = {}) => {
assert.equal(url, "https://omniroute.example.test/hello");
assert.equal(options.method, "POST");
return Response.json({ via: "tls-client" });
};
const tracked = await runWithTlsTracking(() =>
proxyFetch("https://omniroute.example.test/hello", {
method: "POST",
headers: { "x-test": "1" },
})
);
assert.equal(isTlsFingerprintActive(), true);
assert.equal(tracked.tlsFingerprintUsed, true);
assert.deepEqual(await tracked.result.json(), { via: "tls-client" });
}
);
});
test("proxy fetch falls back to native fetch when TLS fingerprint transport throws", async () => {
await withHttpServer(
(_req, res) => {
res.writeHead(200, { "Content-Type": "application/json" });
res.end(JSON.stringify({ via: "native-fetch" }));
},
async (url) => {
await withEnv(
{
ENABLE_TLS_FINGERPRINT: "true",
HTTP_PROXY: undefined,
HTTPS_PROXY: undefined,
ALL_PROXY: undefined,
NO_PROXY: undefined,
},
async () => {
tlsClient.available = true;
tlsClient.fetch = async () => {
throw new Error("tls fingerprint unavailable");
};
const tracked = await runWithTlsTracking(() => proxyFetch(url));
assert.equal(tracked.tlsFingerprintUsed, false);
assert.deepEqual(await tracked.result.json(), { via: "native-fetch" });
}
);
}
);
});
test("runWithProxyContext accepts reachable HTTP proxy endpoints and returns callback result", async () => {
await withHttpServer(
(_req, res) => res.end("proxy-ok"),
async (url) => {
const parsed = new URL(url);
const result = await runWithProxyContext(
{
type: "http",
host: parsed.hostname,
port: parsed.port,
},
async () => "ok"
);
assert.equal(result, "ok");
}
);
});
@@ -17,6 +17,25 @@ const proxyBulkAssignV1Route =
await import("../../src/app/api/v1/management/proxies/bulk-assign/route.ts");
const proxyLogger = await import("../../src/lib/proxyLogger.ts");
async function withEnv(name, value, fn) {
const previous = process.env[name];
if (value === undefined) {
delete process.env[name];
} else {
process.env[name] = value;
}
try {
return await fn();
} finally {
if (previous === undefined) {
delete process.env[name];
} else {
process.env[name] = previous;
}
}
}
async function resetStorage() {
core.resetDbInstance();
fs.rmSync(TEST_DATA_DIR, { recursive: true, force: true });
@@ -200,3 +219,152 @@ test("v1 bulk assignment updates multiple scope IDs in one request", async () =>
const checkPayload = await checkRes.json();
assert.equal(checkPayload.items.length >= 2, true);
});
test("v1 proxy management companion routes require auth when login protection is enabled", async () => {
await resetStorage();
await withEnv("INITIAL_PASSWORD", "secret", async () => {
const assignmentsGetRes = await proxyAssignmentsV1Route.GET(
new Request("http://localhost/api/v1/management/proxies/assignments")
);
assert.equal(assignmentsGetRes.status, 401);
const assignmentsPutRes = await proxyAssignmentsV1Route.PUT(
new Request("http://localhost/api/v1/management/proxies/assignments", {
method: "PUT",
headers: {
"Content-Type": "application/json",
Authorization: "Bearer invalid-management-token",
},
body: JSON.stringify({
scope: "global",
proxyId: null,
}),
})
);
assert.equal(assignmentsPutRes.status, 403);
const healthRes = await proxyHealthV1Route.GET(
new Request("http://localhost/api/v1/management/proxies/health", {
headers: {
Authorization: "Bearer invalid-management-token",
},
})
);
assert.equal(healthRes.status, 403);
const bulkRes = await proxyBulkAssignV1Route.PUT(
new Request("http://localhost/api/v1/management/proxies/bulk-assign", {
method: "PUT",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
scope: "global",
proxyId: null,
}),
})
);
assert.equal(bulkRes.status, 401);
});
});
test("v1 assignments route resolves connection proxies and bulk assignment covers validation branches", async () => {
await resetStorage();
const providerConn = await providersDb.createProviderConnection({
provider: "openai",
authType: "apikey",
name: "v1-resolve",
apiKey: "sk-test-v1-resolve",
});
const proxyRes = await proxyV1Route.POST(
new Request("http://localhost/api/v1/management/proxies", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
name: "Resolve Proxy",
type: "http",
host: "resolve.local",
port: 9000,
}),
})
);
const proxy = await proxyRes.json();
const assignRes = await proxyAssignmentsV1Route.PUT(
new Request("http://localhost/api/v1/management/proxies/assignments", {
method: "PUT",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
scope: "account",
scopeId: providerConn.id,
proxyId: proxy.id,
}),
})
);
assert.equal(assignRes.status, 200);
const resolveRes = await proxyAssignmentsV1Route.GET(
new Request(
`http://localhost/api/v1/management/proxies/assignments?resolve_connection_id=${providerConn.id}`
)
);
assert.equal(resolveRes.status, 200);
const resolvePayload = await resolveRes.json();
assert.equal(resolvePayload.level, "account");
assert.equal(resolvePayload.proxy.host, "resolve.local");
const invalidJsonRes = await proxyBulkAssignV1Route.PUT(
new Request("http://localhost/api/v1/management/proxies/bulk-assign", {
method: "PUT",
headers: { "Content-Type": "application/json" },
body: "{",
})
);
assert.equal(invalidJsonRes.status, 400);
const invalidPayloadRes = await proxyBulkAssignV1Route.PUT(
new Request("http://localhost/api/v1/management/proxies/bulk-assign", {
method: "PUT",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
scope: "provider",
scopeIds: [],
}),
})
);
assert.equal(invalidPayloadRes.status, 400);
const normalizedRes = await proxyBulkAssignV1Route.PUT(
new Request("http://localhost/api/v1/management/proxies/bulk-assign", {
method: "PUT",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
scope: "key",
scopeIds: [providerConn.id, providerConn.id],
proxyId: proxy.id,
}),
})
);
assert.equal(normalizedRes.status, 200);
const normalizedPayload = await normalizedRes.json();
assert.equal(normalizedPayload.scope, "account");
assert.equal(normalizedPayload.requested, 2);
assert.equal(normalizedPayload.updated, 1);
const globalRes = await proxyBulkAssignV1Route.PUT(
new Request("http://localhost/api/v1/management/proxies/bulk-assign", {
method: "PUT",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
scope: "global",
proxyId: proxy.id,
}),
})
);
assert.equal(globalRes.status, 200);
const globalPayload = await globalRes.json();
assert.equal(globalPayload.scope, "global");
assert.equal(globalPayload.requested, 1);
assert.equal(globalPayload.updated, 1);
});
+30 -1
View File
@@ -1,6 +1,13 @@
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-rate-limit-manager-"));
process.env.DATA_DIR = TEST_DATA_DIR;
const core = await import("../../src/lib/db/core.ts");
const rateLimitManager = await import("../../open-sse/services/rateLimitManager.ts");
const accountFallback = await import("../../open-sse/services/accountFallback.ts");
@@ -8,9 +15,31 @@ function wait(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
async function flushBackgroundWork() {
await wait(50);
await new Promise((resolve) => setImmediate(resolve));
}
async function resetStorage() {
core.resetDbInstance();
fs.rmSync(TEST_DATA_DIR, { recursive: true, force: true });
fs.mkdirSync(TEST_DATA_DIR, { recursive: true });
}
test.beforeEach(async () => {
await resetStorage();
});
test.afterEach(async () => {
await rateLimitManager.__resetRateLimitManagerForTests();
await wait(5);
await flushBackgroundWork();
});
test.after(async () => {
await rateLimitManager.__resetRateLimitManagerForTests();
await flushBackgroundWork();
core.resetDbInstance();
fs.rmSync(TEST_DATA_DIR, { recursive: true, force: true });
});
test("rate limit manager bypasses disabled connections and exposes inactive status", async () => {
+175
View File
@@ -0,0 +1,175 @@
import test from "node:test";
import assert from "node:assert/strict";
import {
createDisconnectAwareStream,
createStreamController,
pipeWithDisconnect,
} from "../../open-sse/utils/streamHandler.ts";
const encoder = new TextEncoder();
const decoder = new TextDecoder();
async function readStreamText(stream) {
const reader = stream.getReader();
const chunks = [];
while (true) {
const { done, value } = await reader.read();
if (done) break;
chunks.push(value);
}
return decoder.decode(
chunks.length === 1 ? chunks[0] : Uint8Array.from(chunks.flatMap((chunk) => Array.from(chunk)))
);
}
test("createDisconnectAwareStream converts upstream errors into SSE error chunks", async () => {
const upstreamError = Object.assign(new Error("provider exploded"), { statusCode: 429 });
const transformStream = {
readable: new ReadableStream({
start(controller) {
controller.error(upstreamError);
},
}),
writable: {
getWriter() {
return {
abort() {},
};
},
},
};
const stream = createDisconnectAwareStream(transformStream, createStreamController());
const text = await readStreamText(stream);
assert.match(text, /"finish_reason":"error"/);
assert.match(text, /"message":"provider exploded"/);
assert.match(text, /"code":429/);
assert.match(text, /\[DONE\]/);
});
test("createDisconnectAwareStream cancel propagates disconnect reason and aborts the writer", async () => {
let aborted = false;
let disconnectEvent = null;
const transformStream = {
readable: new ReadableStream({
pull() {},
cancel() {},
}),
writable: {
getWriter() {
return {
abort() {
aborted = true;
},
};
},
},
};
const controller = createStreamController({
onDisconnect(event) {
disconnectEvent = event;
},
});
const stream = createDisconnectAwareStream(transformStream, controller);
await stream.cancel("client-gone");
assert.equal(aborted, true);
assert.equal(controller.isConnected(), false);
assert.equal(disconnectEvent.reason, "client-gone");
assert.ok(disconnectEvent.duration >= 0);
});
test("createDisconnectAwareStream uses the default cancel reason when none is provided", async () => {
let disconnectEvent = null;
const transformStream = {
readable: new ReadableStream({
cancel() {},
}),
writable: {
getWriter() {
return {
abort() {},
};
},
},
};
const controller = createStreamController({
onDisconnect(event) {
disconnectEvent = event;
},
});
const stream = createDisconnectAwareStream(transformStream, controller);
await stream.cancel();
assert.equal(disconnectEvent.reason, "cancelled");
});
test("createDisconnectAwareStream closes immediately when the controller is already disconnected", async () => {
const controller = createStreamController();
controller.handleDisconnect("preclosed");
const stream = createDisconnectAwareStream(
{
readable: new ReadableStream({
pull(inner) {
inner.enqueue(encoder.encode("ignored"));
},
}),
writable: {
getWriter() {
return {
abort() {},
};
},
},
},
controller
);
const reader = stream.getReader();
const first = await reader.read();
assert.equal(first.done, true);
});
test("createStreamController aborts after delayed disconnect and tolerates abort/unknown errors", async () => {
const controller = createStreamController();
const errorOnlyController = createStreamController();
controller.handleDisconnect();
controller.handleDisconnect("ignored-repeat");
errorOnlyController.handleError(new DOMException("aborted", "AbortError"));
errorOnlyController.handleError({ statusCode: 418 });
await new Promise((resolve) => setTimeout(resolve, 550));
assert.equal(controller.signal.aborted, true);
assert.equal(controller.isConnected(), false);
assert.equal(errorOnlyController.signal.aborted, false);
});
test("pipeWithDisconnect pipes transformed bytes and marks the controller complete", async () => {
const source = new ReadableStream({
start(controller) {
controller.enqueue(encoder.encode("hello"));
controller.close();
},
});
const providerResponse = new Response(source);
const controller = createStreamController();
const stream = pipeWithDisconnect(providerResponse, new TransformStream(), controller);
const text = await readStreamText(stream);
assert.equal(text, "hello");
assert.equal(controller.isConnected(), false);
});
@@ -318,3 +318,59 @@ test("refreshGitHubAndCopilotTokens composes GitHub and Copilot refresh response
}
);
});
test("checkAndRefreshToken leaves credentials untouched when nothing is close to expiry", async () => {
const now = 1_700_000_200_000;
const credentials = {
connectionId: "conn-stable",
accessToken: "stable-access",
refreshToken: "stable-refresh",
expiresAt: new Date(now + tokenRefresh.TOKEN_EXPIRY_BUFFER_MS + 60_000).toISOString(),
providerSpecificData: {
copilotToken: "copilot-stable",
copilotTokenExpiresAt: Math.floor(
(now + tokenRefresh.TOKEN_EXPIRY_BUFFER_MS + 60_000) / 1000
),
},
};
await withMockedNow(now, async () => {
await withMockedFetch(
async () => {
throw new Error("fetch should not be called");
},
async () => {
const refreshed = await tokenRefresh.checkAndRefreshToken("github", credentials);
assert.deepEqual(refreshed, credentials);
}
);
});
});
test("refreshGitHubAndCopilotTokens returns refreshed GitHub credentials when Copilot refresh fails", async () => {
await withMockedFetch(
async (url) => {
if (String(url) === OAUTH_ENDPOINTS.github.token) {
return jsonResponse({
access_token: "github-only-access",
refresh_token: "github-only-refresh",
expires_in: 1200,
});
}
assert.equal(String(url), "https://api.github.com/copilot_internal/v2/token");
return new Response("copilot unavailable", { status: 503 });
},
async () => {
const refreshed = await tokenRefresh.refreshGitHubAndCopilotTokens({
refreshToken: "github-refresh-only",
});
assert.deepEqual(refreshed, {
accessToken: "github-only-access",
refreshToken: "github-only-refresh",
expiresIn: 1200,
});
}
);
});