@hotcell/daemon 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (142) hide show
  1. package/dist/agent-check.d.ts +1 -0
  2. package/dist/agent-check.js +105 -0
  3. package/dist/agent-check.js.map +1 -0
  4. package/dist/api/server.d.ts +64 -0
  5. package/dist/api/server.js +1368 -0
  6. package/dist/api/server.js.map +1 -0
  7. package/dist/api/ws.d.ts +14 -0
  8. package/dist/api/ws.js +214 -0
  9. package/dist/api/ws.js.map +1 -0
  10. package/dist/applevz-check.d.ts +1 -0
  11. package/dist/applevz-check.js +280 -0
  12. package/dist/applevz-check.js.map +1 -0
  13. package/dist/backups.d.ts +29 -0
  14. package/dist/backups.js +76 -0
  15. package/dist/backups.js.map +1 -0
  16. package/dist/capacity.d.ts +63 -0
  17. package/dist/capacity.js +95 -0
  18. package/dist/capacity.js.map +1 -0
  19. package/dist/config.d.ts +241 -0
  20. package/dist/config.js +152 -0
  21. package/dist/config.js.map +1 -0
  22. package/dist/cost.d.ts +9 -0
  23. package/dist/cost.js +19 -0
  24. package/dist/cost.js.map +1 -0
  25. package/dist/density-bench.d.ts +1 -0
  26. package/dist/density-bench.js +97 -0
  27. package/dist/density-bench.js.map +1 -0
  28. package/dist/driver/agent-driver.d.ts +67 -0
  29. package/dist/driver/agent-driver.js +197 -0
  30. package/dist/driver/agent-driver.js.map +1 -0
  31. package/dist/driver/agent.d.ts +94 -0
  32. package/dist/driver/agent.js +319 -0
  33. package/dist/driver/agent.js.map +1 -0
  34. package/dist/driver/applevz.d.ts +95 -0
  35. package/dist/driver/applevz.js +527 -0
  36. package/dist/driver/applevz.js.map +1 -0
  37. package/dist/driver/container.d.ts +99 -0
  38. package/dist/driver/container.js +733 -0
  39. package/dist/driver/container.js.map +1 -0
  40. package/dist/driver/fc-api.d.ts +85 -0
  41. package/dist/driver/fc-api.js +173 -0
  42. package/dist/driver/fc-api.js.map +1 -0
  43. package/dist/driver/firecracker.d.ts +126 -0
  44. package/dist/driver/firecracker.js +560 -0
  45. package/dist/driver/firecracker.js.map +1 -0
  46. package/dist/driver/index.d.ts +17 -0
  47. package/dist/driver/index.js +61 -0
  48. package/dist/driver/index.js.map +1 -0
  49. package/dist/driver/router.d.ts +82 -0
  50. package/dist/driver/router.js +159 -0
  51. package/dist/driver/router.js.map +1 -0
  52. package/dist/driver/types.d.ts +234 -0
  53. package/dist/driver/types.js +2 -0
  54. package/dist/driver/types.js.map +1 -0
  55. package/dist/driver/unsupported.d.ts +50 -0
  56. package/dist/driver/unsupported.js +81 -0
  57. package/dist/driver/unsupported.js.map +1 -0
  58. package/dist/driver/vz-image.d.ts +35 -0
  59. package/dist/driver/vz-image.js +75 -0
  60. package/dist/driver/vz-image.js.map +1 -0
  61. package/dist/e2e-harness.d.ts +1 -0
  62. package/dist/e2e-harness.js +99 -0
  63. package/dist/e2e-harness.js.map +1 -0
  64. package/dist/egress-check.d.ts +8 -0
  65. package/dist/egress-check.js +317 -0
  66. package/dist/egress-check.js.map +1 -0
  67. package/dist/fc-check.d.ts +1 -0
  68. package/dist/fc-check.js +113 -0
  69. package/dist/fc-check.js.map +1 -0
  70. package/dist/index.d.ts +2 -0
  71. package/dist/index.js +114 -0
  72. package/dist/index.js.map +1 -0
  73. package/dist/kernels.d.ts +22 -0
  74. package/dist/kernels.js +134 -0
  75. package/dist/kernels.js.map +1 -0
  76. package/dist/lifecycle.d.ts +49 -0
  77. package/dist/lifecycle.js +111 -0
  78. package/dist/lifecycle.js.map +1 -0
  79. package/dist/logger.d.ts +16 -0
  80. package/dist/logger.js +67 -0
  81. package/dist/logger.js.map +1 -0
  82. package/dist/metrics.d.ts +46 -0
  83. package/dist/metrics.js +92 -0
  84. package/dist/metrics.js.map +1 -0
  85. package/dist/net/firewall.d.ts +4 -0
  86. package/dist/net/firewall.js +80 -0
  87. package/dist/net/firewall.js.map +1 -0
  88. package/dist/pricing.d.ts +36 -0
  89. package/dist/pricing.js +81 -0
  90. package/dist/pricing.js.map +1 -0
  91. package/dist/proxy/allowlist-default.d.ts +23 -0
  92. package/dist/proxy/allowlist-default.js +53 -0
  93. package/dist/proxy/allowlist-default.js.map +1 -0
  94. package/dist/proxy/allowlist.d.ts +43 -0
  95. package/dist/proxy/allowlist.js +87 -0
  96. package/dist/proxy/allowlist.js.map +1 -0
  97. package/dist/proxy/egress.d.ts +49 -0
  98. package/dist/proxy/egress.js +599 -0
  99. package/dist/proxy/egress.js.map +1 -0
  100. package/dist/proxy/ratelimit.d.ts +49 -0
  101. package/dist/proxy/ratelimit.js +74 -0
  102. package/dist/proxy/ratelimit.js.map +1 -0
  103. package/dist/proxy/server.d.ts +26 -0
  104. package/dist/proxy/server.js +202 -0
  105. package/dist/proxy/server.js.map +1 -0
  106. package/dist/router-check.d.ts +1 -0
  107. package/dist/router-check.js +97 -0
  108. package/dist/router-check.js.map +1 -0
  109. package/dist/smoke-fc.d.ts +1 -0
  110. package/dist/smoke-fc.js +183 -0
  111. package/dist/smoke-fc.js.map +1 -0
  112. package/dist/smoke-microvm.d.ts +1 -0
  113. package/dist/smoke-microvm.js +187 -0
  114. package/dist/smoke-microvm.js.map +1 -0
  115. package/dist/smoke-remote.d.ts +20 -0
  116. package/dist/smoke-remote.js +155 -0
  117. package/dist/smoke-remote.js.map +1 -0
  118. package/dist/smoke-vz.d.ts +1 -0
  119. package/dist/smoke-vz.js +161 -0
  120. package/dist/smoke-vz.js.map +1 -0
  121. package/dist/smoke.d.ts +7 -0
  122. package/dist/smoke.js +962 -0
  123. package/dist/smoke.js.map +1 -0
  124. package/dist/store.d.ts +124 -0
  125. package/dist/store.js +578 -0
  126. package/dist/store.js.map +1 -0
  127. package/dist/tracing.d.ts +45 -0
  128. package/dist/tracing.js +144 -0
  129. package/dist/tracing.js.map +1 -0
  130. package/dist/types.d.ts +274 -0
  131. package/dist/types.js +3 -0
  132. package/dist/types.js.map +1 -0
  133. package/dist/util.d.ts +27 -0
  134. package/dist/util.js +63 -0
  135. package/dist/util.js.map +1 -0
  136. package/dist/warmpool-check.d.ts +1 -0
  137. package/dist/warmpool-check.js +83 -0
  138. package/dist/warmpool-check.js.map +1 -0
  139. package/dist/web/dashboard.d.ts +1 -0
  140. package/dist/web/dashboard.js +456 -0
  141. package/dist/web/dashboard.js.map +1 -0
  142. package/package.json +53 -0
