File size: 2,346 Bytes
fcd8223
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
import { spawn } from "node:child_process";
import { parseNodeWorkerDesktopLaunchInput } from "../worker/node-desktop-protocol.js";

const DESKTOP_LAUNCH_TIMEOUT_MS = 30_000;

function signalError(signal: AbortSignal): Error {
  return signal.reason instanceof Error
    ? signal.reason
    : new Error("node worker desktop launch aborted");
}

/** Directly runs one provider-attested zero-argument launcher without replay. */
export async function invokeNodeWorkerDesktopLaunch(params: {
  paramsJSON?: string | null;
  signal?: AbortSignal;
}): Promise<{ status: "ready" }> {
  const app = parseNodeWorkerDesktopLaunchInput(params.paramsJSON);
  const signal = params.signal;
  signal?.throwIfAborted();
  const child = spawn(app.executablePath, [], {
    shell: false,
    stdio: "ignore",
    windowsHide: true,
  });
  await new Promise<void>((resolve, reject) => {
    let settled = false;
    const finish = (error?: Error) => {
      if (settled) {
        return;
      }
      settled = true;
      clearTimeout(timer);
      signal?.removeEventListener("abort", onAbort);
      child.off("error", onError);
      child.off("exit", onExit);
      if (error) {
        reject(error);
      } else {
        resolve();
      }
    };
    const stop = (error: Error) => {
      try {
        child.kill("SIGKILL");
      } catch {
        // The terminal error still owns this one-shot launch result.
      }
      finish(error);
    };
    const onAbort = () => signal && stop(signalError(signal));
    const onError = (error: Error) => finish(error);
    const onExit = (code: number | null, terminationSignal: NodeJS.Signals | null) => {
      if (code === 0) {
        finish();
        return;
      }
      finish(
        new Error(
          terminationSignal
            ? `node worker desktop launcher terminated by ${terminationSignal}`
            : `node worker desktop launcher exited with code ${code ?? "unknown"}`,
        ),
      );
    };
    const timer = setTimeout(
      () => stop(new Error("node worker desktop launcher timed out")),
      DESKTOP_LAUNCH_TIMEOUT_MS,
    );
    timer.unref?.();
    child.once("error", onError);
    child.once("exit", onExit);
    signal?.addEventListener("abort", onAbort, { once: true });
    if (signal?.aborted) {
      onAbort();
    }
  });
  return { status: "ready" };
}