@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,3 @@
1
+ import { type RuntimeImageConfig, type SandboxConfig } from "@rig/contracts";
2
+ export declare function loadSandboxConfig(projectRoot: string): SandboxConfig;
3
+ export declare function loadRuntimeImageConfig(projectRoot: string): RuntimeImageConfig;
@@ -0,0 +1,215 @@
1
+ // @bun
2
+ // packages/isolation-plugin/src/runtime-config.ts
3
+ import { existsSync, readFileSync, statSync } from "fs";
4
+ import { resolve } from "path";
5
+ import {
6
+ POLICY_VERSION
7
+ } from "@rig/contracts";
8
+ var DEFAULT_SCOPE = {
9
+ fail_closed: true,
10
+ harness_paths_exempt: true,
11
+ runtime_paths_exempt: true
12
+ };
13
+ var DEFAULT_SANDBOX = {
14
+ mode: "enforce",
15
+ network: true,
16
+ read_deny: [],
17
+ write_allow_from_runtime: true
18
+ };
19
+ var DEFAULT_ISOLATION = {
20
+ default_mode: "worktree",
21
+ repo_symlink_fallback: false,
22
+ strict_provisioning: true,
23
+ fail_closed_on_provision_error: true
24
+ };
25
+ var DEFAULT_COMPLETION = {
26
+ derive_checks_from_scope: true,
27
+ checks: [],
28
+ typescript_config_probe: ["tsconfig.json"],
29
+ eslint_config_probe: [".eslintrc.js", ".eslintrc.json", "eslint.config.js"]
30
+ };
31
+ var DEFAULT_RUNTIME_IMAGE = {
32
+ deps: { monorepo_install: false, hp_next_install: false },
33
+ plugins_require_binaries: true
34
+ };
35
+ var DEFAULT_RUNTIME_SNAPSHOT = { enabled: true };
36
+ var policyCache = null;
37
+ var policyCachePath = null;
38
+ function loadSandboxConfig(projectRoot) {
39
+ return loadPolicy(projectRoot).sandbox;
40
+ }
41
+ function loadRuntimeImageConfig(projectRoot) {
42
+ return loadPolicy(projectRoot).runtime_image ?? {
43
+ deps: { ...DEFAULT_RUNTIME_IMAGE.deps },
44
+ plugins_require_binaries: DEFAULT_RUNTIME_IMAGE.plugins_require_binaries
45
+ };
46
+ }
47
+ function defaultPolicy() {
48
+ return {
49
+ version: POLICY_VERSION,
50
+ mode: "enforce",
51
+ scope: { ...DEFAULT_SCOPE },
52
+ rules: [],
53
+ sandbox: { ...DEFAULT_SANDBOX },
54
+ isolation: { ...DEFAULT_ISOLATION },
55
+ completion: { ...DEFAULT_COMPLETION },
56
+ runtime_image: {
57
+ deps: { ...DEFAULT_RUNTIME_IMAGE.deps },
58
+ plugins_require_binaries: DEFAULT_RUNTIME_IMAGE.plugins_require_binaries
59
+ },
60
+ runtime_snapshot: { ...DEFAULT_RUNTIME_SNAPSHOT }
61
+ };
62
+ }
63
+ function loadPolicy(projectRoot) {
64
+ const configPath = resolve(projectRoot, "rig/policy/policy.json");
65
+ if (!existsSync(configPath))
66
+ return defaultPolicy();
67
+ let mtimeMs;
68
+ try {
69
+ mtimeMs = statSync(configPath).mtimeMs;
70
+ } catch {
71
+ return defaultPolicy();
72
+ }
73
+ if (policyCache && policyCachePath === configPath && policyCache.mtimeMs === mtimeMs) {
74
+ return policyCache.config;
75
+ }
76
+ try {
77
+ const config = mergeWithDefaults(JSON.parse(readFileSync(configPath, "utf-8")));
78
+ policyCache = { mtimeMs, config };
79
+ policyCachePath = configPath;
80
+ return config;
81
+ } catch {
82
+ return defaultPolicy();
83
+ }
84
+ }
85
+ function mergeWithDefaults(parsed) {
86
+ const base = defaultPolicy();
87
+ if (typeof parsed.mode === "string" && isValidMode(parsed.mode))
88
+ base.mode = parsed.mode;
89
+ if (parsed.scope && typeof parsed.scope === "object" && !Array.isArray(parsed.scope)) {
90
+ const scope = parsed.scope;
91
+ if (typeof scope.fail_closed === "boolean")
92
+ base.scope.fail_closed = scope.fail_closed;
93
+ if (typeof scope.harness_paths_exempt === "boolean")
94
+ base.scope.harness_paths_exempt = scope.harness_paths_exempt;
95
+ if (typeof scope.runtime_paths_exempt === "boolean")
96
+ base.scope.runtime_paths_exempt = scope.runtime_paths_exempt;
97
+ }
98
+ if (Array.isArray(parsed.rules))
99
+ base.rules = precompilePolicyRuleRegexes(parsed.rules.filter(isValidRule));
100
+ if (Array.isArray(parsed.deny) && base.rules.length === 0) {
101
+ base.rules = precompilePolicyRuleRegexes(migrateLegacyDeny(parsed.deny));
102
+ }
103
+ if (parsed.sandbox && typeof parsed.sandbox === "object" && !Array.isArray(parsed.sandbox)) {
104
+ const sandbox = parsed.sandbox;
105
+ if (typeof sandbox.mode === "string" && isValidMode(sandbox.mode))
106
+ base.sandbox.mode = sandbox.mode;
107
+ if (typeof sandbox.network === "boolean")
108
+ base.sandbox.network = sandbox.network;
109
+ if (Array.isArray(sandbox.read_deny))
110
+ base.sandbox.read_deny = sandbox.read_deny.filter((value) => typeof value === "string");
111
+ if (typeof sandbox.write_allow_from_runtime === "boolean")
112
+ base.sandbox.write_allow_from_runtime = sandbox.write_allow_from_runtime;
113
+ }
114
+ if (parsed.isolation && typeof parsed.isolation === "object" && !Array.isArray(parsed.isolation)) {
115
+ const isolation = parsed.isolation;
116
+ if (isolation.default_mode === "worktree")
117
+ base.isolation.default_mode = isolation.default_mode;
118
+ if (typeof isolation.repo_symlink_fallback === "boolean")
119
+ base.isolation.repo_symlink_fallback = isolation.repo_symlink_fallback;
120
+ if (typeof isolation.strict_provisioning === "boolean")
121
+ base.isolation.strict_provisioning = isolation.strict_provisioning;
122
+ if (typeof isolation.fail_closed_on_provision_error === "boolean")
123
+ base.isolation.fail_closed_on_provision_error = isolation.fail_closed_on_provision_error;
124
+ }
125
+ if (parsed.completion && typeof parsed.completion === "object" && !Array.isArray(parsed.completion)) {
126
+ const completion = parsed.completion;
127
+ if (typeof completion.derive_checks_from_scope === "boolean")
128
+ base.completion.derive_checks_from_scope = completion.derive_checks_from_scope;
129
+ if (Array.isArray(completion.checks))
130
+ base.completion.checks = completion.checks.filter((value) => typeof value === "string");
131
+ if (Array.isArray(completion.typescript_config_probe))
132
+ base.completion.typescript_config_probe = completion.typescript_config_probe.filter((value) => typeof value === "string");
133
+ if (Array.isArray(completion.eslint_config_probe))
134
+ base.completion.eslint_config_probe = completion.eslint_config_probe.filter((value) => typeof value === "string");
135
+ }
136
+ if (parsed.runtime_image && typeof parsed.runtime_image === "object" && !Array.isArray(parsed.runtime_image)) {
137
+ const runtimeImage = parsed.runtime_image;
138
+ if (runtimeImage.deps && typeof runtimeImage.deps === "object" && !Array.isArray(runtimeImage.deps)) {
139
+ const deps = runtimeImage.deps;
140
+ if (typeof deps.monorepo_install === "boolean")
141
+ base.runtime_image.deps.monorepo_install = deps.monorepo_install;
142
+ if (typeof deps.hp_next_install === "boolean")
143
+ base.runtime_image.deps.hp_next_install = deps.hp_next_install;
144
+ }
145
+ if (typeof runtimeImage.plugins_require_binaries === "boolean")
146
+ base.runtime_image.plugins_require_binaries = runtimeImage.plugins_require_binaries;
147
+ }
148
+ if (parsed.runtime_snapshot && typeof parsed.runtime_snapshot === "object" && !Array.isArray(parsed.runtime_snapshot)) {
149
+ const runtimeSnapshot = parsed.runtime_snapshot;
150
+ if (typeof runtimeSnapshot.enabled === "boolean")
151
+ base.runtime_snapshot.enabled = runtimeSnapshot.enabled;
152
+ }
153
+ return base;
154
+ }
155
+ function isValidMode(value) {
156
+ return value === "off" || value === "observe" || value === "enforce";
157
+ }
158
+ function isValidRule(value) {
159
+ if (!value || typeof value !== "object" || Array.isArray(value))
160
+ return false;
161
+ const rule = value;
162
+ return typeof rule.id === "string" && typeof rule.category === "string" && !!rule.match && typeof rule.match === "object";
163
+ }
164
+ function migrateLegacyDeny(deny) {
165
+ const rules = [];
166
+ for (const entry of deny) {
167
+ if (typeof entry.id !== "string")
168
+ continue;
169
+ const match = {};
170
+ if (typeof entry.pattern === "string")
171
+ match.pattern = entry.pattern;
172
+ if (typeof entry.regex === "string")
173
+ match.regex = entry.regex;
174
+ if (!match.pattern && !match.regex)
175
+ continue;
176
+ const rule = {
177
+ id: entry.id,
178
+ category: "command",
179
+ match,
180
+ action: entry.action === "warn" ? "warn" : "block"
181
+ };
182
+ if (typeof entry.reason === "string") {
183
+ rule.description = entry.reason;
184
+ }
185
+ rules.push(rule);
186
+ }
187
+ return rules;
188
+ }
189
+ function precompilePolicyRuleRegexes(rules) {
190
+ return rules.map((rule) => {
191
+ const compiled = { ...rule };
192
+ const matchRegex = compileRegex(rule.match?.regex);
193
+ const unlessRegex = compileRegex(rule.unless?.regex);
194
+ if (matchRegex) {
195
+ compiled.compiledRegex = matchRegex;
196
+ }
197
+ if (unlessRegex) {
198
+ compiled.compiledUnlessRegex = unlessRegex;
199
+ }
200
+ return compiled;
201
+ });
202
+ }
203
+ function compileRegex(pattern) {
204
+ if (!pattern)
205
+ return;
206
+ try {
207
+ return new RegExp(pattern);
208
+ } catch {
209
+ return;
210
+ }
211
+ }
212
+ export {
213
+ loadSandboxConfig,
214
+ loadRuntimeImageConfig
215
+ };
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Sidecar entry. Shared by two callers:
3
+ * - dev/source: `bun runtime-native-sidecar.ts <json>` (the `import.meta.main` guard below),
4
+ * - compiled binary: re-exec of `rig __rig_native_runtime_sidecar <json>`, routed by
5
+ * `packages/cli/bin/rig.ts` → here with the request as `process.argv[3]`.
6
+ * Writes the JSON response to stdout and exits the process.
7
+ */
8
+ export declare function runRuntimeNativeSidecarCli(rawRequest: string | undefined): never;
@@ -0,0 +1,368 @@
1
+ // @bun
2
+ // packages/isolation-plugin/src/runtime-native.ts
3
+ import { dlopen, ptr, suffix, toBuffer } from "bun:ffi";
4
+ import { copyFileSync, existsSync as existsSync2, mkdirSync as mkdirSync2, renameSync as renameSync2, rmSync, statSync as statSync2 } from "fs";
5
+ import { tmpdir as tmpdir2 } from "os";
6
+ import { dirname, resolve as resolve2 } from "path";
7
+
8
+ // packages/isolation-plugin/src/native-extract.ts
9
+ import { existsSync, mkdirSync, readFileSync, renameSync, statSync, writeFileSync } from "fs";
10
+ import { tmpdir } from "os";
11
+ import { resolve } from "path";
12
+
13
+ // packages/isolation-plugin/src/embedded-native-assets.ts
14
+ var embeddedNatives = null;
15
+
16
+ // packages/isolation-plugin/src/native-extract.ts
17
+ var sharedNativeOutputDir = resolve(tmpdir(), "rig-native");
18
+ var extractionCache = {};
19
+ function extractEmbeddedNative(name) {
20
+ if (name in extractionCache) {
21
+ return extractionCache[name] ?? null;
22
+ }
23
+ const entry = embeddedNatives?.[name];
24
+ if (!entry) {
25
+ extractionCache[name] = null;
26
+ return null;
27
+ }
28
+ try {
29
+ const targetPath = resolve(sharedNativeOutputDir, entry.fileName);
30
+ mkdirSync(sharedNativeOutputDir, { recursive: true });
31
+ const upToDate = existsSync(targetPath) && statSync(targetPath).size === entry.size;
32
+ if (!upToDate) {
33
+ const bytes = readFileSync(entry.filePath);
34
+ const tempPath = `${targetPath}.${process.pid}.${Date.now()}.tmp`;
35
+ writeFileSync(tempPath, bytes, { mode: 493 });
36
+ renameSync(tempPath, targetPath);
37
+ }
38
+ extractionCache[name] = targetPath;
39
+ } catch {
40
+ extractionCache[name] = null;
41
+ }
42
+ return extractionCache[name] ?? null;
43
+ }
44
+
45
+ // packages/isolation-plugin/src/runtime-native.ts
46
+ var sharedNativeRuntimeOutputDir = resolve2(tmpdir2(), "rig-native");
47
+ var sharedNativeRuntimeOutputPath = resolve2(sharedNativeRuntimeOutputDir, `runtime-native-${process.platform}-${process.arch}.${suffix}`);
48
+ var colocatedNativeRuntimeFileName = `runtime-native.${suffix}`;
49
+ var OPERATION_RESULT_SIZE = 24;
50
+ var RUNTIME_SCAN_ENTRY_SIZE = 64;
51
+ var RUNTIME_SCAN_RESULT_SIZE = 40;
52
+ var nativeRuntimeLibrary = await loadNativeRuntimeLibrary();
53
+ function requireNativeRuntimeLibrary(feature) {
54
+ if (!nativeRuntimeLibrary) {
55
+ throw new Error(`Native Zig runtime is required for ${feature}`);
56
+ }
57
+ return nativeRuntimeLibrary;
58
+ }
59
+ function runtimePrepareTrackedPathsInProcess(input) {
60
+ const runtimeLibrary = requireNativeRuntimeLibrary("runtime dependency layer linking");
61
+ const logsDir = Buffer.from(input.logsDir, "utf8");
62
+ const stateDir = Buffer.from(input.stateDir, "utf8");
63
+ const sessionDir = Buffer.from(input.sessionDir, "utf8");
64
+ const eventsFile = Buffer.from(input.eventsFile, "utf8");
65
+ const controlledBashLogFile = Buffer.from(input.controlledBashLogFile, "utf8");
66
+ const resultPtr = runtimeLibrary.symbols.runtime_prepare_paths(Number(ptr(logsDir)), logsDir.byteLength, Number(ptr(stateDir)), stateDir.byteLength, Number(ptr(sessionDir)), sessionDir.byteLength, Number(ptr(eventsFile)), eventsFile.byteLength, Number(ptr(controlledBashLogFile)), controlledBashLogFile.byteLength);
67
+ if (!resultPtr) {
68
+ throw new Error("runtime_prepare_paths returned null");
69
+ }
70
+ try {
71
+ const view = viewAt(resultPtr, OPERATION_RESULT_SIZE);
72
+ throwIfOperationError(view, "runtime_prepare_paths");
73
+ } finally {
74
+ runtimeLibrary.symbols.snapshot_release(resultPtr);
75
+ }
76
+ }
77
+ function runtimeLinkDependencyLayerInProcess(sourceDir, targetDir) {
78
+ const runtimeLibrary = requireNativeRuntimeLibrary("runtime worktree discovery");
79
+ const sourceBuffer = Buffer.from(sourceDir, "utf8");
80
+ const targetBuffer = Buffer.from(targetDir, "utf8");
81
+ const resultPtr = runtimeLibrary.symbols.runtime_link_dependency_layer(Number(ptr(sourceBuffer)), sourceBuffer.byteLength, Number(ptr(targetBuffer)), targetBuffer.byteLength);
82
+ if (!resultPtr) {
83
+ throw new Error("runtime_link_dependency_layer returned null");
84
+ }
85
+ try {
86
+ const view = viewAt(resultPtr, OPERATION_RESULT_SIZE);
87
+ throwIfOperationError(view, "runtime_link_dependency_layer");
88
+ } finally {
89
+ runtimeLibrary.symbols.snapshot_release(resultPtr);
90
+ }
91
+ }
92
+ function runtimeScanWorktreesInProcess(worktreesRoot) {
93
+ const runtimeLibrary = requireNativeRuntimeLibrary("runtime worktree discovery");
94
+ const rootBuffer = Buffer.from(worktreesRoot, "utf8");
95
+ const resultPtr = runtimeLibrary.symbols.runtime_scan_worktrees(Number(ptr(rootBuffer)), rootBuffer.byteLength);
96
+ if (!resultPtr) {
97
+ throw new Error(`runtime_scan_worktrees returned null for ${worktreesRoot}`);
98
+ }
99
+ try {
100
+ const view = viewAt(resultPtr, RUNTIME_SCAN_RESULT_SIZE);
101
+ throwIfScanError(view, "runtime_scan_worktrees");
102
+ const entriesPtr = readU64(view, 8);
103
+ const entriesLen = readU64(view, 16);
104
+ const entries = [];
105
+ for (let index = 0;index < entriesLen; index += 1) {
106
+ const entryView = viewAt(entriesPtr + index * RUNTIME_SCAN_ENTRY_SIZE, RUNTIME_SCAN_ENTRY_SIZE);
107
+ entries.push({
108
+ workspaceDir: readString(readU64(entryView, 0), readU64(entryView, 8)),
109
+ runtimeDir: readString(readU64(entryView, 16), readU64(entryView, 24)),
110
+ contextPath: readString(readU64(entryView, 32), readU64(entryView, 40)),
111
+ metadataPath: readString(readU64(entryView, 48), readU64(entryView, 56))
112
+ });
113
+ }
114
+ return entries;
115
+ } finally {
116
+ runtimeLibrary.symbols.snapshot_release(resultPtr);
117
+ }
118
+ }
119
+ async function ensureNativeRuntimeLibraryPath(outputPath = sharedNativeRuntimeOutputPath, options = {}) {
120
+ const explicitLib = process.env.RIG_NATIVE_RUNTIME_LIB?.trim();
121
+ if (explicitLib && existsSync2(explicitLib)) {
122
+ return explicitLib;
123
+ }
124
+ const embeddedPath = extractEmbeddedNative("snapshot");
125
+ if (embeddedPath) {
126
+ return embeddedPath;
127
+ }
128
+ if (await buildNativeRuntimeLibrary(outputPath, options)) {
129
+ return outputPath;
130
+ }
131
+ return !options.force && existsSync2(outputPath) ? outputPath : null;
132
+ }
133
+ async function loadNativeRuntimeLibrary() {
134
+ if (process.env.RIG_DISABLE_ZIG_NATIVE === "1") {
135
+ return null;
136
+ }
137
+ const explicitLib = process.env.RIG_NATIVE_RUNTIME_LIB?.trim();
138
+ if (explicitLib && existsSync2(explicitLib)) {
139
+ const loaded = tryDlopenNativeRuntimeLibrary(explicitLib);
140
+ if (loaded) {
141
+ return loaded;
142
+ }
143
+ }
144
+ const embeddedPath = extractEmbeddedNative("snapshot");
145
+ if (embeddedPath) {
146
+ const loaded = tryDlopenNativeRuntimeLibrary(embeddedPath);
147
+ if (loaded) {
148
+ return loaded;
149
+ }
150
+ }
151
+ for (const candidate of nativeRuntimeLibraryCandidates()) {
152
+ if (!candidate || !existsSync2(candidate)) {
153
+ continue;
154
+ }
155
+ const loaded = tryDlopenNativeRuntimeLibrary(candidate);
156
+ if (loaded) {
157
+ return loaded;
158
+ }
159
+ }
160
+ const builtLibraryPath = await ensureNativeRuntimeLibraryPath(sharedNativeRuntimeOutputPath, { force: true });
161
+ if (!builtLibraryPath) {
162
+ return null;
163
+ }
164
+ return tryDlopenNativeRuntimeLibrary(builtLibraryPath);
165
+ }
166
+ function nativePackageLibraryCandidates(fromDir, names) {
167
+ const candidates = [];
168
+ let cursor = resolve2(fromDir);
169
+ for (let index = 0;index < 8; index += 1) {
170
+ for (const name of names) {
171
+ candidates.push(resolve2(cursor, "native", `${process.platform}-${process.arch}`, name), resolve2(cursor, "native", `${process.platform}-${process.arch}`, "lib", name), resolve2(cursor, "native", name), resolve2(cursor, "native", "lib", name));
172
+ }
173
+ const parent = dirname(cursor);
174
+ if (parent === cursor)
175
+ break;
176
+ cursor = parent;
177
+ }
178
+ return candidates;
179
+ }
180
+ function nativeRuntimeLibraryCandidates() {
181
+ const explicit = process.env.RIG_NATIVE_RUNTIME_LIB?.trim() || "";
182
+ const execDir = process.execPath?.trim() ? dirname(process.execPath.trim()) : "";
183
+ const platformSpecific = `runtime-native-${process.platform}-${process.arch}.${suffix}`;
184
+ return [...new Set([
185
+ explicit,
186
+ ...nativePackageLibraryCandidates(import.meta.dir, [colocatedNativeRuntimeFileName, platformSpecific]),
187
+ execDir ? resolve2(execDir, colocatedNativeRuntimeFileName) : "",
188
+ execDir ? resolve2(execDir, platformSpecific) : "",
189
+ execDir ? resolve2(execDir, "..", colocatedNativeRuntimeFileName) : "",
190
+ execDir ? resolve2(execDir, "..", platformSpecific) : "",
191
+ execDir ? resolve2(execDir, "lib", colocatedNativeRuntimeFileName) : "",
192
+ execDir ? resolve2(execDir, "..", "lib", colocatedNativeRuntimeFileName) : "",
193
+ sharedNativeRuntimeOutputPath
194
+ ].filter(Boolean))];
195
+ }
196
+ function resolveNativeRuntimeSourcePath() {
197
+ const explicit = process.env.RIG_NATIVE_RUNTIME_SOURCE?.trim();
198
+ if (explicit && existsSync2(explicit)) {
199
+ return explicit;
200
+ }
201
+ const bundled = resolve2(import.meta.dir, "../native/snapshot.zig");
202
+ return existsSync2(bundled) ? bundled : null;
203
+ }
204
+ async function buildNativeRuntimeLibrary(outputPath, options = {}) {
205
+ if (process.env.RIG_DISABLE_ZIG_NATIVE === "1") {
206
+ return false;
207
+ }
208
+ const zigBinary = Bun.which("zig");
209
+ const sourcePath = resolveNativeRuntimeSourcePath();
210
+ if (!zigBinary || !sourcePath) {
211
+ return false;
212
+ }
213
+ const tempOutputPath = `${outputPath}.${process.pid}.${Date.now()}.${Math.random().toString(36).slice(2)}.tmp`;
214
+ try {
215
+ mkdirSync2(dirname(outputPath), { recursive: true });
216
+ const needsBuild = options.force === true || !existsSync2(outputPath) || statSync2(sourcePath).mtimeMs > statSync2(outputPath).mtimeMs;
217
+ if (!needsBuild) {
218
+ return true;
219
+ }
220
+ const build = Bun.spawn([
221
+ zigBinary,
222
+ "build-lib",
223
+ sourcePath,
224
+ "-dynamic",
225
+ "-O",
226
+ "ReleaseFast",
227
+ `-femit-bin=${tempOutputPath}`
228
+ ], {
229
+ cwd: import.meta.dir,
230
+ stdout: "pipe",
231
+ stderr: "pipe"
232
+ });
233
+ const exitCode = await build.exited;
234
+ if (exitCode !== 0 || !existsSync2(tempOutputPath)) {
235
+ rmSync(tempOutputPath, { force: true });
236
+ return false;
237
+ }
238
+ renameSync2(tempOutputPath, outputPath);
239
+ return true;
240
+ } catch {
241
+ rmSync(tempOutputPath, { force: true });
242
+ return false;
243
+ }
244
+ }
245
+ function tryDlopenNativeRuntimeLibrary(outputPath) {
246
+ try {
247
+ return dlopen(outputPath, {
248
+ rig_scope_match: {
249
+ args: ["ptr", "ptr"],
250
+ returns: "u8"
251
+ },
252
+ snapshot_capture: {
253
+ args: ["ptr", "u64", "ptr", "u64"],
254
+ returns: "ptr"
255
+ },
256
+ snapshot_delta: {
257
+ args: ["ptr", "ptr"],
258
+ returns: "ptr"
259
+ },
260
+ snapshot_store_delta: {
261
+ args: ["ptr", "ptr", "ptr", "u64", "ptr", "u64", "ptr", "u64", "ptr", "u64"],
262
+ returns: "ptr"
263
+ },
264
+ snapshot_inspect_delta: {
265
+ args: ["ptr", "u64"],
266
+ returns: "ptr"
267
+ },
268
+ snapshot_apply_delta: {
269
+ args: ["ptr", "u64", "ptr", "u64"],
270
+ returns: "ptr"
271
+ },
272
+ snapshot_release: {
273
+ args: ["ptr"],
274
+ returns: "void"
275
+ },
276
+ runtime_hash_file: {
277
+ args: ["ptr", "u64"],
278
+ returns: "ptr"
279
+ },
280
+ runtime_hash_tree: {
281
+ args: ["ptr", "u64"],
282
+ returns: "ptr"
283
+ },
284
+ runtime_prepare_paths: {
285
+ args: ["ptr", "u64", "ptr", "u64", "ptr", "u64", "ptr", "u64", "ptr", "u64"],
286
+ returns: "ptr"
287
+ },
288
+ runtime_link_dependency_layer: {
289
+ args: ["ptr", "u64", "ptr", "u64"],
290
+ returns: "ptr"
291
+ },
292
+ runtime_scan_worktrees: {
293
+ args: ["ptr", "u64"],
294
+ returns: "ptr"
295
+ }
296
+ });
297
+ } catch {
298
+ return null;
299
+ }
300
+ }
301
+ function viewAt(address, size) {
302
+ return Buffer.from(toBuffer(address, 0, size));
303
+ }
304
+ function readU64(view, offset) {
305
+ return Number(view.readBigUInt64LE(offset));
306
+ }
307
+ function readString(address, length) {
308
+ if (!address || !length) {
309
+ return "";
310
+ }
311
+ return Buffer.from(toBuffer(address, 0, length)).toString("utf8");
312
+ }
313
+ function throwIfOperationError(view, opName) {
314
+ const errorPtr = readU64(view, 8);
315
+ const errorLen = readU64(view, 16);
316
+ if (!errorPtr || errorLen === 0) {
317
+ return;
318
+ }
319
+ throw new Error(`${opName} failed: ${readString(errorPtr, errorLen)}`);
320
+ }
321
+ function throwIfScanError(view, opName) {
322
+ const errorPtr = readU64(view, 24);
323
+ const errorLen = readU64(view, 32);
324
+ if (!errorPtr || errorLen === 0) {
325
+ return;
326
+ }
327
+ throw new Error(`${opName} failed: ${readString(errorPtr, errorLen)}`);
328
+ }
329
+
330
+ // packages/isolation-plugin/src/runtime-native-sidecar.ts
331
+ function runRuntimeNativeSidecarCli(rawRequest) {
332
+ if (!rawRequest) {
333
+ console.error("usage: runtime-native-sidecar <request-json>");
334
+ process.exit(2);
335
+ }
336
+ try {
337
+ const request = JSON.parse(rawRequest);
338
+ const response = handleRequest(request);
339
+ process.stdout.write(`${JSON.stringify(response)}
340
+ `);
341
+ process.exit(0);
342
+ } catch (error) {
343
+ const message = error instanceof Error ? error.message : String(error);
344
+ process.stdout.write(`${JSON.stringify({ ok: false, error: message })}
345
+ `);
346
+ process.exit(1);
347
+ }
348
+ }
349
+ if (import.meta.main && !import.meta.url.includes("$bunfs")) {
350
+ runRuntimeNativeSidecarCli(process.argv[2]);
351
+ }
352
+ function handleRequest(request) {
353
+ switch (request.op) {
354
+ case "prepare-paths":
355
+ runtimePrepareTrackedPathsInProcess(request.input);
356
+ return { ok: true };
357
+ case "link-dependency-layer":
358
+ runtimeLinkDependencyLayerInProcess(request.input.sourceDir, request.input.targetDir);
359
+ return { ok: true };
360
+ case "scan-worktrees":
361
+ return { ok: true, entries: runtimeScanWorktreesInProcess(request.input.worktreesRoot) };
362
+ default:
363
+ return { ok: false, error: `Unsupported runtime native sidecar op: ${request.op ?? "<missing>"}` };
364
+ }
365
+ }
366
+ export {
367
+ runRuntimeNativeSidecarCli
368
+ };
@@ -0,0 +1,51 @@
1
+ import { RIG_NATIVE_RUNTIME_SIDECAR_ARG } from "./sidecar-arg";
2
+ export { RIG_NATIVE_RUNTIME_SIDECAR_ARG };
3
+ export type NativeRuntimeSymbols = {
4
+ rig_scope_match: (patternPtr: number, pathPtr: number) => number;
5
+ snapshot_capture: (rootPtr: number, rootLen: number, excludePtr: number, excludeLen: number) => number;
6
+ snapshot_delta: (beforeHandlePtr: number, afterHandlePtr: number) => number;
7
+ snapshot_store_delta: (beforeHandlePtr: number, afterHandlePtr: number, rootPtr: number, rootLen: number, taskIdPtr: number, taskIdLen: number, capturedAtPtr: number, capturedAtLen: number, outputPtr: number, outputLen: number) => number;
8
+ snapshot_inspect_delta: (pathPtr: number, pathLen: number) => number;
9
+ snapshot_apply_delta: (pathPtr: number, pathLen: number, targetPtr: number, targetLen: number) => number;
10
+ snapshot_release: (resourcePtr: number) => void;
11
+ runtime_hash_file: (pathPtr: number, pathLen: number) => number;
12
+ runtime_hash_tree: (pathPtr: number, pathLen: number) => number;
13
+ runtime_prepare_paths: (logsPtr: number, logsLen: number, statePtr: number, stateLen: number, sessionPtr: number, sessionLen: number, eventsPtr: number, eventsLen: number, bashLogPtr: number, bashLogLen: number) => number;
14
+ runtime_link_dependency_layer: (sourcePtr: number, sourceLen: number, targetPtr: number, targetLen: number) => number;
15
+ runtime_scan_worktrees: (rootPtr: number, rootLen: number) => number;
16
+ };
17
+ export type NativeRuntimeLibrary = {
18
+ symbols: NativeRuntimeSymbols;
19
+ };
20
+ export type NativeRuntimeWorktreeScanEntry = {
21
+ workspaceDir: string;
22
+ runtimeDir: string;
23
+ contextPath: string;
24
+ metadataPath: string;
25
+ };
26
+ export declare const nativeRuntimeLibrary: NativeRuntimeLibrary | null;
27
+ export declare function requireNativeRuntimeLibrary(feature: string): NativeRuntimeLibrary;
28
+ export declare function runtimeNativeLibraryFileName(): string;
29
+ export declare function runtimePrepareTrackedPathsNative(input: {
30
+ logsDir: string;
31
+ stateDir: string;
32
+ sessionDir: string;
33
+ eventsFile: string;
34
+ controlledBashLogFile: string;
35
+ }): void;
36
+ export declare function runtimeLinkDependencyLayerNative(sourceDir: string, targetDir: string): void;
37
+ export declare function runtimeScanWorktreesNative(worktreesRoot: string): NativeRuntimeWorktreeScanEntry[];
38
+ export declare function runtimePrepareTrackedPathsInProcess(input: {
39
+ logsDir: string;
40
+ stateDir: string;
41
+ sessionDir: string;
42
+ eventsFile: string;
43
+ controlledBashLogFile: string;
44
+ }): void;
45
+ export declare function runtimeLinkDependencyLayerInProcess(sourceDir: string, targetDir: string): void;
46
+ export declare function runtimeScanWorktreesInProcess(worktreesRoot: string): NativeRuntimeWorktreeScanEntry[];
47
+ export declare function defaultNativeRuntimeLibraryPath(): string;
48
+ export declare function ensureNativeRuntimeLibraryPath(outputPath?: string, options?: {
49
+ force?: boolean;
50
+ }): Promise<string | null>;
51
+ export declare function materializeNativeRuntimeLibrary(targetDir: string): Promise<string | null>;