@h-rig/isolation-plugin 0.0.6-alpha.156 → 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.
- package/dist/src/embedded-native-assets.d.ts +7 -0
- package/dist/src/embedded-native-assets.js +6 -0
- package/dist/src/image-fingerprint-sidecar.d.ts +1 -0
- package/dist/src/image-fingerprint-sidecar.js +515 -0
- package/dist/src/image.d.ts +40 -0
- package/dist/src/image.js +1498 -0
- package/dist/src/index.js +4220 -20
- package/dist/src/isolation/binary-build-worker.d.ts +1 -0
- package/dist/src/isolation/binary-build-worker.js +323 -0
- package/dist/src/isolation/discovery.d.ts +7 -0
- package/dist/src/isolation/discovery.js +477 -0
- package/dist/src/isolation/git-native.d.ts +28 -0
- package/dist/src/isolation/git-native.js +598 -0
- package/dist/src/isolation/home.d.ts +25 -0
- package/dist/src/isolation/home.js +929 -0
- package/dist/src/isolation/index.d.ts +43 -0
- package/dist/src/isolation/index.js +4062 -0
- package/dist/src/isolation/provisioning-env.d.ts +1 -0
- package/dist/src/isolation/provisioning-env.js +6 -0
- package/dist/src/isolation/runner.d.ts +20 -0
- package/dist/src/isolation/runner.js +1881 -0
- package/dist/src/isolation/runtime-binary-build.d.ts +88 -0
- package/dist/src/isolation/runtime-binary-build.js +480 -0
- package/dist/src/isolation/shared.d.ts +29 -0
- package/dist/src/isolation/shared.js +283 -0
- package/dist/src/isolation/toolchain.d.ts +71 -0
- package/dist/src/isolation/toolchain.js +1348 -0
- package/dist/src/isolation/types.d.ts +15 -0
- package/dist/src/isolation/types.js +1 -0
- package/dist/src/isolation/worktree.d.ts +22 -0
- package/dist/src/isolation/worktree.js +353 -0
- package/dist/src/native-extract.d.ts +2 -0
- package/dist/src/native-extract.js +44 -0
- package/dist/src/plugin.d.ts +2 -2
- package/dist/src/plugin.js +4219 -19
- package/dist/src/runtime-config.d.ts +3 -0
- package/dist/src/runtime-config.js +215 -0
- package/dist/src/runtime-native-sidecar.d.ts +8 -0
- package/dist/src/runtime-native-sidecar.js +368 -0
- package/dist/src/runtime-native.d.ts +51 -0
- package/dist/src/runtime-native.js +485 -0
- package/dist/src/sandbox/backend-bwrap.d.ts +20 -0
- package/dist/src/sandbox/backend-bwrap.js +268 -0
- package/dist/src/sandbox/backend-none.d.ts +11 -0
- package/dist/src/sandbox/backend-none.js +20 -0
- package/dist/src/sandbox/backend-seatbelt.d.ts +13 -0
- package/dist/src/sandbox/backend-seatbelt.js +225 -0
- package/dist/src/sandbox/backend.d.ts +117 -0
- package/dist/src/sandbox/backend.js +864 -0
- package/dist/src/sandbox/orchestrator.d.ts +21 -0
- package/dist/src/sandbox/orchestrator.js +895 -0
- package/dist/src/sandbox/utils.d.ts +43 -0
- package/dist/src/sandbox/utils.js +94 -0
- package/dist/src/service.d.ts +10 -5
- package/dist/src/service.js +4145 -2
- package/dist/src/sidecar-arg.d.ts +7 -0
- package/dist/src/sidecar-arg.js +6 -0
- package/dist/src/sidecar-entrypoint.d.ts +9 -0
- package/dist/src/sidecar-entrypoint.js +401 -0
- package/dist/src/snapshot-sidecar.d.ts +2 -0
- package/dist/src/snapshot-sidecar.js +566 -0
- package/dist/src/snapshot.d.ts +64 -0
- package/dist/src/snapshot.js +515 -0
- package/dist/src/task-run-snapshot.d.ts +26 -0
- package/dist/src/task-run-snapshot.js +713 -0
- package/native/darwin-arm64/rig-git +0 -0
- package/native/darwin-arm64/rig-git.build-manifest.json +4 -0
- package/native/darwin-arm64/runtime-native.dylib +0 -0
- package/native/darwin-x64/rig-git +0 -0
- package/native/darwin-x64/runtime-native.dylib +0 -0
- package/native/linux-arm64/rig-git +0 -0
- package/native/linux-arm64/runtime-native.so +0 -0
- package/native/linux-x64/rig-git +0 -0
- package/native/linux-x64/runtime-native.so +0 -0
- package/native/win32-x64/rig-git.exe +0 -0
- package/native/win32-x64/runtime-native.dll +0 -0
- package/package.json +45 -5
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
export declare const runtimeBinaryAssetEntries: readonly ["hooks", "lib", "tools", "templates", "policy", "plugins", "config.sh", "task-config.json"];
|
|
2
|
+
export type RuntimeBinaryAssetEntry = (typeof runtimeBinaryAssetEntries)[number];
|
|
3
|
+
export type RuntimeBinarySpec = {
|
|
4
|
+
name: string;
|
|
5
|
+
sourcePath: string;
|
|
6
|
+
outputPath: string;
|
|
7
|
+
};
|
|
8
|
+
export type RuntimeBinaryBuildManifest = {
|
|
9
|
+
name: string;
|
|
10
|
+
builtAt: string;
|
|
11
|
+
gitHead: string;
|
|
12
|
+
bunVersion: string;
|
|
13
|
+
binaries: Record<string, string>;
|
|
14
|
+
runtimeAssets: RuntimeBinaryAssetEntry[];
|
|
15
|
+
};
|
|
16
|
+
export declare const runtimeRigCliBinaryExternals: string[];
|
|
17
|
+
export type RuntimeBinaryBuildOptions = {
|
|
18
|
+
sourcePath: string;
|
|
19
|
+
outputPath: string;
|
|
20
|
+
cwd: string;
|
|
21
|
+
define?: Record<string, string>;
|
|
22
|
+
external?: string[];
|
|
23
|
+
env?: Record<string, string | undefined>;
|
|
24
|
+
};
|
|
25
|
+
type ResolvedRuntimeBinaryBuildOptions = RuntimeBinaryBuildOptions & {
|
|
26
|
+
entrypoint: string;
|
|
27
|
+
outputPath: string;
|
|
28
|
+
};
|
|
29
|
+
export type RuntimeBinaryLaunchRequest = {
|
|
30
|
+
binaryPath: string;
|
|
31
|
+
args: string[];
|
|
32
|
+
cwd: string;
|
|
33
|
+
env?: Record<string, string | undefined>;
|
|
34
|
+
timeoutMs?: number;
|
|
35
|
+
};
|
|
36
|
+
export type RuntimeBinaryLaunchResult = {
|
|
37
|
+
exitCode: number;
|
|
38
|
+
stdout: string;
|
|
39
|
+
stderr: string;
|
|
40
|
+
timedOut: boolean;
|
|
41
|
+
};
|
|
42
|
+
export type RuntimeBinaryAssetCopyResult = {
|
|
43
|
+
copiedEntries: RuntimeBinaryAssetEntry[];
|
|
44
|
+
runtimeDir: string;
|
|
45
|
+
};
|
|
46
|
+
export declare function isRuntimeBinaryAssetEntry(value: string): value is RuntimeBinaryAssetEntry;
|
|
47
|
+
export declare function createRuntimeBinaryBuildManifest(input: {
|
|
48
|
+
builtAt?: string;
|
|
49
|
+
gitHead?: string;
|
|
50
|
+
bunVersion: string;
|
|
51
|
+
binaries: Record<string, string>;
|
|
52
|
+
runtimeAssets?: readonly RuntimeBinaryAssetEntry[];
|
|
53
|
+
name?: string;
|
|
54
|
+
}): RuntimeBinaryBuildManifest;
|
|
55
|
+
/**
|
|
56
|
+
* Compiled-binary replacement for building a per-run helper binary from source.
|
|
57
|
+
* The single-file `rig` binary has no rig source to compile, so instead of building
|
|
58
|
+
* `<outputPath>`, hardlink it to THIS executable and drop a `<outputPath>.rig-runconfig.json`
|
|
59
|
+
* carrying its role (basename) + build `define`s. `bin/rig.ts` routes by execPath
|
|
60
|
+
* basename and rehydrates the config (incl. RIG_BAKED_* secrets) into the same
|
|
61
|
+
* `RIG_BUILD_CONFIG_JSON` channel `readBuildConfig()` reads — so the role behaves
|
|
62
|
+
* exactly as the from-source binary did. Secrets land in the run's private binDir,
|
|
63
|
+
* the same place (and protection) the baked binary held them.
|
|
64
|
+
*/
|
|
65
|
+
export declare function materializeSelfExecRole(outputPath: string, define?: Record<string, string>): void;
|
|
66
|
+
/**
|
|
67
|
+
* Build (or, for the compiled single-file binary, self-exec-materialize) a rig
|
|
68
|
+
* runtime helper binary. Floor-level wrapper: when natives are embedded there is
|
|
69
|
+
* no rig source to compile, so hardlink this executable into the role + drop its
|
|
70
|
+
* run-config; otherwise compile from source via buildRuntimeBinary with the
|
|
71
|
+
* runtime provisioning env. Owned by the kernel floor so build-time CLI commands
|
|
72
|
+
* resolve it without importing the isolation plugin's impl.
|
|
73
|
+
*/
|
|
74
|
+
export declare function buildBinary(entrypoint: string, outputPath: string, cwd: string, defines?: Record<string, string>, external?: string[]): Promise<void>;
|
|
75
|
+
export declare function buildRuntimeBinary(options: RuntimeBinaryBuildOptions): Promise<void>;
|
|
76
|
+
export declare function buildRuntimeBinarySync(options: RuntimeBinaryBuildOptions): void;
|
|
77
|
+
export declare function buildRuntimeBinaryInProcess(options: ResolvedRuntimeBinaryBuildOptions, manifest?: {
|
|
78
|
+
manifestPath: string;
|
|
79
|
+
buildKey: string;
|
|
80
|
+
}): Promise<void>;
|
|
81
|
+
export declare function copyRuntimeBinaryAssets(options: {
|
|
82
|
+
projectRoot: string;
|
|
83
|
+
outputDir: string;
|
|
84
|
+
rigDir?: string;
|
|
85
|
+
entries?: readonly RuntimeBinaryAssetEntry[];
|
|
86
|
+
}): RuntimeBinaryAssetCopyResult;
|
|
87
|
+
export declare function launchRuntimeBinary(request: RuntimeBinaryLaunchRequest): Promise<RuntimeBinaryLaunchResult>;
|
|
88
|
+
export {};
|
|
@@ -0,0 +1,480 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
// packages/isolation-plugin/src/isolation/runtime-binary-build.ts
|
|
3
|
+
import { spawn as nodeSpawn } from "child_process";
|
|
4
|
+
import { chmodSync, copyFileSync, cpSync, existsSync, linkSync, mkdirSync, renameSync, rmSync, writeFileSync } from "fs";
|
|
5
|
+
import { basename, dirname, resolve as resolve2 } from "path";
|
|
6
|
+
import { fileURLToPath } from "url";
|
|
7
|
+
import { drainMicrotasks, gcAndSweep } from "bun:jsc";
|
|
8
|
+
import { resolveRigLayout } from "@rig/core/layout";
|
|
9
|
+
import { runtimeProvisioningEnv } from "@rig/core/runtime-provisioning-env";
|
|
10
|
+
|
|
11
|
+
// packages/isolation-plugin/src/native-extract.ts
|
|
12
|
+
import { tmpdir } from "os";
|
|
13
|
+
import { resolve } from "path";
|
|
14
|
+
|
|
15
|
+
// packages/isolation-plugin/src/embedded-native-assets.ts
|
|
16
|
+
var embeddedNatives = null;
|
|
17
|
+
|
|
18
|
+
// packages/isolation-plugin/src/native-extract.ts
|
|
19
|
+
var sharedNativeOutputDir = resolve(tmpdir(), "rig-native");
|
|
20
|
+
function hasEmbeddedNatives() {
|
|
21
|
+
return embeddedNatives != null;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// packages/isolation-plugin/src/isolation/runtime-binary-build.ts
|
|
25
|
+
var runtimeBinaryAssetEntries = [
|
|
26
|
+
"hooks",
|
|
27
|
+
"lib",
|
|
28
|
+
"tools",
|
|
29
|
+
"templates",
|
|
30
|
+
"policy",
|
|
31
|
+
"plugins",
|
|
32
|
+
"config.sh",
|
|
33
|
+
"task-config.json"
|
|
34
|
+
];
|
|
35
|
+
var runtimeRigCliBinaryExternals = ["mupdf"];
|
|
36
|
+
var runtimeBinaryBuildQueue = Promise.resolve();
|
|
37
|
+
function isRuntimeBinaryAssetEntry(value) {
|
|
38
|
+
return runtimeBinaryAssetEntries.includes(value);
|
|
39
|
+
}
|
|
40
|
+
function createRuntimeBinaryBuildManifest(input) {
|
|
41
|
+
return {
|
|
42
|
+
name: input.name ?? "project-rig-harness",
|
|
43
|
+
builtAt: input.builtAt ?? new Date().toISOString(),
|
|
44
|
+
gitHead: input.gitHead ?? "unknown",
|
|
45
|
+
bunVersion: input.bunVersion,
|
|
46
|
+
binaries: { ...input.binaries },
|
|
47
|
+
runtimeAssets: [...input.runtimeAssets ?? runtimeBinaryAssetEntries]
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
function materializeSelfExecRole(outputPath, define) {
|
|
51
|
+
const selfPath = process.execPath;
|
|
52
|
+
mkdirSync(dirname(outputPath), { recursive: true });
|
|
53
|
+
rmSync(outputPath, { force: true });
|
|
54
|
+
try {
|
|
55
|
+
linkSync(selfPath, outputPath);
|
|
56
|
+
} catch {
|
|
57
|
+
copyFileSync(selfPath, outputPath);
|
|
58
|
+
}
|
|
59
|
+
chmodSync(outputPath, 493);
|
|
60
|
+
const role = basename(outputPath).replace(/\.exe$/i, "");
|
|
61
|
+
writeFileSync(`${outputPath}.rig-runconfig.json`, `${JSON.stringify({ role, define: define ?? {} }, null, 2)}
|
|
62
|
+
`, { mode: 384 });
|
|
63
|
+
}
|
|
64
|
+
async function buildBinary(entrypoint, outputPath, cwd, defines, external) {
|
|
65
|
+
if (hasEmbeddedNatives()) {
|
|
66
|
+
materializeSelfExecRole(outputPath, defines);
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
await buildRuntimeBinary({
|
|
70
|
+
sourcePath: entrypoint,
|
|
71
|
+
outputPath,
|
|
72
|
+
cwd,
|
|
73
|
+
...defines ? { define: defines } : {},
|
|
74
|
+
env: runtimeProvisioningEnv(),
|
|
75
|
+
...external ? { external } : {}
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
async function buildRuntimeBinary(options) {
|
|
79
|
+
return runSerializedRuntimeBinaryBuild(async () => {
|
|
80
|
+
const resolved = resolveRuntimeBinaryBuildOptions(options);
|
|
81
|
+
runBestEffortBuildGc();
|
|
82
|
+
const manifestPath = runtimeBinaryCacheManifestPath(resolved.outputPath);
|
|
83
|
+
const buildKey = createRuntimeBinaryBuildKey({
|
|
84
|
+
entrypoint: resolved.entrypoint,
|
|
85
|
+
define: resolved.define,
|
|
86
|
+
env: resolved.env,
|
|
87
|
+
external: resolved.external
|
|
88
|
+
});
|
|
89
|
+
if (await isRuntimeBinaryBuildFresh({ outputPath: resolved.outputPath, manifestPath, buildKey })) {
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
if (shouldUseRuntimeBinaryBuildWorker()) {
|
|
93
|
+
await buildRuntimeBinaryViaWorker(resolved);
|
|
94
|
+
} else {
|
|
95
|
+
await buildRuntimeBinaryInProcess(resolved, { manifestPath, buildKey });
|
|
96
|
+
}
|
|
97
|
+
runBestEffortBuildGc();
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
function buildRuntimeBinarySync(options) {
|
|
101
|
+
const resolved = resolveRuntimeBinaryBuildOptions(options);
|
|
102
|
+
runBestEffortBuildGc();
|
|
103
|
+
runRuntimeBinaryBuildWorkerSync(resolved);
|
|
104
|
+
runBestEffortBuildGc();
|
|
105
|
+
}
|
|
106
|
+
async function buildRuntimeBinaryInProcess(options, manifest) {
|
|
107
|
+
const tempBuildDir = resolve2(dirname(options.outputPath), `.bun-build-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`);
|
|
108
|
+
const tempOutputPath = resolve2(tempBuildDir, basename(options.outputPath));
|
|
109
|
+
mkdirSync(tempBuildDir, { recursive: true });
|
|
110
|
+
await withTemporaryEnv({
|
|
111
|
+
...options.env,
|
|
112
|
+
...options.define ? { RIG_BUILD_CONFIG_JSON: JSON.stringify(options.define) } : {}
|
|
113
|
+
}, async () => withTemporaryCwd(tempBuildDir, async () => {
|
|
114
|
+
const buildResult = await Bun.build({
|
|
115
|
+
entrypoints: [options.entrypoint],
|
|
116
|
+
compile: {
|
|
117
|
+
target: currentCompileTarget(),
|
|
118
|
+
outfile: tempOutputPath
|
|
119
|
+
},
|
|
120
|
+
target: "bun",
|
|
121
|
+
format: "esm",
|
|
122
|
+
minify: true,
|
|
123
|
+
bytecode: true,
|
|
124
|
+
metafile: true,
|
|
125
|
+
...options.external ? { external: options.external } : {},
|
|
126
|
+
...options.define ? { define: { __RIG_BUILD_CONFIG__: JSON.stringify(options.define) } } : {}
|
|
127
|
+
});
|
|
128
|
+
if (!buildResult.success) {
|
|
129
|
+
const details = buildResult.logs.map((log) => [log.message, log.position?.file ? `${log.position.file}:${log.position.line}:${log.position.column}` : ""].filter(Boolean).join(" ")).filter(Boolean).join(`
|
|
130
|
+
`);
|
|
131
|
+
throw new Error(`Failed to build ${options.entrypoint}: ${details || "Bun.build() returned errors"}`);
|
|
132
|
+
}
|
|
133
|
+
if (!existsSync(tempOutputPath)) {
|
|
134
|
+
const emitted = buildResult.outputs.map((output) => output.path).join(", ") || "(none)";
|
|
135
|
+
throw new Error(`Failed to build ${options.entrypoint}: Bun.build() did not emit ${tempOutputPath}. Emitted: ${emitted}`);
|
|
136
|
+
}
|
|
137
|
+
renameSync(tempOutputPath, options.outputPath);
|
|
138
|
+
chmodSync(options.outputPath, 493);
|
|
139
|
+
if (manifest) {
|
|
140
|
+
await writeRuntimeBinaryCacheManifest({
|
|
141
|
+
manifestPath: manifest.manifestPath,
|
|
142
|
+
buildKey: manifest.buildKey,
|
|
143
|
+
cwd: tempBuildDir,
|
|
144
|
+
metafile: buildResult.metafile
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
})).finally(() => {
|
|
148
|
+
rmSync(tempBuildDir, { recursive: true, force: true });
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
function runBestEffortBuildGc() {
|
|
152
|
+
try {
|
|
153
|
+
drainMicrotasks();
|
|
154
|
+
} catch {}
|
|
155
|
+
try {
|
|
156
|
+
gcAndSweep();
|
|
157
|
+
} catch {}
|
|
158
|
+
}
|
|
159
|
+
function runtimeBinaryCacheManifestPath(outputPath) {
|
|
160
|
+
return `${outputPath}.build-manifest.json`;
|
|
161
|
+
}
|
|
162
|
+
function resolveRuntimeBinaryBuildOptions(options) {
|
|
163
|
+
return {
|
|
164
|
+
...options,
|
|
165
|
+
entrypoint: resolve2(options.cwd, options.sourcePath),
|
|
166
|
+
outputPath: resolve2(options.outputPath)
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
function shouldUseRuntimeBinaryBuildWorker() {
|
|
170
|
+
if (process.env.RIG_RUNTIME_BUILD_WORKER === "1") {
|
|
171
|
+
return false;
|
|
172
|
+
}
|
|
173
|
+
if (process.env.RIG_RUNTIME_BUILD_IN_PROCESS === "1") {
|
|
174
|
+
return false;
|
|
175
|
+
}
|
|
176
|
+
return true;
|
|
177
|
+
}
|
|
178
|
+
async function buildRuntimeBinaryViaWorker(options) {
|
|
179
|
+
const workerSourcePath = resolveRuntimeBinaryBuildWorkerSourcePath(options);
|
|
180
|
+
if (!workerSourcePath || !existsSync(workerSourcePath)) {
|
|
181
|
+
await buildRuntimeBinaryInProcess(options, {
|
|
182
|
+
manifestPath: runtimeBinaryCacheManifestPath(options.outputPath),
|
|
183
|
+
buildKey: createRuntimeBinaryBuildKey({
|
|
184
|
+
entrypoint: options.entrypoint,
|
|
185
|
+
define: options.define,
|
|
186
|
+
env: options.env,
|
|
187
|
+
external: options.external
|
|
188
|
+
})
|
|
189
|
+
});
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
const payloadPath = createRuntimeBinaryBuildWorkerPayloadPath(options.outputPath);
|
|
193
|
+
const bunCli = resolveRuntimeBinaryBuildWorkerInvocation();
|
|
194
|
+
await Bun.write(payloadPath, `${JSON.stringify(options)}
|
|
195
|
+
`);
|
|
196
|
+
const build = Bun.spawn([bunCli.command, workerSourcePath, payloadPath], {
|
|
197
|
+
cwd: options.cwd,
|
|
198
|
+
stdout: "pipe",
|
|
199
|
+
stderr: "pipe",
|
|
200
|
+
env: {
|
|
201
|
+
...process.env,
|
|
202
|
+
...options.env,
|
|
203
|
+
...bunCli.env,
|
|
204
|
+
RIG_RUNTIME_BUILD_WORKER: "1"
|
|
205
|
+
}
|
|
206
|
+
});
|
|
207
|
+
const [exitCode, stdout, stderr] = await Promise.all([
|
|
208
|
+
build.exited,
|
|
209
|
+
new Response(build.stdout).text(),
|
|
210
|
+
new Response(build.stderr).text()
|
|
211
|
+
]);
|
|
212
|
+
rmSync(payloadPath, { force: true });
|
|
213
|
+
if (exitCode !== 0) {
|
|
214
|
+
throw new Error(`Failed to build ${options.entrypoint}: ${(stderr || stdout || `worker exited ${exitCode}`).trim()}`);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
function runRuntimeBinaryBuildWorkerSync(options) {
|
|
218
|
+
const workerSourcePath = resolveRuntimeBinaryBuildWorkerSourcePath(options);
|
|
219
|
+
if (!workerSourcePath || !existsSync(workerSourcePath)) {
|
|
220
|
+
throw new Error(`Failed to build ${options.entrypoint}: runtime binary build worker not found`);
|
|
221
|
+
}
|
|
222
|
+
const payloadPath = createRuntimeBinaryBuildWorkerPayloadPath(options.outputPath);
|
|
223
|
+
const bunCli = resolveRuntimeBinaryBuildWorkerInvocation();
|
|
224
|
+
try {
|
|
225
|
+
writeFileSync(payloadPath, `${JSON.stringify(options)}
|
|
226
|
+
`, "utf-8");
|
|
227
|
+
const result = Bun.spawnSync([bunCli.command, workerSourcePath, payloadPath], {
|
|
228
|
+
cwd: options.cwd,
|
|
229
|
+
stdout: "pipe",
|
|
230
|
+
stderr: "pipe",
|
|
231
|
+
env: {
|
|
232
|
+
...process.env,
|
|
233
|
+
...options.env,
|
|
234
|
+
...bunCli.env,
|
|
235
|
+
RIG_RUNTIME_BUILD_WORKER: "1"
|
|
236
|
+
}
|
|
237
|
+
});
|
|
238
|
+
if (result.exitCode !== 0) {
|
|
239
|
+
const stderr = result.stderr.toString();
|
|
240
|
+
const stdout = result.stdout.toString();
|
|
241
|
+
throw new Error(`Failed to build ${options.entrypoint}: ${(stderr || stdout || `worker exited ${result.exitCode}`).trim()}`);
|
|
242
|
+
}
|
|
243
|
+
} finally {
|
|
244
|
+
rmSync(payloadPath, { force: true });
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
function createRuntimeBinaryBuildWorkerPayloadPath(outputPath) {
|
|
248
|
+
return resolve2(dirname(outputPath), `.bun-build-worker-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}.json`);
|
|
249
|
+
}
|
|
250
|
+
function resolveRuntimeBinaryBuildWorkerSourcePath(options) {
|
|
251
|
+
const envRoots = [
|
|
252
|
+
options.cwd?.trim(),
|
|
253
|
+
process.env.RIG_HOST_PROJECT_ROOT?.trim(),
|
|
254
|
+
process.env.PROJECT_RIG_ROOT?.trim()
|
|
255
|
+
].filter(Boolean);
|
|
256
|
+
for (const root of envRoots) {
|
|
257
|
+
const candidate = resolve2(root, "packages/isolation-plugin/src/isolation/binary-build-worker.ts");
|
|
258
|
+
if (existsSync(candidate)) {
|
|
259
|
+
return candidate;
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
const localCandidate = resolve2(import.meta.dir, "binary-build-worker.ts");
|
|
263
|
+
return existsSync(localCandidate) ? localCandidate : null;
|
|
264
|
+
}
|
|
265
|
+
function resolveRuntimeBinaryBuildWorkerInvocation() {
|
|
266
|
+
const bunPath = Bun.which("bun");
|
|
267
|
+
if (bunPath) {
|
|
268
|
+
return { command: bunPath, env: {} };
|
|
269
|
+
}
|
|
270
|
+
if (process.execPath?.trim()) {
|
|
271
|
+
return {
|
|
272
|
+
command: process.execPath,
|
|
273
|
+
env: { BUN_BE_BUN: "1" }
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
throw new Error("bun is required to run the runtime binary build worker.");
|
|
277
|
+
}
|
|
278
|
+
function currentCompileTarget() {
|
|
279
|
+
if (process.platform === "darwin") {
|
|
280
|
+
return process.arch === "arm64" ? "bun-darwin-arm64" : "bun-darwin-x64";
|
|
281
|
+
}
|
|
282
|
+
if (process.platform === "linux") {
|
|
283
|
+
return process.arch === "arm64" ? "bun-linux-arm64" : "bun-linux-x64";
|
|
284
|
+
}
|
|
285
|
+
return "bun-windows-x64";
|
|
286
|
+
}
|
|
287
|
+
function createRuntimeBinaryBuildKey(input) {
|
|
288
|
+
return JSON.stringify({
|
|
289
|
+
version: 1,
|
|
290
|
+
bunVersion: Bun.version,
|
|
291
|
+
platform: process.platform,
|
|
292
|
+
arch: process.arch,
|
|
293
|
+
entrypoint: input.entrypoint,
|
|
294
|
+
define: sortRecord(input.define),
|
|
295
|
+
external: input.external ? [...input.external].sort() : undefined,
|
|
296
|
+
env: sortRecord(input.env)
|
|
297
|
+
});
|
|
298
|
+
}
|
|
299
|
+
async function isRuntimeBinaryBuildFresh(input) {
|
|
300
|
+
if (!existsSync(input.outputPath) || !existsSync(input.manifestPath)) {
|
|
301
|
+
return false;
|
|
302
|
+
}
|
|
303
|
+
let manifest = null;
|
|
304
|
+
try {
|
|
305
|
+
manifest = await Bun.file(input.manifestPath).json();
|
|
306
|
+
} catch {
|
|
307
|
+
return false;
|
|
308
|
+
}
|
|
309
|
+
if (!manifest || manifest.version !== 1 || manifest.buildKey !== input.buildKey) {
|
|
310
|
+
return false;
|
|
311
|
+
}
|
|
312
|
+
for (const [filePath, expectedDigest] of Object.entries(manifest.inputs || {})) {
|
|
313
|
+
if (!existsSync(filePath)) {
|
|
314
|
+
return false;
|
|
315
|
+
}
|
|
316
|
+
if (await sha256File(filePath) !== expectedDigest) {
|
|
317
|
+
return false;
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
return true;
|
|
321
|
+
}
|
|
322
|
+
async function writeRuntimeBinaryCacheManifest(input) {
|
|
323
|
+
const inputs = {};
|
|
324
|
+
for (const inputPath of Object.keys(input.metafile?.inputs || {}).sort()) {
|
|
325
|
+
const normalized = normalizeBuildInputPath(input.cwd, inputPath);
|
|
326
|
+
if (!normalized || !existsSync(normalized)) {
|
|
327
|
+
continue;
|
|
328
|
+
}
|
|
329
|
+
inputs[normalized] = await sha256File(normalized);
|
|
330
|
+
}
|
|
331
|
+
const manifest = {
|
|
332
|
+
version: 1,
|
|
333
|
+
buildKey: input.buildKey,
|
|
334
|
+
inputs
|
|
335
|
+
};
|
|
336
|
+
await Bun.write(input.manifestPath, `${JSON.stringify(manifest, null, 2)}
|
|
337
|
+
`);
|
|
338
|
+
}
|
|
339
|
+
function normalizeBuildInputPath(cwd, inputPath) {
|
|
340
|
+
if (!inputPath) {
|
|
341
|
+
return null;
|
|
342
|
+
}
|
|
343
|
+
if (inputPath.startsWith("file://")) {
|
|
344
|
+
return fileURLToPath(inputPath);
|
|
345
|
+
}
|
|
346
|
+
if (inputPath.startsWith("<")) {
|
|
347
|
+
return null;
|
|
348
|
+
}
|
|
349
|
+
return resolve2(cwd, inputPath);
|
|
350
|
+
}
|
|
351
|
+
async function sha256File(path) {
|
|
352
|
+
const hasher = new Bun.CryptoHasher("sha256");
|
|
353
|
+
hasher.update(await Bun.file(path).arrayBuffer());
|
|
354
|
+
return hasher.digest("hex");
|
|
355
|
+
}
|
|
356
|
+
function sortRecord(value) {
|
|
357
|
+
if (!value) {
|
|
358
|
+
return;
|
|
359
|
+
}
|
|
360
|
+
return Object.fromEntries(Object.entries(value).sort(([left], [right]) => left.localeCompare(right)));
|
|
361
|
+
}
|
|
362
|
+
async function runSerializedRuntimeBinaryBuild(action) {
|
|
363
|
+
const previous = runtimeBinaryBuildQueue;
|
|
364
|
+
let release;
|
|
365
|
+
runtimeBinaryBuildQueue = new Promise((resolve3) => {
|
|
366
|
+
release = resolve3;
|
|
367
|
+
});
|
|
368
|
+
await previous;
|
|
369
|
+
try {
|
|
370
|
+
return await action();
|
|
371
|
+
} finally {
|
|
372
|
+
release();
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
async function withTemporaryEnv(env, action) {
|
|
376
|
+
if (!env) {
|
|
377
|
+
return action();
|
|
378
|
+
}
|
|
379
|
+
const previousValues = new Map;
|
|
380
|
+
for (const [key, value] of Object.entries(env)) {
|
|
381
|
+
previousValues.set(key, process.env[key]);
|
|
382
|
+
if (value === undefined) {
|
|
383
|
+
delete process.env[key];
|
|
384
|
+
} else {
|
|
385
|
+
process.env[key] = value;
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
try {
|
|
389
|
+
return await action();
|
|
390
|
+
} finally {
|
|
391
|
+
for (const [key, value] of previousValues.entries()) {
|
|
392
|
+
if (value === undefined) {
|
|
393
|
+
delete process.env[key];
|
|
394
|
+
} else {
|
|
395
|
+
process.env[key] = value;
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
async function withTemporaryCwd(cwd, action) {
|
|
401
|
+
const previousCwd = process.cwd();
|
|
402
|
+
process.chdir(cwd);
|
|
403
|
+
try {
|
|
404
|
+
return await action();
|
|
405
|
+
} finally {
|
|
406
|
+
process.chdir(previousCwd);
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
function copyRuntimeBinaryAssets(options) {
|
|
410
|
+
const definitionRoot = options.rigDir ?? resolveRigLayout(options.projectRoot).definitionRoot;
|
|
411
|
+
const runtimeDir = resolve2(options.outputDir, "runtime", "rig");
|
|
412
|
+
mkdirSync(runtimeDir, { recursive: true });
|
|
413
|
+
const copiedEntries = [];
|
|
414
|
+
for (const entry of options.entries ?? runtimeBinaryAssetEntries) {
|
|
415
|
+
const source = resolve2(definitionRoot, entry);
|
|
416
|
+
if (!existsSync(source)) {
|
|
417
|
+
continue;
|
|
418
|
+
}
|
|
419
|
+
cpSync(source, resolve2(runtimeDir, entry), { recursive: true });
|
|
420
|
+
copiedEntries.push(entry);
|
|
421
|
+
}
|
|
422
|
+
return { copiedEntries, runtimeDir };
|
|
423
|
+
}
|
|
424
|
+
async function launchRuntimeBinary(request) {
|
|
425
|
+
const options = {
|
|
426
|
+
cwd: request.cwd,
|
|
427
|
+
env: request.env ? { ...process.env, ...request.env } : process.env
|
|
428
|
+
};
|
|
429
|
+
if (request.timeoutMs !== undefined) {
|
|
430
|
+
options.timeoutMs = request.timeoutMs;
|
|
431
|
+
}
|
|
432
|
+
return spawnProcess(request.binaryPath, request.args, options);
|
|
433
|
+
}
|
|
434
|
+
async function spawnProcess(command, args, options) {
|
|
435
|
+
const child = nodeSpawn(command, args, {
|
|
436
|
+
cwd: options.cwd,
|
|
437
|
+
env: options.env,
|
|
438
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
439
|
+
});
|
|
440
|
+
let stdout = "";
|
|
441
|
+
let stderr = "";
|
|
442
|
+
child.stdout?.setEncoding("utf8");
|
|
443
|
+
child.stderr?.setEncoding("utf8");
|
|
444
|
+
child.stdout?.on("data", (chunk) => {
|
|
445
|
+
stdout += chunk;
|
|
446
|
+
});
|
|
447
|
+
child.stderr?.on("data", (chunk) => {
|
|
448
|
+
stderr += chunk;
|
|
449
|
+
});
|
|
450
|
+
let timedOut = false;
|
|
451
|
+
let timer;
|
|
452
|
+
const exitCode = await new Promise((resolveExit, rejectExit) => {
|
|
453
|
+
if (options.timeoutMs && options.timeoutMs > 0) {
|
|
454
|
+
timer = setTimeout(() => {
|
|
455
|
+
timedOut = true;
|
|
456
|
+
child.kill();
|
|
457
|
+
}, options.timeoutMs);
|
|
458
|
+
}
|
|
459
|
+
child.once("error", rejectExit);
|
|
460
|
+
child.once("close", (code) => resolveExit(code ?? (timedOut ? 1 : 0)));
|
|
461
|
+
}).finally(() => {
|
|
462
|
+
if (timer) {
|
|
463
|
+
clearTimeout(timer);
|
|
464
|
+
}
|
|
465
|
+
});
|
|
466
|
+
return { exitCode, stdout, stderr, timedOut };
|
|
467
|
+
}
|
|
468
|
+
export {
|
|
469
|
+
runtimeRigCliBinaryExternals,
|
|
470
|
+
runtimeBinaryAssetEntries,
|
|
471
|
+
materializeSelfExecRole,
|
|
472
|
+
launchRuntimeBinary,
|
|
473
|
+
isRuntimeBinaryAssetEntry,
|
|
474
|
+
createRuntimeBinaryBuildManifest,
|
|
475
|
+
copyRuntimeBinaryAssets,
|
|
476
|
+
buildRuntimeBinarySync,
|
|
477
|
+
buildRuntimeBinaryInProcess,
|
|
478
|
+
buildRuntimeBinary,
|
|
479
|
+
buildBinary
|
|
480
|
+
};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { agentId, taskRuntimeId } from "@rig/core/safe-identifiers";
|
|
2
|
+
export { agentId, taskRuntimeId };
|
|
3
|
+
export declare function isRuntimeGatewayGitPath(candidate: string): boolean;
|
|
4
|
+
export declare function isRuntimeGatewayGhPath(candidate: string): boolean;
|
|
5
|
+
export declare function resolveHostGitBinary(): string;
|
|
6
|
+
export declare function resolveGithubCliBinary(options?: {
|
|
7
|
+
scanPath?: boolean;
|
|
8
|
+
}): string;
|
|
9
|
+
export declare function resolveMonorepoRoot(projectRoot: string): string;
|
|
10
|
+
export declare function runGitCommand(repoRoot: string, args: string[]): Promise<Awaited<ReturnType<typeof Bun.$>>>;
|
|
11
|
+
export declare function readGitConfigValue(repoRoot: string, key: string, global?: boolean): Promise<string>;
|
|
12
|
+
export declare function readGitStdout(repoRoot: string, args: string[]): Promise<string>;
|
|
13
|
+
export declare function hasGitRemote(repoRoot: string, remote: string): Promise<boolean>;
|
|
14
|
+
export declare function ensureFullGitHistory(repoRoot: string): Promise<void>;
|
|
15
|
+
export declare function refreshRemoteBranch(repoRoot: string, remote: string, branch: string): Promise<void>;
|
|
16
|
+
export declare function tryReadGitHead(repoRoot: string): Promise<string | undefined>;
|
|
17
|
+
export declare function captureRepoDirtyFiles(repoRoot: string): Promise<string[]>;
|
|
18
|
+
export declare function sha256Hex(input: string | Buffer | Uint8Array): string;
|
|
19
|
+
export declare function registerCredentialCleanup(path: string): void;
|
|
20
|
+
export declare function captureStdout(fn: () => Promise<void> | void): Promise<string>;
|
|
21
|
+
export declare function sanitizeRuntimeRefSegment(value: string): string;
|
|
22
|
+
export declare function runtimeBranchBackupName(branch: string): string;
|
|
23
|
+
export declare function hashProjectPath(workspaceDir: string): string;
|
|
24
|
+
export declare function resolveGithubCliAuthToken(ghBinary?: string): Promise<string>;
|
|
25
|
+
export declare function resolveSystemCertBundlePath(): string;
|
|
26
|
+
export declare const __testOnly: {
|
|
27
|
+
cleanupGeneratedCredentialFiles(): void;
|
|
28
|
+
};
|
|
29
|
+
export declare function readKnownHosts(path: string): Set<string>;
|