char-slop/berry

multipurpose self-modifiable agentic harness

git clone https://git.t4t.associates/char-slop/berry

Charlotte Sommcp: test discovery, calls, environment isolation, and cancellation230f21e

main
3.6 KiB101 linesraw
1let calls = 0;
2let cancelled = 0;
3let roots: unknown;
4const output = Deno.stdout.writable.getWriter();
5const encoder = new TextEncoder();
6const send = async (value: unknown) => {
7  const bytes = encoder.encode(JSON.stringify(value) + "\n");
8  const split = Math.floor(bytes.length / 2);
9  await output.write(bytes.slice(0, split));
10  await output.write(bytes.slice(split));
11};
12if (Deno.args.includes("stubborn")) Deno.addSignalListener("SIGTERM", () => {});
13if (Deno.args.some((arg) => ["descendant", "escaped", "quiet-child"].includes(arg))) {
14  const escaped = Deno.args.includes("escaped");
15  const quiet = Deno.args.includes("quiet-child");
16  const child = new Deno.Command(escaped ? "setsid" : Deno.execPath(), {
17    args: [
18      ...(escaped ? [Deno.execPath()] : []),
19      "eval",
20      "Deno.addSignalListener('SIGTERM', () => {}); Deno.writeTextFileSync('descendant-ready', ''); setInterval(() => {}, 60000)",
21    ],
22    stdin: "null",
23    stdout: escaped || quiet ? "null" : "inherit",
24    stderr: quiet ? "null" : "inherit",
25  }).spawn();
26  await Deno.writeTextFile("descendant", String(child.pid));
27  while (!(await Deno.stat("descendant-ready").then(() => true, () => false))) {
28    await new Promise((resolve) => setTimeout(resolve, 5));
29  }
30}
31let buffered = "";
32for await (const chunk of Deno.stdin.readable) {
33  buffered += new TextDecoder().decode(chunk);
34  let newline: number;
35  while ((newline = buffered.indexOf("\n")) >= 0) {
36    const line = buffered.slice(0, newline);
37    buffered = buffered.slice(newline + 1);
38    const message = JSON.parse(line);
39    if (message.id === "roots") {
40      roots = message.result.roots;
41      continue;
42    }
43    if (message.method === "notifications/initialized") {
44      await send({ jsonrpc: "2.0", id: "roots", method: "roots/list" });
45      continue;
46    }
47    if (message.method === "notifications/cancelled") {
48      cancelled++;
49      continue;
50    }
51    if (message.id === undefined) continue;
52    let result: unknown;
53    if (message.method === "initialize") {
54      result = {
55        protocolVersion: message.params.protocolVersion,
56        capabilities: { tools: {} },
57        serverInfo: { name: "fixture", version: "1" },
58        instructions: "Use echo to inspect the environment.",
59      };
60    } else if (message.method === "tools/list") {
61      result = {
62        tools: [{
63          name: "echo",
64          description: "Echo arguments: café, 猫",
65          inputSchema: { type: "object", properties: { fail: { type: "boolean" } } },
66          outputSchema: { type: "object", properties: { count: { type: "integer" } } },
67          annotations: { readOnlyHint: true },
68        }],
69      };
70    } else if (message.method === "tools/call") {
71      calls++;
72      if (message.params.name === "crash") Deno.exit(7);
73      if (message.params.name === "wait") {
74        await Deno.writeTextFile("waiting", "");
75        continue;
76      }
77      if (message.params._meta?.progressToken !== undefined) {
78        await send({
79          jsonrpc: "2.0",
80          method: "notifications/progress",
81          params: { progressToken: message.params._meta.progressToken, progress: 1, total: 1 },
82        });
83      }
84      result = {
85        content: [{ type: "text", text: "café, 猫" }],
86        structuredContent: {
87          count: calls,
88          cancelled,
89          pid: Deno.pid,
90          cwd: Deno.cwd(),
91          token: Deno.env.get("TOKEN") ?? "",
92          roots,
93          arguments: message.params.arguments,
94        },
95        isError: message.params.arguments.fail === true,
96      };
97    } else result = {};
98    await send({ jsonrpc: "2.0", id: message.id, result });
99  }
100}
101if (Deno.args.includes("stubborn")) setInterval(() => {}, 60_000);