char-slop/ai-dots

ai dotfiles

git clone https://git.t4t.associates/char-slop/ai-dots

Charlotte Somcomputer use for windowsdc2c12a

main
2.4 KiB63 linesraw
1import { spawn } from "node:child_process";
2import { createInterface } from "node:readline";
3import { fileURLToPath } from "node:url";
4import { checkSignal, type DesktopBackend } from "./backend.ts";
5
6export function createWindowsBackend(): DesktopBackend {
7  const child = spawn("powershell.exe", [
8    "-NoLogo", "-NoProfile", "-NonInteractive", "-ExecutionPolicy", "Bypass",
9    "-File", fileURLToPath(new URL("./windows.ps1", import.meta.url)),
10  ], { stdio: ["pipe", "pipe", "pipe"], windowsHide: true });
11  const lines = createInterface({ input: child.stdout, crlfDelay: Infinity });
12  const responses = lines[Symbol.asyncIterator]();
13  let stderr = "";
14  let failure: Error | undefined;
15  child.stderr.setEncoding("utf8").on("data", (chunk: string) => {
16    stderr = (stderr + chunk).slice(-16_384);
17  });
18  // A failed spawn can also emit an error on stdin.
19  child.stdin.on("error", (error) => { failure = error; });
20  const exited = new Promise<void>((resolve) => {
21    child.once("error", (error) => { failure = error; resolve(); });
22    child.once("close", resolve);
23  });
24
25  return {
26    async execute(action, signal) {
27      checkSignal(signal);
28      let abort: () => void = () => {};
29      const cancelled = new Promise<never>((_, reject) => {
30        abort = () => reject(new Error("Operation aborted"));
31        signal?.addEventListener("abort", abort, { once: true });
32      });
33      try {
34        if (failure) throw failure;
35        child.stdin.write(`${JSON.stringify(action)}\n`);
36        const line = await Promise.race([responses.next(), cancelled]);
37        if (line.done) {
38          await exited;
39          throw failure ?? new Error(stderr.trim() || "Windows desktop helper disconnected");
40        }
41        const response = JSON.parse(line.value) as { error?: string; png?: string };
42        if (response.error) throw new Error(response.error);
43        if (action.action === "screenshot") {
44          if (!response.png) throw new Error("Windows desktop helper returned no screenshot");
45          return Buffer.from(response.png, "base64");
46        }
47      } finally {
48        signal?.removeEventListener("abort", abort);
49      }
50    },
51    async close() {
52      // EOF lets the helper release held inputs even after a cancelled request.
53      child.stdin.end();
54      const timer = setTimeout(() => child.kill(), 5_000);
55      try {
56        await exited;
57      } finally {
58        clearTimeout(timer);
59        lines.close();
60      }
61    },
62  };
63}