feat: add claw backend adapter
This commit is contained in:
180
tests/claw-runner.test.ts
Normal file
180
tests/claw-runner.test.ts
Normal file
@@ -0,0 +1,180 @@
|
||||
import assert from "node:assert/strict";
|
||||
import { mkdtemp, realpath, writeFile } from "node:fs/promises";
|
||||
import { tmpdir } from "node:os";
|
||||
import { join } from "node:path";
|
||||
import test from "node:test";
|
||||
|
||||
import { runClawCommandForTesting } from "../src/lib/execution/backends/claw-runner.ts";
|
||||
|
||||
async function createTempScript(source: string) {
|
||||
const dir = await mkdtemp(join(tmpdir(), "claw-runner-"));
|
||||
const scriptPath = join(dir, "claw-script.mjs");
|
||||
await writeFile(scriptPath, source, "utf8");
|
||||
return { dir, scriptPath };
|
||||
}
|
||||
|
||||
test("Claw runner 把 completed JSON 响应映射成 completed,并把 payload 写入 stdin", async () => {
|
||||
const workspace = await mkdtemp(join(tmpdir(), "claw-runner-cwd-"));
|
||||
const expectedWorkspace = await realpath(workspace);
|
||||
const { scriptPath } = await createTempScript(`
|
||||
import { readFile } from "node:fs/promises";
|
||||
|
||||
let stdin = "";
|
||||
process.stdin.setEncoding("utf8");
|
||||
for await (const chunk of process.stdin) {
|
||||
stdin += chunk;
|
||||
}
|
||||
|
||||
const payload = JSON.parse(stdin);
|
||||
process.stdout.write(JSON.stringify({
|
||||
status: "completed",
|
||||
output: JSON.stringify({
|
||||
body: payload.body,
|
||||
cwd: process.cwd(),
|
||||
command: payload.command,
|
||||
}),
|
||||
}));
|
||||
`);
|
||||
|
||||
const result = await runClawCommandForTesting({
|
||||
config: {
|
||||
enabled: true,
|
||||
command: process.execPath,
|
||||
args: [scriptPath],
|
||||
cwd: workspace,
|
||||
timeoutMs: 1000,
|
||||
},
|
||||
payload: {
|
||||
body: "继续执行",
|
||||
command: "claw",
|
||||
},
|
||||
});
|
||||
|
||||
assert.equal(result.status, "completed");
|
||||
if (result.status !== "completed") {
|
||||
assert.fail("expected completed");
|
||||
}
|
||||
|
||||
const output = JSON.parse(result.output) as {
|
||||
body: string;
|
||||
cwd: string;
|
||||
command: string;
|
||||
};
|
||||
|
||||
assert.equal(output.body, "继续执行");
|
||||
assert.equal(output.cwd, expectedWorkspace);
|
||||
assert.equal(output.command, "claw");
|
||||
});
|
||||
|
||||
test("Claw runner 把 failed JSON 响应映射成 failed", async () => {
|
||||
const { scriptPath } = await createTempScript(`
|
||||
let stdin = "";
|
||||
process.stdin.setEncoding("utf8");
|
||||
for await (const chunk of process.stdin) {
|
||||
stdin += chunk;
|
||||
}
|
||||
|
||||
const payload = JSON.parse(stdin);
|
||||
process.stdout.write(JSON.stringify({
|
||||
status: "failed",
|
||||
error: "bad-request:" + payload.body,
|
||||
}));
|
||||
`);
|
||||
|
||||
const result = await runClawCommandForTesting({
|
||||
config: {
|
||||
enabled: true,
|
||||
command: process.execPath,
|
||||
args: [scriptPath],
|
||||
timeoutMs: 1000,
|
||||
},
|
||||
payload: {
|
||||
body: "格式不对",
|
||||
},
|
||||
});
|
||||
|
||||
assert.equal(result.status, "failed");
|
||||
if (result.status !== "failed") {
|
||||
assert.fail("expected failed");
|
||||
}
|
||||
|
||||
assert.equal(result.error, "bad-request:格式不对");
|
||||
});
|
||||
|
||||
test("Claw runner 把无效 JSON 响应映射成 INVALID_CLAW_RESPONSE", async () => {
|
||||
const { scriptPath } = await createTempScript(`
|
||||
process.stdout.write("not-json");
|
||||
`);
|
||||
|
||||
const result = await runClawCommandForTesting({
|
||||
config: {
|
||||
enabled: true,
|
||||
command: process.execPath,
|
||||
args: [scriptPath],
|
||||
timeoutMs: 1000,
|
||||
},
|
||||
payload: {
|
||||
body: "anything",
|
||||
},
|
||||
});
|
||||
|
||||
assert.equal(result.status, "failed");
|
||||
if (result.status !== "failed") {
|
||||
assert.fail("expected failed");
|
||||
}
|
||||
|
||||
assert.match(result.error, /INVALID_CLAW_RESPONSE/);
|
||||
});
|
||||
|
||||
test("Claw runner 把非零退出码映射成 stderr 或退出码错误", async () => {
|
||||
const { scriptPath } = await createTempScript(`
|
||||
process.stderr.write("claw crashed");
|
||||
process.exit(2);
|
||||
`);
|
||||
|
||||
const result = await runClawCommandForTesting({
|
||||
config: {
|
||||
enabled: true,
|
||||
command: process.execPath,
|
||||
args: [scriptPath],
|
||||
timeoutMs: 1000,
|
||||
},
|
||||
payload: {
|
||||
body: "anything",
|
||||
},
|
||||
});
|
||||
|
||||
assert.equal(result.status, "failed");
|
||||
if (result.status !== "failed") {
|
||||
assert.fail("expected failed");
|
||||
}
|
||||
|
||||
assert.match(result.error, /claw crashed/);
|
||||
});
|
||||
|
||||
test("Claw runner 超时后返回 CLAW_TIMEOUT", async () => {
|
||||
const { scriptPath } = await createTempScript(`
|
||||
setTimeout(() => {
|
||||
process.stdout.write(JSON.stringify({ status: "completed", output: "late" }));
|
||||
}, 500);
|
||||
`);
|
||||
|
||||
const result = await runClawCommandForTesting({
|
||||
config: {
|
||||
enabled: true,
|
||||
command: process.execPath,
|
||||
args: [scriptPath],
|
||||
timeoutMs: 50,
|
||||
},
|
||||
payload: {
|
||||
body: "slow",
|
||||
},
|
||||
});
|
||||
|
||||
assert.equal(result.status, "failed");
|
||||
if (result.status !== "failed") {
|
||||
assert.fail("expected failed");
|
||||
}
|
||||
|
||||
assert.match(result.error, /CLAW_TIMEOUT/);
|
||||
});
|
||||
Reference in New Issue
Block a user