@h-rig/isolation-plugin 0.0.6-alpha.157 → 0.0.6-alpha.158

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 (77) hide show
  1. package/dist/src/embedded-native-assets.d.ts +7 -0
  2. package/dist/src/embedded-native-assets.js +6 -0
  3. package/dist/src/image-fingerprint-sidecar.d.ts +1 -0
  4. package/dist/src/image-fingerprint-sidecar.js +515 -0
  5. package/dist/src/image.d.ts +40 -0
  6. package/dist/src/image.js +1498 -0
  7. package/dist/src/index.js +4220 -20
  8. package/dist/src/isolation/binary-build-worker.d.ts +1 -0
  9. package/dist/src/isolation/binary-build-worker.js +323 -0
  10. package/dist/src/isolation/discovery.d.ts +7 -0
  11. package/dist/src/isolation/discovery.js +477 -0
  12. package/dist/src/isolation/git-native.d.ts +28 -0
  13. package/dist/src/isolation/git-native.js +598 -0
  14. package/dist/src/isolation/home.d.ts +25 -0
  15. package/dist/src/isolation/home.js +929 -0
  16. package/dist/src/isolation/index.d.ts +43 -0
  17. package/dist/src/isolation/index.js +4062 -0
  18. package/dist/src/isolation/provisioning-env.d.ts +1 -0
  19. package/dist/src/isolation/provisioning-env.js +6 -0
  20. package/dist/src/isolation/runner.d.ts +20 -0
  21. package/dist/src/isolation/runner.js +1881 -0
  22. package/dist/src/isolation/runtime-binary-build.d.ts +88 -0
  23. package/dist/src/isolation/runtime-binary-build.js +480 -0
  24. package/dist/src/isolation/shared.d.ts +29 -0
  25. package/dist/src/isolation/shared.js +283 -0
  26. package/dist/src/isolation/toolchain.d.ts +71 -0
  27. package/dist/src/isolation/toolchain.js +1348 -0
  28. package/dist/src/isolation/types.d.ts +15 -0
  29. package/dist/src/isolation/types.js +1 -0
  30. package/dist/src/isolation/worktree.d.ts +22 -0
  31. package/dist/src/isolation/worktree.js +353 -0
  32. package/dist/src/native-extract.d.ts +2 -0
  33. package/dist/src/native-extract.js +44 -0
  34. package/dist/src/plugin.d.ts +2 -2
  35. package/dist/src/plugin.js +4219 -19
  36. package/dist/src/runtime-config.d.ts +3 -0
  37. package/dist/src/runtime-config.js +215 -0
  38. package/dist/src/runtime-native-sidecar.d.ts +8 -0
  39. package/dist/src/runtime-native-sidecar.js +368 -0
  40. package/dist/src/runtime-native.d.ts +51 -0
  41. package/dist/src/runtime-native.js +485 -0
  42. package/dist/src/sandbox/backend-bwrap.d.ts +20 -0
  43. package/dist/src/sandbox/backend-bwrap.js +268 -0
  44. package/dist/src/sandbox/backend-none.d.ts +11 -0
  45. package/dist/src/sandbox/backend-none.js +20 -0
  46. package/dist/src/sandbox/backend-seatbelt.d.ts +13 -0
  47. package/dist/src/sandbox/backend-seatbelt.js +225 -0
  48. package/dist/src/sandbox/backend.d.ts +117 -0
  49. package/dist/src/sandbox/backend.js +864 -0
  50. package/dist/src/sandbox/orchestrator.d.ts +21 -0
  51. package/dist/src/sandbox/orchestrator.js +895 -0
  52. package/dist/src/sandbox/utils.d.ts +43 -0
  53. package/dist/src/sandbox/utils.js +94 -0
  54. package/dist/src/service.d.ts +10 -5
  55. package/dist/src/service.js +4145 -2
  56. package/dist/src/sidecar-arg.d.ts +7 -0
  57. package/dist/src/sidecar-arg.js +6 -0
  58. package/dist/src/sidecar-entrypoint.d.ts +9 -0
  59. package/dist/src/sidecar-entrypoint.js +401 -0
  60. package/dist/src/snapshot-sidecar.d.ts +2 -0
  61. package/dist/src/snapshot-sidecar.js +566 -0
  62. package/dist/src/snapshot.d.ts +64 -0
  63. package/dist/src/snapshot.js +515 -0
  64. package/dist/src/task-run-snapshot.d.ts +26 -0
  65. package/dist/src/task-run-snapshot.js +713 -0
  66. package/native/darwin-arm64/rig-git +0 -0
  67. package/native/darwin-arm64/rig-git.build-manifest.json +4 -0
  68. package/native/darwin-arm64/runtime-native.dylib +0 -0
  69. package/native/darwin-x64/rig-git +0 -0
  70. package/native/darwin-x64/runtime-native.dylib +0 -0
  71. package/native/linux-arm64/rig-git +0 -0
  72. package/native/linux-arm64/runtime-native.so +0 -0
  73. package/native/linux-x64/rig-git +0 -0
  74. package/native/linux-x64/runtime-native.so +0 -0
  75. package/native/win32-x64/rig-git.exe +0 -0
  76. package/native/win32-x64/runtime-native.dll +0 -0
  77. package/package.json +45 -5
