返回 CodeWhale
agent.mjs
根目录 / crates / tui / plugins / computer-use / agent.mjs
1 // codewhale-cu remote agent — runs on an ssh-registered computer.
2 // One-shot: `node agent.mjs <base64(json)>` prints exactly one JSON receipt
3 // line. The request is {"tool": "...", "args": {...}}; the shared handler
4 // enforces the tool allow-list, so the transport can never become a shell.
5 import { handle } from "./src/app-handler.mjs";
6
7 function reply(obj) {
8 process.stdout.write(JSON.stringify(obj) + "\n");
9 process.exit(0);
10 }
11
12 const argv = process.argv.slice(2);
13 if (!argv[0]) reply({ ok: false, error: { code: "missing_payload", message: "usage: node agent.mjs <base64 payload> | node agent.mjs --serve" } });
14
15 if (argv[0] === "--serve") {
16 // Persistent mode: each stdin line is base64 {id, tool, args}; each stdout
17 // line is the JSON receipt {id, ok, ...}. The process stays alive, so its
18 // backend retains the open_application binding and owned input between
19 // calls. The allow-list still applies — the channel cannot become a shell.
20 let buf = "";
21 process.stdin.setEncoding("utf8");
22 process.stdin.on("data", (chunk) => {
23 buf += chunk;
24 let i;
25 while ((i = buf.indexOf("\n")) !== -1) {
26 const line = buf.slice(0, i).trim();
27 buf = buf.slice(i + 1);
28 if (line) void serve(line);
29 }
30 });
31 process.stdin.on("end", () => process.exit(0));
32 } else {
33 let req;
34 try {
35 req = JSON.parse(Buffer.from(argv[0], "base64").toString("utf8"));
36 } catch {
37 reply({ ok: false, error: { code: "bad_payload", message: "payload is not base64 JSON" } });
38 }
39
40 if (["left_mouse_down", "recordingStart"].includes(req?.tool)) {
41 reply({ ok: false, error: { code: "persistent_session_required", message: "This operation needs a persistent computer session; the one-shot SSH agent exits after each request. Upgrade the plugin so it serves the agent over one connection, or use a complete drag gesture." } });
42 }
43
44 reply(await handle(req, { computerId: "remote" }));
45 }
46
47 async function serve(line) {
48 let req;
49 try {
50 req = JSON.parse(Buffer.from(line, "base64").toString("utf8"));
51 } catch {
52 process.stdout.write(JSON.stringify({ id: null, ok: false, error: { code: "bad_payload", message: "line is not base64 JSON" } }) + "\n");
53 return;
54 }
55 const receipt = await handle(req, { computerId: "remote", sessionId: "ssh-serve", persistentInputOwner: true });
56 process.stdout.write(JSON.stringify({ id: req?.id ?? null, ...receipt }) + "\n");
57 }
58
58 lines Plain Text