Files
OmniRoute/tests/unit/qoder-executor.test.mjs
2026-04-02 01:35:23 -03:00

259 lines
8.6 KiB
JavaScript

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";
import { QoderExecutor } from "../../open-sse/executors/qoder.ts";
import {
buildQoderPrompt,
getStaticQoderModels,
mapQoderModelToLevel,
normalizeQoderPatProviderData,
parseQoderCliFailure,
validateQoderCliPat,
} from "../../open-sse/services/qoderCli.ts";
function createTempDir() {
const testRoot = path.join(os.tmpdir(), "omniroute-test-tmp");
fs.mkdirSync(testRoot, { recursive: true });
return fs.mkdtempSync(path.join(testRoot, "qoder-"));
}
function writeExecutable(dir, name, body) {
const filePath = path.join(dir, name);
fs.writeFileSync(filePath, body, "utf8");
if (process.platform !== "win32") {
fs.chmodSync(filePath, 0o755);
}
return filePath;
}
function createQoderCliScript(dir, name, mode) {
if (process.platform === "win32") {
const successJson = '{"message":{"content":"OK"}}';
const successStream = [
'{"message":{"content":"O"}}',
'{"message":{"content":"OK"}}',
'{"type":"result","done":true}',
].join("\\n");
const body =
mode === "invalid"
? `@echo off\r\nif "%1"=="--version" echo qodercli 0.1.37 & exit /b 0\r\necho Invalid API key 1>&2\r\nexit /b 1\r\n`
: `@echo off\r\nif "%1"=="--version" echo qodercli 0.1.37 & exit /b 0\r\nset MODE=json\r\n:loop\r\nif "%1"=="" goto done\r\nif "%1"=="--output-format" (\r\n set MODE=%2\r\n)\r\nshift\r\ngoto loop\r\n:done\r\nif "%MODE%"=="stream-json" (\r\n echo ${successStream}\r\n) else (\r\n echo ${successJson}\r\n)\r\nexit /b 0\r\n`;
return writeExecutable(dir, `${name}.cmd`, body);
}
const successJson = `{"message":{"content":"OK"}}`;
const successStream = `{"message":{"content":"O"}}\n{"message":{"content":"OK"}}\n{"type":"result","done":true}`;
const body =
mode === "invalid"
? `#!/bin/sh
if [ "$1" = "--version" ] || [ "$1" = "-v" ]; then
echo "qodercli 0.1.37"
exit 0
fi
echo "Invalid API key" >&2
exit 1
`
: `#!/bin/sh
if [ "$1" = "--version" ] || [ "$1" = "-v" ]; then
echo "qodercli 0.1.37"
exit 0
fi
MODE=json
PREV=""
for ARG in "$@"; do
if [ "$PREV" = "--output-format" ]; then
MODE="$ARG"
fi
PREV="$ARG"
done
if [ "$MODE" = "stream-json" ]; then
printf '%s\n' '${successStream}'
else
printf '%s\n' '${successJson}'
fi
exit 0
`;
return writeExecutable(dir, name, body);
}
test("QoderExecutor: constructor sets provider to qoder", () => {
const executor = new QoderExecutor();
assert.equal(executor.getProvider(), "qoder");
});
test("QoderExecutor: buildHeaders only keeps generic JSON and stream headers", () => {
const executor = new QoderExecutor();
assert.deepEqual(executor.buildHeaders({ apiKey: "pat" }, true), {
"Content-Type": "application/json",
Accept: "text/event-stream",
});
assert.deepEqual(executor.buildHeaders({ apiKey: "pat" }, false), {
"Content-Type": "application/json",
});
});
test("QoderExecutor: buildUrl uses the live qoder.com API base", () => {
const executor = new QoderExecutor();
assert.equal(executor.buildUrl("qoder-rome-30ba3b", false), "https://api.qoder.com/v1/chat/completions");
});
test("normalizeQoderPatProviderData forces PAT + qodercli transport", () => {
assert.deepEqual(normalizeQoderPatProviderData({ region: "sa-east-1" }), {
region: "sa-east-1",
authMode: "pat",
transport: "qodercli",
});
});
test("mapQoderModelToLevel maps static models to qodercli levels", () => {
assert.equal(mapQoderModelToLevel("qoder-rome-30ba3b"), "qmodel");
assert.equal(mapQoderModelToLevel("deepseek-r1"), "ultimate");
assert.equal(mapQoderModelToLevel("qwen3-max"), "performance");
assert.equal(mapQoderModelToLevel(""), null);
});
test("getStaticQoderModels exposes the static if/* catalog seed", () => {
const models = getStaticQoderModels();
assert.ok(models.some((model) => model.id === "qoder-rome-30ba3b"));
assert.ok(models.some((model) => model.id === "deepseek-r1"));
});
test("buildQoderPrompt flattens transcript and warns against local tools", () => {
const prompt = buildQoderPrompt({
messages: [
{ role: "system", content: "Follow the user request." },
{
role: "user",
content: [{ type: "text", text: "Reply with OK." }],
},
{
role: "assistant",
tool_calls: [
{
type: "function",
function: { name: "pwd", arguments: "{}" },
},
],
content: "",
},
],
tools: [{ type: "function", function: { name: "pwd" } }],
});
assert.match(prompt, /Conversation transcript:/);
assert.match(prompt, /USER:\nReply with OK\./);
assert.match(prompt, /TOOL_CALL pwd: \{\}/);
assert.match(prompt, /Do not call those tools yourself\./);
});
test("parseQoderCliFailure classifies auth, runtime and timeout failures", () => {
assert.deepEqual(parseQoderCliFailure("Invalid API key"), {
status: 401,
message: "Invalid API key",
code: "upstream_auth_error",
});
assert.deepEqual(parseQoderCliFailure("command not found: qodercli"), {
status: 503,
message: "command not found: qodercli",
code: "runtime_error",
});
assert.deepEqual(parseQoderCliFailure("request timed out"), {
status: 504,
message: "request timed out",
code: "timeout",
});
});
test("validateQoderCliPat succeeds when qodercli returns a JSON response", async () => {
const prev = process.env.CLI_QODER_BIN;
const tmpDir = createTempDir();
const script = createQoderCliScript(tmpDir, "qodercli-ok", "success");
process.env.CLI_QODER_BIN = script;
try {
const result = await validateQoderCliPat({ apiKey: "pat_test" });
assert.deepEqual(result, { valid: true, error: null, unsupported: false });
} finally {
if (prev === undefined) delete process.env.CLI_QODER_BIN;
else process.env.CLI_QODER_BIN = prev;
fs.rmSync(tmpDir, { recursive: true, force: true });
}
});
test("validateQoderCliPat returns invalid api key for auth failures", async () => {
const prev = process.env.CLI_QODER_BIN;
const tmpDir = createTempDir();
const script = createQoderCliScript(tmpDir, "qodercli-bad", "invalid");
process.env.CLI_QODER_BIN = script;
try {
const result = await validateQoderCliPat({ apiKey: "pat_bad" });
assert.deepEqual(result, { valid: false, error: "Invalid API key", unsupported: false });
} finally {
if (prev === undefined) delete process.env.CLI_QODER_BIN;
else process.env.CLI_QODER_BIN = prev;
fs.rmSync(tmpDir, { recursive: true, force: true });
}
});
test("QoderExecutor: non-stream calls return an OpenAI-compatible completion payload", async () => {
const prev = process.env.CLI_QODER_BIN;
const tmpDir = createTempDir();
const script = createQoderCliScript(tmpDir, "qodercli-exec", "success");
process.env.CLI_QODER_BIN = script;
try {
const executor = new QoderExecutor();
const { response, url } = await executor.execute({
model: "qoder-rome-30ba3b",
body: { messages: [{ role: "user", content: "Reply with OK only." }] },
stream: false,
credentials: { apiKey: "pat_test" },
});
assert.equal(url, "qodercli://local");
assert.equal(response.status, 200);
const payload = await response.json();
assert.equal(payload.object, "chat.completion");
assert.equal(payload.choices[0].message.role, "assistant");
assert.equal(payload.choices[0].message.content, "OK");
} finally {
if (prev === undefined) delete process.env.CLI_QODER_BIN;
else process.env.CLI_QODER_BIN = prev;
fs.rmSync(tmpDir, { recursive: true, force: true });
}
});
test("QoderExecutor: stream calls emit OpenAI-compatible SSE chunks", async () => {
const prev = process.env.CLI_QODER_BIN;
const tmpDir = createTempDir();
const script = createQoderCliScript(tmpDir, "qodercli-stream", "success");
process.env.CLI_QODER_BIN = script;
try {
const executor = new QoderExecutor();
const { response } = await executor.execute({
model: "qoder-rome-30ba3b",
body: { messages: [{ role: "user", content: "Reply with OK only." }] },
stream: true,
credentials: { apiKey: "pat_test" },
});
assert.equal(response.status, 200);
const body = await response.text();
assert.match(body, /chat\.completion\.chunk/);
assert.match(body, /"role":"assistant"/);
assert.match(body, /"content":"O"/);
assert.match(body, /"content":"K"/);
assert.match(body, /\[DONE\]/);
} finally {
if (prev === undefined) delete process.env.CLI_QODER_BIN;
else process.env.CLI_QODER_BIN = prev;
fs.rmSync(tmpDir, { recursive: true, force: true });
}
});