@@ -0,0 +1,95 @@
1
+ import { AgentConn } from "./agent.js";
2
+ import { AgentDriver } from "./agent-driver.js";
3
+ import type { CreateOptions, HostInfo } from "./types.js";
4
+ /** Config the driver factory hands the VZ driver (subset of the daemon config). */
5
+ export interface VzConfig {
6
+ helperPath: string;
7
+ kernel: string;
8
+ rootfs: string;
9
+ stateDir: string;
10
+ diskGb: number;
11
+ /** Cache dir for OCI→ext4 converted rootfs images + the blank workspace template. */
12
+ imageCacheDir: string;
13
+ /** Pre-boot this many base-image microVMs for instant adopt (0 = off). */
14
+ warmPool?: number;
15
+ /**
16
+ * Egress gateway port for the guest relay (0/unset = no relay). The guest gets
17
+ * a loopback listener on this port whose connections tunnel over vsock (helper
18
+ * listener) to `egressHost:egressPort` — the NIC-less guest's only way out.
19
+ */
20
+ egressPort?: number;
21
+ /** Host the egress gateway listens on (default 127.0.0.1). */
22
+ egressHost?: string;
23
+ }
24
+ /**
25
+ * Apple Virtualization.framework microVM driver (macOS). Each sandbox is a real
26
+ * VM: a long-lived signed `sbx-vz serve` helper boots it (rootfs + a persistent
27
+ * `workspace.img` over virtio-blk) and relays a unix socket to the guest's vsock,
28
+ * so the daemon's `AgentConn` speaks the agent wire protocol straight into the
29
+ * guest — the same surface the container driver gets from `docker exec`.
30
+ *
31
+ * Implemented (M1–M5): create/stop/start/destroy lifecycle with workspace
32
+ * persistence, exec, files, waitForPort, processes, terminal, preview bridge,
33
+ * stats, and backup/restore. `watchFiles` (M3 inotify) is the remaining gap.
34
+ */
35
+ export declare class AppleVzDriver extends AgentDriver {
36
+ private readonly cfg;
37
+ readonly name = "applevz";
38
+ private vms;
39
+ private images;
40
+ private pool;
41
+ private poolTarget;
42
+ private poolSeq;
43
+ private filling;
44
+ private readonly poolImage;
45
+ private readonly poolDir;
46
+ constructor(cfg: VzConfig);
47
+ create(opts: CreateOptions): Promise<void>;
48
+ start(opts: CreateOptions): Promise<void>;
49
+ /** Bring a sandbox live: adopt a warm-pool guest when eligible (instant), else
50
+ * cold-boot a VM. Then apply the sandbox env. */
51
+ private launch;
52
+ /**
53
+ * Boot a VM and wait for its in-guest agent, returning the live VmState. Shared
54
+ * by the cold-launch path and the warm-pool filler. Does not touch `this.vms`
55
+ * or apply sandbox env — the caller owns those.
56
+ */
57
+ private bootVm;
58
+ /** Poll the relay until the in-guest agent answers (Hello), or time out. */
59
+ private waitForAgentSocket;
60
+ /** Number of pre-booted spare guests ready to adopt. */
61
+ poolSize(): number;
62
+ /**
63
+ * Adopt a pre-booted spare for `opts` when eligible — a plain create of the
64
+ * pooled base image with default limits and no existing workspace. Renames the
65
+ * spare's slot dir to the sandbox's canonical state dir (an APFS rename leaves
66
+ * the running VM's open workspace fd valid), registers it, and replenishes the
67
+ * pool. Returns true on adopt, false to fall through to a cold boot.
68
+ */
69
+ private tryClaimFromPool;
70
+ /** Top the pool up to its target in the background (one filler at a time). */
71
+ private fillPool;
72
+ private doFill;
73
+ /** Tear down all spare guests (e.g. on shutdown). Idempotent. */
74
+ drainPool(): Promise<void>;
75
+ stop(id: string): Promise<void>;
76
+ /** VZ save/restore needs macOS 14+ (Darwin 23+) and a live VM. */
77
+ canSnapshot(id: string): boolean;
78
+ /**
79
+ * Fast-pause: save the live VM's full state (RAM + virtual devices) to disk and
80
+ * tear the helper down, so the next `start` resumes **without a kernel boot**
81
+ * (VZ `saveMachineStateTo`/`restoreMachineStateFrom`, macOS 14+). The workspace
82
+ * disk + the snapshot file are all that's needed to resume; unlike `stop`, no
83
+ * `sync` is needed (the snapshot is a consistent point-in-time including the
84
+ * guest page cache). Background processes/servers come back live on resume.
85
+ */
86
+ snapshot(id: string): Promise<void>;
87
+ destroy(id: string): Promise<void>;
88
+ /** Open a fresh AgentConn to the sandbox's relay socket (the signed VZ helper
89
+ * relays the guest vsock to this unix socket). Backs every agent-served op. */
90
+ protected openConn(id: string): Promise<AgentConn>;
91
+ ping(): Promise<void>;
92
+ hostInfo(): Promise<HostInfo>;
93
+ /** One-shot stdio RPC to a throwaway helper process (probe/hostInfo). */
94
+ private oneShot;
95
+ }
@@ -0,0 +1,527 @@
1
+ import { execFileSync, spawn } from "node:child_process";
2
+ import { closeSync, createWriteStream, existsSync, ftruncateSync, mkdirSync, openSync, renameSync, rmSync, unlinkSync, } from "node:fs";
3
+ import { release } from "node:os";
4
+ import { dirname, join } from "node:path";
5
+ import { setTimeout as sleep } from "node:timers/promises";
6
+ import { AgentConn } from "./agent.js";
7
+ import { AgentDriver } from "./agent-driver.js";
8
+ import { VzImageCache } from "./vz-image.js";
9
+ import { log } from "../logger.js";
10
+ /**
11
+ * Apple Virtualization.framework microVM driver (macOS). Each sandbox is a real
12
+ * VM: a long-lived signed `sbx-vz serve` helper boots it (rootfs + a persistent
13
+ * `workspace.img` over virtio-blk) and relays a unix socket to the guest's vsock,
14
+ * so the daemon's `AgentConn` speaks the agent wire protocol straight into the
15
+ * guest — the same surface the container driver gets from `docker exec`.
16
+ *
17
+ * Implemented (M1–M5): create/stop/start/destroy lifecycle with workspace
18
+ * persistence, exec, files, waitForPort, processes, terminal, preview bridge,
19
+ * stats, and backup/restore. `watchFiles` (M3 inotify) is the remaining gap.
20
+ */
21
+ export class AppleVzDriver extends AgentDriver {
22
+ cfg;
23
+ name = "applevz";
24
+ vms = new Map();
25
+ images;
26
+ // Warm pool: pre-booted spare base-image guests for instant adopt on create.
27
+ pool = [];
28
+ poolTarget;
29
+ poolSeq = 0;
30
+ filling = false;
31
+ poolImage = "base"; // sentinel → the prebuilt Alpine base rootfs
32
+ poolDir;
33
+ constructor(cfg) {
34
+ super();
35
+ this.cfg = cfg;
36
+ // `helpers/hotcell-vz` holds the converter scripts + staged guest files, two dirs
37
+ // up from the helper binary (helpers/hotcell-vz/dist/hotcell-vz).
38
+ const vzDir = dirname(dirname(cfg.helperPath));
39
+ this.images = new VzImageCache({
40
+ vzDir,
41
+ cacheDir: cfg.imageCacheDir,
42
+ prebuiltRootfs: cfg.rootfs,
43
+ });
44
+ this.poolTarget = Math.max(0, cfg.warmPool ?? 0);
45
+ this.poolDir = join(cfg.stateDir, "_pool");
46
+ if (this.poolTarget > 0) {
47
+ // Clear stale slots from a previous run (their helpers died with the daemon).
48
+ try {
49
+ rmSync(this.poolDir, { recursive: true, force: true });
50
+ }
51
+ catch {
52
+ /* not there */
53
+ }
54
+ this.fillPool();
55
+ }
56
+ }
57
+ // --- lifecycle ------------------------------------------------------------
58
+ async create(opts) {
59
+ await this.launch(opts);
60
+ // Best-effort setup commands, mirroring the container driver (non-fatal).
61
+ for (const command of opts.setup ?? []) {
62
+ const code = await this.exec(opts.id, command, {}, () => { }).catch(() => -1);
63
+ if (code === 0)
64
+ log.info("setup command ok", { sandbox: opts.id, command });
65
+ else
66
+ log.warn("setup command failed (continuing)", { sandbox: opts.id, command, code });
67
+ }
68
+ }
69
+ async start(opts) {
70
+ await this.launch(opts);
71
+ }
72
+ /** Bring a sandbox live: adopt a warm-pool guest when eligible (instant), else
73
+ * cold-boot a VM. Then apply the sandbox env. */
74
+ async launch(opts) {
75
+ const id = opts.id;
76
+ if (this.vms.has(id))
77
+ return; // already running
78
+ const adopted = await this.tryClaimFromPool(opts);
79
+ if (!adopted) {
80
+ const stateDir = join(this.cfg.stateDir, id);
81
+ // If a snapshot exists from a fast-pause, resume from it (RAM + device state
82
+ // restored, no kernel boot) instead of cold-booting.
83
+ const snapPath = join(stateDir, "snapshot.bin");
84
+ const restoreFrom = existsSync(snapPath) ? snapPath : undefined;
85
+ let vm;
86
+ try {
87
+ vm = await this.bootVm({
88
+ id,
89
+ stateDir,
90
+ image: opts.image,
91
+ socketPath: `/tmp/hc-${id}.sock`, // short, fits sun_path
92
+ limits: opts.limits,
93
+ restoreFrom,
94
+ });
95
+ }
96
+ catch (err) {
97
+ if (restoreFrom) {
98
+ // A snapshot that won't restore must never brick the sandbox: discard it
99
+ // and cold-boot. The workspace disk is intact — only live RAM state is lost.
100
+ log.warn("snapshot restore failed; discarding it and cold-booting", {
101
+ sandbox: id,
102
+ error: err.message,
103
+ });
104
+ try {
105
+ unlinkSync(snapPath);
106
+ }
107
+ catch {
108
+ /* ignore */
109
+ }
110
+ return this.launch(opts); // snapshot gone → cold boot this time
111
+ }
112
+ throw new Error(`applevz: VM start failed: ${err.message}`);
113
+ }
114
+ this.vms.set(id, vm);
115
+ if (restoreFrom) {
116
+ try {
117
+ unlinkSync(snapPath); // single-use: the in-RAM state is now live
118
+ }
119
+ catch {
120
+ /* ignore */
121
+ }
122
+ }
123
+ }
124
+ // Sandbox-level env: applied once on the shared agent so every exec inherits it.
125
+ if (opts.env && Object.keys(opts.env).length) {
126
+ await this.withConn(id, (c) => c.setEnv(opts.env));
127
+ }
128
+ log.info("applevz VM up", { sandbox: id, warm: adopted });
129
+ }
130
+ /**
131
+ * Boot a VM and wait for its in-guest agent, returning the live VmState. Shared
132
+ * by the cold-launch path and the warm-pool filler. Does not touch `this.vms`
133
+ * or apply sandbox env — the caller owns those.
134
+ */
135
+ async bootVm(p) {
136
+ mkdirSync(p.stateDir, { recursive: true });
137
+ // Resolve the rootfs for the image (sentinels → prebuilt base; else converted).
138
+ const rootfs = await this.images.ensureRootfs(p.image);
139
+ // First boot only: give the VM its own workspace disk. Prefer cloning the blank
140
+ // pre-formatted template (works for images without mkfs.ext4); else a sparse
141
+ // file the guest formats itself.
142
+ const workspaceImg = join(p.stateDir, "workspace.img");
143
+ if (!existsSync(workspaceImg)) {
144
+ let blank = null;
145
+ try {
146
+ blank = await this.images.ensureBlankWorkspace(this.cfg.diskGb);
147
+ }
148
+ catch (err) {
149
+ log.warn("blank workspace build failed; guest will format a sparse disk", {
150
+ sandbox: p.id,
151
+ error: err.message,
152
+ });
153
+ }
154
+ if (blank)
155
+ cloneFile(blank, workspaceImg);
156
+ else
157
+ ensureSparseFile(workspaceImg, this.cfg.diskGb * 1024 ** 3);
158
+ }
159
+ try {
160
+ unlinkSync(p.socketPath);
161
+ }
162
+ catch {
163
+ /* not there */
164
+ }
165
+ const helper = new HelperProcess(this.cfg.helperPath, join(p.stateDir, "console.log"));
166
+ const vm = { helper, socketPath: p.socketPath, workspaceImg, stateDir: p.stateDir };
167
+ // Memory + CPU are hard VM caps (VZ memorySize/cpuCount). VZ needs an integer
168
+ // vCPU count, so a fractional `cpus` rounds up. pidsLimit has no VM analogue —
169
+ // it's enforced inside the guest via a cgroup the init sets up from the cmdline.
170
+ const cpus = p.limits?.cpus ? Math.max(1, Math.ceil(p.limits.cpus)) : 2;
171
+ const memMb = p.limits?.memoryMb && p.limits.memoryMb > 0 ? p.limits.memoryMb : 1024;
172
+ const pidsMax = p.limits?.pidsLimit && p.limits.pidsLimit > 0 ? p.limits.pidsLimit : 0;
173
+ try {
174
+ await helper.rpc("start", {
175
+ kernel: this.cfg.kernel,
176
+ rootfs,
177
+ workspace: workspaceImg,
178
+ cpus,
179
+ memMb,
180
+ pidsMax,
181
+ socketPath: p.socketPath,
182
+ vsockPort: 1024,
183
+ restoreFrom: p.restoreFrom,
184
+ // Per-sandbox pinned machine identity (minted on first boot, reloaded
185
+ // after): VZ refuses to restore saved state under a different (fresh,
186
+ // randomized) VZGenericMachineIdentifier. Lives in the stateDir so a
187
+ // warm-pool slot rename carries it along.
188
+ machineIdPath: join(p.stateDir, "machine-id.bin"),
189
+ // Guest egress relay: the helper listens on this vsock port and splices
190
+ // each guest-initiated connection to the egress gateway.
191
+ egressPort: this.cfg.egressPort ?? 0,
192
+ egressTarget: this.cfg.egressPort
193
+ ? `${this.cfg.egressHost ?? "127.0.0.1"}:${this.cfg.egressPort}`
194
+ : "",
195
+ });
196
+ }
197
+ catch (err) {
198
+ helper.kill();
199
+ throw err;
200
+ }
201
+ // The VM has started, but the guest agent needs a moment to boot + bind vsock.
202
+ await this.waitForAgentSocket(p.socketPath);
203
+ // Cold boots need the in-guest side of the egress relay started (after a
204
+ // snapshot resume it's already alive in the restored RAM).
205
+ if (this.cfg.egressPort && this.cfg.egressPort > 0) {
206
+ const conn = await AgentConn.connect({ path: p.socketPath, timeoutMs: 5000 });
207
+ try {
208
+ await conn.egressListen(this.cfg.egressPort);
209
+ }
210
+ finally {
211
+ conn.close();
212
+ }
213
+ }
214
+ return vm;
215
+ }
216
+ /** Poll the relay until the in-guest agent answers (Hello), or time out. */
217
+ async waitForAgentSocket(socketPath, timeoutMs = 30000) {
218
+ const deadline = Date.now() + timeoutMs;
219
+ let lastErr;
220
+ while (Date.now() < deadline) {
221
+ try {
222
+ const conn = await AgentConn.connect({ path: socketPath, timeoutMs: 2000 });
223
+ conn.close();
224
+ return;
225
+ }
226
+ catch (err) {
227
+ lastErr = err;
228
+ await sleep(400);
229
+ }
230
+ }
231
+ throw new Error(`applevz: agent never came up (${socketPath}): ${String(lastErr?.message ?? lastErr)}`);
232
+ }
233
+ // --- warm pool ------------------------------------------------------------
234
+ /** Number of pre-booted spare guests ready to adopt. */
235
+ poolSize() {
236
+ return this.pool.length;
237
+ }
238
+ /**
239
+ * Adopt a pre-booted spare for `opts` when eligible — a plain create of the
240
+ * pooled base image with default limits and no existing workspace. Renames the
241
+ * spare's slot dir to the sandbox's canonical state dir (an APFS rename leaves
242
+ * the running VM's open workspace fd valid), registers it, and replenishes the
243
+ * pool. Returns true on adopt, false to fall through to a cold boot.
244
+ */
245
+ async tryClaimFromPool(opts) {
246
+ if (this.poolTarget <= 0)
247
+ return false;
248
+ const noLimits = !opts.limits || (!opts.limits.memoryMb && !opts.limits.cpus && !opts.limits.pidsLimit);
249
+ const canonical = join(this.cfg.stateDir, opts.id);
250
+ const eligible = (opts.image === this.poolImage || opts.image === "alpine") &&
251
+ noLimits &&
252
+ !existsSync(join(canonical, "workspace.img")); // a resume already has a workspace
253
+ if (!eligible)
254
+ return false;
255
+ const spare = this.pool.shift();
256
+ if (!spare) {
257
+ this.fillPool(); // none ready — warm up for next time
258
+ return false;
259
+ }
260
+ // Adopt: move the spare's slot dir to the canonical sandbox dir. The running
261
+ // helper keeps its open fds (inode survives the rename), so the live VM is
262
+ // unaffected; a later stop/start recomputes the canonical path and finds it.
263
+ renameSync(spare.stateDir, canonical);
264
+ this.vms.set(opts.id, {
265
+ helper: spare.helper,
266
+ socketPath: spare.socketPath,
267
+ workspaceImg: join(canonical, "workspace.img"),
268
+ stateDir: canonical,
269
+ });
270
+ this.fillPool(); // replenish in the background
271
+ log.info("applevz adopted a warm-pool guest", { sandbox: opts.id });
272
+ return true;
273
+ }
274
+ /** Top the pool up to its target in the background (one filler at a time). */
275
+ fillPool() {
276
+ if (this.poolTarget <= 0 || this.filling)
277
+ return;
278
+ void this.doFill();
279
+ }
280
+ async doFill() {
281
+ this.filling = true;
282
+ try {
283
+ while (this.pool.length < this.poolTarget) {
284
+ const n = ++this.poolSeq;
285
+ try {
286
+ const vm = await this.bootVm({
287
+ id: `pool-${n}`,
288
+ stateDir: join(this.poolDir, `slot-${n}`),
289
+ image: this.poolImage,
290
+ socketPath: `/tmp/hc-pool-${n}.sock`,
291
+ });
292
+ this.pool.push(vm);
293
+ log.info("warm pool: spare guest ready", { size: this.pool.length, target: this.poolTarget });
294
+ }
295
+ catch (err) {
296
+ log.warn("warm pool: spare boot failed (will retry on next claim)", {
297
+ error: err.message,
298
+ });
299
+ break; // don't hot-loop on a persistent failure
300
+ }
301
+ }
302
+ }
303
+ finally {
304
+ this.filling = false;
305
+ }
306
+ }
307
+ /** Tear down all spare guests (e.g. on shutdown). Idempotent. */
308
+ async drainPool() {
309
+ this.poolTarget = 0;
310
+ const spares = this.pool.splice(0);
311
+ for (const g of spares) {
312
+ g.helper.kill();
313
+ try {
314
+ unlinkSync(g.socketPath);
315
+ }
316
+ catch {
317
+ /* ignore */
318
+ }
319
+ }
320
+ try {
321
+ rmSync(this.poolDir, { recursive: true, force: true });
322
+ }
323
+ catch {
324
+ /* ignore */
325
+ }
326
+ }
327
+ async stop(id) {
328
+ const vm = this.vms.get(id);
329
+ if (!vm)
330
+ return;
331
+ // Flush the guest filesystem to the workspace disk before the abrupt VM
332
+ // teardown — otherwise writes still in the guest page cache are lost, and the
333
+ // workspace wouldn't survive stop/start. Best-effort.
334
+ await this.exec(id, "sync", {}, () => { }).catch(() => { });
335
+ vm.helper.kill(); // killing the helper tears down the VM; workspace.img persists
336
+ this.vms.delete(id);
337
+ try {
338
+ unlinkSync(vm.socketPath);
339
+ }
340
+ catch {
341
+ /* ignore */
342
+ }
343
+ }
344
+ /** VZ save/restore needs macOS 14+ (Darwin 23+) and a live VM. */
345
+ canSnapshot(id) {
346
+ return this.vms.has(id) && Number(release().split(".")[0]) >= 23;
347
+ }
348
+ /**
349
+ * Fast-pause: save the live VM's full state (RAM + virtual devices) to disk and
350
+ * tear the helper down, so the next `start` resumes **without a kernel boot**
351
+ * (VZ `saveMachineStateTo`/`restoreMachineStateFrom`, macOS 14+). The workspace
352
+ * disk + the snapshot file are all that's needed to resume; unlike `stop`, no
353
+ * `sync` is needed (the snapshot is a consistent point-in-time including the
354
+ * guest page cache). Background processes/servers come back live on resume.
355
+ */
356
+ async snapshot(id) {
357
+ const vm = this.vms.get(id);
358
+ if (!vm)
359
+ throw new Error(`applevz: sandbox ${id} is not running`);
360
+ // Flush the guest fs first so workspace writes are durable on disk even if a
361
+ // later resume can't restore the snapshot and has to cold-boot (a true restore
362
+ // would carry the page cache in the saved RAM state, so this only helps the
363
+ // fallback — it never hurts).
364
+ await this.exec(id, "sync", {}, () => { }).catch(() => { });
365
+ const snapPath = join(vm.stateDir, "snapshot.bin");
366
+ await vm.helper.rpc("snapshot", { path: snapPath });
367
+ vm.helper.kill(); // state saved; free the compute
368
+ this.vms.delete(id);
369
+ try {
370
+ unlinkSync(vm.socketPath);
371
+ }
372
+ catch {
373
+ /* ignore */
374
+ }
375
+ }
376
+ async destroy(id) {
377
+ await this.stop(id);
378
+ try {
379
+ rmSync(join(this.cfg.stateDir, id), { recursive: true, force: true });
380
+ }
381
+ catch {
382
+ /* ignore */
383
+ }
384
+ }
385
+ // --- agent transport ------------------------------------------------------
386
+ /** Open a fresh AgentConn to the sandbox's relay socket (the signed VZ helper
387
+ * relays the guest vsock to this unix socket). Backs every agent-served op. */
388
+ async openConn(id) {
389
+ const vm = this.vms.get(id);
390
+ if (!vm)
391
+ throw new Error(`applevz: sandbox ${id} is not running`);
392
+ return AgentConn.connect({ path: vm.socketPath, timeoutMs: 15000 });
393
+ }
394
+ // --- host probes (one-shot helper, no VM) ---------------------------------
395
+ async ping() {
396
+ let res;
397
+ try {
398
+ res = await this.oneShot("probe");
399
+ }
400
+ catch (err) {
401
+ throw new Error(`applevz: cannot run the sbx-vz helper at "${this.cfg.helperPath}" (${err.message}). ` +
402
+ `Build it with 'npm run build:vz', or set SBX_VZ_HELPER_PATH.`);
403
+ }
404
+ const r = res.result;
405
+ if (!res.ok || !r?.available) {
406
+ throw new Error(`applevz: Virtualization.framework not available: ${r?.reason || res.error || "unknown"}`);
407
+ }
408
+ }
409
+ async hostInfo() {
410
+ const res = await this.oneShot("hostInfo");
411
+ if (!res.ok)
412
+ throw new Error(`applevz hostInfo failed: ${res.error ?? "unknown"}`);
413
+ const r = res.result;
414
+ return { memoryMb: Number(r?.memoryMb) || 0, cpus: Number(r?.cpus) || 0 };
415
+ }
416
+ /** One-shot stdio RPC to a throwaway helper process (probe/hostInfo). */
417
+ oneShot(method) {
418
+ return new Promise((resolve, reject) => {
419
+ const child = spawn(this.cfg.helperPath, [], { stdio: ["pipe", "pipe", "pipe"] });
420
+ let out = "";
421
+ let err = "";
422
+ child.stdout.on("data", (d) => (out += d.toString()));
423
+ child.stderr.on("data", (d) => (err += d.toString()));
424
+ child.on("error", reject);
425
+ child.on("close", () => {
426
+ const line = out.split("\n").find((l) => l.trim());
427
+ if (!line)
428
+ return reject(new Error(err.trim() || "no response from sbx-vz"));
429
+ try {
430
+ resolve(JSON.parse(line));
431
+ }
432
+ catch {
433
+ reject(new Error(`bad sbx-vz response: ${line}`));
434
+ }
435
+ });
436
+ child.stdin.write(JSON.stringify({ id: 1, method }) + "\n");
437
+ child.stdin.end();
438
+ });
439
+ }
440
+ }
441
+ /**
442
+ * Long-lived `sbx-vz serve` process for one sandbox. Drives it over stdio
443
+ * JSON-RPC (`start`/`stop`); the guest console + helper logs go to a console
444
+ * file. RPC replies are matched by id; stdout carries only JSON replies.
445
+ */
446
+ class HelperProcess {
447
+ proc;
448
+ nextId = 1;
449
+ pending = new Map();
450
+ buf = "";
451
+ constructor(helperPath, consoleLogPath) {
452
+ this.proc = spawn(helperPath, ["serve"], { stdio: ["pipe", "pipe", "pipe"] });
453
+ this.proc.stdout.on("data", (d) => this.feed(d.toString()));
454
+ this.proc.stderr.pipe(createWriteStream(consoleLogPath, { flags: "a" }));
455
+ const fail = (e) => {
456
+ for (const p of this.pending.values())
457
+ p.reject(e);
458
+ this.pending.clear();
459
+ };
460
+ this.proc.on("exit", () => fail(new Error("sbx-vz helper exited")));
461
+ this.proc.on("error", (e) => fail(e));
462
+ }
463
+ rpc(method, params = {}) {
464
+ const id = this.nextId++;
465
+ return new Promise((resolve, reject) => {
466
+ this.pending.set(id, { resolve, reject });
467
+ this.proc.stdin.write(JSON.stringify({ id, method, params }) + "\n");
468
+ });
469
+ }
470
+ feed(s) {
471
+ this.buf += s;
472
+ let i;
473
+ while ((i = this.buf.indexOf("\n")) >= 0) {
474
+ const line = this.buf.slice(0, i);
475
+ this.buf = this.buf.slice(i + 1);
476
+ if (!line.trim())
477
+ continue;
478
+ let m;
479
+ try {
480
+ m = JSON.parse(line);
481
+ }
482
+ catch {
483
+ continue;
484
+ }
485
+ const p = m.id != null ? this.pending.get(m.id) : undefined;
486
+ if (!p || m.id == null)
487
+ continue;
488
+ this.pending.delete(m.id);
489
+ if (m.ok)
490
+ p.resolve(m.result);
491
+ else
492
+ p.reject(new Error(m.error || "sbx-vz helper error"));
493
+ }
494
+ }
495
+ kill() {
496
+ try {
497
+ this.proc.kill();
498
+ }
499
+ catch {
500
+ /* already gone */
501
+ }
502
+ }
503
+ }
504
+ /** Copy `src` to `dst`, preferring an APFS copy-on-write clone (instant, shares
505
+ * blocks until written) and falling back to a sparse-preserving `cp`. Used to
506
+ * give each sandbox its own workspace disk from the blank template cheaply. */
507
+ function cloneFile(src, dst) {
508
+ try {
509
+ execFileSync("cp", ["-c", src, dst]); // APFS clonefile()
510
+ }
511
+ catch {
512
+ execFileSync("cp", [src, dst]); // non-APFS: plain copy (still sparse-aware on macOS)
513
+ }
514
+ }
515
+ /** Create a sparse file of `sizeBytes` if it doesn't exist (workspace disk). */
516
+ function ensureSparseFile(path, sizeBytes) {
517
+ if (existsSync(path))
518
+ return;
519
+ const fd = openSync(path, "w");
520
+ try {
521
+ ftruncateSync(fd, sizeBytes);
522
+ }
523
+ finally {
524
+ closeSync(fd);
525
+ }
526
+ }
527
+ //# sourceMappingURL=applevz.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"applevz.js","sourceRoot":"","sources":["../../src/driver/applevz.ts"],"names":[],"mappings":"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"}