43 lines
2.7 KiB
TypeScript
43 lines
2.7 KiB
TypeScript
import { test } from "node:test";
|
|
import assert from "node:assert/strict";
|
|
import { complete } from "../src/model.js";
|
|
import { desktopArguments, shellArguments, toolsForCoordinates } from "../src/tools.js";
|
|
|
|
const config: import("../src/config.js").Config = { coordinateSpace: "pixels", llamaCppOrigin: "http://example.test", modelId: "test", databasePath: ":memory:" };
|
|
|
|
test("adapter accepts tool calls and rejects truncated responses", async (t) => {
|
|
let finish = "tool_calls";
|
|
t.mock.method(globalThis, "fetch", async (_url: unknown, options: RequestInit) => {
|
|
assert.equal(JSON.parse(String(options.body)).model, "test");
|
|
return Response.json({ choices: [{ finish_reason: finish, message: {
|
|
role: "assistant", content: null,
|
|
tool_calls: [{ id: "one", type: "function", function: { name: "desktop", arguments: '{"actions":[]}' } }],
|
|
} }] });
|
|
});
|
|
assert.equal((await complete(config, [], [])).tool_calls?.[0]?.function.name, "desktop");
|
|
finish = "length";
|
|
await assert.rejects(complete(config, [], []), /incomplete/);
|
|
});
|
|
|
|
test("tool descriptions advertise coordinate conventions", () => {
|
|
const normalized = toolsForCoordinates("normalized_1000")[0]?.function.description ?? "";
|
|
assert.match(normalized, /Coordinates must be normalized integers in the range \[0, 1000\], where \(0, 0\) is top-left and \(1000, 1000\) is bottom-right\./);
|
|
assert.match(normalized, /ymin, xmin, ymax, and xmax/);
|
|
|
|
const pixels = toolsForCoordinates("pixels")[0]?.function.description ?? "";
|
|
assert.match(pixels, /Click coordinates are screenshot pixels, not normalized coordinates\./);
|
|
assert.doesNotMatch(pixels, /normalized integers in the range/);
|
|
});
|
|
|
|
test("tool inputs reject invalid commands, bounds, and action names", () => {
|
|
assert.throws(() => shellArguments.parse({ command: "", timeoutSeconds: 1 }));
|
|
assert.throws(() => shellArguments.parse({ command: "true", timeoutSeconds: 999 }));
|
|
assert.throws(() => desktopArguments.parse({ actions: [{ type: "click", ymin: -1, xmin: 0, ymax: 0, xmax: 0 }] }));
|
|
assert.throws(() => desktopArguments.parse({ actions: [{ type: "click", x: 10, y: 20 }] }));
|
|
assert.throws(() => desktopArguments.parse({ actions: [{ type: "execute" }] }));
|
|
assert.deepEqual(desktopArguments.parse({ actions: [] }), { actions: [] });
|
|
assert.throws(() => desktopArguments.parse({ actions: [{ type: "click_target", target: "1" }] }));
|
|
assert.equal(desktopArguments.parse({ actions: [{ type: "click_target", target: "1", observationId: "frame" }] }).actions[0]?.type, "click_target");
|
|
assert.equal(desktopArguments.parse({ actions: [{ type: "click", ymin: 10, xmin: 20, ymax: 30, xmax: 40 }] }).actions[0]?.type, "click");
|
|
});
|