b7bd41942d
Move chat pipeline validation, circuit breaker execution, proxy resolution, logging, and session header handling into dedicated helpers to keep the SSE handler smaller and easier to verify. Also fix shared API option precedence, rebuild skill version caches after deletions, ignore api.trycloudflare.com false positives, and add rate-limit manager test flush/reset hooks for deterministic coverage. Expand integration and unit coverage across chat routing, auth, cloud sync, skills, executors, streaming, DB helpers, proxy handling, and provider/model utilities.
291 lines
9.0 KiB
JavaScript
291 lines
9.0 KiB
JavaScript
import test from "node:test";
|
|
import assert from "node:assert/strict";
|
|
|
|
const qoderCli = await import("../../open-sse/services/qoderCli.ts");
|
|
|
|
function withEnv(overrides, fn) {
|
|
const previous = new Map();
|
|
for (const [key, value] of Object.entries(overrides)) {
|
|
previous.set(key, process.env[key]);
|
|
if (value === undefined) {
|
|
delete process.env[key];
|
|
} else {
|
|
process.env[key] = value;
|
|
}
|
|
}
|
|
|
|
return Promise.resolve()
|
|
.then(fn)
|
|
.finally(() => {
|
|
for (const [key, value] of previous.entries()) {
|
|
if (value === undefined) {
|
|
delete process.env[key];
|
|
} else {
|
|
process.env[key] = value;
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
test("qoder cli env helpers honor explicit command and workspace overrides", async () => {
|
|
await withEnv(
|
|
{
|
|
CLI_QODER_BIN: " custom-qoder ",
|
|
QODER_CLI_WORKSPACE: "/tmp/qoder-workspace",
|
|
OMNIROUTE_QODER_WORKSPACE: "/tmp/ignored",
|
|
},
|
|
() => {
|
|
assert.equal(qoderCli.getQoderCliCommand(), "custom-qoder");
|
|
assert.equal(qoderCli.getQoderCliWorkspace(), "/tmp/qoder-workspace");
|
|
}
|
|
);
|
|
|
|
await withEnv(
|
|
{
|
|
CLI_QODER_BIN: undefined,
|
|
QODER_CLI_WORKSPACE: undefined,
|
|
OMNIROUTE_QODER_WORKSPACE: "/tmp/fallback-workspace",
|
|
},
|
|
() => {
|
|
assert.equal(qoderCli.getQoderCliCommand(), "qodercli");
|
|
assert.equal(qoderCli.getQoderCliWorkspace(), "/tmp/fallback-workspace");
|
|
}
|
|
);
|
|
});
|
|
|
|
test("qoder cli provider metadata helpers normalize PAT transport and detect transport type", () => {
|
|
assert.deepEqual(qoderCli.normalizeQoderPatProviderData({ region: "us" }), {
|
|
region: "us",
|
|
authMode: "pat",
|
|
transport: "qodercli",
|
|
});
|
|
|
|
assert.equal(qoderCli.isQoderCliTransport({ transport: "qodercli" }), true);
|
|
assert.equal(qoderCli.isQoderCliTransport({ authMode: "pat" }), true);
|
|
assert.equal(qoderCli.isQoderCliTransport({ transport: "http-legacy", authMode: "pat" }), false);
|
|
assert.equal(qoderCli.isQoderCliTransport({ transport: "http" }), false);
|
|
});
|
|
|
|
test("qoder cli static models are copied and model-to-level mapping covers major families", () => {
|
|
const models = qoderCli.getStaticQoderModels();
|
|
const snapshot = qoderCli.getStaticQoderModels();
|
|
|
|
models[0].name = "mutated";
|
|
|
|
assert.notEqual(snapshot[0].name, "mutated");
|
|
assert.equal(qoderCli.mapQoderModelToLevel("deepseek-r1"), "ultimate");
|
|
assert.equal(qoderCli.mapQoderModelToLevel("qwen3-max-preview"), "performance");
|
|
assert.equal(qoderCli.mapQoderModelToLevel("kimi-k2-0905"), "kmodel");
|
|
assert.equal(qoderCli.mapQoderModelToLevel("qwen3-coder-plus"), "qmodel");
|
|
assert.equal(qoderCli.mapQoderModelToLevel("qoder-rome-30ba3b"), "qmodel");
|
|
assert.equal(qoderCli.mapQoderModelToLevel("totally-unknown"), "auto");
|
|
assert.equal(qoderCli.mapQoderModelToLevel(""), null);
|
|
});
|
|
|
|
test("buildQoderPrompt flattens mixed content, tool calls, tool results and JSON output instructions", () => {
|
|
const prompt = qoderCli.buildQoderPrompt({
|
|
tools: [
|
|
{ type: "function", function: { name: "lookup_weather" } },
|
|
{ type: "function", function: { name: "" } },
|
|
{ name: "anthropic_tool" },
|
|
],
|
|
response_format: {
|
|
type: "json_schema",
|
|
json_schema: { schema: { type: "object", properties: { city: { type: "string" } } } },
|
|
},
|
|
messages: [
|
|
{ role: "system", content: "Top level system" },
|
|
{
|
|
role: "user",
|
|
content: [
|
|
{ type: "text", text: "Describe this image" },
|
|
{ type: "input_image", image_url: "ignored" },
|
|
],
|
|
},
|
|
{
|
|
role: "assistant",
|
|
content: "Thinking aloud",
|
|
tool_calls: [
|
|
{
|
|
function: {
|
|
name: "lookup_weather",
|
|
arguments: '{"city":"Sao Paulo"}',
|
|
},
|
|
},
|
|
],
|
|
},
|
|
{
|
|
role: "tool",
|
|
name: "lookup_weather",
|
|
content: [{ type: "text", text: "26C and sunny" }],
|
|
},
|
|
],
|
|
});
|
|
|
|
assert.match(
|
|
prompt,
|
|
/Caller-side tools are available externally: lookup_weather, anthropic_tool/
|
|
);
|
|
assert.match(prompt, /Return only valid JSON matching this schema/);
|
|
assert.match(prompt, /SYSTEM:\nTop level system/);
|
|
assert.match(prompt, /USER:\nDescribe this image\n\[Image omitted\]/);
|
|
assert.match(prompt, /TOOL_CALL lookup_weather: \{"city":"Sao Paulo"\}/);
|
|
assert.match(prompt, /TOOL \(lookup_weather\):\n26C and sunny/);
|
|
assert.match(prompt, /Reply now with the assistant response only\./);
|
|
});
|
|
|
|
test("buildQoderPrompt supports input arrays and json_object responses", () => {
|
|
const prompt = qoderCli.buildQoderPrompt({
|
|
response_format: { type: "json_object" },
|
|
input: [{ role: "user", content: [{ type: "input_text", text: "hello from input" }] }],
|
|
});
|
|
|
|
assert.match(prompt, /Return only valid JSON\./);
|
|
assert.match(prompt, /Conversation transcript:/);
|
|
assert.match(prompt, /USER:\nhello from input/);
|
|
});
|
|
|
|
test("qoder cli payload helpers normalize envelope text and completion payload shapes", () => {
|
|
assert.equal(
|
|
qoderCli.extractTextFromQoderEnvelope({
|
|
message: { content: "hello" },
|
|
}),
|
|
"hello"
|
|
);
|
|
assert.equal(
|
|
qoderCli.extractTextFromQoderEnvelope({
|
|
content: [
|
|
{ type: "text", text: "hi" },
|
|
{ type: "ignored", text: "drop" },
|
|
{ text: " there" },
|
|
],
|
|
}),
|
|
"hi there"
|
|
);
|
|
assert.equal(qoderCli.extractTextFromQoderEnvelope(null), "");
|
|
|
|
const completion = qoderCli.buildQoderCompletionPayload({
|
|
model: "qwen3-coder-plus",
|
|
text: "Ship it",
|
|
});
|
|
assert.equal(completion.object, "chat.completion");
|
|
assert.equal(completion.model, "qwen3-coder-plus");
|
|
assert.equal(completion.choices[0].message.content, "Ship it");
|
|
|
|
const chunk = qoderCli.buildQoderChunk({
|
|
id: "chunk-1",
|
|
model: "qoder-rome-30ba3b",
|
|
created: 123,
|
|
delta: { content: "partial" },
|
|
finishReason: "stop",
|
|
});
|
|
assert.deepEqual(chunk, {
|
|
id: "chunk-1",
|
|
object: "chat.completion.chunk",
|
|
created: 123,
|
|
model: "qoder-rome-30ba3b",
|
|
choices: [
|
|
{
|
|
index: 0,
|
|
delta: { content: "partial" },
|
|
finish_reason: "stop",
|
|
},
|
|
],
|
|
});
|
|
});
|
|
|
|
test("qoder cli failure parsing classifies auth, timeout and generic upstream errors", async () => {
|
|
assert.deepEqual(qoderCli.parseQoderCliFailure("Invalid API key"), {
|
|
status: 401,
|
|
message: "Invalid API key",
|
|
code: "upstream_auth_error",
|
|
});
|
|
assert.deepEqual(qoderCli.parseQoderCliFailure("", "request timeout"), {
|
|
status: 504,
|
|
message: "request timeout",
|
|
code: "timeout",
|
|
});
|
|
assert.deepEqual(qoderCli.parseQoderCliFailure("bad gateway", "more context"), {
|
|
status: 502,
|
|
message: "bad gateway\nmore context",
|
|
code: "upstream_error",
|
|
});
|
|
|
|
const authResponse = qoderCli.createQoderErrorResponse({
|
|
status: 401,
|
|
message: "denied",
|
|
code: "upstream_auth_error",
|
|
});
|
|
const providerResponse = qoderCli.createQoderErrorResponse({
|
|
status: 502,
|
|
message: "boom",
|
|
code: "upstream_error",
|
|
});
|
|
|
|
assert.equal(authResponse.status, 401);
|
|
assert.deepEqual(await authResponse.json(), {
|
|
error: {
|
|
message: "denied",
|
|
type: "authentication_error",
|
|
code: "upstream_auth_error",
|
|
},
|
|
});
|
|
assert.equal(providerResponse.status, 502);
|
|
assert.deepEqual(await providerResponse.json(), {
|
|
error: {
|
|
message: "boom",
|
|
type: "provider_error",
|
|
code: "upstream_error",
|
|
},
|
|
});
|
|
});
|
|
|
|
test("validateQoderCliPat builds COSY headers and handles success, HTTP failures and fetch errors", async () => {
|
|
const originalFetch = globalThis.fetch;
|
|
const calls = [];
|
|
|
|
globalThis.fetch = async (url, options = {}) => {
|
|
calls.push({ url: String(url), options });
|
|
if (calls.length === 1) {
|
|
return new Response("ok", { status: 200 });
|
|
}
|
|
if (calls.length === 2) {
|
|
return new Response("denied", { status: 403 });
|
|
}
|
|
throw new Error("network down");
|
|
};
|
|
|
|
try {
|
|
const success = await qoderCli.validateQoderCliPat({
|
|
apiKey: "pat-token",
|
|
providerSpecificData: { validationModelId: "kimi-k2" },
|
|
});
|
|
const denied = await qoderCli.validateQoderCliPat({
|
|
apiKey: "pat-token",
|
|
providerSpecificData: { modelId: "qwen3-max" },
|
|
});
|
|
const failed = await qoderCli.validateQoderCliPat({ apiKey: "pat-token" });
|
|
|
|
const firstBody = JSON.parse(String(calls[0].options.body));
|
|
assert.equal(success.valid, true);
|
|
assert.equal(success.error, null);
|
|
assert.equal(success.unsupported, false);
|
|
assert.equal(calls[0].url.includes("agent_chat_generation"), true);
|
|
assert.equal(firstBody.model, "kimi-k2");
|
|
assert.equal(firstBody.stream, false);
|
|
assert.match(calls[0].options.headers.Authorization, /^Bearer COSY\./);
|
|
assert.equal(typeof calls[0].options.headers["Cosy-Key"], "string");
|
|
assert.equal(calls[0].options.signal instanceof AbortSignal, true);
|
|
|
|
assert.equal(denied.valid, false);
|
|
assert.match(denied.error, /HTTP 403: denied/);
|
|
assert.equal(denied.unsupported, false);
|
|
|
|
assert.equal(failed.valid, false);
|
|
assert.equal(failed.error, "network down");
|
|
assert.equal(failed.unsupported, false);
|
|
} finally {
|
|
globalThis.fetch = originalFetch;
|
|
}
|
|
});
|