mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-08-05 06:42:12 +03:00
- Remove `new Request('http://localhost/api/keys')` default arg from GET handler in src/app/api/keys/route.ts (line 26)
- Fix api-key-reveal-route.test.mjs to pass explicit Request instead of calling GET() with no args
- Add --output-dir coverage to all c8 scripts in package.json
- Add coverage.reportsDirectory: 'coverage' to vitest.config.ts and vitest.mcp.config.ts
- Fix CHANGELOG.md structure (# Changelog + [Unreleased] to top)
- Remove 30+ stale coverage-* directories from project root
- Coverage: Statements 78.76% | Branches 72.75% | Functions 80.93% | Lines 78.76% (all thresholds passed)
321 lines
9.9 KiB
JavaScript
321 lines
9.9 KiB
JavaScript
import test from "node:test";
|
|
import assert from "node:assert/strict";
|
|
|
|
import { CursorExecutor } from "../../open-sse/executors/cursor.ts";
|
|
import {
|
|
decodeMessage,
|
|
encodeField,
|
|
parseConnectRPCFrame,
|
|
wrapConnectRPCFrame,
|
|
} from "../../open-sse/utils/cursorProtobuf.ts";
|
|
import {
|
|
generateCursorChecksum,
|
|
generateHashed64Hex,
|
|
generateSessionId,
|
|
} from "../../open-sse/utils/cursorChecksum.ts";
|
|
|
|
const LEN = 2;
|
|
const VARINT = 0;
|
|
const TOP_LEVEL_TOOL_CALL = 1;
|
|
const TOP_LEVEL_RESPONSE = 2;
|
|
const RESPONSE_TEXT = 1;
|
|
const TOOL_ID = 3;
|
|
const TOOL_NAME = 9;
|
|
const TOOL_RAW_ARGS = 10;
|
|
const TOOL_IS_LAST = 11;
|
|
|
|
function concatArrays(...arrays) {
|
|
const total = arrays.reduce((sum, array) => sum + array.length, 0);
|
|
const result = new Uint8Array(total);
|
|
let offset = 0;
|
|
|
|
for (const array of arrays) {
|
|
result.set(array, offset);
|
|
offset += array.length;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
function buildTextFrame(text) {
|
|
return Buffer.from(
|
|
wrapConnectRPCFrame(
|
|
encodeField(TOP_LEVEL_RESPONSE, LEN, encodeField(RESPONSE_TEXT, LEN, text)),
|
|
false
|
|
)
|
|
);
|
|
}
|
|
|
|
function buildToolCallFrame({ id, name, args, isLast }) {
|
|
return Buffer.from(
|
|
wrapConnectRPCFrame(
|
|
encodeField(
|
|
TOP_LEVEL_TOOL_CALL,
|
|
LEN,
|
|
concatArrays(
|
|
encodeField(TOOL_ID, LEN, id),
|
|
encodeField(TOOL_NAME, LEN, name),
|
|
encodeField(TOOL_RAW_ARGS, LEN, args),
|
|
encodeField(TOOL_IS_LAST, VARINT, isLast ? 1 : 0)
|
|
)
|
|
),
|
|
false
|
|
)
|
|
);
|
|
}
|
|
|
|
function buildJsonErrorFrame(error) {
|
|
return Buffer.from(wrapConnectRPCFrame(new TextEncoder().encode(JSON.stringify(error)), false));
|
|
}
|
|
|
|
test("CursorExecutor.buildUrl uses the configured Cursor endpoint", () => {
|
|
const executor = new CursorExecutor();
|
|
assert.equal(
|
|
executor.buildUrl(),
|
|
"https://api2.cursor.sh/aiserver.v1.ChatService/StreamUnifiedChatWithTools"
|
|
);
|
|
});
|
|
|
|
test("CursorExecutor.buildHeaders strips token prefixes and derives checksum/session headers", () => {
|
|
const executor = new CursorExecutor();
|
|
const originalDateNow = Date.now;
|
|
Date.now = () => 1_700_000_000_000;
|
|
|
|
try {
|
|
const headers = executor.buildHeaders({
|
|
accessToken: "prefix::real-token",
|
|
providerSpecificData: { machineId: "machine-1", ghostMode: false },
|
|
});
|
|
|
|
assert.equal(headers.authorization, "Bearer real-token");
|
|
assert.equal(headers["x-client-key"], generateHashed64Hex("real-token"));
|
|
assert.equal(headers["x-session-id"], generateSessionId("real-token"));
|
|
assert.equal(headers["x-cursor-checksum"], generateCursorChecksum("machine-1"));
|
|
assert.equal(headers["x-ghost-mode"], "false");
|
|
assert.equal(headers["connect-protocol-version"], "1");
|
|
assert.match(headers["x-amzn-trace-id"], /^Root=/);
|
|
assert.ok(headers["x-request-id"]);
|
|
} finally {
|
|
Date.now = originalDateNow;
|
|
}
|
|
});
|
|
|
|
test("CursorExecutor.buildHeaders requires a machine ID", () => {
|
|
const executor = new CursorExecutor();
|
|
assert.throws(
|
|
() => executor.buildHeaders({ accessToken: "real-token", providerSpecificData: {} }),
|
|
/Machine ID is required/
|
|
);
|
|
});
|
|
|
|
test("CursorExecutor.transformRequest produces a framed protobuf payload", () => {
|
|
const executor = new CursorExecutor();
|
|
const transformed = executor.transformRequest(
|
|
"claude-3.5-sonnet",
|
|
{ messages: [{ role: "user", content: "Hello" }], tools: [] },
|
|
true,
|
|
{}
|
|
);
|
|
const frame = parseConnectRPCFrame(transformed);
|
|
const fields = decodeMessage(frame.payload);
|
|
|
|
assert.ok(transformed instanceof Uint8Array);
|
|
assert.equal(frame.flags, 0);
|
|
assert.equal(frame.consumed, transformed.length);
|
|
assert.equal(fields.has(1), true);
|
|
});
|
|
|
|
test("CursorExecutor.transformProtobufToJSON aggregates text and split tool call arguments", async () => {
|
|
const executor = new CursorExecutor();
|
|
const body = { messages: [{ role: "user", content: "hi" }] };
|
|
const buffer = Buffer.concat([
|
|
buildTextFrame("Hello "),
|
|
buildToolCallFrame({
|
|
id: "call_1",
|
|
name: "read_file",
|
|
args: '{"path":',
|
|
isLast: false,
|
|
}),
|
|
buildToolCallFrame({
|
|
id: "call_1",
|
|
name: "read_file",
|
|
args: '"/tmp/a"}',
|
|
isLast: true,
|
|
}),
|
|
]);
|
|
|
|
const response = executor.transformProtobufToJSON(buffer, "cursor-small", body);
|
|
const payload = await response.json();
|
|
|
|
assert.equal(response.status, 200);
|
|
assert.equal(payload.object, "chat.completion");
|
|
assert.equal(payload.model, "cursor-small");
|
|
assert.equal(payload.choices[0].message.content, "Hello ");
|
|
assert.equal(payload.choices[0].finish_reason, "tool_calls");
|
|
assert.equal(payload.choices[0].message.tool_calls[0].function.name, "read_file");
|
|
assert.equal(payload.choices[0].message.tool_calls[0].function.arguments, '{"path":"/tmp/a"}');
|
|
assert.equal(payload.usage.estimated, true);
|
|
});
|
|
|
|
test("CursorExecutor.transformProtobufToSSE emits assistant chunks, tool deltas and DONE marker", async () => {
|
|
const executor = new CursorExecutor();
|
|
const body = { messages: [{ role: "user", content: "hi" }] };
|
|
const buffer = Buffer.concat([
|
|
buildTextFrame("Hello "),
|
|
buildToolCallFrame({
|
|
id: "call_1",
|
|
name: "read_file",
|
|
args: '{"path":',
|
|
isLast: false,
|
|
}),
|
|
buildToolCallFrame({
|
|
id: "call_1",
|
|
name: "read_file",
|
|
args: '"/tmp/a"}',
|
|
isLast: true,
|
|
}),
|
|
]);
|
|
|
|
const response = executor.transformProtobufToSSE(buffer, "cursor-small", body);
|
|
const text = await response.text();
|
|
|
|
assert.equal(response.status, 200);
|
|
assert.equal(response.headers.get("Content-Type"), "text/event-stream");
|
|
assert.match(text, /"role":"assistant","content":"Hello "/);
|
|
assert.match(text, /"tool_calls":\[/);
|
|
assert.match(text, /"name":"read_file"/);
|
|
assert.match(text, /"finish_reason":"tool_calls"/);
|
|
assert.match(text, /\[DONE\]/);
|
|
});
|
|
|
|
test("CursorExecutor.transformProtobufToSSE converts JSON error frames into rate-limit responses", async () => {
|
|
const executor = new CursorExecutor();
|
|
const response = executor.transformProtobufToSSE(
|
|
buildJsonErrorFrame({
|
|
error: {
|
|
code: "resource_exhausted",
|
|
message: "rate limited",
|
|
details: [{ debug: { error: "LIMIT", details: { title: "Limit", detail: "Slow down" } } }],
|
|
},
|
|
}),
|
|
"cursor-small",
|
|
{ messages: [{ role: "user", content: "hi" }] }
|
|
);
|
|
const payload = await response.json();
|
|
|
|
assert.equal(response.status, 429);
|
|
assert.equal(payload.error.type, "rate_limit_error");
|
|
assert.equal(payload.error.message, "Limit");
|
|
assert.equal(payload.error.code, "LIMIT");
|
|
});
|
|
|
|
test("CursorExecutor.execute returns transformed JSON for non-stream responses", async () => {
|
|
const executor = new CursorExecutor();
|
|
const body = { messages: [{ role: "user", content: "hi" }] };
|
|
const responseBuffer = Buffer.concat([buildTextFrame("Hello from Cursor")]);
|
|
executor.makeHttp2Request = async () => ({
|
|
status: 200,
|
|
headers: {},
|
|
body: responseBuffer,
|
|
});
|
|
executor.makeFetchRequest = executor.makeHttp2Request;
|
|
|
|
const result = await executor.execute({
|
|
model: "cursor-small",
|
|
body,
|
|
stream: false,
|
|
credentials: {
|
|
accessToken: "token",
|
|
providerSpecificData: { machineId: "machine-1" },
|
|
},
|
|
});
|
|
const payload = await result.response.json();
|
|
|
|
assert.equal(
|
|
result.url,
|
|
"https://api2.cursor.sh/aiserver.v1.ChatService/StreamUnifiedChatWithTools"
|
|
);
|
|
assert.equal(result.transformedBody, body);
|
|
assert.equal(result.headers.authorization, "Bearer token");
|
|
assert.equal(payload.object, "chat.completion");
|
|
assert.equal(payload.choices[0].message.content, "Hello from Cursor");
|
|
assert.equal(payload.choices[0].finish_reason, "stop");
|
|
});
|
|
|
|
test("CursorExecutor.execute returns transformed SSE for stream responses", async () => {
|
|
const executor = new CursorExecutor();
|
|
const body = { messages: [{ role: "user", content: "hi" }] };
|
|
const responseBuffer = Buffer.concat([buildTextFrame("Hello stream")]);
|
|
executor.makeHttp2Request = async () => ({
|
|
status: 200,
|
|
headers: {},
|
|
body: responseBuffer,
|
|
});
|
|
executor.makeFetchRequest = executor.makeHttp2Request;
|
|
|
|
const result = await executor.execute({
|
|
model: "cursor-small",
|
|
body,
|
|
stream: true,
|
|
credentials: {
|
|
accessToken: "token",
|
|
providerSpecificData: { machineId: "machine-1" },
|
|
},
|
|
});
|
|
const text = await result.response.text();
|
|
|
|
assert.equal(result.response.status, 200);
|
|
assert.match(text, /"content":"Hello stream"/);
|
|
assert.match(text, /\[DONE\]/);
|
|
});
|
|
|
|
test("CursorExecutor.execute maps non-200 upstream responses to OpenAI-style errors", async () => {
|
|
const executor = new CursorExecutor();
|
|
const body = { messages: [{ role: "user", content: "hi" }] };
|
|
executor.makeHttp2Request = async () => ({
|
|
status: 403,
|
|
headers: {},
|
|
body: Buffer.from("denied"),
|
|
});
|
|
executor.makeFetchRequest = executor.makeHttp2Request;
|
|
|
|
const result = await executor.execute({
|
|
model: "cursor-small",
|
|
body,
|
|
stream: false,
|
|
credentials: {
|
|
accessToken: "token",
|
|
providerSpecificData: { machineId: "machine-1" },
|
|
},
|
|
});
|
|
const payload = await result.response.json();
|
|
|
|
assert.equal(result.response.status, 403);
|
|
assert.equal(payload.error.type, "invalid_request_error");
|
|
assert.match(payload.error.message, /\[403\]: denied/);
|
|
});
|
|
|
|
test("CursorExecutor.execute maps transport failures to connection_error and refreshCredentials returns null", async () => {
|
|
const executor = new CursorExecutor();
|
|
executor.makeHttp2Request = async () => {
|
|
throw new Error("socket hang up");
|
|
};
|
|
executor.makeFetchRequest = executor.makeHttp2Request;
|
|
|
|
const result = await executor.execute({
|
|
model: "cursor-small",
|
|
body: { messages: [{ role: "user", content: "hi" }] },
|
|
stream: false,
|
|
credentials: {
|
|
accessToken: "token",
|
|
providerSpecificData: { machineId: "machine-1" },
|
|
},
|
|
});
|
|
const payload = await result.response.json();
|
|
|
|
assert.equal(result.response.status, 500);
|
|
assert.equal(payload.error.type, "connection_error");
|
|
assert.equal(payload.error.message, "socket hang up");
|
|
assert.equal(await executor.refreshCredentials(), null);
|
|
});
|