返回 CodeWhale
host-decision.mjs
根目录 / crates / tui / plugins / computer-use / tests / fixtures / host-decision.mjs
1 // Test host: what Codewhale does for the plugin it spawns. The first stdin
2 // line carries the per-connection decision key (and the ledger key), and a
3 // tools/call the user approved carries an attested decision in _meta.
4 import crypto from "node:crypto";
5
6 export const TEST_DECISION_KEY = "11".repeat(32);
7 export const TEST_LEDGER_KEY = "22".repeat(32);
8
9 export function hostKeysLine({ ledger = true } = {}) {
10 return JSON.stringify({
11 jsonrpc: "2.0",
12 method: "codewhale/host_keys",
13 params: { decision_key: TEST_DECISION_KEY, ...(ledger ? { ledger_key: TEST_LEDGER_KEY } : {}) },
14 }) + "\n";
15 }
16
17 /** tools/call params with a decision attested under the test key. */
18 export function attest(params, key = TEST_DECISION_KEY) {
19 if (!params || typeof params.name !== "string") return params;
20 const argsJson = JSON.stringify(params.arguments ?? {});
21 const nonce = crypto.randomBytes(16).toString("hex");
22 const mac = crypto.createHmac("sha256", Buffer.from(key, "hex"))
23 .update(Buffer.concat([Buffer.from(params.name), Buffer.from([0]), Buffer.from(argsJson), Buffer.from([0]), Buffer.from(nonce)]))
24 .digest("hex");
25 return { ...params, _meta: { ...(params._meta ?? {}), "codewhale/user_decision": { nonce, args_json: argsJson, mac } } };
26 }
27
28 export const attestParams = (method, params) => (method === "tools/call" ? attest(params) : params);
29
30 /** Sign a persisted allow the way the plugin does under TEST_LEDGER_KEY. */
31 export function ledgerMac(computerId, key, entry) {
32 return crypto.createHmac("sha256", Buffer.from(TEST_LEDGER_KEY, "hex"))
33 .update(`${computerId}\0${key}\0${entry.decision}\0${entry.at ?? ""}`)
34 .digest("hex");
35 }
36
36 lines Plain Text