@@ -0,0 +1,1881 @@
1
+ // @bun
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropNames = Object.getOwnPropertyNames;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ function __accessProp(key) {
7
+ return this[key];
8
+ }
9
+ var __toCommonJS = (from) => {
10
+ var entry = (__moduleCache ??= new WeakMap).get(from), desc;
11
+ if (entry)
12
+ return entry;
13
+ entry = __defProp({}, "__esModule", { value: true });
14
+ if (from && typeof from === "object" || typeof from === "function") {
15
+ for (var key of __getOwnPropNames(from))
16
+ if (!__hasOwnProp.call(entry, key))
17
+ __defProp(entry, key, {
18
+ get: __accessProp.bind(from, key),
19
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
20
+ });
21
+ }
22
+ __moduleCache.set(from, entry);
23
+ return entry;
24
+ };
25
+ var __moduleCache;
26
+ var __returnValue = (v) => v;
27
+ function __exportSetter(name, newValue) {
28
+ this[name] = __returnValue.bind(null, newValue);
29
+ }
30
+ var __export = (target, all) => {
31
+ for (var name in all)
32
+ __defProp(target, name, {
33
+ get: all[name],
34
+ enumerable: true,
35
+ configurable: true,
36
+ set: __exportSetter.bind(all, name)
37
+ });
38
+ };
39
+ var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
40
+ var __require = import.meta.require;
41
+
42
+ // packages/isolation-plugin/src/sandbox/utils.ts
43
+ import { existsSync as existsSync2, readdirSync, realpathSync } from "fs";
44
+ import { resolve as resolve2 } from "path";
45
+ import { resolveMonorepoRoot } from "@rig/core/layout";
46
+ function toRealPath(path) {
47
+ if (!existsSync2(path)) {
48
+ return resolve2(path);
49
+ }
50
+ try {
51
+ return realpathSync.native(path);
52
+ } catch {
53
+ return resolve2(path);
54
+ }
55
+ }
56
+ function resolveHostGitMetadataPaths(projectRoot, workspaceDir) {
57
+ const candidates = new Set;
58
+ const addPath = (candidate) => {
59
+ if (existsSync2(candidate)) {
60
+ candidates.add(toRealPath(candidate));
61
+ }
62
+ };
63
+ addPath(resolve2(projectRoot, ".git"));
64
+ addPath(resolve2(workspaceDir, "..", "..", ".git"));
65
+ for (const repoRoot of resolveHostRepoRootPaths(projectRoot)) {
66
+ addPath(resolve2(repoRoot, ".git"));
67
+ }
68
+ const workspaceGit = resolve2(workspaceDir, ".git");
69
+ if (existsSync2(workspaceGit)) {
70
+ addPath(workspaceGit);
71
+ }
72
+ return [...candidates];
73
+ }
74
+ function resolveHostRepoRootPaths(projectRoot) {
75
+ const candidates = new Set;
76
+ const addPath = (candidate) => {
77
+ if (existsSync2(candidate)) {
78
+ candidates.add(toRealPath(candidate));
79
+ }
80
+ };
81
+ try {
82
+ const monorepoRoot = resolveMonorepoRoot(projectRoot);
83
+ if (toRealPath(monorepoRoot) !== toRealPath(projectRoot)) {
84
+ addPath(monorepoRoot);
85
+ }
86
+ } catch {}
87
+ const reposDir = resolve2(projectRoot, "repos");
88
+ if (existsSync2(reposDir)) {
89
+ for (const entry of readdirSync(reposDir, { withFileTypes: true })) {
90
+ if (entry.isDirectory() || entry.isSymbolicLink()) {
91
+ addPath(resolve2(reposDir, entry.name));
92
+ }
93
+ }
94
+ }
95
+ return [...candidates];
96
+ }
97
+ function resolveNetworkWithPolicy(sandboxConfig, envOverride) {
98
+ if (envOverride) {
99
+ const envValue = parseBooleanEnv(envOverride, sandboxConfig.network);
100
+ if (envValue !== sandboxConfig.network) {
101
+ console.warn(`[sandbox] RIG_RUNTIME_SANDBOX_NETWORK=${envOverride} overrides policy sandbox.network=${sandboxConfig.network}`);
102
+ }
103
+ return envValue;
104
+ }
105
+ return sandboxConfig.network;
106
+ }
107
+ function parseBooleanEnv(raw, fallback) {
108
+ if (!raw) {
109
+ return fallback;
110
+ }
111
+ const normalized = raw.trim().toLowerCase();
112
+ if (normalized === "1" || normalized === "true" || normalized === "yes" || normalized === "on") {
113
+ return true;
114
+ }
115
+ if (normalized === "0" || normalized === "false" || normalized === "no" || normalized === "off") {
116
+ return false;
117
+ }
118
+ return fallback;
119
+ }
120
+ function uniq(values) {
121
+ return [...new Set(values)];
122
+ }
123
+ function seatbeltString(value) {
124
+ return `"${value.replace(/\\/g, "\\\\").replace(/"/g, "\\\"")}"`;
125
+ }
126
+ var init_utils = () => {};
127
+
128
+ // packages/isolation-plugin/src/sandbox/backend-seatbelt.ts
129
+ var exports_backend_seatbelt = {};
130
+ __export(exports_backend_seatbelt, {
131
+ SeatbeltBackend: () => SeatbeltBackend
132
+ });
133
+ import { mkdirSync, writeFileSync } from "fs";
134
+ import { resolve as resolve3 } from "path";
135
+
136
+ class SeatbeltBackend {
137
+ kind = "macos-seatbelt";
138
+ binaryPath;
139
+ config;
140
+ ctx;
141
+ resolvedPaths;
142
+ constructor(binaryPath, config, ctx, resolvedPaths) {
143
+ this.binaryPath = binaryPath;
144
+ this.config = config;
145
+ this.ctx = ctx;
146
+ this.resolvedPaths = resolvedPaths;
147
+ }
148
+ wrap(options) {
149
+ const profilePath = this.writeSeatbeltProfile(options);
150
+ return {
151
+ command: [this.binaryPath, "-f", profilePath, ...options.command],
152
+ enabled: true,
153
+ backend: "macos-seatbelt",
154
+ profilePath
155
+ };
156
+ }
157
+ writeSeatbeltProfile(options) {
158
+ const sandboxDir = resolve3(options.runtime.rootDir, "sandbox");
159
+ mkdirSync(sandboxDir, { recursive: true });
160
+ const profilePath = resolve3(sandboxDir, "seatbelt.sb");
161
+ const profile = this.renderProfile(options);
162
+ writeFileSync(profilePath, `${profile}
163
+ `, "utf-8");
164
+ return profilePath;
165
+ }
166
+ renderProfile(options) {
167
+ const { runtime, projectRoot } = options;
168
+ const { ctx, resolvedPaths, config } = this;
169
+ const workspaceReal = ctx.realPath(runtime.workspaceDir);
170
+ const runtimeRootReal = ctx.realPath(runtime.rootDir);
171
+ const homeReal = ctx.realPath(runtime.homeDir);
172
+ const tmpReal = ctx.realPath(runtime.tmpDir);
173
+ const cacheReal = ctx.realPath(runtime.cacheDir);
174
+ const hostGitDirs = resolveHostGitMetadataPaths(projectRoot, runtime.workspaceDir);
175
+ const hostRepoRoots = resolveHostRepoRootPaths(projectRoot).map((repoRoot) => ctx.realPath(repoRoot));
176
+ const bunDir = ctx.realPath(resolvedPaths.bunDir);
177
+ const claudeDir = resolvedPaths.claudeDir ? ctx.realPath(resolvedPaths.claudeDir) : null;
178
+ const allowNetwork = resolveNetworkWithPolicy(config, process.env.RIG_RUNTIME_SANDBOX_NETWORK);
179
+ const lines = [
180
+ "(version 1)",
181
+ "(deny default)",
182
+ '(import "system.sb")',
183
+ "(allow process*)",
184
+ "(allow process-info*)",
185
+ "(allow signal)",
186
+ "(allow sysctl-read)",
187
+ "(allow file-read-metadata)"
188
+ ];
189
+ if (allowNetwork) {
190
+ lines.push("(allow network*)");
191
+ }
192
+ for (const sysPath of [
193
+ "/usr/lib",
194
+ "/usr/bin",
195
+ "/usr/sbin",
196
+ "/usr/share",
197
+ "/bin",
198
+ "/sbin",
199
+ "/System",
200
+ "/Library",
201
+ "/Library/Frameworks",
202
+ "/Library/Developer",
203
+ "/Library/Apple",
204
+ "/Applications",
205
+ "/private/var/db",
206
+ "/opt/homebrew"
207
+ ]) {
208
+ lines.push(`(allow file-read* (subpath ${seatbeltString(sysPath)}))`);
209
+ }
210
+ lines.push(`(allow file-read* (subpath ${seatbeltString(bunDir)}))`);
211
+ if (claudeDir) {
212
+ lines.push(`(allow file-read* (subpath ${seatbeltString(claudeDir)}))`);
213
+ }
214
+ if (resolvedPaths.nodeDir) {
215
+ lines.push(`(allow file-read* (subpath ${seatbeltString(resolvedPaths.nodeDir)}))`);
216
+ }
217
+ for (const depPath of resolvedPaths.depRoots) {
218
+ lines.push(`(allow file-read* (subpath ${seatbeltString(depPath)}))`);
219
+ }
220
+ for (const rwPath of uniq([
221
+ workspaceReal,
222
+ runtimeRootReal,
223
+ homeReal,
224
+ tmpReal,
225
+ cacheReal
226
+ ])) {
227
+ lines.push(`(allow file-read* (subpath ${seatbeltString(rwPath)}))`);
228
+ lines.push(`(allow file-write* (subpath ${seatbeltString(rwPath)}))`);
229
+ }
230
+ for (const gitPath of hostGitDirs) {
231
+ lines.push(`(allow file-read* (subpath ${seatbeltString(gitPath)}))`);
232
+ lines.push(`(allow file-write* (subpath ${seatbeltString(gitPath)}))`);
233
+ }
234
+ const projectRootReal = ctx.realPath(projectRoot);
235
+ if (projectRootReal !== workspaceReal && !projectRootReal.startsWith(workspaceReal + "/")) {
236
+ lines.push(`(allow file-read* (subpath ${seatbeltString(projectRootReal)}))`);
237
+ }
238
+ for (const repoRoot of hostRepoRoots) {
239
+ if (!ctx.pathExists(repoRoot) || repoRoot === workspaceReal || repoRoot.startsWith(workspaceReal + "/") || repoRoot === projectRootReal || repoRoot.startsWith(projectRootReal + "/")) {
240
+ continue;
241
+ }
242
+ lines.push(`(allow file-read* (subpath ${seatbeltString(repoRoot)}))`);
243
+ }
244
+ const realHome = process.env.HOME?.trim();
245
+ if (realHome) {
246
+ for (const binSubdir of [".local/bin", ".cargo/bin"]) {
247
+ const binPath = resolve3(realHome, binSubdir);
248
+ if (ctx.pathExists(binPath)) {
249
+ lines.push(`(allow file-read* (subpath ${seatbeltString(ctx.realPath(binPath))}))`);
250
+ }
251
+ }
252
+ }
253
+ for (const tempPath of [
254
+ "/dev",
255
+ "/tmp",
256
+ "/private/tmp",
257
+ "/var/folders",
258
+ "/private/var/folders"
259
+ ]) {
260
+ lines.push(`(allow file-read* (subpath ${seatbeltString(tempPath)}))`);
261
+ lines.push(`(allow file-write* (subpath ${seatbeltString(tempPath)}))`);
262
+ }
263
+ return lines.join(`
264
+ `);
265
+ }
266
+ }
267
+ var init_backend_seatbelt = __esm(() => {
268
+ init_utils();
269
+ });
270
+
271
+ // packages/isolation-plugin/src/sandbox/backend-bwrap.ts
272
+ var exports_backend_bwrap = {};
273
+ __export(exports_backend_bwrap, {
274
+ BwrapBackend: () => BwrapBackend
275
+ });
276
+ import { mkdirSync as mkdirSync2 } from "fs";
277
+ import { resolve as resolve4 } from "path";
278
+
279
+ class BwrapBackend {
280
+ kind = "linux-bwrap";
281
+ binaryPath;
282
+ config;
283
+ ctx;
284
+ resolvedPaths;
285
+ which;
286
+ constructor(binaryPath, config, ctx, resolvedPaths, which) {
287
+ this.binaryPath = binaryPath;
288
+ this.config = config;
289
+ this.ctx = ctx;
290
+ this.resolvedPaths = resolvedPaths;
291
+ this.which = which ?? ((bin) => Bun.which(bin));
292
+ }
293
+ wrap(options) {
294
+ const command = this.buildCommand(options);
295
+ return {
296
+ command,
297
+ enabled: true,
298
+ backend: "linux-bwrap"
299
+ };
300
+ }
301
+ buildCommand(options) {
302
+ const { runtime, projectRoot, command } = options;
303
+ const { ctx, resolvedPaths, config } = this;
304
+ const workspaceReal = ctx.realPath(runtime.workspaceDir);
305
+ const runtimeRootReal = ctx.realPath(runtime.rootDir);
306
+ const homeReal = ctx.realPath(runtime.homeDir);
307
+ const tmpReal = ctx.realPath(runtime.tmpDir);
308
+ const cacheReal = ctx.realPath(runtime.cacheDir);
309
+ const hostGitDirs = resolveHostGitMetadataPaths(projectRoot, runtime.workspaceDir);
310
+ const hostRepoRoots = resolveHostRepoRootPaths(projectRoot).map((repoRoot) => ctx.realPath(repoRoot));
311
+ const bunDir = ctx.realPath(resolvedPaths.bunDir);
312
+ const claudeDir = resolvedPaths.claudeDir ? ctx.realPath(resolvedPaths.claudeDir) : null;
313
+ const allowNetwork = resolveNetworkWithPolicy(config, process.env.RIG_RUNTIME_SANDBOX_NETWORK);
314
+ const args = [
315
+ this.binaryPath,
316
+ "--die-with-parent",
317
+ "--new-session",
318
+ "--unshare-pid",
319
+ "--tmpfs",
320
+ "/",
321
+ "--ro-bind",
322
+ "/usr",
323
+ "/usr",
324
+ "--ro-bind",
325
+ "/bin",
326
+ "/bin",
327
+ "--ro-bind",
328
+ "/sbin",
329
+ "/sbin"
330
+ ];
331
+ for (const libPath of ["/lib", "/lib64"]) {
332
+ if (ctx.pathExists(libPath)) {
333
+ args.push("--ro-bind", libPath, libPath);
334
+ }
335
+ }
336
+ for (const etcEntry of [
337
+ "/etc/ld.so.cache",
338
+ "/etc/ld.so.conf",
339
+ "/etc/ld.so.conf.d",
340
+ "/etc/resolv.conf",
341
+ "/etc/hosts",
342
+ "/etc/nsswitch.conf",
343
+ "/etc/gai.conf",
344
+ "/etc/host.conf",
345
+ "/etc/ssl",
346
+ "/etc/ca-certificates",
347
+ "/etc/pki",
348
+ "/etc/passwd",
349
+ "/etc/group",
350
+ "/etc/localtime",
351
+ "/etc/timezone",
352
+ "/etc/locale.conf",
353
+ "/etc/default/locale"
354
+ ]) {
355
+ if (ctx.pathExists(etcEntry)) {
356
+ args.push("--ro-bind", etcEntry, etcEntry);
357
+ }
358
+ }
359
+ if (ctx.pathExists("/run/systemd/resolve")) {
360
+ args.push("--ro-bind", "/run/systemd/resolve", "/run/systemd/resolve");
361
+ }
362
+ if (ctx.pathExists("/run/nscd")) {
363
+ args.push("--ro-bind", "/run/nscd", "/run/nscd");
364
+ }
365
+ args.push("--ro-bind", bunDir, bunDir);
366
+ if (claudeDir) {
367
+ args.push("--ro-bind", claudeDir, claudeDir);
368
+ }
369
+ if (resolvedPaths.nodeDir && ctx.pathExists(resolvedPaths.nodeDir)) {
370
+ args.push("--ro-bind", resolvedPaths.nodeDir, resolvedPaths.nodeDir);
371
+ }
372
+ for (const depPath of resolvedPaths.depRoots) {
373
+ if (ctx.pathExists(depPath)) {
374
+ args.push("--ro-bind", depPath, depPath);
375
+ }
376
+ }
377
+ const projectRootReal = ctx.realPath(projectRoot);
378
+ if (projectRootReal !== workspaceReal && !projectRootReal.startsWith(workspaceReal + "/") && ctx.pathExists(projectRootReal)) {
379
+ args.push("--ro-bind", projectRootReal, projectRootReal);
380
+ }
381
+ for (const repoRoot of hostRepoRoots) {
382
+ if (!ctx.pathExists(repoRoot) || repoRoot === workspaceReal || repoRoot.startsWith(workspaceReal + "/") || repoRoot === projectRootReal || repoRoot.startsWith(projectRootReal + "/")) {
383
+ continue;
384
+ }
385
+ args.push("--ro-bind", repoRoot, repoRoot);
386
+ }
387
+ args.push("--bind", workspaceReal, workspaceReal);
388
+ args.push("--bind", runtimeRootReal, runtimeRootReal);
389
+ for (const rwPath of uniq([homeReal, tmpReal, cacheReal])) {
390
+ if (rwPath !== runtimeRootReal && !rwPath.startsWith(runtimeRootReal + "/")) {
391
+ args.push("--bind", rwPath, rwPath);
392
+ }
393
+ }
394
+ for (const gitPath of hostGitDirs) {
395
+ if (!ctx.pathExists(gitPath))
396
+ continue;
397
+ if (gitPath === runtimeRootReal || gitPath.startsWith(runtimeRootReal + "/"))
398
+ continue;
399
+ if (gitPath === workspaceReal || gitPath.startsWith(workspaceReal + "/"))
400
+ continue;
401
+ args.push("--bind", gitPath, gitPath);
402
+ }
403
+ const realHome = process.env.HOME?.trim();
404
+ if (realHome) {
405
+ for (const binSubdir of [".local/bin", ".local/lib", ".cargo/bin"]) {
406
+ const binPath = ctx.realPath(resolve4(realHome, binSubdir));
407
+ if (ctx.pathExists(binPath)) {
408
+ args.push("--ro-bind", binPath, binPath);
409
+ }
410
+ }
411
+ const agentSshDir = resolve4(homeReal, ".ssh");
412
+ if (ctx.pathExists(agentSshDir)) {
413
+ args.push("--ro-bind", agentSshDir, agentSshDir);
414
+ } else {
415
+ const hostSshDir = resolve4(realHome, ".ssh");
416
+ if (ctx.pathExists(hostSshDir)) {
417
+ mkdirSync2(agentSshDir, { recursive: true });
418
+ args.push("--ro-bind", hostSshDir, agentSshDir);
419
+ args.push("--ro-bind", hostSshDir, hostSshDir);
420
+ }
421
+ }
422
+ }
423
+ args.push("--proc", "/proc");
424
+ args.push("--dev", "/dev");
425
+ args.push("--tmpfs", "/tmp");
426
+ args.push("--unsetenv", "CLAUDECODE");
427
+ args.push("--setenv", "HOME", homeReal);
428
+ args.push("--setenv", "TMPDIR", "/tmp");
429
+ args.push("--chdir", workspaceReal);
430
+ if (!allowNetwork) {
431
+ args.push("--unshare-net");
432
+ }
433
+ args.push("--", ...this.resolveCommandBinary(command));
434
+ return args;
435
+ }
436
+ resolveCommandBinary(command) {
437
+ if (command.length === 0)
438
+ return command;
439
+ const [bin, ...rest] = command;
440
+ if (!bin)
441
+ return command;
442
+ const resolved = this.which(bin);
443
+ if (!resolved)
444
+ return command;
445
+ try {
446
+ const { realpathSync: realpathSync2 } = __require("fs");
447
+ const resolvedBinary = realpathSync2(resolved);
448
+ return [resolvedBinary, ...rest];
449
+ } catch {
450
+ return [resolved, ...rest];
451
+ }
452
+ }
453
+ }
454
+ var init_backend_bwrap = __esm(() => {
455
+ init_utils();
456
+ });
457
+
458
+ // packages/isolation-plugin/src/isolation/runner.ts
459
+ import { existsSync as existsSync8, rmSync as rmSync3, writeFileSync as writeFileSync4 } from "fs";
460
+ import { basename as basename2, resolve as resolve12 } from "path";
461
+
462
+ // packages/isolation-plugin/src/sandbox/backend.ts
463
+ import { existsSync as existsSync3 } from "fs";
464
+
465
+ // packages/isolation-plugin/src/runtime-config.ts
466
+ import { existsSync, readFileSync, statSync } from "fs";
467
+ import { resolve } from "path";
468
+ import {
469
+ POLICY_VERSION
470
+ } from "@rig/contracts";
471
+ var DEFAULT_SCOPE = {
472
+ fail_closed: true,
473
+ harness_paths_exempt: true,
474
+ runtime_paths_exempt: true
475
+ };
476
+ var DEFAULT_SANDBOX = {
477
+ mode: "enforce",
478
+ network: true,
479
+ read_deny: [],
480
+ write_allow_from_runtime: true
481
+ };
482
+ var DEFAULT_ISOLATION = {
483
+ default_mode: "worktree",
484
+ repo_symlink_fallback: false,
485
+ strict_provisioning: true,
486
+ fail_closed_on_provision_error: true
487
+ };
488
+ var DEFAULT_COMPLETION = {
489
+ derive_checks_from_scope: true,
490
+ checks: [],
491
+ typescript_config_probe: ["tsconfig.json"],
492
+ eslint_config_probe: [".eslintrc.js", ".eslintrc.json", "eslint.config.js"]
493
+ };
494
+ var DEFAULT_RUNTIME_IMAGE = {
495
+ deps: { monorepo_install: false, hp_next_install: false },
496
+ plugins_require_binaries: true
497
+ };
498
+ var DEFAULT_RUNTIME_SNAPSHOT = { enabled: true };
499
+ var policyCache = null;
500
+ var policyCachePath = null;
501
+ function loadSandboxConfig(projectRoot) {
502
+ return loadPolicy(projectRoot).sandbox;
503
+ }
504
+ function defaultPolicy() {
505
+ return {
506
+ version: POLICY_VERSION,
507
+ mode: "enforce",
508
+ scope: { ...DEFAULT_SCOPE },
509
+ rules: [],
510
+ sandbox: { ...DEFAULT_SANDBOX },
511
+ isolation: { ...DEFAULT_ISOLATION },
512
+ completion: { ...DEFAULT_COMPLETION },
513
+ runtime_image: {
514
+ deps: { ...DEFAULT_RUNTIME_IMAGE.deps },
515
+ plugins_require_binaries: DEFAULT_RUNTIME_IMAGE.plugins_require_binaries
516
+ },
517
+ runtime_snapshot: { ...DEFAULT_RUNTIME_SNAPSHOT }
518
+ };
519
+ }
520
+ function loadPolicy(projectRoot) {
521
+ const configPath = resolve(projectRoot, "rig/policy/policy.json");
522
+ if (!existsSync(configPath))
523
+ return defaultPolicy();
524
+ let mtimeMs;
525
+ try {
526
+ mtimeMs = statSync(configPath).mtimeMs;
527
+ } catch {
528
+ return defaultPolicy();
529
+ }
530
+ if (policyCache && policyCachePath === configPath && policyCache.mtimeMs === mtimeMs) {
531
+ return policyCache.config;
532
+ }
533
+ try {
534
+ const config = mergeWithDefaults(JSON.parse(readFileSync(configPath, "utf-8")));
535
+ policyCache = { mtimeMs, config };
536
+ policyCachePath = configPath;
537
+ return config;
538
+ } catch {
539
+ return defaultPolicy();
540
+ }
541
+ }
542
+ function mergeWithDefaults(parsed) {
543
+ const base = defaultPolicy();
544
+ if (typeof parsed.mode === "string" && isValidMode(parsed.mode))
545
+ base.mode = parsed.mode;
546
+ if (parsed.scope && typeof parsed.scope === "object" && !Array.isArray(parsed.scope)) {
547
+ const scope = parsed.scope;
548
+ if (typeof scope.fail_closed === "boolean")
549
+ base.scope.fail_closed = scope.fail_closed;
550
+ if (typeof scope.harness_paths_exempt === "boolean")
551
+ base.scope.harness_paths_exempt = scope.harness_paths_exempt;
552
+ if (typeof scope.runtime_paths_exempt === "boolean")
553
+ base.scope.runtime_paths_exempt = scope.runtime_paths_exempt;
554
+ }
555
+ if (Array.isArray(parsed.rules))
556
+ base.rules = precompilePolicyRuleRegexes(parsed.rules.filter(isValidRule));
557
+ if (Array.isArray(parsed.deny) && base.rules.length === 0) {
558
+ base.rules = precompilePolicyRuleRegexes(migrateLegacyDeny(parsed.deny));
559
+ }
560
+ if (parsed.sandbox && typeof parsed.sandbox === "object" && !Array.isArray(parsed.sandbox)) {
561
+ const sandbox = parsed.sandbox;
562
+ if (typeof sandbox.mode === "string" && isValidMode(sandbox.mode))
563
+ base.sandbox.mode = sandbox.mode;
564
+ if (typeof sandbox.network === "boolean")
565
+ base.sandbox.network = sandbox.network;
566
+ if (Array.isArray(sandbox.read_deny))
567
+ base.sandbox.read_deny = sandbox.read_deny.filter((value) => typeof value === "string");
568
+ if (typeof sandbox.write_allow_from_runtime === "boolean")
569
+ base.sandbox.write_allow_from_runtime = sandbox.write_allow_from_runtime;
570
+ }
571
+ if (parsed.isolation && typeof parsed.isolation === "object" && !Array.isArray(parsed.isolation)) {
572
+ const isolation = parsed.isolation;
573
+ if (isolation.default_mode === "worktree")
574
+ base.isolation.default_mode = isolation.default_mode;
575
+ if (typeof isolation.repo_symlink_fallback === "boolean")
576
+ base.isolation.repo_symlink_fallback = isolation.repo_symlink_fallback;
577
+ if (typeof isolation.strict_provisioning === "boolean")
578
+ base.isolation.strict_provisioning = isolation.strict_provisioning;
579
+ if (typeof isolation.fail_closed_on_provision_error === "boolean")
580
+ base.isolation.fail_closed_on_provision_error = isolation.fail_closed_on_provision_error;
581
+ }
582
+ if (parsed.completion && typeof parsed.completion === "object" && !Array.isArray(parsed.completion)) {
583
+ const completion = parsed.completion;
584
+ if (typeof completion.derive_checks_from_scope === "boolean")
585
+ base.completion.derive_checks_from_scope = completion.derive_checks_from_scope;
586
+ if (Array.isArray(completion.checks))
587
+ base.completion.checks = completion.checks.filter((value) => typeof value === "string");
588
+ if (Array.isArray(completion.typescript_config_probe))
589
+ base.completion.typescript_config_probe = completion.typescript_config_probe.filter((value) => typeof value === "string");
590
+ if (Array.isArray(completion.eslint_config_probe))
591
+ base.completion.eslint_config_probe = completion.eslint_config_probe.filter((value) => typeof value === "string");
592
+ }
593
+ if (parsed.runtime_image && typeof parsed.runtime_image === "object" && !Array.isArray(parsed.runtime_image)) {
594
+ const runtimeImage = parsed.runtime_image;
595
+ if (runtimeImage.deps && typeof runtimeImage.deps === "object" && !Array.isArray(runtimeImage.deps)) {
596
+ const deps = runtimeImage.deps;
597
+ if (typeof deps.monorepo_install === "boolean")
598
+ base.runtime_image.deps.monorepo_install = deps.monorepo_install;
599
+ if (typeof deps.hp_next_install === "boolean")
600
+ base.runtime_image.deps.hp_next_install = deps.hp_next_install;
601
+ }
602
+ if (typeof runtimeImage.plugins_require_binaries === "boolean")
603
+ base.runtime_image.plugins_require_binaries = runtimeImage.plugins_require_binaries;
604
+ }
605
+ if (parsed.runtime_snapshot && typeof parsed.runtime_snapshot === "object" && !Array.isArray(parsed.runtime_snapshot)) {
606
+ const runtimeSnapshot = parsed.runtime_snapshot;
607
+ if (typeof runtimeSnapshot.enabled === "boolean")
608
+ base.runtime_snapshot.enabled = runtimeSnapshot.enabled;
609
+ }
610
+ return base;
611
+ }
612
+ function isValidMode(value) {
613
+ return value === "off" || value === "observe" || value === "enforce";
614
+ }
615
+ function isValidRule(value) {
616
+ if (!value || typeof value !== "object" || Array.isArray(value))
617
+ return false;
618
+ const rule = value;
619
+ return typeof rule.id === "string" && typeof rule.category === "string" && !!rule.match && typeof rule.match === "object";
620
+ }
621
+ function migrateLegacyDeny(deny) {
622
+ const rules = [];
623
+ for (const entry of deny) {
624
+ if (typeof entry.id !== "string")
625
+ continue;
626
+ const match = {};
627
+ if (typeof entry.pattern === "string")
628
+ match.pattern = entry.pattern;
629
+ if (typeof entry.regex === "string")
630
+ match.regex = entry.regex;
631
+ if (!match.pattern && !match.regex)
632
+ continue;
633
+ const rule = {
634
+ id: entry.id,
635
+ category: "command",
636
+ match,
637
+ action: entry.action === "warn" ? "warn" : "block"
638
+ };
639
+ if (typeof entry.reason === "string") {
640
+ rule.description = entry.reason;
641
+ }
642
+ rules.push(rule);
643
+ }
644
+ return rules;
645
+ }
646
+ function precompilePolicyRuleRegexes(rules) {
647
+ return rules.map((rule) => {
648
+ const compiled = { ...rule };
649
+ const matchRegex = compileRegex(rule.match?.regex);
650
+ const unlessRegex = compileRegex(rule.unless?.regex);
651
+ if (matchRegex) {
652
+ compiled.compiledRegex = matchRegex;
653
+ }
654
+ if (unlessRegex) {
655
+ compiled.compiledUnlessRegex = unlessRegex;
656
+ }
657
+ return compiled;
658
+ });
659
+ }
660
+ function compileRegex(pattern) {
661
+ if (!pattern)
662
+ return;
663
+ try {
664
+ return new RegExp(pattern);
665
+ } catch {
666
+ return;
667
+ }
668
+ }
669
+
670
+ // packages/isolation-plugin/src/sandbox/backend.ts
671
+ init_utils();
672
+ import {
673
+ resolveBunInstallDir,
674
+ resolveClaudeInstallDir,
675
+ resolveNodeInstallDir,
676
+ resolveRuntimeDependencyRoots
677
+ } from "@rig/core/runtime-paths";
678
+
679
+ // packages/isolation-plugin/src/sandbox/backend-none.ts
680
+ class NoSandboxBackend {
681
+ kind = "none";
682
+ reason;
683
+ constructor(reason) {
684
+ this.reason = reason;
685
+ }
686
+ wrap(options) {
687
+ return {
688
+ command: options.command,
689
+ enabled: false,
690
+ backend: "none",
691
+ ...this.reason !== undefined ? { reason: this.reason } : {}
692
+ };
693
+ }
694
+ }
695
+
696
+ // packages/isolation-plugin/src/sandbox/backend.ts
697
+ class SandboxError extends Error {
698
+ code;
699
+ constructor(code, message) {
700
+ super(message);
701
+ this.code = code;
702
+ this.name = "SandboxError";
703
+ }
704
+ }
705
+ function resolveRuntimeSandboxModeWithPolicy(sandboxConfig, envOverride) {
706
+ if (envOverride) {
707
+ const normalized = envOverride.trim().toLowerCase();
708
+ if (normalized === "off" || normalized === "auto" || normalized === "enforce") {
709
+ if (normalized !== sandboxConfig.mode) {
710
+ console.warn(`[sandbox] RIG_RUNTIME_SANDBOX=${normalized} overrides policy sandbox.mode=${sandboxConfig.mode}`);
711
+ }
712
+ return normalized;
713
+ }
714
+ }
715
+ const policyMode = sandboxConfig.mode;
716
+ if (policyMode === "off")
717
+ return "off";
718
+ if (policyMode === "observe")
719
+ return "auto";
720
+ return "enforce";
721
+ }
722
+ var bwrapProbeCache = null;
723
+ async function probeBubblewrap(binary) {
724
+ if (bwrapProbeCache !== null) {
725
+ return bwrapProbeCache;
726
+ }
727
+ const probe = await Bun.$`${binary} ${["--ro-bind", "/", "/", "--proc", "/proc", "--dev", "/dev", "--", "true"]}`.quiet().nothrow();
728
+ bwrapProbeCache = probe.exitCode === 0;
729
+ return bwrapProbeCache;
730
+ }
731
+ async function resolveBackend(projectRoot, options) {
732
+ const config = loadSandboxConfig(projectRoot);
733
+ const mode = resolveRuntimeSandboxModeWithPolicy(config, options?.envOverride);
734
+ const probed = [];
735
+ if (mode === "off") {
736
+ return {
737
+ backend: new NoSandboxBackend,
738
+ selectedKind: "none",
739
+ probed,
740
+ reason: "disabled-by-config"
741
+ };
742
+ }
743
+ const explicitBackend = options?.backendOverride ?? process.env.RIG_SANDBOX_BACKEND?.trim().toLowerCase();
744
+ const requestedBackend = resolveExplicitBackend(explicitBackend);
745
+ if (requestedBackend) {
746
+ if (requestedBackend === "docker") {
747
+ throw new SandboxError("backend-unavailable", `Backend "docker" is not yet implemented.`);
748
+ }
749
+ if (requestedBackend === "none") {
750
+ return {
751
+ backend: new NoSandboxBackend("explicit-none"),
752
+ selectedKind: "none",
753
+ probed,
754
+ reason: "explicit-none"
755
+ };
756
+ }
757
+ }
758
+ const bunDir = resolveBunInstallDir();
759
+ const claudeDir = (() => {
760
+ try {
761
+ return resolveClaudeInstallDir();
762
+ } catch {
763
+ return null;
764
+ }
765
+ })();
766
+ const nodeDir = resolveNodeInstallDir();
767
+ const depRoots = resolveRuntimeDependencyRoots([bunDir, claudeDir, nodeDir].filter(Boolean));
768
+ const resolvedPaths = {
769
+ bunDir,
770
+ claudeDir,
771
+ nodeDir,
772
+ depRoots
773
+ };
774
+ const fsContext = {
775
+ pathExists: (p) => existsSync3(p),
776
+ realPath: toRealPath
777
+ };
778
+ if (process.platform === "darwin" && (!requestedBackend || requestedBackend === "macos-seatbelt")) {
779
+ const seatbelt = Bun.which("sandbox-exec");
780
+ probed.push("sandbox-exec");
781
+ if (seatbelt && existsSync3(seatbelt)) {
782
+ const SeatbeltBackendClass = loadSeatbeltBackend();
783
+ if (SeatbeltBackendClass) {
784
+ return {
785
+ backend: new SeatbeltBackendClass(seatbelt, config, fsContext, resolvedPaths),
786
+ selectedKind: "macos-seatbelt",
787
+ probed,
788
+ reason: "detected-seatbelt"
789
+ };
790
+ }
791
+ return handleUnavailableBackend(mode, probed, "macos-seatbelt", "Seatbelt sandbox backend module failed to load.", "seatbelt-backend-module-unavailable", { explicit: requestedBackend === "macos-seatbelt" });
792
+ }
793
+ }
794
+ if (process.platform === "linux" && (!requestedBackend || requestedBackend === "linux-bwrap")) {
795
+ const bwrap = Bun.which("bwrap");
796
+ probed.push("bwrap");
797
+ if (bwrap && await probeBubblewrap(bwrap)) {
798
+ const BwrapBackendClass = loadBwrapBackend();
799
+ if (BwrapBackendClass) {
800
+ return {
801
+ backend: new BwrapBackendClass(bwrap, config, fsContext, resolvedPaths),
802
+ selectedKind: "linux-bwrap",
803
+ probed,
804
+ reason: "detected-bwrap"
805
+ };
806
+ }
807
+ return handleUnavailableBackend(mode, probed, "linux-bwrap", "Bubblewrap sandbox backend module failed to load.", "bwrap-backend-module-unavailable", { explicit: requestedBackend === "linux-bwrap" });
808
+ }
809
+ }
810
+ if (requestedBackend) {
811
+ return handleUnavailableBackend(mode, probed, requestedBackend, `Explicit sandbox backend "${requestedBackend}" is unavailable on ${process.platform}.`, "explicit-backend-unavailable", { explicit: true });
812
+ }
813
+ if (mode === "enforce") {
814
+ throw new SandboxError("backend-unavailable", `Runtime sandbox required (mode=enforce) but no backend available. Probed: ${probed.join(", ")}`);
815
+ }
816
+ return {
817
+ backend: new NoSandboxBackend("sandbox-backend-unavailable"),
818
+ selectedKind: "none",
819
+ probed,
820
+ reason: "sandbox-backend-unavailable"
821
+ };
822
+ }
823
+ function resolveExplicitBackend(explicitBackend) {
824
+ if (!explicitBackend) {
825
+ return null;
826
+ }
827
+ switch (explicitBackend) {
828
+ case "none":
829
+ case "macos-seatbelt":
830
+ case "linux-bwrap":
831
+ case "docker":
832
+ return explicitBackend;
833
+ default:
834
+ throw new SandboxError("backend-unavailable", `Unknown sandbox backend "${explicitBackend}".`);
835
+ }
836
+ }
837
+ function loadSeatbeltBackend() {
838
+ try {
839
+ const mod = (init_backend_seatbelt(), __toCommonJS(exports_backend_seatbelt));
840
+ return mod.SeatbeltBackend ?? null;
841
+ } catch {
842
+ return null;
843
+ }
844
+ }
845
+ function loadBwrapBackend() {
846
+ try {
847
+ const mod = (init_backend_bwrap(), __toCommonJS(exports_backend_bwrap));
848
+ return mod.BwrapBackend ?? null;
849
+ } catch {
850
+ return null;
851
+ }
852
+ }
853
+ function handleUnavailableBackend(mode, probed, detectedKind, message, reason, options) {
854
+ if (mode === "enforce" || options?.explicit) {
855
+ throw new SandboxError("backend-unavailable", `${message} Probed: ${probed.join(", ")}`);
856
+ }
857
+ return {
858
+ backend: new NoSandboxBackend(reason),
859
+ selectedKind: "none",
860
+ probed,
861
+ reason: `${reason}:${detectedKind}`
862
+ };
863
+ }
864
+
865
+ // packages/isolation-plugin/src/sandbox/orchestrator.ts
866
+ function shouldSandboxRuntime(_runtime) {
867
+ return true;
868
+ }
869
+ async function wrapWithRuntimeSandbox(options) {
870
+ const envOverride = process.env.RIG_RUNTIME_SANDBOX;
871
+ const resolution = await resolveBackend(options.projectRoot, { ...envOverride !== undefined ? { envOverride } : {} });
872
+ if (resolution.backend.kind === "none") {
873
+ const plan = resolution.backend.wrap({
874
+ projectRoot: options.projectRoot,
875
+ runtime: options.runtime,
876
+ command: options.command
877
+ });
878
+ return {
879
+ ...plan,
880
+ reason: plan.reason ?? resolution.reason
881
+ };
882
+ }
883
+ if (!shouldSandboxRuntime(options.runtime)) {
884
+ return {
885
+ command: options.command,
886
+ enabled: false,
887
+ backend: "none",
888
+ reason: "runtime-mode-not-sandboxed"
889
+ };
890
+ }
891
+ return resolution.backend.wrap({
892
+ projectRoot: options.projectRoot,
893
+ runtime: options.runtime,
894
+ command: options.command
895
+ });
896
+ }
897
+
898
+ // packages/isolation-plugin/src/isolation/home.ts
899
+ import {
900
+ chmodSync,
901
+ copyFileSync as copyFileSync2,
902
+ cpSync,
903
+ existsSync as existsSync7,
904
+ mkdirSync as mkdirSync5,
905
+ readFileSync as readFileSync4,
906
+ statSync as statSync4,
907
+ writeFileSync as writeFileSync3
908
+ } from "fs";
909
+ import { mkdir } from "fs/promises";
910
+ import { basename, delimiter, resolve as resolve9 } from "path";
911
+ import { resolveBunBinaryPath, resolveBunInstallDir as resolveBunInstallDir2, resolveClaudeBinaryPath, resolveClaudeInstallDir as resolveClaudeInstallDir2, resolveNodeInstallDir as resolveNodeInstallDir2 } from "@rig/core/runtime-paths";
912
+ import { resolveRuntimeSecrets } from "@rig/core/baked-secrets";
913
+
914
+ // packages/isolation-plugin/src/runtime-native.ts
915
+ import { dlopen, ptr, suffix, toBuffer } from "bun:ffi";
916
+ import { copyFileSync, existsSync as existsSync5, mkdirSync as mkdirSync4, renameSync as renameSync2, rmSync, statSync as statSync3 } from "fs";
917
+ import { tmpdir as tmpdir2 } from "os";
918
+ import { dirname, resolve as resolve6 } from "path";
919
+
920
+ // packages/isolation-plugin/src/native-extract.ts
921
+ import { existsSync as existsSync4, mkdirSync as mkdirSync3, readFileSync as readFileSync2, renameSync, statSync as statSync2, writeFileSync as writeFileSync2 } from "fs";
922
+ import { tmpdir } from "os";
923
+ import { resolve as resolve5 } from "path";
924
+
925
+ // packages/isolation-plugin/src/embedded-native-assets.ts
926
+ var embeddedNatives = null;
927
+
928
+ // packages/isolation-plugin/src/native-extract.ts
929
+ var sharedNativeOutputDir = resolve5(tmpdir(), "rig-native");
930
+ var extractionCache = {};
931
+ function extractEmbeddedNative(name) {
932
+ if (name in extractionCache) {
933
+ return extractionCache[name] ?? null;
934
+ }
935
+ const entry = embeddedNatives?.[name];
936
+ if (!entry) {
937
+ extractionCache[name] = null;
938
+ return null;
939
+ }
940
+ try {
941
+ const targetPath = resolve5(sharedNativeOutputDir, entry.fileName);
942
+ mkdirSync3(sharedNativeOutputDir, { recursive: true });
943
+ const upToDate = existsSync4(targetPath) && statSync2(targetPath).size === entry.size;
944
+ if (!upToDate) {
945
+ const bytes = readFileSync2(entry.filePath);
946
+ const tempPath = `${targetPath}.${process.pid}.${Date.now()}.tmp`;
947
+ writeFileSync2(tempPath, bytes, { mode: 493 });
948
+ renameSync(tempPath, targetPath);
949
+ }
950
+ extractionCache[name] = targetPath;
951
+ } catch {
952
+ extractionCache[name] = null;
953
+ }
954
+ return extractionCache[name] ?? null;
955
+ }
956
+
957
+ // packages/isolation-plugin/src/runtime-native.ts
958
+ var sharedNativeRuntimeOutputDir = resolve6(tmpdir2(), "rig-native");
959
+ var sharedNativeRuntimeOutputPath = resolve6(sharedNativeRuntimeOutputDir, `runtime-native-${process.platform}-${process.arch}.${suffix}`);
960
+ var colocatedNativeRuntimeFileName = `runtime-native.${suffix}`;
961
+ var nativeRuntimeLibrary = await loadNativeRuntimeLibrary();
962
+ async function ensureNativeRuntimeLibraryPath(outputPath = sharedNativeRuntimeOutputPath, options = {}) {
963
+ const explicitLib = process.env.RIG_NATIVE_RUNTIME_LIB?.trim();
964
+ if (explicitLib && existsSync5(explicitLib)) {
965
+ return explicitLib;
966
+ }
967
+ const embeddedPath = extractEmbeddedNative("snapshot");
968
+ if (embeddedPath) {
969
+ return embeddedPath;
970
+ }
971
+ if (await buildNativeRuntimeLibrary(outputPath, options)) {
972
+ return outputPath;
973
+ }
974
+ return !options.force && existsSync5(outputPath) ? outputPath : null;
975
+ }
976
+ async function materializeNativeRuntimeLibrary(targetDir) {
977
+ const sourcePath = await ensureNativeRuntimeLibraryPath();
978
+ if (!sourcePath) {
979
+ return null;
980
+ }
981
+ const targetPath = resolve6(targetDir, colocatedNativeRuntimeFileName);
982
+ mkdirSync4(targetDir, { recursive: true });
983
+ const needsCopy = !existsSync5(targetPath) || statSync3(sourcePath).mtimeMs > statSync3(targetPath).mtimeMs;
984
+ if (needsCopy) {
985
+ copyFileSync(sourcePath, targetPath);
986
+ }
987
+ return targetPath;
988
+ }
989
+ async function loadNativeRuntimeLibrary() {
990
+ if (process.env.RIG_DISABLE_ZIG_NATIVE === "1") {
991
+ return null;
992
+ }
993
+ const explicitLib = process.env.RIG_NATIVE_RUNTIME_LIB?.trim();
994
+ if (explicitLib && existsSync5(explicitLib)) {
995
+ const loaded = tryDlopenNativeRuntimeLibrary(explicitLib);
996
+ if (loaded) {
997
+ return loaded;
998
+ }
999
+ }
1000
+ const embeddedPath = extractEmbeddedNative("snapshot");
1001
+ if (embeddedPath) {
1002
+ const loaded = tryDlopenNativeRuntimeLibrary(embeddedPath);
1003
+ if (loaded) {
1004
+ return loaded;
1005
+ }
1006
+ }
1007
+ for (const candidate of nativeRuntimeLibraryCandidates()) {
1008
+ if (!candidate || !existsSync5(candidate)) {
1009
+ continue;
1010
+ }
1011
+ const loaded = tryDlopenNativeRuntimeLibrary(candidate);
1012
+ if (loaded) {
1013
+ return loaded;
1014
+ }
1015
+ }
1016
+ const builtLibraryPath = await ensureNativeRuntimeLibraryPath(sharedNativeRuntimeOutputPath, { force: true });
1017
+ if (!builtLibraryPath) {
1018
+ return null;
1019
+ }
1020
+ return tryDlopenNativeRuntimeLibrary(builtLibraryPath);
1021
+ }
1022
+ function nativePackageLibraryCandidates(fromDir, names) {
1023
+ const candidates = [];
1024
+ let cursor = resolve6(fromDir);
1025
+ for (let index = 0;index < 8; index += 1) {
1026
+ for (const name of names) {
1027
+ candidates.push(resolve6(cursor, "native", `${process.platform}-${process.arch}`, name), resolve6(cursor, "native", `${process.platform}-${process.arch}`, "lib", name), resolve6(cursor, "native", name), resolve6(cursor, "native", "lib", name));
1028
+ }
1029
+ const parent = dirname(cursor);
1030
+ if (parent === cursor)
1031
+ break;
1032
+ cursor = parent;
1033
+ }
1034
+ return candidates;
1035
+ }
1036
+ function nativeRuntimeLibraryCandidates() {
1037
+ const explicit = process.env.RIG_NATIVE_RUNTIME_LIB?.trim() || "";
1038
+ const execDir = process.execPath?.trim() ? dirname(process.execPath.trim()) : "";
1039
+ const platformSpecific = `runtime-native-${process.platform}-${process.arch}.${suffix}`;
1040
+ return [...new Set([
1041
+ explicit,
1042
+ ...nativePackageLibraryCandidates(import.meta.dir, [colocatedNativeRuntimeFileName, platformSpecific]),
1043
+ execDir ? resolve6(execDir, colocatedNativeRuntimeFileName) : "",
1044
+ execDir ? resolve6(execDir, platformSpecific) : "",
1045
+ execDir ? resolve6(execDir, "..", colocatedNativeRuntimeFileName) : "",
1046
+ execDir ? resolve6(execDir, "..", platformSpecific) : "",
1047
+ execDir ? resolve6(execDir, "lib", colocatedNativeRuntimeFileName) : "",
1048
+ execDir ? resolve6(execDir, "..", "lib", colocatedNativeRuntimeFileName) : "",
1049
+ sharedNativeRuntimeOutputPath
1050
+ ].filter(Boolean))];
1051
+ }
1052
+ function resolveNativeRuntimeSourcePath() {
1053
+ const explicit = process.env.RIG_NATIVE_RUNTIME_SOURCE?.trim();
1054
+ if (explicit && existsSync5(explicit)) {
1055
+ return explicit;
1056
+ }
1057
+ const bundled = resolve6(import.meta.dir, "../native/snapshot.zig");
1058
+ return existsSync5(bundled) ? bundled : null;
1059
+ }
1060
+ async function buildNativeRuntimeLibrary(outputPath, options = {}) {
1061
+ if (process.env.RIG_DISABLE_ZIG_NATIVE === "1") {
1062
+ return false;
1063
+ }
1064
+ const zigBinary = Bun.which("zig");
1065
+ const sourcePath = resolveNativeRuntimeSourcePath();
1066
+ if (!zigBinary || !sourcePath) {
1067
+ return false;
1068
+ }
1069
+ const tempOutputPath = `${outputPath}.${process.pid}.${Date.now()}.${Math.random().toString(36).slice(2)}.tmp`;
1070
+ try {
1071
+ mkdirSync4(dirname(outputPath), { recursive: true });
1072
+ const needsBuild = options.force === true || !existsSync5(outputPath) || statSync3(sourcePath).mtimeMs > statSync3(outputPath).mtimeMs;
1073
+ if (!needsBuild) {
1074
+ return true;
1075
+ }
1076
+ const build = Bun.spawn([
1077
+ zigBinary,
1078
+ "build-lib",
1079
+ sourcePath,
1080
+ "-dynamic",
1081
+ "-O",
1082
+ "ReleaseFast",
1083
+ `-femit-bin=${tempOutputPath}`
1084
+ ], {
1085
+ cwd: import.meta.dir,
1086
+ stdout: "pipe",
1087
+ stderr: "pipe"
1088
+ });
1089
+ const exitCode = await build.exited;
1090
+ if (exitCode !== 0 || !existsSync5(tempOutputPath)) {
1091
+ rmSync(tempOutputPath, { force: true });
1092
+ return false;
1093
+ }
1094
+ renameSync2(tempOutputPath, outputPath);
1095
+ return true;
1096
+ } catch {
1097
+ rmSync(tempOutputPath, { force: true });
1098
+ return false;
1099
+ }
1100
+ }
1101
+ function tryDlopenNativeRuntimeLibrary(outputPath) {
1102
+ try {
1103
+ return dlopen(outputPath, {
1104
+ rig_scope_match: {
1105
+ args: ["ptr", "ptr"],
1106
+ returns: "u8"
1107
+ },
1108
+ snapshot_capture: {
1109
+ args: ["ptr", "u64", "ptr", "u64"],
1110
+ returns: "ptr"
1111
+ },
1112
+ snapshot_delta: {
1113
+ args: ["ptr", "ptr"],
1114
+ returns: "ptr"
1115
+ },
1116
+ snapshot_store_delta: {
1117
+ args: ["ptr", "ptr", "ptr", "u64", "ptr", "u64", "ptr", "u64", "ptr", "u64"],
1118
+ returns: "ptr"
1119
+ },
1120
+ snapshot_inspect_delta: {
1121
+ args: ["ptr", "u64"],
1122
+ returns: "ptr"
1123
+ },
1124
+ snapshot_apply_delta: {
1125
+ args: ["ptr", "u64", "ptr", "u64"],
1126
+ returns: "ptr"
1127
+ },
1128
+ snapshot_release: {
1129
+ args: ["ptr"],
1130
+ returns: "void"
1131
+ },
1132
+ runtime_hash_file: {
1133
+ args: ["ptr", "u64"],
1134
+ returns: "ptr"
1135
+ },
1136
+ runtime_hash_tree: {
1137
+ args: ["ptr", "u64"],
1138
+ returns: "ptr"
1139
+ },
1140
+ runtime_prepare_paths: {
1141
+ args: ["ptr", "u64", "ptr", "u64", "ptr", "u64", "ptr", "u64", "ptr", "u64"],
1142
+ returns: "ptr"
1143
+ },
1144
+ runtime_link_dependency_layer: {
1145
+ args: ["ptr", "u64", "ptr", "u64"],
1146
+ returns: "ptr"
1147
+ },
1148
+ runtime_scan_worktrees: {
1149
+ args: ["ptr", "u64"],
1150
+ returns: "ptr"
1151
+ }
1152
+ });
1153
+ } catch {
1154
+ return null;
1155
+ }
1156
+ }
1157
+
1158
+ // packages/isolation-plugin/src/isolation/home.ts
1159
+ import { browserEnvFromContext, loadRuntimeContext, runtimeMemoryEnvFromContext, RUNTIME_CONTEXT_ENV } from "@rig/core/runtime-context";
1160
+
1161
+ // packages/isolation-plugin/src/isolation/shared.ts
1162
+ import { existsSync as existsSync6, readFileSync as readFileSync3, rmSync as rmSync2 } from "fs";
1163
+ import { resolve as resolve7 } from "path";
1164
+ import { agentId, safeGitRefComponent, taskRuntimeId } from "@rig/core/safe-identifiers";
1165
+ import { resolveCheckoutRoot } from "@rig/core/checkout-root";
1166
+ function isRuntimeGatewayGitPath(candidate) {
1167
+ return /\/\.rig\/bin\/git$/.test(candidate.replace(/\\/g, "/"));
1168
+ }
1169
+ function isRuntimeGatewayGhPath(candidate) {
1170
+ return /\/\.rig\/bin\/gh$/.test(candidate.replace(/\\/g, "/"));
1171
+ }
1172
+ function resolveHostGitBinary() {
1173
+ const candidates = [
1174
+ process.env.RIG_GIT_BIN?.trim() || "",
1175
+ "/usr/bin/git",
1176
+ "/opt/homebrew/bin/git",
1177
+ "/usr/local/bin/git"
1178
+ ];
1179
+ const bunResolved = Bun.which("git");
1180
+ if (bunResolved && !isRuntimeGatewayGitPath(bunResolved)) {
1181
+ candidates.push(bunResolved);
1182
+ }
1183
+ for (const candidate of candidates) {
1184
+ if (candidate && !isRuntimeGatewayGitPath(candidate) && existsSync6(candidate)) {
1185
+ return candidate;
1186
+ }
1187
+ }
1188
+ return "git";
1189
+ }
1190
+ function resolveGithubCliBinary(options = {}) {
1191
+ const candidates = new Set;
1192
+ const explicit = process.env.RIG_GH_BIN?.trim();
1193
+ if (explicit) {
1194
+ candidates.add(explicit);
1195
+ }
1196
+ for (const candidate of ["/usr/bin/gh", "/opt/homebrew/bin/gh", "/usr/local/bin/gh"]) {
1197
+ candidates.add(candidate);
1198
+ }
1199
+ if (options.scanPath) {
1200
+ for (const entry of (process.env.PATH || "").split(":").map((value) => value.trim()).filter(Boolean)) {
1201
+ candidates.add(resolve7(entry, "gh"));
1202
+ }
1203
+ }
1204
+ const bunResolved = Bun.which("gh");
1205
+ if (bunResolved) {
1206
+ candidates.add(bunResolved);
1207
+ }
1208
+ for (const candidate of candidates) {
1209
+ if (candidate && existsSync6(candidate) && !isRuntimeGatewayGhPath(candidate)) {
1210
+ return candidate;
1211
+ }
1212
+ }
1213
+ return "";
1214
+ }
1215
+ var generatedCredentialFiles = new Set;
1216
+ function resolveMonorepoRoot2(projectRoot) {
1217
+ return resolveCheckoutRoot(projectRoot);
1218
+ }
1219
+ async function runGitCommand(repoRoot, args) {
1220
+ const gitBinary = resolveHostGitBinary();
1221
+ return Bun.$`${gitBinary} -C ${repoRoot} ${args}`.quiet().nothrow();
1222
+ }
1223
+ function sanitizeRuntimeRefSegment(value) {
1224
+ return safeGitRefComponent(value, { fallback: "runtime", maxLength: 64 });
1225
+ }
1226
+ async function resolveGithubCliAuthToken(ghBinary = "") {
1227
+ const gh = ghBinary || resolveGithubCliBinary();
1228
+ if (!gh) {
1229
+ return "";
1230
+ }
1231
+ const auth = Bun.spawn([gh, "auth", "token"], {
1232
+ stdout: "pipe",
1233
+ stderr: "pipe"
1234
+ });
1235
+ const [exitCode, stdout] = await Promise.all([
1236
+ auth.exited,
1237
+ new Response(auth.stdout).text()
1238
+ ]);
1239
+ if (exitCode !== 0) {
1240
+ return "";
1241
+ }
1242
+ return stdout.trim();
1243
+ }
1244
+ function resolveSystemCertBundlePath() {
1245
+ const candidates = [
1246
+ process.env.SSL_CERT_FILE?.trim(),
1247
+ "/etc/ssl/cert.pem",
1248
+ "/private/etc/ssl/cert.pem",
1249
+ "/opt/homebrew/etc/openssl@3/cert.pem"
1250
+ ];
1251
+ for (const candidate of candidates) {
1252
+ if (candidate && existsSync6(candidate)) {
1253
+ return resolve7(candidate);
1254
+ }
1255
+ }
1256
+ return "";
1257
+ }
1258
+
1259
+ // packages/isolation-plugin/src/isolation/git-native.ts
1260
+ import { tmpdir as tmpdir3 } from "os";
1261
+ import { dirname as dirname2, isAbsolute, resolve as resolve8 } from "path";
1262
+ var sharedGitNativeOutputDir = resolve8(tmpdir3(), "rig-native");
1263
+ var sharedGitNativeOutputPath = resolve8(sharedGitNativeOutputDir, `rig-git-${process.platform}-${process.arch}${process.platform === "win32" ? ".exe" : ""}`);
1264
+ function runtimeRigGitFileName() {
1265
+ return `rig-git${process.platform === "win32" ? ".exe" : ""}`;
1266
+ }
1267
+
1268
+ // packages/isolation-plugin/src/isolation/home.ts
1269
+ var GITHUB_KNOWN_HOSTS = [
1270
+ "github.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOMqqnkVzrm0SdG6UOoqKLsabgH5C9okWi0dh2l9GKJl",
1271
+ "github.com ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBEmKSENjQEezOmxkZMy7opKgwFB9nkt5YRrYMjNuG5N87uRgg6CLrbo5wAdT/y6v0mKV0U2w0WZ2YB/++Tpockg=",
1272
+ "github.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCj7ndNxQowgcQnjshcLrqPEiiphnt+VTTvDP6mHBL9j1aNUkY4Ue1gvwnGLVlOhGeYrnZaMgRK6+PKCUXaDbC7qtbW8gIkhL7aGCsOr/C56SJMy/BCZfxd1nWzAOxSDPgVsmerOBYfNqltV9/hWCqBywINIR+5dIg6JTJ72pcEpEjcYgXkE2YEFXV1JHnsKgbLWNlhScqb2UmyRkQyytRLtL+38TGxkxCflmO+5Z8CSSNY7GidjMIZ7Q4zMjA2n1nGrlTDkzwDCsw+wqFPGQA179cnfGWOWRVruj16z6XyvxvjJwbz0wQZ75XK5tKSb7FNyeIEs4TT4jk+S4dhPeAUC5y+bDYirYgM4GC7uEnztnZyaVWQ7B381AK4Qdrwt51ZqExKbQpTUNn+EjqoTwvqNj4kqx5QUCI0ThS/YkOxJCXmPUWZbhjpCg56i+2aB6CmK2JGhn57K5mj0MNdBXA4/WnwH6XoPWJzK5Nyu2zB3nAZp+S5hpQs+p1vN1/wsjk="
1273
+ ].join(`
1274
+ `);
1275
+ function authStateToken(env = process.env) {
1276
+ const file = env.RIG_GITHUB_AUTH_STATE_FILE?.trim();
1277
+ if (!file || !existsSync7(file))
1278
+ return null;
1279
+ try {
1280
+ const parsed = JSON.parse(readFileSync4(file, "utf8"));
1281
+ const token = typeof parsed.token === "string" ? parsed.token.trim() : "";
1282
+ return token.length > 0 ? token : null;
1283
+ } catch {
1284
+ return null;
1285
+ }
1286
+ }
1287
+ function resolveControlPlaneSourceRoot(projectRoot) {
1288
+ const candidates = [
1289
+ process.env.RIG_CONTROL_PLANE_SOURCE_ROOT?.trim(),
1290
+ process.env.RIG_HOST_PROJECT_ROOT?.trim(),
1291
+ resolve9(import.meta.dir, "../../../../.."),
1292
+ projectRoot
1293
+ ].filter((value) => Boolean(value));
1294
+ for (const candidate of candidates) {
1295
+ const root = resolve9(candidate);
1296
+ if (existsSync7(resolve9(root, "packages/cli/bin/rig.ts"))) {
1297
+ return root;
1298
+ }
1299
+ }
1300
+ return "";
1301
+ }
1302
+ async function runtimeEnv(projectRoot, runtime) {
1303
+ const bunBinaryPath = resolveBunBinaryPath();
1304
+ const bunDir = resolveBunInstallDir2(bunBinaryPath);
1305
+ const claudeBinaryPath = process.env.RIG_CLAUDE_PATH?.trim() || (() => {
1306
+ try {
1307
+ return resolveClaudeBinaryPath();
1308
+ } catch {
1309
+ return "";
1310
+ }
1311
+ })();
1312
+ const claudeDir = claudeBinaryPath ? (() => {
1313
+ try {
1314
+ return resolveClaudeInstallDir2();
1315
+ } catch {
1316
+ return resolve9(claudeBinaryPath, "..");
1317
+ }
1318
+ })() : "";
1319
+ const nodeDir = resolveNodeInstallDir2();
1320
+ const hostGhBinary = resolveGithubCliBinary();
1321
+ const runtimeCertBundlePath = await materializeRuntimeCertBundle(runtime);
1322
+ const monorepoMainRoot = resolveMonorepoRoot2(projectRoot);
1323
+ const realHome = process.env.HOME?.trim();
1324
+ const inheritedPath = (process.env.PATH ?? "").split(delimiter).map((entry) => entry.trim()).filter(Boolean).filter((entry) => !entry.endsWith("/.rig/bin") && !entry.endsWith("/rig/tools"));
1325
+ const pathEntries = [
1326
+ runtime.binDir,
1327
+ `${projectRoot}/rig/tools`,
1328
+ `${bunDir}/bin`,
1329
+ claudeDir,
1330
+ nodeDir ? `${nodeDir}/bin` : "",
1331
+ realHome ? resolve9(realHome, ".local/bin") : "",
1332
+ realHome ? resolve9(realHome, ".cargo/bin") : "",
1333
+ ...inheritedPath,
1334
+ "/usr/local/bin",
1335
+ "/usr/local/sbin",
1336
+ "/opt/homebrew/bin",
1337
+ "/opt/homebrew/sbin",
1338
+ "/usr/bin",
1339
+ "/bin",
1340
+ "/usr/sbin",
1341
+ "/sbin"
1342
+ ].filter(Boolean);
1343
+ const runtimeBash = resolve9(runtime.binDir, "bash");
1344
+ const runtimeRigGit = resolve9(runtime.binDir, runtimeRigGitFileName());
1345
+ const preferredShell = existsSync7(runtimeBash) ? runtimeBash : "/bin/bash";
1346
+ const nativeRuntimeLibraryPath = await materializeNativeRuntimeLibrary(runtime.binDir);
1347
+ const controlPlaneSourceRoot = resolveControlPlaneSourceRoot(projectRoot);
1348
+ const env = {
1349
+ PROJECT_RIG_ROOT: projectRoot,
1350
+ RIG_HOST_PROJECT_ROOT: projectRoot,
1351
+ ...controlPlaneSourceRoot ? { RIG_CONTROL_PLANE_SOURCE_ROOT: controlPlaneSourceRoot } : {},
1352
+ HOME: runtime.homeDir,
1353
+ TMPDIR: runtime.tmpDir,
1354
+ XDG_CACHE_HOME: runtime.cacheDir,
1355
+ XDG_STATE_HOME: runtime.stateDir,
1356
+ RIG_AGENT_ID: runtime.id,
1357
+ ...process.env.RIG_RUN_ID?.trim() ? { RIG_RUN_ID: process.env.RIG_RUN_ID.trim() } : {},
1358
+ ...process.env.RIG_SERVER_RUN_ID?.trim() ? { RIG_SERVER_RUN_ID: process.env.RIG_SERVER_RUN_ID.trim() } : {},
1359
+ ...process.env.RIG_SERVER_URL?.trim() ? { RIG_SERVER_URL: process.env.RIG_SERVER_URL.trim() } : {},
1360
+ ...process.env.RIG_AUTH_TOKEN?.trim() ? { RIG_AUTH_TOKEN: process.env.RIG_AUTH_TOKEN.trim() } : {},
1361
+ RIG_TASK_ID: runtime.taskId,
1362
+ RIG_TASK_RUNTIME_ID: runtime.id,
1363
+ RIG_TASK_WORKSPACE: runtime.workspaceDir,
1364
+ RIG_TASK_RUNTIME_MODE: runtime.mode,
1365
+ RIG_RUNTIME_MODE: runtime.mode,
1366
+ RIG_RUNTIME_ADAPTER: "pi",
1367
+ RIG_RUNTIME_HOME: runtime.rootDir,
1368
+ RIG_RUNTIME_BIN_DIR: runtime.binDir,
1369
+ ...existsSync7(runtimeRigGit) ? { RIG_NATIVE_GIT_BIN: runtimeRigGit } : {},
1370
+ RIG_BUN_PATH: bunBinaryPath,
1371
+ ...claudeBinaryPath ? { RIG_CLAUDE_PATH: claudeBinaryPath } : {},
1372
+ RIG_AGENT_BIN: resolve9(runtime.binDir, "rig-agent"),
1373
+ RIG_HOOKS_ACTIVE: "1",
1374
+ RIG_AUTO_PR_ON_COMPLETE: "1",
1375
+ RIG_POLICY_FILE: resolve9(projectRoot, "rig/policy/policy.json"),
1376
+ RIG_STATE_DIR: runtime.stateDir,
1377
+ RIG_LOGS_DIR: runtime.logsDir,
1378
+ RIG_SESSION_FILE: resolve9(runtime.sessionDir, "session.json"),
1379
+ MONOREPO_ROOT: runtime.workspaceDir,
1380
+ MONOREPO_MAIN_ROOT: monorepoMainRoot,
1381
+ TS_API_TESTS_DIR: resolve9(runtime.workspaceDir, "TSAPITests"),
1382
+ BASH: preferredShell,
1383
+ SHELL: preferredShell,
1384
+ PATH: [...new Set(pathEntries)].join(delimiter),
1385
+ LANG: process.env.LANG ?? "en_US.UTF-8",
1386
+ TERM: process.env.TERM ?? "xterm-256color",
1387
+ PYTHONDONTWRITEBYTECODE: "1",
1388
+ PYTHONPYCACHEPREFIX: resolve9(runtime.cacheDir, "python"),
1389
+ ...process.env.RIG_PR_BASE_PROJECT && { RIG_PR_BASE_PROJECT: process.env.RIG_PR_BASE_PROJECT },
1390
+ ...process.env.RIG_PR_BASE_MONOREPO && { RIG_PR_BASE_MONOREPO: process.env.RIG_PR_BASE_MONOREPO },
1391
+ CLAUDE_HOME: runtime.claudeHomeDir,
1392
+ PI_CODING_AGENT_DIR: resolve9(runtime.homeDir, ".pi", "agent"),
1393
+ OMP_SKIP_SETUP: "1",
1394
+ [RUNTIME_CONTEXT_ENV]: runtime.contextFile,
1395
+ ...nativeRuntimeLibraryPath ? { RIG_NATIVE_RUNTIME_LIB: nativeRuntimeLibraryPath } : {},
1396
+ ...hostGhBinary ? { RIG_GH_BIN: hostGhBinary } : {},
1397
+ ...runtimeCertBundlePath ? {
1398
+ SSL_CERT_FILE: runtimeCertBundlePath,
1399
+ CURL_CA_BUNDLE: runtimeCertBundlePath,
1400
+ REQUESTS_CA_BUNDLE: runtimeCertBundlePath,
1401
+ NODE_EXTRA_CA_CERTS: runtimeCertBundlePath
1402
+ } : {}
1403
+ };
1404
+ const knownHostsPath = resolve9(runtime.homeDir, ".ssh", "known_hosts");
1405
+ if (existsSync7(knownHostsPath)) {
1406
+ const agentSshKey = resolve9(runtime.homeDir, ".ssh", "rig-agent-key");
1407
+ const sshParts = [
1408
+ "ssh",
1409
+ `-o UserKnownHostsFile="${knownHostsPath}"`,
1410
+ "-o StrictHostKeyChecking=yes",
1411
+ "-F /dev/null"
1412
+ ];
1413
+ if (existsSync7(agentSshKey)) {
1414
+ sshParts.splice(1, 0, `-i "${agentSshKey}"`, "-o IdentitiesOnly=yes");
1415
+ }
1416
+ env.GIT_SSH_COMMAND = sshParts.join(" ");
1417
+ }
1418
+ const persistedSecretsPath = resolve9(runtime.rootDir, "runtime-secrets.json");
1419
+ if (existsSync7(persistedSecretsPath)) {
1420
+ try {
1421
+ const persisted = JSON.parse(readFileSync4(persistedSecretsPath, "utf8"));
1422
+ if (persisted && typeof persisted === "object") {
1423
+ for (const [key, value] of Object.entries(persisted)) {
1424
+ if (key === "GITHUB_SSH_KEY")
1425
+ continue;
1426
+ if (typeof value === "string" && value && !env[key])
1427
+ env[key] = value;
1428
+ }
1429
+ }
1430
+ } catch {}
1431
+ }
1432
+ for (const [key, value] of Object.entries(resolveRuntimeSecrets(process.env))) {
1433
+ if (key === "GITHUB_SSH_KEY") {
1434
+ continue;
1435
+ }
1436
+ if (value) {
1437
+ env[key] = value;
1438
+ }
1439
+ }
1440
+ const authStateGithubToken = authStateToken(process.env) || "";
1441
+ const explicitRigGithubToken = process.env.RIG_GITHUB_TOKEN?.trim() || "";
1442
+ const rigGithubToken = explicitRigGithubToken || authStateGithubToken;
1443
+ if (rigGithubToken) {
1444
+ env.RIG_GITHUB_TOKEN = rigGithubToken;
1445
+ env.GITHUB_TOKEN = rigGithubToken;
1446
+ env.GH_TOKEN = rigGithubToken;
1447
+ }
1448
+ const fallbackGithubToken = !env.GITHUB_TOKEN && !env.GH_TOKEN ? await resolveGithubCliAuthToken(hostGhBinary) : "";
1449
+ if (fallbackGithubToken) {
1450
+ env.GITHUB_TOKEN = fallbackGithubToken;
1451
+ }
1452
+ if (!env.GITHUB_TOKEN && env.GH_TOKEN) {
1453
+ env.GITHUB_TOKEN = env.GH_TOKEN;
1454
+ }
1455
+ if (!env.GH_TOKEN && env.GITHUB_TOKEN) {
1456
+ env.GH_TOKEN = env.GITHUB_TOKEN;
1457
+ }
1458
+ const gitHubToken = env.GITHUB_TOKEN || env.GH_TOKEN || rigGithubToken;
1459
+ if (gitHubToken) {
1460
+ env.RIG_GITHUB_TOKEN = gitHubToken;
1461
+ env.GITHUB_TOKEN = env.GITHUB_TOKEN || gitHubToken;
1462
+ env.GH_TOKEN = env.GH_TOKEN || gitHubToken;
1463
+ applyGitHubCredentialHelperEnv(env);
1464
+ }
1465
+ if (!env.GREPTILE_GITHUB_TOKEN && env.GITHUB_TOKEN) {
1466
+ env.GREPTILE_GITHUB_TOKEN = env.GITHUB_TOKEN;
1467
+ }
1468
+ if (existsSync7(runtime.contextFile)) {
1469
+ const runtimeContext = loadRuntimeContext(runtime.contextFile);
1470
+ Object.assign(env, runtimeMemoryEnvFromContext(runtimeContext));
1471
+ Object.assign(env, browserEnvFromContext(runtimeContext.browser));
1472
+ }
1473
+ persistRuntimeSecrets(runtime.rootDir, env);
1474
+ return env;
1475
+ }
1476
+ function runtimeCommandEnv(baseEnv, command) {
1477
+ const env = { ...baseEnv };
1478
+ delete env.ENV;
1479
+ delete env.BASH_ENV;
1480
+ const executable = command[0]?.trim() ?? "";
1481
+ const shellName = basename(executable);
1482
+ const isPosixSh = executable === "/bin/sh" || shellName === "sh" || shellName === "dash";
1483
+ if (isPosixSh) {
1484
+ delete env.BASH;
1485
+ if (executable) {
1486
+ env.SHELL = executable;
1487
+ }
1488
+ }
1489
+ return env;
1490
+ }
1491
+ async function materializeRuntimeCertBundle(runtime) {
1492
+ const sourcePath = resolveSystemCertBundlePath();
1493
+ if (!sourcePath) {
1494
+ return "";
1495
+ }
1496
+ const certsDir = resolve9(runtime.rootDir, "certs");
1497
+ const targetPath = resolve9(certsDir, "ca-certificates.pem");
1498
+ await mkdir(certsDir, { recursive: true });
1499
+ let shouldCopy = !existsSync7(targetPath);
1500
+ if (!shouldCopy) {
1501
+ try {
1502
+ shouldCopy = statSync4(sourcePath).mtimeMs > statSync4(targetPath).mtimeMs;
1503
+ } catch {
1504
+ shouldCopy = true;
1505
+ }
1506
+ }
1507
+ if (shouldCopy) {
1508
+ copyFileSync2(sourcePath, targetPath);
1509
+ }
1510
+ return targetPath;
1511
+ }
1512
+ function applyGitHubCredentialHelperEnv(env) {
1513
+ env.GIT_TERMINAL_PROMPT = "0";
1514
+ env.GIT_CONFIG_COUNT = "2";
1515
+ env.GIT_CONFIG_KEY_0 = "credential.helper";
1516
+ env.GIT_CONFIG_VALUE_0 = "";
1517
+ env.GIT_CONFIG_KEY_1 = "credential.helper";
1518
+ env.GIT_CONFIG_VALUE_1 = '!f() { test "$1" = get || exit 0; token="${GITHUB_TOKEN:-${GH_TOKEN:-${RIG_GITHUB_TOKEN:-}}}"; test -n "$token" || exit 0; echo username=x-access-token; echo password="$token"; }; f';
1519
+ }
1520
+ var PERSISTED_RUNTIME_SECRET_KEYS = [
1521
+ "ANTHROPIC_API_KEY",
1522
+ "OPENAI_API_KEY",
1523
+ "OPENROUTER_API_KEY",
1524
+ "AI_REVIEW_MODE",
1525
+ "AI_REVIEW_PROVIDER",
1526
+ "GREPTILE_API_BASE",
1527
+ "GREPTILE_REMOTE",
1528
+ "GREPTILE_REPOSITORY",
1529
+ "GREPTILE_CONTEXT_BRANCH",
1530
+ "GREPTILE_DEFAULT_BRANCH",
1531
+ "GREPTILE_API_KEY",
1532
+ "GREPTILE_GITHUB_TOKEN",
1533
+ "GREPTILE_POLL_ATTEMPTS",
1534
+ "GREPTILE_POLL_INTERVAL_MS",
1535
+ "GH_TOKEN",
1536
+ "GITHUB_TOKEN",
1537
+ "AWS_ACCESS_KEY_ID",
1538
+ "AWS_SECRET_ACCESS_KEY",
1539
+ "AWS_REGION",
1540
+ "LINEAR_API_KEY",
1541
+ "LINEAR_WEBHOOK_SECRET",
1542
+ "RIG_GITHUB_TOKEN"
1543
+ ];
1544
+ function persistRuntimeSecrets(runtimeRoot, env) {
1545
+ const secretsPath = resolve9(runtimeRoot, "runtime-secrets.json");
1546
+ const resolvedSecrets = resolveRuntimeSecrets(env);
1547
+ const persisted = {};
1548
+ const secretSource = {
1549
+ ...resolvedSecrets,
1550
+ RIG_GITHUB_TOKEN: env.RIG_GITHUB_TOKEN
1551
+ };
1552
+ for (const key of PERSISTED_RUNTIME_SECRET_KEYS) {
1553
+ const value = secretSource[key]?.trim();
1554
+ if (value) {
1555
+ persisted[key] = value;
1556
+ }
1557
+ }
1558
+ if (Object.keys(persisted).length === 0) {
1559
+ return;
1560
+ }
1561
+ writeFileSync3(secretsPath, `${JSON.stringify(persisted, null, 2)}
1562
+ `, { encoding: "utf-8", mode: 384 });
1563
+ chmodSync(secretsPath, 384);
1564
+ }
1565
+
1566
+ // packages/isolation-plugin/src/isolation/worktree.ts
1567
+ import { dirname as dirname3, resolve as resolve10 } from "path";
1568
+ import { assertPathInsideRoot, safeGitRefComponent as safeGitRefComponent2, safePathSegment } from "@rig/core/safe-identifiers";
1569
+ async function cleanupRuntimeWorktree(monorepoRoot, workspaceDir) {
1570
+ assertPathInsideRoot(resolve10(monorepoRoot, ".worktrees"), workspaceDir, "runtime worktree path");
1571
+ await runGitCommand(monorepoRoot, ["worktree", "remove", "--force", workspaceDir]);
1572
+ }
1573
+ function runtimeWorktreeNameFromRuntimeId(runtimeId) {
1574
+ return safePathSegment(runtimeId.replace(/^task-/, ""), { fallback: "runtime", maxLength: 72 });
1575
+ }
1576
+
1577
+ // packages/isolation-plugin/src/isolation/discovery.ts
1578
+ import { resolve as resolve11 } from "path";
1579
+ import { resolveRuntimeWorkspaceLayout } from "@rig/core/layout";
1580
+ import { loadRuntimeContext as loadRuntimeContext2 } from "@rig/core/runtime-context";
1581
+
1582
+ // packages/isolation-plugin/src/isolation/toolchain.ts
1583
+ import { assertPathInsideRoot as assertPathInsideRoot2, safePathSegment as safePathSegment2 } from "@rig/core/safe-identifiers";
1584
+
1585
+ // packages/isolation-plugin/src/isolation/runtime-binary-build.ts
1586
+ import { resolveRigLayout } from "@rig/core/layout";
1587
+ import { runtimeProvisioningEnv } from "@rig/core/runtime-provisioning-env";
1588
+ var runtimeBinaryBuildQueue = Promise.resolve();
1589
+
1590
+ // packages/isolation-plugin/src/isolation/toolchain.ts
1591
+ import {
1592
+ GUARD_TOOLCHAIN_SOURCES,
1593
+ LIFECYCLE_TOOLCHAIN_SOURCES,
1594
+ TOOL_MATERIALIZER
1595
+ } from "@rig/contracts";
1596
+ import { defineCapability } from "@rig/core/capability";
1597
+ import { buildProjectPluginHost, requireInstalledCapability } from "@rig/core/capability-loaders";
1598
+ import { resolveBunBinaryPath as resolveBunBinaryPath2 } from "@rig/core/runtime-paths";
1599
+ var ToolMaterializerCap = defineCapability(TOOL_MATERIALIZER);
1600
+ var GuardToolchainSourcesCap = defineCapability(GUARD_TOOLCHAIN_SOURCES);
1601
+ var LifecycleToolchainSourcesCap = defineCapability(LIFECYCLE_TOOLCHAIN_SOURCES);
1602
+ var SNAPSHOT_SIDECAR_SOURCE = ["packages", "isolation-plugin", "src", "snapshot-sidecar.ts"].join("/");
1603
+
1604
+ // packages/isolation-plugin/src/isolation/discovery.ts
1605
+ function runtimeRootForCleanup(projectRoot, runtimeId) {
1606
+ let monorepoRoot = null;
1607
+ try {
1608
+ monorepoRoot = resolveMonorepoRoot2(projectRoot);
1609
+ } catch {}
1610
+ const workspaceRootCandidate = monorepoRoot ?? projectRoot;
1611
+ const initialWorkspaceDir = resolve11(workspaceRootCandidate, ".worktrees", runtimeWorktreeNameFromRuntimeId(runtimeId));
1612
+ const runtimeRoot = resolveRuntimeWorkspaceLayout(initialWorkspaceDir).runtimeDir;
1613
+ return { monorepoRoot, initialWorkspaceDir, runtimeRoot };
1614
+ }
1615
+
1616
+ // packages/isolation-plugin/src/isolation/runner.ts
1617
+ import { resolveRuntimeWorkspaceLayout as resolveRuntimeWorkspaceLayout2 } from "@rig/core/layout";
1618
+ import { resolveBunBinaryPath as resolveBunBinaryPath3 } from "@rig/core/runtime-paths";
1619
+ var SNAPSHOT_SIDECAR_READY_TIMEOUT_MS = 1e4;
1620
+ async function startRuntimeSnapshotSidecar(runtime, options = {}) {
1621
+ const instanceId = sanitizeRuntimeRefSegment(options.instanceId?.trim() || runtime.id);
1622
+ const readyFile = resolve12(runtime.stateDir, `runtime-snapshot-sidecar-${instanceId}.ready`);
1623
+ const requestFile = resolve12(runtime.stateDir, `runtime-snapshot-sidecar-${instanceId}.request.json`);
1624
+ rmSync3(readyFile, { force: true });
1625
+ rmSync3(requestFile, { force: true });
1626
+ const sidecarBinary = resolveSnapshotSidecarBinaryPath(runtime.binDir);
1627
+ const useCompiledSidecar = shouldUseCompiledSnapshotSidecar(sidecarBinary);
1628
+ const bunCli = useCompiledSidecar ? null : resolveBunCliInvocation();
1629
+ const command = useCompiledSidecar ? [sidecarBinary] : [bunCli.command, resolveSnapshotSidecarScriptPath()];
1630
+ const proc = Bun.spawn([
1631
+ ...command,
1632
+ "--workspace",
1633
+ runtime.workspaceDir,
1634
+ "--task",
1635
+ runtime.taskId,
1636
+ "--runtime-id",
1637
+ runtime.id,
1638
+ "--instance-id",
1639
+ instanceId,
1640
+ "--ready-file",
1641
+ readyFile,
1642
+ "--request-file",
1643
+ requestFile
1644
+ ], {
1645
+ cwd: runtime.workspaceDir,
1646
+ stdin: "ignore",
1647
+ stdout: "pipe",
1648
+ stderr: "pipe",
1649
+ env: {
1650
+ ...process.env,
1651
+ ...bunCli?.env ?? {}
1652
+ }
1653
+ });
1654
+ const stdoutTextPromise = drainStream(proc.stdout);
1655
+ const stderrTextPromise = drainStream(proc.stderr);
1656
+ await waitForSnapshotSidecarReady(readyFile, proc, stdoutTextPromise, stderrTextPromise);
1657
+ return {
1658
+ cancel: async () => {
1659
+ try {
1660
+ proc.kill("SIGTERM");
1661
+ } catch {}
1662
+ await proc.exited;
1663
+ rmSync3(readyFile, { force: true });
1664
+ rmSync3(requestFile, { force: true });
1665
+ },
1666
+ finalize: async (commandParts, exitCode) => {
1667
+ writeFileSync4(requestFile, `${JSON.stringify({ command: commandParts, exitCode })}
1668
+ `, "utf-8");
1669
+ const [sidecarExitCode, stdout, stderr] = await Promise.all([
1670
+ proc.exited,
1671
+ stdoutTextPromise,
1672
+ stderrTextPromise
1673
+ ]);
1674
+ rmSync3(readyFile, { force: true });
1675
+ rmSync3(requestFile, { force: true });
1676
+ if (sidecarExitCode !== 0) {
1677
+ throw new Error(`snapshot sidecar failed (${sidecarExitCode}): ${stderr || stdout}`);
1678
+ }
1679
+ }
1680
+ };
1681
+ }
1682
+ async function drainStream(stream) {
1683
+ if (!stream)
1684
+ return "";
1685
+ try {
1686
+ return await new Response(stream).text();
1687
+ } catch {
1688
+ return "";
1689
+ }
1690
+ }
1691
+ async function runInAgentRuntime(options) {
1692
+ const snapshotSidecar = await startRuntimeSnapshotSidecar(options.runtime);
1693
+ try {
1694
+ const runtimeCommand = resolveInternalRuntimeCommand(options.command);
1695
+ const sandboxPlan = await wrapWithRuntimeSandbox({
1696
+ projectRoot: options.projectRoot,
1697
+ runtime: {
1698
+ id: options.runtime.id,
1699
+ mode: options.runtime.mode,
1700
+ rootDir: options.runtime.rootDir,
1701
+ workspaceDir: options.runtime.workspaceDir,
1702
+ homeDir: options.runtime.homeDir,
1703
+ tmpDir: options.runtime.tmpDir,
1704
+ cacheDir: options.runtime.cacheDir,
1705
+ stateDir: options.runtime.stateDir,
1706
+ sessionDir: options.runtime.sessionDir,
1707
+ claudeHomeDir: options.runtime.claudeHomeDir,
1708
+ binDir: options.runtime.binDir
1709
+ },
1710
+ command: runtimeCommand
1711
+ });
1712
+ const proc = Bun.spawn(sandboxPlan.command, {
1713
+ cwd: options.runtime.workspaceDir,
1714
+ env: runtimeCommandEnv(await runtimeEnv(options.projectRoot, options.runtime), sandboxPlan.command),
1715
+ stdin: options.inheritStdio ? "inherit" : "pipe",
1716
+ stdout: options.inheritStdio ? "inherit" : "pipe",
1717
+ stderr: options.inheritStdio ? "inherit" : "pipe"
1718
+ });
1719
+ const exitCode = await proc.exited;
1720
+ if (options.inheritStdio) {
1721
+ await snapshotSidecar.finalize(runtimeCommand, exitCode);
1722
+ return {
1723
+ exitCode,
1724
+ sandboxBackend: sandboxPlan.backend,
1725
+ sandboxEnabled: sandboxPlan.enabled
1726
+ };
1727
+ }
1728
+ const stdout = await new Response(proc.stdout).text();
1729
+ const stderr = await new Response(proc.stderr).text();
1730
+ try {
1731
+ await Bun.write(resolve12(options.runtime.logsDir, "agent-stdout.log"), stdout);
1732
+ await Bun.write(resolve12(options.runtime.logsDir, "agent-stderr.log"), stderr);
1733
+ } catch {}
1734
+ await snapshotSidecar.finalize(runtimeCommand, exitCode);
1735
+ return {
1736
+ exitCode,
1737
+ stdout,
1738
+ stderr,
1739
+ sandboxBackend: sandboxPlan.backend,
1740
+ sandboxEnabled: sandboxPlan.enabled
1741
+ };
1742
+ } catch (error) {
1743
+ await snapshotSidecar.cancel();
1744
+ throw error;
1745
+ }
1746
+ }
1747
+ function resolveInternalRuntimeCommand(command) {
1748
+ if (command.length === 0) {
1749
+ return [];
1750
+ }
1751
+ const executable = command[0]?.trim() ?? "";
1752
+ if (!executable) {
1753
+ return [...command];
1754
+ }
1755
+ if (basename2(executable) === "bun") {
1756
+ return [resolveBunBinaryPath3(), ...command.slice(1)];
1757
+ }
1758
+ return [...command];
1759
+ }
1760
+ async function cleanupAgentRuntime(options) {
1761
+ const { monorepoRoot, initialWorkspaceDir, runtimeRoot } = runtimeRootForCleanup(options.projectRoot, options.id);
1762
+ const metadataPath = resolve12(runtimeRoot, "runtime.json");
1763
+ if (!existsSync8(runtimeRoot)) {
1764
+ return;
1765
+ }
1766
+ let mode = "worktree";
1767
+ let workspaceDir = "";
1768
+ const metadata = await readRuntimeMetadata(metadataPath);
1769
+ const metadataMatchesRequestedRuntime = metadata !== null && metadata.id === options.id && resolve12(metadata.workspaceDir) === resolve12(initialWorkspaceDir);
1770
+ if (metadata && metadataMatchesRequestedRuntime) {
1771
+ mode = metadata.mode;
1772
+ workspaceDir = metadata.workspaceDir;
1773
+ } else if (existsSync8(initialWorkspaceDir)) {
1774
+ workspaceDir = initialWorkspaceDir;
1775
+ }
1776
+ const preservesTaskWorktree = metadataMatchesRequestedRuntime && metadata ? options.id === taskRuntimeId(metadata.taskId) : false;
1777
+ if (mode === "worktree" && workspaceDir && monorepoRoot && !preservesTaskWorktree) {
1778
+ await cleanupRuntimeWorktree(monorepoRoot, workspaceDir);
1779
+ } else if (mode === "worktree" && workspaceDir && preservesTaskWorktree) {
1780
+ cleanupTaskRuntimeOverlay(workspaceDir);
1781
+ }
1782
+ rmSync3(runtimeRoot, { recursive: true, force: true });
1783
+ }
1784
+ function cleanupTaskRuntimeOverlay(workspaceDir) {
1785
+ const layout = resolveRuntimeWorkspaceLayout2(workspaceDir);
1786
+ for (const path of [
1787
+ layout.homeDir,
1788
+ layout.tmpDir,
1789
+ layout.cacheDir,
1790
+ layout.logsDir,
1791
+ layout.stateDir,
1792
+ layout.sessionDir,
1793
+ layout.binDir,
1794
+ layout.distDir,
1795
+ layout.runtimeDir,
1796
+ layout.contextPath
1797
+ ]) {
1798
+ rmSync3(path, { recursive: true, force: true });
1799
+ }
1800
+ }
1801
+ function resolveSnapshotSidecarScriptPath() {
1802
+ return resolveRuntimeSourceScriptPath("snapshot-sidecar.ts");
1803
+ }
1804
+ function resolveSnapshotSidecarBinaryPath(binDir) {
1805
+ return resolve12(binDir, "snapshot-sidecar");
1806
+ }
1807
+ function shouldUseCompiledSnapshotSidecar(binaryPath) {
1808
+ if (!existsSync8(binaryPath)) {
1809
+ return false;
1810
+ }
1811
+ const preference = process.env.RIG_USE_COMPILED_SNAPSHOT_SIDECAR?.trim().toLowerCase();
1812
+ if (!preference) {
1813
+ return false;
1814
+ }
1815
+ return preference === "1" || preference === "true" || preference === "yes";
1816
+ }
1817
+ function resolveRuntimeSourceScriptPath(fileName) {
1818
+ const hostRoots = [
1819
+ process.env.RIG_HOST_PROJECT_ROOT?.trim(),
1820
+ process.env.PROJECT_RIG_ROOT?.trim()
1821
+ ].filter((value) => Boolean(value));
1822
+ for (const root of hostRoots) {
1823
+ const candidate = resolve12(root, "packages/isolation-plugin/src", fileName);
1824
+ if (existsSync8(candidate)) {
1825
+ return candidate;
1826
+ }
1827
+ }
1828
+ return resolve12(import.meta.dir, "..", fileName);
1829
+ }
1830
+ function resolveBunCliInvocation() {
1831
+ if (process.env.RIG_BUN_PATH?.trim()) {
1832
+ return {
1833
+ command: process.env.RIG_BUN_PATH.trim(),
1834
+ env: {}
1835
+ };
1836
+ }
1837
+ const systemBun = Bun.which("bun")?.trim();
1838
+ if (systemBun) {
1839
+ return {
1840
+ command: systemBun,
1841
+ env: {}
1842
+ };
1843
+ }
1844
+ if (process.execPath?.trim()) {
1845
+ return {
1846
+ command: process.execPath,
1847
+ env: { BUN_BE_BUN: "1" }
1848
+ };
1849
+ }
1850
+ return { command: "bun", env: {} };
1851
+ }
1852
+ async function waitForSnapshotSidecarReady(readyFile, proc, stdoutTextPromise, stderrTextPromise) {
1853
+ const deadline = Date.now() + SNAPSHOT_SIDECAR_READY_TIMEOUT_MS;
1854
+ while (Date.now() < deadline) {
1855
+ if (existsSync8(readyFile)) {
1856
+ return;
1857
+ }
1858
+ const exitCode = proc.exitCode;
1859
+ if (exitCode !== null) {
1860
+ const [stderr, stdout] = await Promise.all([stderrTextPromise, stdoutTextPromise]);
1861
+ throw new Error(`snapshot sidecar exited before ready (${exitCode}): ${stderr || stdout}`);
1862
+ }
1863
+ await Bun.sleep(25);
1864
+ }
1865
+ throw new Error(`snapshot sidecar did not become ready within ${SNAPSHOT_SIDECAR_READY_TIMEOUT_MS}ms`);
1866
+ }
1867
+ async function readRuntimeMetadata(metadataPath) {
1868
+ if (!existsSync8(metadataPath)) {
1869
+ return null;
1870
+ }
1871
+ try {
1872
+ return await Bun.file(metadataPath).json();
1873
+ } catch {
1874
+ return null;
1875
+ }
1876
+ }
1877
+ export {
1878
+ startRuntimeSnapshotSidecar,
1879
+ runInAgentRuntime,
1880
+ cleanupAgentRuntime
1881
+ };