@h-rig/runtime 0.0.6-alpha.28 → 0.0.6-alpha.29
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/bin/rig-agent-dispatch.js +552 -483
- package/dist/bin/rig-agent.js +418 -364
- package/dist/src/control-plane/agent-wrapper.js +557 -488
- package/dist/src/control-plane/harness-main.js +559 -1418
- package/dist/src/control-plane/hooks/completion-verification.js +451 -808
- package/dist/src/control-plane/hooks/inject-context.js +191 -137
- package/dist/src/control-plane/hooks/submodule-branch.js +596 -542
- package/dist/src/control-plane/hooks/task-runtime-start.js +596 -542
- package/dist/src/control-plane/materialize-task-config.js +64 -8
- package/dist/src/control-plane/native/git-ops.js +3 -0
- package/dist/src/control-plane/native/harness-cli.js +544 -496
- package/dist/src/control-plane/native/repo-ops.js +3 -0
- package/dist/src/control-plane/native/run-ops.js +3 -0
- package/dist/src/control-plane/native/task-ops.js +418 -370
- package/dist/src/control-plane/native/validator.js +161 -107
- package/dist/src/control-plane/native/verifier.js +217 -169
- package/dist/src/control-plane/pi-sessiond/launcher.js +12 -2
- package/dist/src/control-plane/plugin-host-context.js +54 -0
- package/dist/src/control-plane/runtime/image/fingerprint-sidecar.js +3 -0
- package/dist/src/control-plane/runtime/image/index.js +3 -0
- package/dist/src/control-plane/runtime/image-fingerprint-sidecar.js +3 -0
- package/dist/src/control-plane/runtime/image.js +3 -0
- package/dist/src/control-plane/runtime/index.js +487 -718
- package/dist/src/control-plane/runtime/isolation/index.js +511 -457
- package/dist/src/control-plane/runtime/isolation.js +511 -457
- package/dist/src/control-plane/runtime/plugin-mode.js +3 -27
- package/dist/src/control-plane/runtime/queue.js +428 -381
- package/dist/src/control-plane/runtime/snapshot/task-run.js +3 -0
- package/dist/src/control-plane/runtime/task-run-snapshot.js +3 -0
- package/dist/src/control-plane/skill-materializer.js +46 -0
- package/dist/src/control-plane/tasks/source-lifecycle.js +84 -30
- package/dist/src/index.js +0 -278
- package/native/darwin-arm64/rig-shell +0 -0
- package/native/darwin-arm64/rig-shell.build-manifest.json +1 -1
- package/native/darwin-arm64/rig-tools +0 -0
- package/native/darwin-arm64/rig-tools.build-manifest.json +1 -1
- package/package.json +8 -7
- package/dist/src/control-plane/runtime/plugins.js +0 -1131
- package/dist/src/plugins.js +0 -329
|
@@ -149,32 +149,32 @@ var RIG_DEFINITION_DIRNAME = "rig", RIG_ARTIFACTS_DIRNAME = "artifacts";
|
|
|
149
149
|
var init_layout = () => {};
|
|
150
150
|
|
|
151
151
|
// packages/runtime/src/control-plane/runtime/sandbox/utils.ts
|
|
152
|
-
import { existsSync as
|
|
153
|
-
import { resolve as
|
|
152
|
+
import { existsSync as existsSync20, readdirSync as readdirSync4, realpathSync } from "fs";
|
|
153
|
+
import { resolve as resolve20 } from "path";
|
|
154
154
|
function toRealPath(path) {
|
|
155
|
-
if (!
|
|
156
|
-
return
|
|
155
|
+
if (!existsSync20(path)) {
|
|
156
|
+
return resolve20(path);
|
|
157
157
|
}
|
|
158
158
|
try {
|
|
159
159
|
return realpathSync.native(path);
|
|
160
160
|
} catch {
|
|
161
|
-
return
|
|
161
|
+
return resolve20(path);
|
|
162
162
|
}
|
|
163
163
|
}
|
|
164
164
|
function resolveHostGitMetadataPaths(projectRoot, workspaceDir) {
|
|
165
165
|
const candidates = new Set;
|
|
166
166
|
const addPath = (candidate) => {
|
|
167
|
-
if (
|
|
167
|
+
if (existsSync20(candidate)) {
|
|
168
168
|
candidates.add(toRealPath(candidate));
|
|
169
169
|
}
|
|
170
170
|
};
|
|
171
|
-
addPath(
|
|
172
|
-
addPath(
|
|
171
|
+
addPath(resolve20(projectRoot, ".git"));
|
|
172
|
+
addPath(resolve20(workspaceDir, "..", "..", ".git"));
|
|
173
173
|
for (const repoRoot of resolveHostRepoRootPaths(projectRoot)) {
|
|
174
|
-
addPath(
|
|
174
|
+
addPath(resolve20(repoRoot, ".git"));
|
|
175
175
|
}
|
|
176
|
-
const workspaceGit =
|
|
177
|
-
if (
|
|
176
|
+
const workspaceGit = resolve20(workspaceDir, ".git");
|
|
177
|
+
if (existsSync20(workspaceGit)) {
|
|
178
178
|
addPath(workspaceGit);
|
|
179
179
|
}
|
|
180
180
|
return [...candidates];
|
|
@@ -182,7 +182,7 @@ function resolveHostGitMetadataPaths(projectRoot, workspaceDir) {
|
|
|
182
182
|
function resolveHostRepoRootPaths(projectRoot) {
|
|
183
183
|
const candidates = new Set;
|
|
184
184
|
const addPath = (candidate) => {
|
|
185
|
-
if (
|
|
185
|
+
if (existsSync20(candidate)) {
|
|
186
186
|
candidates.add(toRealPath(candidate));
|
|
187
187
|
}
|
|
188
188
|
};
|
|
@@ -192,11 +192,11 @@ function resolveHostRepoRootPaths(projectRoot) {
|
|
|
192
192
|
addPath(monorepoRoot);
|
|
193
193
|
}
|
|
194
194
|
} catch {}
|
|
195
|
-
const reposDir =
|
|
196
|
-
if (
|
|
197
|
-
for (const entry of
|
|
195
|
+
const reposDir = resolve20(projectRoot, "repos");
|
|
196
|
+
if (existsSync20(reposDir)) {
|
|
197
|
+
for (const entry of readdirSync4(reposDir, { withFileTypes: true })) {
|
|
198
198
|
if (entry.isDirectory() || entry.isSymbolicLink()) {
|
|
199
|
-
addPath(
|
|
199
|
+
addPath(resolve20(reposDir, entry.name));
|
|
200
200
|
}
|
|
201
201
|
}
|
|
202
202
|
}
|
|
@@ -240,8 +240,8 @@ var exports_backend_seatbelt = {};
|
|
|
240
240
|
__export(exports_backend_seatbelt, {
|
|
241
241
|
SeatbeltBackend: () => SeatbeltBackend
|
|
242
242
|
});
|
|
243
|
-
import { mkdirSync as
|
|
244
|
-
import { resolve as
|
|
243
|
+
import { mkdirSync as mkdirSync17, writeFileSync as writeFileSync12 } from "fs";
|
|
244
|
+
import { resolve as resolve33 } from "path";
|
|
245
245
|
|
|
246
246
|
class SeatbeltBackend {
|
|
247
247
|
kind = "macos-seatbelt";
|
|
@@ -265,11 +265,11 @@ class SeatbeltBackend {
|
|
|
265
265
|
};
|
|
266
266
|
}
|
|
267
267
|
writeSeatbeltProfile(options) {
|
|
268
|
-
const sandboxDir =
|
|
269
|
-
|
|
270
|
-
const profilePath =
|
|
268
|
+
const sandboxDir = resolve33(options.runtime.rootDir, "sandbox");
|
|
269
|
+
mkdirSync17(sandboxDir, { recursive: true });
|
|
270
|
+
const profilePath = resolve33(sandboxDir, "seatbelt.sb");
|
|
271
271
|
const profile = this.renderProfile(options);
|
|
272
|
-
|
|
272
|
+
writeFileSync12(profilePath, `${profile}
|
|
273
273
|
`, "utf-8");
|
|
274
274
|
return profilePath;
|
|
275
275
|
}
|
|
@@ -354,7 +354,7 @@ class SeatbeltBackend {
|
|
|
354
354
|
const realHome = process.env.HOME?.trim();
|
|
355
355
|
if (realHome) {
|
|
356
356
|
for (const binSubdir of [".local/bin", ".cargo/bin"]) {
|
|
357
|
-
const binPath =
|
|
357
|
+
const binPath = resolve33(realHome, binSubdir);
|
|
358
358
|
if (ctx.pathExists(binPath)) {
|
|
359
359
|
lines.push(`(allow file-read* (subpath ${seatbeltString(ctx.realPath(binPath))}))`);
|
|
360
360
|
}
|
|
@@ -383,8 +383,8 @@ var exports_backend_bwrap = {};
|
|
|
383
383
|
__export(exports_backend_bwrap, {
|
|
384
384
|
BwrapBackend: () => BwrapBackend
|
|
385
385
|
});
|
|
386
|
-
import { mkdirSync as
|
|
387
|
-
import { resolve as
|
|
386
|
+
import { mkdirSync as mkdirSync18 } from "fs";
|
|
387
|
+
import { resolve as resolve34 } from "path";
|
|
388
388
|
|
|
389
389
|
class BwrapBackend {
|
|
390
390
|
kind = "linux-bwrap";
|
|
@@ -513,18 +513,18 @@ class BwrapBackend {
|
|
|
513
513
|
const realHome = process.env.HOME?.trim();
|
|
514
514
|
if (realHome) {
|
|
515
515
|
for (const binSubdir of [".local/bin", ".local/lib", ".cargo/bin"]) {
|
|
516
|
-
const binPath = ctx.realPath(
|
|
516
|
+
const binPath = ctx.realPath(resolve34(realHome, binSubdir));
|
|
517
517
|
if (ctx.pathExists(binPath)) {
|
|
518
518
|
args.push("--ro-bind", binPath, binPath);
|
|
519
519
|
}
|
|
520
520
|
}
|
|
521
|
-
const agentSshDir =
|
|
521
|
+
const agentSshDir = resolve34(homeReal, ".ssh");
|
|
522
522
|
if (ctx.pathExists(agentSshDir)) {
|
|
523
523
|
args.push("--ro-bind", agentSshDir, agentSshDir);
|
|
524
524
|
} else {
|
|
525
|
-
const hostSshDir =
|
|
525
|
+
const hostSshDir = resolve34(realHome, ".ssh");
|
|
526
526
|
if (ctx.pathExists(hostSshDir)) {
|
|
527
|
-
|
|
527
|
+
mkdirSync18(agentSshDir, { recursive: true });
|
|
528
528
|
args.push("--ro-bind", hostSshDir, agentSshDir);
|
|
529
529
|
args.push("--ro-bind", hostSshDir, hostSshDir);
|
|
530
530
|
}
|
|
@@ -566,9 +566,9 @@ var init_backend_bwrap = __esm(() => {
|
|
|
566
566
|
});
|
|
567
567
|
|
|
568
568
|
// packages/runtime/src/control-plane/runtime/isolation/index.ts
|
|
569
|
-
import { existsSync as
|
|
569
|
+
import { existsSync as existsSync34, mkdirSync as mkdirSync19, readFileSync as readFileSync16, rmSync as rmSync13 } from "fs";
|
|
570
570
|
import { copyFile, mkdir as mkdir3, writeFile as writeFile2 } from "fs/promises";
|
|
571
|
-
import { resolve as
|
|
571
|
+
import { resolve as resolve36 } from "path";
|
|
572
572
|
|
|
573
573
|
// packages/runtime/src/control-plane/native/git-native.ts
|
|
574
574
|
import { chmodSync, copyFileSync, existsSync, mkdirSync, readFileSync, renameSync, rmSync, writeFileSync } from "fs";
|
|
@@ -1858,8 +1858,8 @@ function isAgentRuntimeContextPath(path) {
|
|
|
1858
1858
|
var DEFAULT_RESULT_LIMIT = DEFAULT_RUNTIME_MEMORY_RETRIEVAL.topK;
|
|
1859
1859
|
var DAY_MS = 24 * 60 * 60 * 1000;
|
|
1860
1860
|
// packages/runtime/src/control-plane/native/task-ops.ts
|
|
1861
|
-
import { appendFileSync, existsSync as
|
|
1862
|
-
import { resolve as
|
|
1861
|
+
import { appendFileSync, existsSync as existsSync23, mkdirSync as mkdirSync10, readFileSync as readFileSync11, writeFileSync as writeFileSync9 } from "fs";
|
|
1862
|
+
import { resolve as resolve24 } from "path";
|
|
1863
1863
|
|
|
1864
1864
|
// packages/runtime/src/build-time-config.ts
|
|
1865
1865
|
function normalizeBuildConfig(value) {
|
|
@@ -2710,6 +2710,49 @@ function safeReadJson(path) {
|
|
|
2710
2710
|
}
|
|
2711
2711
|
}
|
|
2712
2712
|
|
|
2713
|
+
// packages/runtime/src/control-plane/skill-materializer.ts
|
|
2714
|
+
import { existsSync as existsSync12, mkdirSync as mkdirSync8, readFileSync as readFileSync5, readdirSync, rmSync as rmSync7, writeFileSync as writeFileSync5 } from "fs";
|
|
2715
|
+
import { resolve as resolve12 } from "path";
|
|
2716
|
+
import { loadSkill } from "@rig/skill-loader";
|
|
2717
|
+
var MARKER_FILENAME = ".rig-plugin";
|
|
2718
|
+
function skillDirName(id) {
|
|
2719
|
+
return id.replace(/[^a-zA-Z0-9._-]+/g, "-");
|
|
2720
|
+
}
|
|
2721
|
+
async function materializeSkills(projectRoot, entries) {
|
|
2722
|
+
const skillsRoot = resolve12(projectRoot, ".pi", "skills");
|
|
2723
|
+
if (existsSync12(skillsRoot)) {
|
|
2724
|
+
for (const name of readdirSync(skillsRoot)) {
|
|
2725
|
+
const dir = resolve12(skillsRoot, name);
|
|
2726
|
+
if (existsSync12(resolve12(dir, MARKER_FILENAME))) {
|
|
2727
|
+
rmSync7(dir, { recursive: true, force: true });
|
|
2728
|
+
}
|
|
2729
|
+
}
|
|
2730
|
+
}
|
|
2731
|
+
const written = [];
|
|
2732
|
+
for (const { pluginName, skill } of entries) {
|
|
2733
|
+
const sourcePath = resolve12(projectRoot, skill.path);
|
|
2734
|
+
if (!existsSync12(sourcePath)) {
|
|
2735
|
+
console.warn(`[plugin-host] skill "${skill.id}" from plugin "${pluginName}" not materialized: ${sourcePath} does not exist`);
|
|
2736
|
+
continue;
|
|
2737
|
+
}
|
|
2738
|
+
let body;
|
|
2739
|
+
try {
|
|
2740
|
+
await loadSkill(sourcePath);
|
|
2741
|
+
body = readFileSync5(sourcePath, "utf-8");
|
|
2742
|
+
} catch (err) {
|
|
2743
|
+
console.warn(`[plugin-host] skill "${skill.id}" from plugin "${pluginName}" not materialized: ${err instanceof Error ? err.message : err}`);
|
|
2744
|
+
continue;
|
|
2745
|
+
}
|
|
2746
|
+
const dir = resolve12(skillsRoot, skillDirName(skill.id));
|
|
2747
|
+
mkdirSync8(dir, { recursive: true });
|
|
2748
|
+
writeFileSync5(resolve12(dir, "SKILL.md"), body, "utf-8");
|
|
2749
|
+
writeFileSync5(resolve12(dir, MARKER_FILENAME), `${JSON.stringify({ plugin: pluginName, skillId: skill.id }, null, 2)}
|
|
2750
|
+
`, "utf-8");
|
|
2751
|
+
written.push({ id: skill.id, pluginName, directory: dir });
|
|
2752
|
+
}
|
|
2753
|
+
return written;
|
|
2754
|
+
}
|
|
2755
|
+
|
|
2713
2756
|
// packages/runtime/src/control-plane/plugin-host-context.ts
|
|
2714
2757
|
async function buildPluginHostContext(projectRoot) {
|
|
2715
2758
|
let config;
|
|
@@ -2746,6 +2789,17 @@ async function buildPluginHostContext(projectRoot) {
|
|
|
2746
2789
|
} catch (err) {
|
|
2747
2790
|
console.warn(`[plugin-host] hook materialization failed: ${err instanceof Error ? err.message : err}`);
|
|
2748
2791
|
}
|
|
2792
|
+
try {
|
|
2793
|
+
const skillEntries = config.plugins.flatMap((plugin) => (plugin.contributes?.skills ?? []).map((skill) => ({
|
|
2794
|
+
pluginName: plugin.name,
|
|
2795
|
+
skill
|
|
2796
|
+
})));
|
|
2797
|
+
if (skillEntries.length > 0) {
|
|
2798
|
+
await materializeSkills(projectRoot, skillEntries);
|
|
2799
|
+
}
|
|
2800
|
+
} catch (err) {
|
|
2801
|
+
console.warn(`[plugin-host] skill materialization failed: ${err instanceof Error ? err.message : err}`);
|
|
2802
|
+
}
|
|
2749
2803
|
return {
|
|
2750
2804
|
config,
|
|
2751
2805
|
pluginHost,
|
|
@@ -2759,12 +2813,12 @@ async function buildPluginHostContext(projectRoot) {
|
|
|
2759
2813
|
|
|
2760
2814
|
// packages/runtime/src/control-plane/tasks/source-aware-task-config-source.ts
|
|
2761
2815
|
import { spawnSync } from "child_process";
|
|
2762
|
-
import { existsSync as
|
|
2763
|
-
import { basename as basename4, join as join3, resolve as
|
|
2816
|
+
import { existsSync as existsSync14, readFileSync as readFileSync7, readdirSync as readdirSync2, statSync as statSync3, writeFileSync as writeFileSync6 } from "fs";
|
|
2817
|
+
import { basename as basename4, join as join3, resolve as resolve14 } from "path";
|
|
2764
2818
|
|
|
2765
2819
|
// packages/runtime/src/control-plane/tasks/legacy-task-config-source.ts
|
|
2766
|
-
import { existsSync as
|
|
2767
|
-
import { resolve as
|
|
2820
|
+
import { existsSync as existsSync13, readFileSync as readFileSync6 } from "fs";
|
|
2821
|
+
import { resolve as resolve13 } from "path";
|
|
2768
2822
|
|
|
2769
2823
|
// packages/runtime/src/control-plane/tasks/task-record-reader.ts
|
|
2770
2824
|
async function findTaskById(reader, id) {
|
|
@@ -2787,7 +2841,7 @@ class LegacyTaskConfigReadError extends Error {
|
|
|
2787
2841
|
}
|
|
2788
2842
|
}
|
|
2789
2843
|
function createLegacyTaskConfigRecordReader(projectRoot, options = {}) {
|
|
2790
|
-
const configPath = options.configPath ??
|
|
2844
|
+
const configPath = options.configPath ?? resolve13(projectRoot, ".rig", "task-config.json");
|
|
2791
2845
|
const reader = {
|
|
2792
2846
|
async listTasks() {
|
|
2793
2847
|
return readLegacyTaskRecords(projectRoot, configPath);
|
|
@@ -2798,8 +2852,8 @@ function createLegacyTaskConfigRecordReader(projectRoot, options = {}) {
|
|
|
2798
2852
|
};
|
|
2799
2853
|
return reader;
|
|
2800
2854
|
}
|
|
2801
|
-
function readLegacyTaskRecords(projectRoot, configPath =
|
|
2802
|
-
if (!
|
|
2855
|
+
function readLegacyTaskRecords(projectRoot, configPath = resolve13(projectRoot, ".rig", "task-config.json")) {
|
|
2856
|
+
if (!existsSync13(configPath)) {
|
|
2803
2857
|
return [];
|
|
2804
2858
|
}
|
|
2805
2859
|
const rawConfig = readLegacyTaskConfigJson(projectRoot, configPath);
|
|
@@ -2807,7 +2861,7 @@ function readLegacyTaskRecords(projectRoot, configPath = resolve12(projectRoot,
|
|
|
2807
2861
|
}
|
|
2808
2862
|
function readLegacyTaskConfigJson(projectRoot, configPath) {
|
|
2809
2863
|
try {
|
|
2810
|
-
const parsed = JSON.parse(
|
|
2864
|
+
const parsed = JSON.parse(readFileSync6(configPath, "utf8"));
|
|
2811
2865
|
if (isPlainRecord(parsed)) {
|
|
2812
2866
|
return parsed;
|
|
2813
2867
|
}
|
|
@@ -2891,7 +2945,7 @@ function isPlainRecord(candidate) {
|
|
|
2891
2945
|
var STATUS_LABELS = new Set(["ready", "blocked", "in-progress", "under-review", "failed", "cancelled"]);
|
|
2892
2946
|
var FILE_TASK_PATTERN = /\.(task\.)?json$/;
|
|
2893
2947
|
function createSourceAwareTaskConfigRecordReader(projectRoot, options = {}) {
|
|
2894
|
-
const configPath = options.configPath ??
|
|
2948
|
+
const configPath = options.configPath ?? resolve14(projectRoot, ".rig", "task-config.json");
|
|
2895
2949
|
const legacy = createLegacyTaskConfigRecordReader(projectRoot, { configPath });
|
|
2896
2950
|
const spawnFn = options.spawn ?? spawnSync;
|
|
2897
2951
|
const ghBinary = options.ghBinary ?? "gh";
|
|
@@ -2974,10 +3028,10 @@ function readMaterializedTaskMetadata(entry) {
|
|
|
2974
3028
|
return metadata;
|
|
2975
3029
|
}
|
|
2976
3030
|
function readConfiguredFilesTaskSourcePath(projectRoot) {
|
|
2977
|
-
const jsonPath =
|
|
2978
|
-
if (
|
|
3031
|
+
const jsonPath = resolve14(projectRoot, "rig.config.json");
|
|
3032
|
+
if (existsSync14(jsonPath)) {
|
|
2979
3033
|
try {
|
|
2980
|
-
const parsed = JSON.parse(
|
|
3034
|
+
const parsed = JSON.parse(readFileSync7(jsonPath, "utf8"));
|
|
2981
3035
|
if (isPlainRecord2(parsed) && isPlainRecord2(parsed.taskSource)) {
|
|
2982
3036
|
const source = parsed.taskSource;
|
|
2983
3037
|
return source.kind === "files" && typeof source.path === "string" ? source.path : null;
|
|
@@ -2986,12 +3040,12 @@ function readConfiguredFilesTaskSourcePath(projectRoot) {
|
|
|
2986
3040
|
return null;
|
|
2987
3041
|
}
|
|
2988
3042
|
}
|
|
2989
|
-
const tsPath =
|
|
2990
|
-
if (!
|
|
3043
|
+
const tsPath = resolve14(projectRoot, "rig.config.ts");
|
|
3044
|
+
if (!existsSync14(tsPath)) {
|
|
2991
3045
|
return null;
|
|
2992
3046
|
}
|
|
2993
3047
|
try {
|
|
2994
|
-
const source =
|
|
3048
|
+
const source = readFileSync7(tsPath, "utf8");
|
|
2995
3049
|
const taskSourceBlock = source.match(/taskSource\s*:\s*\{[\s\S]*?\}/m)?.[0] ?? "";
|
|
2996
3050
|
const kind = taskSourceBlock.match(/kind\s*:\s*["']([^"']+)["']/)?.[1];
|
|
2997
3051
|
if (kind !== "files") {
|
|
@@ -3011,10 +3065,10 @@ function readRawTaskEntry(configPath, taskId) {
|
|
|
3011
3065
|
return isPlainRecord2(entry) ? entry : null;
|
|
3012
3066
|
}
|
|
3013
3067
|
function readRawTaskConfig(configPath) {
|
|
3014
|
-
if (!
|
|
3068
|
+
if (!existsSync14(configPath)) {
|
|
3015
3069
|
return null;
|
|
3016
3070
|
}
|
|
3017
|
-
const parsed = JSON.parse(
|
|
3071
|
+
const parsed = JSON.parse(readFileSync7(configPath, "utf8"));
|
|
3018
3072
|
return isPlainRecord2(parsed) ? parsed : null;
|
|
3019
3073
|
}
|
|
3020
3074
|
function stripLegacyTaskConfigMetadata2(raw) {
|
|
@@ -3022,12 +3076,12 @@ function stripLegacyTaskConfigMetadata2(raw) {
|
|
|
3022
3076
|
return tasks;
|
|
3023
3077
|
}
|
|
3024
3078
|
function listFileBackedTasks(projectRoot, sourcePath) {
|
|
3025
|
-
const directory =
|
|
3026
|
-
if (!
|
|
3079
|
+
const directory = resolve14(projectRoot, sourcePath);
|
|
3080
|
+
if (!existsSync14(directory)) {
|
|
3027
3081
|
return [];
|
|
3028
3082
|
}
|
|
3029
3083
|
const tasks = [];
|
|
3030
|
-
for (const name of
|
|
3084
|
+
for (const name of readdirSync2(directory)) {
|
|
3031
3085
|
if (!FILE_TASK_PATTERN.test(name))
|
|
3032
3086
|
continue;
|
|
3033
3087
|
const inferredId = basename4(name).replace(FILE_TASK_PATTERN, "");
|
|
@@ -3038,11 +3092,11 @@ function listFileBackedTasks(projectRoot, sourcePath) {
|
|
|
3038
3092
|
return tasks;
|
|
3039
3093
|
}
|
|
3040
3094
|
function readFileBackedTask(projectRoot, sourcePath, taskId, rawEntry) {
|
|
3041
|
-
const file = findFileBackedTaskFile(
|
|
3095
|
+
const file = findFileBackedTaskFile(resolve14(projectRoot, sourcePath), taskId);
|
|
3042
3096
|
if (!file) {
|
|
3043
3097
|
return null;
|
|
3044
3098
|
}
|
|
3045
|
-
const raw = JSON.parse(
|
|
3099
|
+
const raw = JSON.parse(readFileSync7(file, "utf8"));
|
|
3046
3100
|
if (!isPlainRecord2(raw)) {
|
|
3047
3101
|
return null;
|
|
3048
3102
|
}
|
|
@@ -3055,17 +3109,17 @@ function readFileBackedTask(projectRoot, sourcePath, taskId, rawEntry) {
|
|
|
3055
3109
|
};
|
|
3056
3110
|
}
|
|
3057
3111
|
function findFileBackedTaskFile(directory, taskId) {
|
|
3058
|
-
if (!
|
|
3112
|
+
if (!existsSync14(directory)) {
|
|
3059
3113
|
return null;
|
|
3060
3114
|
}
|
|
3061
|
-
for (const name of
|
|
3115
|
+
for (const name of readdirSync2(directory)) {
|
|
3062
3116
|
if (!FILE_TASK_PATTERN.test(name))
|
|
3063
3117
|
continue;
|
|
3064
3118
|
const file = join3(directory, name);
|
|
3065
3119
|
try {
|
|
3066
3120
|
if (!statSync3(file).isFile())
|
|
3067
3121
|
continue;
|
|
3068
|
-
const raw = JSON.parse(
|
|
3122
|
+
const raw = JSON.parse(readFileSync7(file, "utf8"));
|
|
3069
3123
|
const inferredId = basename4(file).replace(FILE_TASK_PATTERN, "");
|
|
3070
3124
|
const id = isPlainRecord2(raw) && typeof raw.id === "string" ? raw.id : inferredId;
|
|
3071
3125
|
if (id === taskId) {
|
|
@@ -3225,8 +3279,8 @@ async function readConfiguredTaskSourceTask(projectRoot, taskId) {
|
|
|
3225
3279
|
}
|
|
3226
3280
|
|
|
3227
3281
|
// packages/runtime/src/control-plane/native/task-state.ts
|
|
3228
|
-
import { existsSync as
|
|
3229
|
-
import { basename as basename6, resolve as
|
|
3282
|
+
import { existsSync as existsSync18, readFileSync as readFileSync9, readdirSync as readdirSync3, statSync as statSync4, writeFileSync as writeFileSync7 } from "fs";
|
|
3283
|
+
import { basename as basename6, resolve as resolve18 } from "path";
|
|
3230
3284
|
|
|
3231
3285
|
// packages/runtime/src/control-plane/state-sync/types.ts
|
|
3232
3286
|
var SUPPORTED_TASK_STATE_SCHEMA_VERSION = 1;
|
|
@@ -3334,39 +3388,39 @@ function readTaskStateMetadataEnvelope(raw) {
|
|
|
3334
3388
|
};
|
|
3335
3389
|
}
|
|
3336
3390
|
// packages/runtime/src/control-plane/state-sync/read.ts
|
|
3337
|
-
import { existsSync as
|
|
3338
|
-
import { resolve as
|
|
3391
|
+
import { existsSync as existsSync17, readFileSync as readFileSync8 } from "fs";
|
|
3392
|
+
import { resolve as resolve17 } from "path";
|
|
3339
3393
|
|
|
3340
3394
|
// packages/runtime/src/control-plane/state-sync/repo.ts
|
|
3341
|
-
import { existsSync as
|
|
3342
|
-
import { resolve as
|
|
3395
|
+
import { existsSync as existsSync16 } from "fs";
|
|
3396
|
+
import { resolve as resolve16 } from "path";
|
|
3343
3397
|
|
|
3344
3398
|
// packages/runtime/src/control-plane/repos/layout.ts
|
|
3345
3399
|
init_layout();
|
|
3346
|
-
import { existsSync as
|
|
3347
|
-
import { basename as basename5, dirname as dirname9, join as join4, resolve as
|
|
3400
|
+
import { existsSync as existsSync15 } from "fs";
|
|
3401
|
+
import { basename as basename5, dirname as dirname9, join as join4, resolve as resolve15 } from "path";
|
|
3348
3402
|
function resolveRepoStateDir(projectRoot) {
|
|
3349
|
-
const normalizedProjectRoot =
|
|
3403
|
+
const normalizedProjectRoot = resolve15(projectRoot);
|
|
3350
3404
|
const projectParent = dirname9(normalizedProjectRoot);
|
|
3351
3405
|
if (basename5(projectParent) === ".worktrees") {
|
|
3352
3406
|
const ownerRoot = dirname9(projectParent);
|
|
3353
|
-
const ownerHasRepoMarkers =
|
|
3407
|
+
const ownerHasRepoMarkers = existsSync15(resolve15(ownerRoot, ".git")) || existsSync15(resolve15(ownerRoot, ".rig", "state"));
|
|
3354
3408
|
if (ownerHasRepoMarkers) {
|
|
3355
|
-
return
|
|
3409
|
+
return resolve15(ownerRoot, ".rig", "state");
|
|
3356
3410
|
}
|
|
3357
3411
|
}
|
|
3358
|
-
return
|
|
3412
|
+
return resolve15(projectRoot, ".rig", "state");
|
|
3359
3413
|
}
|
|
3360
3414
|
function resolveManagedRepoLayout(projectRoot, repoId) {
|
|
3361
|
-
const normalizedProjectRoot =
|
|
3415
|
+
const normalizedProjectRoot = resolve15(projectRoot);
|
|
3362
3416
|
const entry = getManagedRepoEntry(repoId);
|
|
3363
3417
|
const stateDir = resolveRepoStateDir(normalizedProjectRoot);
|
|
3364
3418
|
const metadataRelativePath = join4("repos", entry.id);
|
|
3365
|
-
const metadataRoot =
|
|
3419
|
+
const metadataRoot = resolve15(stateDir, metadataRelativePath);
|
|
3366
3420
|
const runtimeWorkspace = process.env.RIG_TASK_WORKSPACE?.trim();
|
|
3367
|
-
const runsInsideTaskWorktree = runtimeWorkspace &&
|
|
3421
|
+
const runsInsideTaskWorktree = runtimeWorkspace && resolve15(runtimeWorkspace) === normalizedProjectRoot || basename5(dirname9(normalizedProjectRoot)) === ".worktrees";
|
|
3368
3422
|
const isPrimaryManagedRepo = listManagedRepoEntries()[0]?.id === repoId;
|
|
3369
|
-
const checkoutRoot = isPrimaryManagedRepo && runsInsideTaskWorktree ? resolveMonorepoRoot(normalizedProjectRoot) : entry.checkoutEnvVar && process.env[entry.checkoutEnvVar]?.trim() ?
|
|
3423
|
+
const checkoutRoot = isPrimaryManagedRepo && runsInsideTaskWorktree ? resolveMonorepoRoot(normalizedProjectRoot) : entry.checkoutEnvVar && process.env[entry.checkoutEnvVar]?.trim() ? resolve15(process.env[entry.checkoutEnvVar].trim()) : resolve15(normalizedProjectRoot, entry.alias);
|
|
3370
3424
|
return {
|
|
3371
3425
|
projectRoot: normalizedProjectRoot,
|
|
3372
3426
|
repoId: entry.id,
|
|
@@ -3374,12 +3428,12 @@ function resolveManagedRepoLayout(projectRoot, repoId) {
|
|
|
3374
3428
|
defaultBranch: entry.defaultBranch,
|
|
3375
3429
|
remoteUrl: entry.remoteEnvVar && process.env[entry.remoteEnvVar]?.trim() ? process.env[entry.remoteEnvVar].trim() : entry.defaultRemoteUrl,
|
|
3376
3430
|
checkoutRoot,
|
|
3377
|
-
worktreesRoot:
|
|
3431
|
+
worktreesRoot: resolve15(checkoutRoot, ".worktrees"),
|
|
3378
3432
|
stateDir,
|
|
3379
3433
|
metadataRoot,
|
|
3380
3434
|
metadataRelativePath,
|
|
3381
|
-
mirrorRoot:
|
|
3382
|
-
mirrorStatePath:
|
|
3435
|
+
mirrorRoot: resolve15(metadataRoot, "mirror.git"),
|
|
3436
|
+
mirrorStatePath: resolve15(metadataRoot, "mirror-state.json"),
|
|
3383
3437
|
mirrorStateRelativePath: join4(metadataRelativePath, "mirror-state.json")
|
|
3384
3438
|
};
|
|
3385
3439
|
}
|
|
@@ -3397,7 +3451,7 @@ function resolveTrackerRepoPath(projectRoot) {
|
|
|
3397
3451
|
const monorepoRoot = resolveMonorepoRoot2(projectRoot);
|
|
3398
3452
|
try {
|
|
3399
3453
|
const layout = resolveMonorepoRepoLayout(projectRoot);
|
|
3400
|
-
if (
|
|
3454
|
+
if (existsSync16(resolve16(layout.mirrorRoot, "HEAD"))) {
|
|
3401
3455
|
return layout.mirrorRoot;
|
|
3402
3456
|
}
|
|
3403
3457
|
} catch {}
|
|
@@ -3408,8 +3462,8 @@ function resolveTrackerRepoPath(projectRoot) {
|
|
|
3408
3462
|
var DEFAULT_READ_DEPS2 = {
|
|
3409
3463
|
fetchRef: nativeFetchRef,
|
|
3410
3464
|
readBlobAtRef: nativeReadBlobAtRef,
|
|
3411
|
-
exists:
|
|
3412
|
-
readFile: (path) =>
|
|
3465
|
+
exists: existsSync17,
|
|
3466
|
+
readFile: (path) => readFileSync8(path, "utf8")
|
|
3413
3467
|
};
|
|
3414
3468
|
function parseIssueStatus(rawStatus) {
|
|
3415
3469
|
const normalized = normalizeTaskLifecycleStatus(rawStatus);
|
|
@@ -3490,12 +3544,12 @@ function shouldPreferLocalTrackerState(options) {
|
|
|
3490
3544
|
if (runtimeContextPath) {
|
|
3491
3545
|
return true;
|
|
3492
3546
|
}
|
|
3493
|
-
return
|
|
3547
|
+
return existsSync17(resolve17(runtimeWorkspace, ".rig", "runtime-context.json"));
|
|
3494
3548
|
}
|
|
3495
3549
|
function readLocalTrackerState(projectRoot, deps) {
|
|
3496
3550
|
const monorepoRoot = resolveMonorepoRoot2(projectRoot);
|
|
3497
|
-
const issuesPath =
|
|
3498
|
-
const taskStatePath =
|
|
3551
|
+
const issuesPath = resolve17(monorepoRoot, ".beads", "issues.jsonl");
|
|
3552
|
+
const taskStatePath = resolve17(monorepoRoot, ".beads", "task-state.json");
|
|
3499
3553
|
return projectSyncedTrackerSnapshot({
|
|
3500
3554
|
source: "local",
|
|
3501
3555
|
issuesBaseOid: null,
|
|
@@ -3557,7 +3611,7 @@ function readValidationDescriptions(projectRoot) {
|
|
|
3557
3611
|
return readValidationDescriptionMap(raw);
|
|
3558
3612
|
}
|
|
3559
3613
|
function readSourceValidationDescriptions(projectRoot) {
|
|
3560
|
-
const rootRaw = readJsonFile(
|
|
3614
|
+
const rootRaw = readJsonFile(resolve18(projectRoot, "rig", "task-config.json"), {});
|
|
3561
3615
|
const sourcePath = findSourceTaskConfigPath(projectRoot);
|
|
3562
3616
|
const sourceRaw = sourcePath ? readJsonFile(sourcePath, {}) : {};
|
|
3563
3617
|
const rootDescriptions = readValidationDescriptionMap(rootRaw);
|
|
@@ -3633,15 +3687,15 @@ function readValidationDescriptionsFromMeta(meta) {
|
|
|
3633
3687
|
return meta.validation_descriptions;
|
|
3634
3688
|
}
|
|
3635
3689
|
function readLocalSourceTaskStateEnvelope(projectRoot) {
|
|
3636
|
-
const taskStatePath =
|
|
3690
|
+
const taskStatePath = resolve18(resolveMonorepoRoot2(projectRoot), ".beads", "task-state.json");
|
|
3637
3691
|
return readTaskStateMetadataEnvelope(readJsonFile(taskStatePath, {}));
|
|
3638
3692
|
}
|
|
3639
3693
|
function readLocalSourceTaskLifecycleStatus(projectRoot, taskId) {
|
|
3640
|
-
const issuesPath =
|
|
3641
|
-
if (!
|
|
3694
|
+
const issuesPath = resolve18(resolveMonorepoRoot2(projectRoot), ".beads", "issues.jsonl");
|
|
3695
|
+
if (!existsSync18(issuesPath)) {
|
|
3642
3696
|
return null;
|
|
3643
3697
|
}
|
|
3644
|
-
for (const line of
|
|
3698
|
+
for (const line of readFileSync9(issuesPath, "utf8").split(/\r?\n/)) {
|
|
3645
3699
|
const trimmed = line.trim();
|
|
3646
3700
|
if (!trimmed) {
|
|
3647
3701
|
continue;
|
|
@@ -3666,25 +3720,25 @@ function inferTaskIdFromRuntimePath(path) {
|
|
|
3666
3720
|
function artifactDirForId(projectRoot, id) {
|
|
3667
3721
|
const workspaceDir = process.env.RIG_TASK_WORKSPACE?.trim();
|
|
3668
3722
|
if (workspaceDir) {
|
|
3669
|
-
const worktreeArtifacts =
|
|
3670
|
-
if (
|
|
3723
|
+
const worktreeArtifacts = resolve18(workspaceDir, "artifacts", id);
|
|
3724
|
+
if (existsSync18(worktreeArtifacts) || existsSync18(resolve18(workspaceDir, "artifacts"))) {
|
|
3671
3725
|
return worktreeArtifacts;
|
|
3672
3726
|
}
|
|
3673
3727
|
}
|
|
3674
3728
|
try {
|
|
3675
3729
|
const paths = resolveHarnessPaths(projectRoot);
|
|
3676
|
-
return
|
|
3730
|
+
return resolve18(paths.artifactsDir, id);
|
|
3677
3731
|
} catch {
|
|
3678
|
-
return
|
|
3732
|
+
return resolve18(resolveMonorepoRoot2(projectRoot), "artifacts", id);
|
|
3679
3733
|
}
|
|
3680
3734
|
}
|
|
3681
3735
|
function resolveTaskConfigPath(projectRoot) {
|
|
3682
3736
|
const paths = resolveHarnessPaths(projectRoot);
|
|
3683
|
-
if (
|
|
3737
|
+
if (existsSync18(paths.taskConfigPath)) {
|
|
3684
3738
|
return paths.taskConfigPath;
|
|
3685
3739
|
}
|
|
3686
3740
|
for (const candidate of sourceTaskConfigCandidates(projectRoot)) {
|
|
3687
|
-
if (
|
|
3741
|
+
if (existsSync18(candidate)) {
|
|
3688
3742
|
return candidate;
|
|
3689
3743
|
}
|
|
3690
3744
|
}
|
|
@@ -3692,7 +3746,7 @@ function resolveTaskConfigPath(projectRoot) {
|
|
|
3692
3746
|
}
|
|
3693
3747
|
function findSourceTaskConfigPath(projectRoot) {
|
|
3694
3748
|
for (const candidate of sourceTaskConfigCandidates(projectRoot)) {
|
|
3695
|
-
if (
|
|
3749
|
+
if (existsSync18(candidate)) {
|
|
3696
3750
|
return candidate;
|
|
3697
3751
|
}
|
|
3698
3752
|
}
|
|
@@ -3705,7 +3759,7 @@ function readAndSyncSourceTaskConfig(projectRoot) {
|
|
|
3705
3759
|
const synced = synchronizeTaskConfigWithTracker(projectRoot, raw);
|
|
3706
3760
|
if (sourcePath && synced.updated) {
|
|
3707
3761
|
try {
|
|
3708
|
-
|
|
3762
|
+
writeFileSync7(sourcePath, `${JSON.stringify(synced.config, null, 2)}
|
|
3709
3763
|
`, "utf-8");
|
|
3710
3764
|
} catch {}
|
|
3711
3765
|
}
|
|
@@ -3757,12 +3811,12 @@ function shouldRefreshAutoSyncedTaskConfigEntry(entry) {
|
|
|
3757
3811
|
return !candidate.role;
|
|
3758
3812
|
}
|
|
3759
3813
|
function readSourceIssueRecords(projectRoot) {
|
|
3760
|
-
const issuesPath =
|
|
3761
|
-
if (!
|
|
3814
|
+
const issuesPath = resolve18(resolveMonorepoRoot2(projectRoot), ".beads", "issues.jsonl");
|
|
3815
|
+
if (!existsSync18(issuesPath)) {
|
|
3762
3816
|
return [];
|
|
3763
3817
|
}
|
|
3764
3818
|
const records = [];
|
|
3765
|
-
for (const line of
|
|
3819
|
+
for (const line of readFileSync9(issuesPath, "utf-8").split(/\r?\n/)) {
|
|
3766
3820
|
const trimmed = line.trim();
|
|
3767
3821
|
if (!trimmed) {
|
|
3768
3822
|
continue;
|
|
@@ -3818,19 +3872,19 @@ function readConfiguredFileTaskConfig(projectRoot) {
|
|
|
3818
3872
|
if (!sourcePath) {
|
|
3819
3873
|
return {};
|
|
3820
3874
|
}
|
|
3821
|
-
const directory =
|
|
3822
|
-
if (!
|
|
3875
|
+
const directory = resolve18(projectRoot, sourcePath);
|
|
3876
|
+
if (!existsSync18(directory)) {
|
|
3823
3877
|
return {};
|
|
3824
3878
|
}
|
|
3825
3879
|
const config = {};
|
|
3826
|
-
for (const name of
|
|
3880
|
+
for (const name of readdirSync3(directory)) {
|
|
3827
3881
|
if (!FILE_TASK_PATTERN2.test(name))
|
|
3828
3882
|
continue;
|
|
3829
|
-
const file =
|
|
3883
|
+
const file = resolve18(directory, name);
|
|
3830
3884
|
try {
|
|
3831
3885
|
if (!statSync4(file).isFile())
|
|
3832
3886
|
continue;
|
|
3833
|
-
const raw = JSON.parse(
|
|
3887
|
+
const raw = JSON.parse(readFileSync9(file, "utf8"));
|
|
3834
3888
|
if (!raw || typeof raw !== "object" || Array.isArray(raw))
|
|
3835
3889
|
continue;
|
|
3836
3890
|
const record = raw;
|
|
@@ -3872,10 +3926,10 @@ function firstStringList2(...candidates) {
|
|
|
3872
3926
|
return [];
|
|
3873
3927
|
}
|
|
3874
3928
|
function readConfiguredFilesTaskSourcePath2(projectRoot) {
|
|
3875
|
-
const jsonPath =
|
|
3876
|
-
if (
|
|
3929
|
+
const jsonPath = resolve18(projectRoot, "rig.config.json");
|
|
3930
|
+
if (existsSync18(jsonPath)) {
|
|
3877
3931
|
try {
|
|
3878
|
-
const parsed = JSON.parse(
|
|
3932
|
+
const parsed = JSON.parse(readFileSync9(jsonPath, "utf8"));
|
|
3879
3933
|
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
3880
3934
|
const taskSource = parsed.taskSource;
|
|
3881
3935
|
if (taskSource && typeof taskSource === "object" && !Array.isArray(taskSource)) {
|
|
@@ -3887,12 +3941,12 @@ function readConfiguredFilesTaskSourcePath2(projectRoot) {
|
|
|
3887
3941
|
return null;
|
|
3888
3942
|
}
|
|
3889
3943
|
}
|
|
3890
|
-
const tsPath =
|
|
3891
|
-
if (!
|
|
3944
|
+
const tsPath = resolve18(projectRoot, "rig.config.ts");
|
|
3945
|
+
if (!existsSync18(tsPath)) {
|
|
3892
3946
|
return null;
|
|
3893
3947
|
}
|
|
3894
3948
|
try {
|
|
3895
|
-
const source =
|
|
3949
|
+
const source = readFileSync9(tsPath, "utf8");
|
|
3896
3950
|
const taskSourceBlock = source.match(/taskSource\s*:\s*\{[\s\S]*?\}/m)?.[0] ?? "";
|
|
3897
3951
|
const kind = taskSourceBlock.match(/kind\s*:\s*["']([^"']+)["']/)?.[1];
|
|
3898
3952
|
if (kind !== "files") {
|
|
@@ -3906,9 +3960,9 @@ function readConfiguredFilesTaskSourcePath2(projectRoot) {
|
|
|
3906
3960
|
function sourceTaskConfigCandidates(projectRoot) {
|
|
3907
3961
|
const runtimeContext = loadRuntimeContextFromEnv();
|
|
3908
3962
|
return [
|
|
3909
|
-
runtimeContext?.monorepoMainRoot ?
|
|
3910
|
-
process.env.MONOREPO_MAIN_ROOT?.trim() ?
|
|
3911
|
-
|
|
3963
|
+
runtimeContext?.monorepoMainRoot ? resolve18(runtimeContext.monorepoMainRoot, ".rig", "task-config.json") : "",
|
|
3964
|
+
process.env.MONOREPO_MAIN_ROOT?.trim() ? resolve18(process.env.MONOREPO_MAIN_ROOT.trim(), ".rig", "task-config.json") : "",
|
|
3965
|
+
resolve18(resolveMonorepoRoot2(projectRoot), ".rig", "task-config.json")
|
|
3912
3966
|
].filter(Boolean);
|
|
3913
3967
|
}
|
|
3914
3968
|
|
|
@@ -3917,8 +3971,8 @@ init_layout();
|
|
|
3917
3971
|
|
|
3918
3972
|
// packages/runtime/src/binary-run.ts
|
|
3919
3973
|
init_layout();
|
|
3920
|
-
import { chmodSync as chmodSync4, cpSync, existsSync as
|
|
3921
|
-
import { basename as basename7, dirname as dirname10, resolve as
|
|
3974
|
+
import { chmodSync as chmodSync4, cpSync, existsSync as existsSync19, mkdirSync as mkdirSync9, renameSync as renameSync3, rmSync as rmSync8, writeFileSync as writeFileSync8 } from "fs";
|
|
3975
|
+
import { basename as basename7, dirname as dirname10, resolve as resolve19 } from "path";
|
|
3922
3976
|
import { fileURLToPath } from "url";
|
|
3923
3977
|
import { drainMicrotasks, gcAndSweep } from "bun:jsc";
|
|
3924
3978
|
var runtimeBinaryBuildQueue = Promise.resolve();
|
|
@@ -3944,9 +3998,9 @@ async function buildRuntimeBinary(options) {
|
|
|
3944
3998
|
});
|
|
3945
3999
|
}
|
|
3946
4000
|
async function buildRuntimeBinaryInProcess(options, manifest) {
|
|
3947
|
-
const tempBuildDir =
|
|
3948
|
-
const tempOutputPath =
|
|
3949
|
-
|
|
4001
|
+
const tempBuildDir = resolve19(dirname10(options.outputPath), `.bun-build-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`);
|
|
4002
|
+
const tempOutputPath = resolve19(tempBuildDir, basename7(options.outputPath));
|
|
4003
|
+
mkdirSync9(tempBuildDir, { recursive: true });
|
|
3950
4004
|
await withTemporaryEnv({
|
|
3951
4005
|
...options.env,
|
|
3952
4006
|
...options.define ? { RIG_BUILD_CONFIG_JSON: JSON.stringify(options.define) } : {}
|
|
@@ -3971,7 +4025,7 @@ async function buildRuntimeBinaryInProcess(options, manifest) {
|
|
|
3971
4025
|
`);
|
|
3972
4026
|
throw new Error(`Failed to build ${options.entrypoint}: ${details || "Bun.build() returned errors"}`);
|
|
3973
4027
|
}
|
|
3974
|
-
if (!
|
|
4028
|
+
if (!existsSync19(tempOutputPath)) {
|
|
3975
4029
|
const emitted = buildResult.outputs.map((output) => output.path).join(", ") || "(none)";
|
|
3976
4030
|
throw new Error(`Failed to build ${options.entrypoint}: Bun.build() did not emit ${tempOutputPath}. Emitted: ${emitted}`);
|
|
3977
4031
|
}
|
|
@@ -3986,7 +4040,7 @@ async function buildRuntimeBinaryInProcess(options, manifest) {
|
|
|
3986
4040
|
});
|
|
3987
4041
|
}
|
|
3988
4042
|
})).finally(() => {
|
|
3989
|
-
|
|
4043
|
+
rmSync8(tempBuildDir, { recursive: true, force: true });
|
|
3990
4044
|
});
|
|
3991
4045
|
}
|
|
3992
4046
|
function runBestEffortBuildGc() {
|
|
@@ -4003,8 +4057,8 @@ function runtimeBinaryCacheManifestPath(outputPath) {
|
|
|
4003
4057
|
function resolveRuntimeBinaryBuildOptions(options) {
|
|
4004
4058
|
return {
|
|
4005
4059
|
...options,
|
|
4006
|
-
entrypoint:
|
|
4007
|
-
outputPath:
|
|
4060
|
+
entrypoint: resolve19(options.cwd, options.sourcePath),
|
|
4061
|
+
outputPath: resolve19(options.outputPath)
|
|
4008
4062
|
};
|
|
4009
4063
|
}
|
|
4010
4064
|
function shouldUseRuntimeBinaryBuildWorker() {
|
|
@@ -4018,7 +4072,7 @@ function shouldUseRuntimeBinaryBuildWorker() {
|
|
|
4018
4072
|
}
|
|
4019
4073
|
async function buildRuntimeBinaryViaWorker(options) {
|
|
4020
4074
|
const workerSourcePath = resolveRuntimeBinaryBuildWorkerSourcePath(options);
|
|
4021
|
-
if (!workerSourcePath || !
|
|
4075
|
+
if (!workerSourcePath || !existsSync19(workerSourcePath)) {
|
|
4022
4076
|
await buildRuntimeBinaryInProcess(options, {
|
|
4023
4077
|
manifestPath: runtimeBinaryCacheManifestPath(options.outputPath),
|
|
4024
4078
|
buildKey: createRuntimeBinaryBuildKey({
|
|
@@ -4049,13 +4103,13 @@ async function buildRuntimeBinaryViaWorker(options) {
|
|
|
4049
4103
|
new Response(build.stdout).text(),
|
|
4050
4104
|
new Response(build.stderr).text()
|
|
4051
4105
|
]);
|
|
4052
|
-
|
|
4106
|
+
rmSync8(payloadPath, { force: true });
|
|
4053
4107
|
if (exitCode !== 0) {
|
|
4054
4108
|
throw new Error(`Failed to build ${options.entrypoint}: ${(stderr || stdout || `worker exited ${exitCode}`).trim()}`);
|
|
4055
4109
|
}
|
|
4056
4110
|
}
|
|
4057
4111
|
function createRuntimeBinaryBuildWorkerPayloadPath(outputPath) {
|
|
4058
|
-
return
|
|
4112
|
+
return resolve19(dirname10(outputPath), `.bun-build-worker-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}.json`);
|
|
4059
4113
|
}
|
|
4060
4114
|
function resolveRuntimeBinaryBuildWorkerSourcePath(options) {
|
|
4061
4115
|
const envRoots = [
|
|
@@ -4064,13 +4118,13 @@ function resolveRuntimeBinaryBuildWorkerSourcePath(options) {
|
|
|
4064
4118
|
process.env.PROJECT_RIG_ROOT?.trim()
|
|
4065
4119
|
].filter(Boolean);
|
|
4066
4120
|
for (const root of envRoots) {
|
|
4067
|
-
const candidate =
|
|
4068
|
-
if (
|
|
4121
|
+
const candidate = resolve19(root, "packages/runtime/src/binary-build-worker.ts");
|
|
4122
|
+
if (existsSync19(candidate)) {
|
|
4069
4123
|
return candidate;
|
|
4070
4124
|
}
|
|
4071
4125
|
}
|
|
4072
|
-
const localCandidate =
|
|
4073
|
-
return
|
|
4126
|
+
const localCandidate = resolve19(import.meta.dir, "binary-build-worker.ts");
|
|
4127
|
+
return existsSync19(localCandidate) ? localCandidate : null;
|
|
4074
4128
|
}
|
|
4075
4129
|
function resolveRuntimeBinaryBuildWorkerInvocation() {
|
|
4076
4130
|
const bunPath = Bun.which("bun");
|
|
@@ -4106,7 +4160,7 @@ function createRuntimeBinaryBuildKey(input) {
|
|
|
4106
4160
|
});
|
|
4107
4161
|
}
|
|
4108
4162
|
async function isRuntimeBinaryBuildFresh(input) {
|
|
4109
|
-
if (!
|
|
4163
|
+
if (!existsSync19(input.outputPath) || !existsSync19(input.manifestPath)) {
|
|
4110
4164
|
return false;
|
|
4111
4165
|
}
|
|
4112
4166
|
let manifest = null;
|
|
@@ -4119,7 +4173,7 @@ async function isRuntimeBinaryBuildFresh(input) {
|
|
|
4119
4173
|
return false;
|
|
4120
4174
|
}
|
|
4121
4175
|
for (const [filePath, expectedDigest] of Object.entries(manifest.inputs || {})) {
|
|
4122
|
-
if (!
|
|
4176
|
+
if (!existsSync19(filePath)) {
|
|
4123
4177
|
return false;
|
|
4124
4178
|
}
|
|
4125
4179
|
if (await sha256File4(filePath) !== expectedDigest) {
|
|
@@ -4132,7 +4186,7 @@ async function writeRuntimeBinaryCacheManifest(input) {
|
|
|
4132
4186
|
const inputs = {};
|
|
4133
4187
|
for (const inputPath of Object.keys(input.metafile?.inputs || {}).sort()) {
|
|
4134
4188
|
const normalized = normalizeBuildInputPath(input.cwd, inputPath);
|
|
4135
|
-
if (!normalized || !
|
|
4189
|
+
if (!normalized || !existsSync19(normalized)) {
|
|
4136
4190
|
continue;
|
|
4137
4191
|
}
|
|
4138
4192
|
inputs[normalized] = await sha256File4(normalized);
|
|
@@ -4155,7 +4209,7 @@ function normalizeBuildInputPath(cwd, inputPath) {
|
|
|
4155
4209
|
if (inputPath.startsWith("<")) {
|
|
4156
4210
|
return null;
|
|
4157
4211
|
}
|
|
4158
|
-
return
|
|
4212
|
+
return resolve19(cwd, inputPath);
|
|
4159
4213
|
}
|
|
4160
4214
|
async function sha256File4(path) {
|
|
4161
4215
|
const hasher = new Bun.CryptoHasher("sha256");
|
|
@@ -4171,8 +4225,8 @@ function sortRecord(value) {
|
|
|
4171
4225
|
async function runSerializedRuntimeBinaryBuild(action) {
|
|
4172
4226
|
const previous = runtimeBinaryBuildQueue;
|
|
4173
4227
|
let release;
|
|
4174
|
-
runtimeBinaryBuildQueue = new Promise((
|
|
4175
|
-
release =
|
|
4228
|
+
runtimeBinaryBuildQueue = new Promise((resolve20) => {
|
|
4229
|
+
release = resolve20;
|
|
4176
4230
|
});
|
|
4177
4231
|
await previous;
|
|
4178
4232
|
try {
|
|
@@ -4217,11 +4271,11 @@ async function withTemporaryCwd(cwd, action) {
|
|
|
4217
4271
|
}
|
|
4218
4272
|
|
|
4219
4273
|
// packages/runtime/src/control-plane/runtime/provisioning-env.ts
|
|
4220
|
-
import { delimiter, resolve as
|
|
4274
|
+
import { delimiter, resolve as resolve22 } from "path";
|
|
4221
4275
|
|
|
4222
4276
|
// packages/runtime/src/control-plane/runtime/runtime-paths.ts
|
|
4223
|
-
import { existsSync as
|
|
4224
|
-
import { resolve as
|
|
4277
|
+
import { existsSync as existsSync21, readdirSync as readdirSync5, realpathSync as realpathSync2 } from "fs";
|
|
4278
|
+
import { resolve as resolve21 } from "path";
|
|
4225
4279
|
|
|
4226
4280
|
// packages/runtime/src/control-plane/runtime/sandbox-utils.ts
|
|
4227
4281
|
init_utils();
|
|
@@ -4238,7 +4292,7 @@ function resolveBunBinaryPath() {
|
|
|
4238
4292
|
}
|
|
4239
4293
|
const home = process.env.HOME?.trim();
|
|
4240
4294
|
const fallbackCandidates = [
|
|
4241
|
-
home ?
|
|
4295
|
+
home ? resolve21(home, ".bun/bin/bun") : "",
|
|
4242
4296
|
"/opt/homebrew/bin/bun",
|
|
4243
4297
|
"/usr/local/bin/bun",
|
|
4244
4298
|
"/usr/bin/bun"
|
|
@@ -4266,8 +4320,8 @@ function resolveClaudeBinaryPath() {
|
|
|
4266
4320
|
}
|
|
4267
4321
|
const home = process.env.HOME?.trim();
|
|
4268
4322
|
const fallbackCandidates = [
|
|
4269
|
-
home ?
|
|
4270
|
-
home ?
|
|
4323
|
+
home ? resolve21(home, ".local/bin/claude") : "",
|
|
4324
|
+
home ? resolve21(home, ".local/share/claude/local/claude") : "",
|
|
4271
4325
|
"/opt/homebrew/bin/claude",
|
|
4272
4326
|
"/usr/local/bin/claude",
|
|
4273
4327
|
"/usr/bin/claude"
|
|
@@ -4281,35 +4335,35 @@ function resolveClaudeBinaryPath() {
|
|
|
4281
4335
|
throw new Error("claude not found in PATH");
|
|
4282
4336
|
}
|
|
4283
4337
|
function resolveBunInstallDir(bunBinaryPath = resolveBunBinaryPath()) {
|
|
4284
|
-
return
|
|
4338
|
+
return resolve21(bunBinaryPath, "../..");
|
|
4285
4339
|
}
|
|
4286
4340
|
function resolveClaudeInstallDir() {
|
|
4287
4341
|
const realPath = resolveClaudeBinaryPath();
|
|
4288
|
-
return
|
|
4342
|
+
return resolve21(realPath, "..");
|
|
4289
4343
|
}
|
|
4290
4344
|
function resolveNodeInstallDir() {
|
|
4291
4345
|
const preferredNode = resolvePreferredNodeBinary();
|
|
4292
4346
|
if (!preferredNode)
|
|
4293
4347
|
return null;
|
|
4294
4348
|
const explicitNode = process.env.RIG_NODE_BIN?.trim();
|
|
4295
|
-
if (explicitNode &&
|
|
4296
|
-
return preferredNode.endsWith("/bin/node") ?
|
|
4349
|
+
if (explicitNode && resolve21(explicitNode) === resolve21(preferredNode)) {
|
|
4350
|
+
return preferredNode.endsWith("/bin/node") ? resolve21(preferredNode, "../..") : resolve21(preferredNode, "..");
|
|
4297
4351
|
}
|
|
4298
4352
|
try {
|
|
4299
4353
|
const realPath = realpathSync2(preferredNode);
|
|
4300
4354
|
if (realPath.endsWith("/bin/node")) {
|
|
4301
|
-
return
|
|
4355
|
+
return resolve21(realPath, "../..");
|
|
4302
4356
|
}
|
|
4303
|
-
return
|
|
4357
|
+
return resolve21(realPath, "..");
|
|
4304
4358
|
} catch {
|
|
4305
|
-
return
|
|
4359
|
+
return resolve21(preferredNode, "..");
|
|
4306
4360
|
}
|
|
4307
4361
|
}
|
|
4308
4362
|
function resolveRuntimeDependencyRoots(runtimeDirs) {
|
|
4309
4363
|
const roots = [];
|
|
4310
4364
|
if (process.platform === "darwin") {
|
|
4311
4365
|
for (const macPath of ["/opt/homebrew", "/opt/homebrew/opt"]) {
|
|
4312
|
-
if (
|
|
4366
|
+
if (existsSync21(macPath)) {
|
|
4313
4367
|
roots.push(macPath);
|
|
4314
4368
|
}
|
|
4315
4369
|
}
|
|
@@ -4327,23 +4381,23 @@ function resolvePreferredNodeBinary() {
|
|
|
4327
4381
|
const candidates = [];
|
|
4328
4382
|
const envNode = process.env.RIG_NODE_BIN?.trim();
|
|
4329
4383
|
if (envNode) {
|
|
4330
|
-
const explicit =
|
|
4331
|
-
if (
|
|
4384
|
+
const explicit = resolve21(envNode);
|
|
4385
|
+
if (existsSync21(explicit)) {
|
|
4332
4386
|
return explicit;
|
|
4333
4387
|
}
|
|
4334
4388
|
}
|
|
4335
4389
|
const nvmBin = process.env.NVM_BIN?.trim();
|
|
4336
4390
|
if (nvmBin) {
|
|
4337
|
-
candidates.push(
|
|
4391
|
+
candidates.push(resolve21(nvmBin, "node"));
|
|
4338
4392
|
}
|
|
4339
4393
|
const home = process.env.HOME?.trim();
|
|
4340
4394
|
if (home) {
|
|
4341
|
-
const nvmVersionsDir =
|
|
4342
|
-
if (
|
|
4395
|
+
const nvmVersionsDir = resolve21(home, ".nvm/versions/node");
|
|
4396
|
+
if (existsSync21(nvmVersionsDir)) {
|
|
4343
4397
|
try {
|
|
4344
|
-
const versionDirs =
|
|
4398
|
+
const versionDirs = readdirSync5(nvmVersionsDir).map((entry) => entry.trim()).filter((entry) => /^v\d+\.\d+\.\d+$/.test(entry)).sort((a, b) => Bun.semver.order(b.replace(/^v/, ""), a.replace(/^v/, "")));
|
|
4345
4399
|
for (const versionDir of versionDirs) {
|
|
4346
|
-
candidates.push(
|
|
4400
|
+
candidates.push(resolve21(nvmVersionsDir, versionDir, "bin/node"));
|
|
4347
4401
|
}
|
|
4348
4402
|
} catch {}
|
|
4349
4403
|
}
|
|
@@ -4352,8 +4406,8 @@ function resolvePreferredNodeBinary() {
|
|
|
4352
4406
|
if (whichNode) {
|
|
4353
4407
|
candidates.push(whichNode);
|
|
4354
4408
|
}
|
|
4355
|
-
const deduped = uniq(candidates.map((candidate) =>
|
|
4356
|
-
const existing = deduped.filter((candidate) =>
|
|
4409
|
+
const deduped = uniq(candidates.map((candidate) => resolve21(candidate)));
|
|
4410
|
+
const existing = deduped.filter((candidate) => existsSync21(candidate));
|
|
4357
4411
|
if (existing.length === 0) {
|
|
4358
4412
|
return null;
|
|
4359
4413
|
}
|
|
@@ -4367,7 +4421,7 @@ function resolvePreferredNodeBinary() {
|
|
|
4367
4421
|
return existing[0] ?? null;
|
|
4368
4422
|
}
|
|
4369
4423
|
function inferNodeMajor(nodeBinaryPath) {
|
|
4370
|
-
const normalized =
|
|
4424
|
+
const normalized = resolve21(nodeBinaryPath).replace(/\\/g, "/");
|
|
4371
4425
|
const match = normalized.match(/(?:^|\/)(?:node-)?v?(\d+)\.\d+\.\d+(?:\/|$)/);
|
|
4372
4426
|
if (!match) {
|
|
4373
4427
|
return null;
|
|
@@ -4379,8 +4433,8 @@ function normalizeExecutablePath(candidate) {
|
|
|
4379
4433
|
if (!candidate) {
|
|
4380
4434
|
return "";
|
|
4381
4435
|
}
|
|
4382
|
-
const normalized =
|
|
4383
|
-
if (!
|
|
4436
|
+
const normalized = resolve21(candidate);
|
|
4437
|
+
if (!existsSync21(normalized)) {
|
|
4384
4438
|
return "";
|
|
4385
4439
|
}
|
|
4386
4440
|
try {
|
|
@@ -4390,7 +4444,7 @@ function normalizeExecutablePath(candidate) {
|
|
|
4390
4444
|
}
|
|
4391
4445
|
}
|
|
4392
4446
|
function looksLikeRuntimeGateway(candidate) {
|
|
4393
|
-
const normalized =
|
|
4447
|
+
const normalized = resolve21(candidate).replace(/\\/g, "/");
|
|
4394
4448
|
return normalized.includes("/.rig/bin/") || normalized.endsWith("/rig-shell") || normalized.endsWith("/rig-agent");
|
|
4395
4449
|
}
|
|
4396
4450
|
|
|
@@ -4411,7 +4465,7 @@ function runtimeProvisioningEnv(baseEnv = process.env) {
|
|
|
4411
4465
|
try {
|
|
4412
4466
|
return resolveClaudeInstallDir();
|
|
4413
4467
|
} catch {
|
|
4414
|
-
return
|
|
4468
|
+
return resolve22(claudeBinary, "..");
|
|
4415
4469
|
}
|
|
4416
4470
|
})() : "";
|
|
4417
4471
|
const nodeDir = resolveNodeInstallDir();
|
|
@@ -4421,8 +4475,8 @@ function runtimeProvisioningEnv(baseEnv = process.env) {
|
|
|
4421
4475
|
`${bunDir}/bin`,
|
|
4422
4476
|
claudeDir,
|
|
4423
4477
|
nodeDir ? `${nodeDir}/bin` : "",
|
|
4424
|
-
realHome ?
|
|
4425
|
-
realHome ?
|
|
4478
|
+
realHome ? resolve22(realHome, ".local/bin") : "",
|
|
4479
|
+
realHome ? resolve22(realHome, ".cargo/bin") : "",
|
|
4426
4480
|
...inheritedPath,
|
|
4427
4481
|
"/usr/local/bin",
|
|
4428
4482
|
"/usr/local/sbin",
|
|
@@ -4451,8 +4505,8 @@ function runtimeProvisioningEnv(baseEnv = process.env) {
|
|
|
4451
4505
|
}
|
|
4452
4506
|
|
|
4453
4507
|
// packages/runtime/src/control-plane/runtime/baked-secrets.ts
|
|
4454
|
-
import { existsSync as
|
|
4455
|
-
import { resolve as
|
|
4508
|
+
import { existsSync as existsSync22, readFileSync as readFileSync10 } from "fs";
|
|
4509
|
+
import { resolve as resolve23 } from "path";
|
|
4456
4510
|
var BAKED_RUNTIME_SECRETS = {
|
|
4457
4511
|
ANTHROPIC_API_KEY: typeof RIG_BAKED_ANTHROPIC_API_KEY !== "undefined" ? RIG_BAKED_ANTHROPIC_API_KEY : "",
|
|
4458
4512
|
OPENAI_API_KEY: typeof RIG_BAKED_OPENAI_API_KEY !== "undefined" ? RIG_BAKED_OPENAI_API_KEY : "",
|
|
@@ -4495,12 +4549,12 @@ function resolveRuntimeSecrets(env, baked = BAKED_RUNTIME_SECRETS) {
|
|
|
4495
4549
|
return resolved;
|
|
4496
4550
|
}
|
|
4497
4551
|
function loadDotEnvSecrets(projectRoot, env = process.env) {
|
|
4498
|
-
const dotenvPath =
|
|
4499
|
-
if (!
|
|
4552
|
+
const dotenvPath = resolve23(projectRoot, ".env");
|
|
4553
|
+
if (!existsSync22(dotenvPath)) {
|
|
4500
4554
|
return {};
|
|
4501
4555
|
}
|
|
4502
4556
|
const parsed = {};
|
|
4503
|
-
const lines =
|
|
4557
|
+
const lines = readFileSync10(dotenvPath, "utf-8").split(/\r?\n/);
|
|
4504
4558
|
for (const rawLine of lines) {
|
|
4505
4559
|
const line = rawLine.trim();
|
|
4506
4560
|
if (!line || line.startsWith("#")) {
|
|
@@ -4857,16 +4911,16 @@ async function taskDeps(projectRoot, taskId) {
|
|
|
4857
4911
|
for (const dep of deps) {
|
|
4858
4912
|
const artifactDir = artifactDirForId(projectRoot, dep);
|
|
4859
4913
|
console.log(`=== ${dep} ===`);
|
|
4860
|
-
if (!
|
|
4914
|
+
if (!existsSync23(artifactDir)) {
|
|
4861
4915
|
console.log(` (no artifacts yet)
|
|
4862
4916
|
`);
|
|
4863
4917
|
continue;
|
|
4864
4918
|
}
|
|
4865
|
-
printArtifactSection(
|
|
4866
|
-
printArtifactSection(
|
|
4867
|
-
const changedFiles =
|
|
4868
|
-
if (
|
|
4869
|
-
const lines =
|
|
4919
|
+
printArtifactSection(resolve24(artifactDir, "decision-log.md"), "--- Decisions ---");
|
|
4920
|
+
printArtifactSection(resolve24(artifactDir, "next-actions.md"), "--- Next Actions (for you) ---");
|
|
4921
|
+
const changedFiles = resolve24(artifactDir, "changed-files.txt");
|
|
4922
|
+
if (existsSync23(changedFiles)) {
|
|
4923
|
+
const lines = readFileSync11(changedFiles, "utf-8").split(/\r?\n/).filter(Boolean);
|
|
4870
4924
|
console.log(`--- Changed Files (${lines.length}) ---`);
|
|
4871
4925
|
for (const line of lines) {
|
|
4872
4926
|
console.log(line);
|
|
@@ -4990,12 +5044,12 @@ function printIndented(text) {
|
|
|
4990
5044
|
}
|
|
4991
5045
|
}
|
|
4992
5046
|
function readLocalBeadsTasks(projectRoot) {
|
|
4993
|
-
const issuesPath =
|
|
4994
|
-
if (!
|
|
5047
|
+
const issuesPath = resolve24(resolveMonorepoRoot2(projectRoot), ".beads/issues.jsonl");
|
|
5048
|
+
if (!existsSync23(issuesPath)) {
|
|
4995
5049
|
return [];
|
|
4996
5050
|
}
|
|
4997
5051
|
const tasks = [];
|
|
4998
|
-
for (const line of
|
|
5052
|
+
for (const line of readFileSync11(issuesPath, "utf-8").split(/\r?\n/)) {
|
|
4999
5053
|
const trimmed = line.trim();
|
|
5000
5054
|
if (!trimmed) {
|
|
5001
5055
|
continue;
|
|
@@ -5108,11 +5162,11 @@ function taskDependencies(projectRoot, taskId, tracker) {
|
|
|
5108
5162
|
return [...ids].sort();
|
|
5109
5163
|
}
|
|
5110
5164
|
function printArtifactSection(path, header) {
|
|
5111
|
-
if (!
|
|
5165
|
+
if (!existsSync23(path)) {
|
|
5112
5166
|
return;
|
|
5113
5167
|
}
|
|
5114
5168
|
console.log(header);
|
|
5115
|
-
process.stdout.write(
|
|
5169
|
+
process.stdout.write(readFileSync11(path, "utf-8"));
|
|
5116
5170
|
console.log("");
|
|
5117
5171
|
}
|
|
5118
5172
|
|
|
@@ -5214,7 +5268,7 @@ init_layout();
|
|
|
5214
5268
|
|
|
5215
5269
|
// packages/runtime/src/control-plane/runtime/overlay.ts
|
|
5216
5270
|
init_layout();
|
|
5217
|
-
import { mkdirSync as
|
|
5271
|
+
import { mkdirSync as mkdirSync11 } from "fs";
|
|
5218
5272
|
function ensureRuntimeOverlay(projectRoot, runtimeId, workspaceDir) {
|
|
5219
5273
|
const layout = resolveRuntimeWorkspaceLayout(workspaceDir ?? projectRoot);
|
|
5220
5274
|
const rootDir = layout.rigRoot;
|
|
@@ -5226,14 +5280,14 @@ function ensureRuntimeOverlay(projectRoot, runtimeId, workspaceDir) {
|
|
|
5226
5280
|
const sessionDir = layout.sessionDir;
|
|
5227
5281
|
const runtimeDir = layout.runtimeDir;
|
|
5228
5282
|
const contextPath = layout.contextPath;
|
|
5229
|
-
|
|
5230
|
-
|
|
5231
|
-
|
|
5232
|
-
|
|
5233
|
-
|
|
5234
|
-
|
|
5235
|
-
|
|
5236
|
-
|
|
5283
|
+
mkdirSync11(rootDir, { recursive: true });
|
|
5284
|
+
mkdirSync11(homeDir, { recursive: true });
|
|
5285
|
+
mkdirSync11(tmpDir, { recursive: true });
|
|
5286
|
+
mkdirSync11(cacheDir, { recursive: true });
|
|
5287
|
+
mkdirSync11(logsDir, { recursive: true });
|
|
5288
|
+
mkdirSync11(stateDir, { recursive: true });
|
|
5289
|
+
mkdirSync11(sessionDir, { recursive: true });
|
|
5290
|
+
mkdirSync11(runtimeDir, { recursive: true });
|
|
5237
5291
|
return {
|
|
5238
5292
|
rootDir,
|
|
5239
5293
|
homeDir,
|
|
@@ -5251,17 +5305,17 @@ import {
|
|
|
5251
5305
|
chmodSync as chmodSync5,
|
|
5252
5306
|
copyFileSync as copyFileSync5,
|
|
5253
5307
|
cpSync as cpSync2,
|
|
5254
|
-
existsSync as
|
|
5255
|
-
mkdirSync as
|
|
5308
|
+
existsSync as existsSync25,
|
|
5309
|
+
mkdirSync as mkdirSync12,
|
|
5256
5310
|
statSync as statSync5,
|
|
5257
|
-
writeFileSync as
|
|
5311
|
+
writeFileSync as writeFileSync10
|
|
5258
5312
|
} from "fs";
|
|
5259
5313
|
import { mkdir } from "fs/promises";
|
|
5260
|
-
import { basename as basename8, delimiter as delimiter2, resolve as
|
|
5314
|
+
import { basename as basename8, delimiter as delimiter2, resolve as resolve26 } from "path";
|
|
5261
5315
|
|
|
5262
5316
|
// packages/runtime/src/control-plane/runtime/isolation/shared.ts
|
|
5263
|
-
import { existsSync as
|
|
5264
|
-
import { resolve as
|
|
5317
|
+
import { existsSync as existsSync24, readFileSync as readFileSync12, rmSync as rmSync9 } from "fs";
|
|
5318
|
+
import { resolve as resolve25 } from "path";
|
|
5265
5319
|
import { randomUUID } from "crypto";
|
|
5266
5320
|
var generatedCredentialFiles = new Set;
|
|
5267
5321
|
var credentialCleanupRegistered = false;
|
|
@@ -5286,7 +5340,7 @@ function resolveHostGitBinary() {
|
|
|
5286
5340
|
if (!candidate || isRuntimeGatewayGitPath(candidate)) {
|
|
5287
5341
|
continue;
|
|
5288
5342
|
}
|
|
5289
|
-
if (
|
|
5343
|
+
if (existsSync24(candidate)) {
|
|
5290
5344
|
return candidate;
|
|
5291
5345
|
}
|
|
5292
5346
|
}
|
|
@@ -5352,7 +5406,7 @@ async function refreshRemoteBranch(repoRoot, remote, branch) {
|
|
|
5352
5406
|
}
|
|
5353
5407
|
}
|
|
5354
5408
|
async function tryReadGitHead(repoRoot) {
|
|
5355
|
-
if (!
|
|
5409
|
+
if (!existsSync24(resolve25(repoRoot, ".git"))) {
|
|
5356
5410
|
return;
|
|
5357
5411
|
}
|
|
5358
5412
|
const result = await runGitCommand(repoRoot, ["rev-parse", "HEAD"]);
|
|
@@ -5363,7 +5417,7 @@ async function tryReadGitHead(repoRoot) {
|
|
|
5363
5417
|
return value || undefined;
|
|
5364
5418
|
}
|
|
5365
5419
|
async function captureRepoDirtyFiles(repoRoot) {
|
|
5366
|
-
if (!
|
|
5420
|
+
if (!existsSync24(resolve25(repoRoot, ".git"))) {
|
|
5367
5421
|
return [];
|
|
5368
5422
|
}
|
|
5369
5423
|
const files = new Set;
|
|
@@ -5399,7 +5453,7 @@ function registerCredentialCleanup(path) {
|
|
|
5399
5453
|
const cleanup = () => {
|
|
5400
5454
|
for (const filePath of generatedCredentialFiles) {
|
|
5401
5455
|
try {
|
|
5402
|
-
|
|
5456
|
+
rmSync9(filePath, { force: true });
|
|
5403
5457
|
} catch {}
|
|
5404
5458
|
}
|
|
5405
5459
|
generatedCredentialFiles.clear();
|
|
@@ -5454,16 +5508,16 @@ function hashProjectPath(workspaceDir) {
|
|
|
5454
5508
|
}
|
|
5455
5509
|
function resolveGithubCliBinaryPath() {
|
|
5456
5510
|
const explicit = process.env.RIG_GH_BIN?.trim();
|
|
5457
|
-
if (explicit &&
|
|
5511
|
+
if (explicit && existsSync24(explicit) && !isRuntimeGatewayGhPath(explicit)) {
|
|
5458
5512
|
return explicit;
|
|
5459
5513
|
}
|
|
5460
5514
|
for (const candidate of ["/usr/bin/gh", "/opt/homebrew/bin/gh", "/usr/local/bin/gh"]) {
|
|
5461
|
-
if (
|
|
5515
|
+
if (existsSync24(candidate)) {
|
|
5462
5516
|
return candidate;
|
|
5463
5517
|
}
|
|
5464
5518
|
}
|
|
5465
5519
|
const bunResolved = Bun.which("gh");
|
|
5466
|
-
if (bunResolved &&
|
|
5520
|
+
if (bunResolved && existsSync24(bunResolved) && !isRuntimeGatewayGhPath(bunResolved)) {
|
|
5467
5521
|
return bunResolved;
|
|
5468
5522
|
}
|
|
5469
5523
|
return "";
|
|
@@ -5497,17 +5551,17 @@ function resolveSystemCertBundlePath() {
|
|
|
5497
5551
|
"/opt/homebrew/etc/openssl@3/cert.pem"
|
|
5498
5552
|
];
|
|
5499
5553
|
for (const candidate of candidates) {
|
|
5500
|
-
if (candidate &&
|
|
5501
|
-
return
|
|
5554
|
+
if (candidate && existsSync24(candidate)) {
|
|
5555
|
+
return resolve25(candidate);
|
|
5502
5556
|
}
|
|
5503
5557
|
}
|
|
5504
5558
|
return "";
|
|
5505
5559
|
}
|
|
5506
5560
|
function readKnownHosts(path) {
|
|
5507
|
-
if (!
|
|
5561
|
+
if (!existsSync24(path)) {
|
|
5508
5562
|
return new Set;
|
|
5509
5563
|
}
|
|
5510
|
-
return new Set(
|
|
5564
|
+
return new Set(readFileSync12(path, "utf-8").split(/\r?\n/).map((line) => line.trim()).filter(Boolean));
|
|
5511
5565
|
}
|
|
5512
5566
|
|
|
5513
5567
|
// packages/runtime/src/control-plane/runtime/isolation/home.ts
|
|
@@ -5522,12 +5576,12 @@ function resolveControlPlaneSourceRoot(projectRoot) {
|
|
|
5522
5576
|
const candidates = [
|
|
5523
5577
|
process.env.RIG_CONTROL_PLANE_SOURCE_ROOT?.trim(),
|
|
5524
5578
|
process.env.RIG_HOST_PROJECT_ROOT?.trim(),
|
|
5525
|
-
|
|
5579
|
+
resolve26(import.meta.dir, "../../../../.."),
|
|
5526
5580
|
projectRoot
|
|
5527
5581
|
].filter((value) => Boolean(value));
|
|
5528
5582
|
for (const candidate of candidates) {
|
|
5529
|
-
const root =
|
|
5530
|
-
if (
|
|
5583
|
+
const root = resolve26(candidate);
|
|
5584
|
+
if (existsSync25(resolve26(root, "packages/runtime/src/control-plane/pi-sessiond/bin.ts"))) {
|
|
5531
5585
|
return root;
|
|
5532
5586
|
}
|
|
5533
5587
|
}
|
|
@@ -5547,7 +5601,7 @@ async function runtimeEnv(projectRoot, runtime) {
|
|
|
5547
5601
|
try {
|
|
5548
5602
|
return resolveClaudeInstallDir();
|
|
5549
5603
|
} catch {
|
|
5550
|
-
return
|
|
5604
|
+
return resolve26(claudeBinaryPath, "..");
|
|
5551
5605
|
}
|
|
5552
5606
|
})() : "";
|
|
5553
5607
|
const nodeDir = resolveNodeInstallDir();
|
|
@@ -5562,8 +5616,8 @@ async function runtimeEnv(projectRoot, runtime) {
|
|
|
5562
5616
|
`${bunDir}/bin`,
|
|
5563
5617
|
claudeDir,
|
|
5564
5618
|
nodeDir ? `${nodeDir}/bin` : "",
|
|
5565
|
-
realHome ?
|
|
5566
|
-
realHome ?
|
|
5619
|
+
realHome ? resolve26(realHome, ".local/bin") : "",
|
|
5620
|
+
realHome ? resolve26(realHome, ".cargo/bin") : "",
|
|
5567
5621
|
...inheritedPath,
|
|
5568
5622
|
"/usr/local/bin",
|
|
5569
5623
|
"/usr/local/sbin",
|
|
@@ -5574,9 +5628,9 @@ async function runtimeEnv(projectRoot, runtime) {
|
|
|
5574
5628
|
"/usr/sbin",
|
|
5575
5629
|
"/sbin"
|
|
5576
5630
|
].filter(Boolean);
|
|
5577
|
-
const runtimeBash =
|
|
5578
|
-
const runtimeRigGit =
|
|
5579
|
-
const preferredShell =
|
|
5631
|
+
const runtimeBash = resolve26(runtime.binDir, "bash");
|
|
5632
|
+
const runtimeRigGit = resolve26(runtime.binDir, runtimeRigGitFileName());
|
|
5633
|
+
const preferredShell = existsSync25(runtimeBash) ? runtimeBash : "/bin/bash";
|
|
5580
5634
|
const nativeRuntimeLibraryPath = await materializeNativeRuntimeLibrary(runtime.binDir);
|
|
5581
5635
|
const controlPlaneSourceRoot = resolveControlPlaneSourceRoot(projectRoot);
|
|
5582
5636
|
const env = {
|
|
@@ -5597,30 +5651,30 @@ async function runtimeEnv(projectRoot, runtime) {
|
|
|
5597
5651
|
RIG_RUNTIME_MODE: runtime.mode,
|
|
5598
5652
|
RIG_RUNTIME_HOME: runtime.rootDir,
|
|
5599
5653
|
RIG_RUNTIME_BIN_DIR: runtime.binDir,
|
|
5600
|
-
...
|
|
5654
|
+
...existsSync25(runtimeRigGit) ? { RIG_NATIVE_GIT_BIN: runtimeRigGit } : {},
|
|
5601
5655
|
RIG_BUN_PATH: bunBinaryPath,
|
|
5602
5656
|
...claudeBinaryPath ? { RIG_CLAUDE_PATH: claudeBinaryPath } : {},
|
|
5603
|
-
RIG_AGENT_BIN:
|
|
5657
|
+
RIG_AGENT_BIN: resolve26(runtime.binDir, "rig-agent"),
|
|
5604
5658
|
RIG_HOOKS_ACTIVE: "1",
|
|
5605
5659
|
RIG_AUTO_PR_ON_COMPLETE: "1",
|
|
5606
|
-
RIG_POLICY_FILE:
|
|
5660
|
+
RIG_POLICY_FILE: resolve26(projectRoot, "rig/policy/policy.json"),
|
|
5607
5661
|
RIG_STATE_DIR: runtime.stateDir,
|
|
5608
5662
|
RIG_LOGS_DIR: runtime.logsDir,
|
|
5609
|
-
RIG_SESSION_FILE:
|
|
5663
|
+
RIG_SESSION_FILE: resolve26(runtime.sessionDir, "session.json"),
|
|
5610
5664
|
MONOREPO_ROOT: runtime.workspaceDir,
|
|
5611
5665
|
MONOREPO_MAIN_ROOT: monorepoMainRoot,
|
|
5612
|
-
TS_API_TESTS_DIR:
|
|
5666
|
+
TS_API_TESTS_DIR: resolve26(runtime.workspaceDir, "TSAPITests"),
|
|
5613
5667
|
BASH: preferredShell,
|
|
5614
5668
|
SHELL: preferredShell,
|
|
5615
5669
|
PATH: [...new Set(pathEntries)].join(delimiter2),
|
|
5616
5670
|
LANG: process.env.LANG ?? "en_US.UTF-8",
|
|
5617
5671
|
TERM: process.env.TERM ?? "xterm-256color",
|
|
5618
5672
|
PYTHONDONTWRITEBYTECODE: "1",
|
|
5619
|
-
PYTHONPYCACHEPREFIX:
|
|
5673
|
+
PYTHONPYCACHEPREFIX: resolve26(runtime.cacheDir, "python"),
|
|
5620
5674
|
...process.env.RIG_PR_BASE_PROJECT && { RIG_PR_BASE_PROJECT: process.env.RIG_PR_BASE_PROJECT },
|
|
5621
5675
|
...process.env.RIG_PR_BASE_MONOREPO && { RIG_PR_BASE_MONOREPO: process.env.RIG_PR_BASE_MONOREPO },
|
|
5622
5676
|
CLAUDE_HOME: runtime.claudeHomeDir,
|
|
5623
|
-
PI_CODING_AGENT_DIR:
|
|
5677
|
+
PI_CODING_AGENT_DIR: resolve26(runtime.homeDir, ".pi", "agent"),
|
|
5624
5678
|
[RUNTIME_CONTEXT_ENV]: runtime.contextFile,
|
|
5625
5679
|
...nativeRuntimeLibraryPath ? { RIG_NATIVE_RUNTIME_LIB: nativeRuntimeLibraryPath } : {},
|
|
5626
5680
|
...hostGhBinary ? { RIG_GH_BIN: hostGhBinary } : {},
|
|
@@ -5631,16 +5685,16 @@ async function runtimeEnv(projectRoot, runtime) {
|
|
|
5631
5685
|
NODE_EXTRA_CA_CERTS: runtimeCertBundlePath
|
|
5632
5686
|
} : {}
|
|
5633
5687
|
};
|
|
5634
|
-
const knownHostsPath =
|
|
5635
|
-
if (
|
|
5636
|
-
const agentSshKey =
|
|
5688
|
+
const knownHostsPath = resolve26(runtime.homeDir, ".ssh", "known_hosts");
|
|
5689
|
+
if (existsSync25(knownHostsPath)) {
|
|
5690
|
+
const agentSshKey = resolve26(runtime.homeDir, ".ssh", "rig-agent-key");
|
|
5637
5691
|
const sshParts = [
|
|
5638
5692
|
"ssh",
|
|
5639
5693
|
`-o UserKnownHostsFile="${knownHostsPath}"`,
|
|
5640
5694
|
"-o StrictHostKeyChecking=yes",
|
|
5641
5695
|
"-F /dev/null"
|
|
5642
5696
|
];
|
|
5643
|
-
if (
|
|
5697
|
+
if (existsSync25(agentSshKey)) {
|
|
5644
5698
|
sshParts.splice(1, 0, `-i "${agentSshKey}"`, "-o IdentitiesOnly=yes");
|
|
5645
5699
|
}
|
|
5646
5700
|
env.GIT_SSH_COMMAND = sshParts.join(" ");
|
|
@@ -5677,7 +5731,7 @@ async function runtimeEnv(projectRoot, runtime) {
|
|
|
5677
5731
|
if (!env.GREPTILE_GITHUB_TOKEN && env.GITHUB_TOKEN) {
|
|
5678
5732
|
env.GREPTILE_GITHUB_TOKEN = env.GITHUB_TOKEN;
|
|
5679
5733
|
}
|
|
5680
|
-
if (
|
|
5734
|
+
if (existsSync25(runtime.contextFile)) {
|
|
5681
5735
|
const runtimeContext = loadRuntimeContext(runtime.contextFile);
|
|
5682
5736
|
Object.assign(env, runtimeMemoryEnvFromContext(runtimeContext));
|
|
5683
5737
|
Object.assign(env, browserEnvFromContext(runtimeContext.browser));
|
|
@@ -5706,30 +5760,30 @@ async function provisionRuntimeHome(runtime, options = {}) {
|
|
|
5706
5760
|
await mkdir(runtime.cacheDir, { recursive: true });
|
|
5707
5761
|
await provisionAgentSshKey(runtime.homeDir);
|
|
5708
5762
|
if (options.provider === "codex") {
|
|
5709
|
-
const hasCodexAuth = await injectCodexAuth(
|
|
5763
|
+
const hasCodexAuth = await injectCodexAuth(resolve26(runtime.homeDir, ".codex"));
|
|
5710
5764
|
if (!hasCodexAuth) {
|
|
5711
5765
|
console.warn("[rig] No Codex auth.json found for isolated runtime. " + "Run `codex login` in your host shell, then retry the agent run.");
|
|
5712
5766
|
}
|
|
5713
5767
|
}
|
|
5714
5768
|
if (options.provider === "pi") {
|
|
5715
|
-
const hasPiAuth = await injectPiAgentConfig(
|
|
5769
|
+
const hasPiAuth = await injectPiAgentConfig(resolve26(runtime.homeDir, ".pi", "agent"));
|
|
5716
5770
|
if (!hasPiAuth) {
|
|
5717
5771
|
console.warn("[rig] No Pi auth.json found for isolated runtime. " + "Run `pi /login` in your host shell, then retry the agent run.");
|
|
5718
5772
|
}
|
|
5719
5773
|
}
|
|
5720
5774
|
}
|
|
5721
5775
|
async function provisionClaudeHome(config) {
|
|
5722
|
-
|
|
5723
|
-
const workspaceSettings =
|
|
5724
|
-
const hostSettings =
|
|
5725
|
-
const projectSettings =
|
|
5776
|
+
mkdirSync12(config.claudeHomeDir, { recursive: true });
|
|
5777
|
+
const workspaceSettings = resolve26(config.workspaceDir, ".claude/settings.json");
|
|
5778
|
+
const hostSettings = resolve26(config.hostProjectRoot, ".claude/settings.json");
|
|
5779
|
+
const projectSettings = existsSync25(workspaceSettings) ? workspaceSettings : hostSettings;
|
|
5726
5780
|
const runtimeSettings = await loadRuntimeClaudeSettings(projectSettings);
|
|
5727
|
-
if (
|
|
5728
|
-
|
|
5781
|
+
if (existsSync25(projectSettings)) {
|
|
5782
|
+
writeFileSync10(resolve26(config.claudeHomeDir, "settings.local.json"), `${JSON.stringify(runtimeSettings, null, 2)}
|
|
5729
5783
|
`, "utf-8");
|
|
5730
5784
|
}
|
|
5731
5785
|
writeClaudeProjectSettings(config.claudeHomeDir, config.workspaceDir, runtimeSettings);
|
|
5732
|
-
|
|
5786
|
+
writeFileSync10(resolve26(config.claudeHomeDir, "settings.json"), JSON.stringify({
|
|
5733
5787
|
permissions: { defaultMode: "bypassPermissions" },
|
|
5734
5788
|
autoMemoryEnabled: false
|
|
5735
5789
|
}, null, 2));
|
|
@@ -5737,12 +5791,12 @@ async function provisionClaudeHome(config) {
|
|
|
5737
5791
|
if (!hasCredentials) {
|
|
5738
5792
|
console.warn("[rig] No Claude credentials found for isolated runtime. " + "Run `claude /login` in your host shell, then retry the agent run.");
|
|
5739
5793
|
}
|
|
5740
|
-
const realClaudeHome =
|
|
5741
|
-
if (process.env.HOME &&
|
|
5742
|
-
cpSync2(
|
|
5794
|
+
const realClaudeHome = resolve26(process.env.HOME ?? "", ".claude");
|
|
5795
|
+
if (process.env.HOME && existsSync25(resolve26(realClaudeHome, "CLAUDE.md"))) {
|
|
5796
|
+
cpSync2(resolve26(realClaudeHome, "CLAUDE.md"), resolve26(config.claudeHomeDir, "CLAUDE.md"));
|
|
5743
5797
|
}
|
|
5744
|
-
if (process.env.HOME &&
|
|
5745
|
-
cpSync2(
|
|
5798
|
+
if (process.env.HOME && existsSync25(resolve26(realClaudeHome, "agents"))) {
|
|
5799
|
+
cpSync2(resolve26(realClaudeHome, "agents"), resolve26(config.claudeHomeDir, "agents"), { recursive: true });
|
|
5746
5800
|
}
|
|
5747
5801
|
if (process.platform === "darwin" && process.env.HOME) {
|
|
5748
5802
|
writeClaudeProjectSettings(realClaudeHome, config.workspaceDir, runtimeSettings);
|
|
@@ -5753,10 +5807,10 @@ async function materializeRuntimeCertBundle(runtime) {
|
|
|
5753
5807
|
if (!sourcePath) {
|
|
5754
5808
|
return "";
|
|
5755
5809
|
}
|
|
5756
|
-
const certsDir =
|
|
5757
|
-
const targetPath =
|
|
5810
|
+
const certsDir = resolve26(runtime.rootDir, "certs");
|
|
5811
|
+
const targetPath = resolve26(certsDir, "ca-certificates.pem");
|
|
5758
5812
|
await mkdir(certsDir, { recursive: true });
|
|
5759
|
-
let shouldCopy = !
|
|
5813
|
+
let shouldCopy = !existsSync25(targetPath);
|
|
5760
5814
|
if (!shouldCopy) {
|
|
5761
5815
|
try {
|
|
5762
5816
|
shouldCopy = statSync5(sourcePath).mtimeMs > statSync5(targetPath).mtimeMs;
|
|
@@ -5778,7 +5832,7 @@ function applyGitHubCredentialHelperEnv(env) {
|
|
|
5778
5832
|
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';
|
|
5779
5833
|
}
|
|
5780
5834
|
function persistRuntimeSecrets(runtimeRoot, env) {
|
|
5781
|
-
const secretsPath =
|
|
5835
|
+
const secretsPath = resolve26(runtimeRoot, "runtime-secrets.json");
|
|
5782
5836
|
const persisted = {};
|
|
5783
5837
|
for (const key of [
|
|
5784
5838
|
"GITHUB_TOKEN",
|
|
@@ -5797,12 +5851,12 @@ function persistRuntimeSecrets(runtimeRoot, env) {
|
|
|
5797
5851
|
if (Object.keys(persisted).length === 0) {
|
|
5798
5852
|
return;
|
|
5799
5853
|
}
|
|
5800
|
-
|
|
5854
|
+
writeFileSync10(secretsPath, `${JSON.stringify(persisted, null, 2)}
|
|
5801
5855
|
`, "utf-8");
|
|
5802
5856
|
}
|
|
5803
5857
|
async function provisionAgentSshKey(homeDir) {
|
|
5804
|
-
const sshDir =
|
|
5805
|
-
if (!
|
|
5858
|
+
const sshDir = resolve26(homeDir, ".ssh");
|
|
5859
|
+
if (!existsSync25(sshDir)) {
|
|
5806
5860
|
await mkdir(sshDir, { recursive: true });
|
|
5807
5861
|
}
|
|
5808
5862
|
seedKnownHosts(sshDir);
|
|
@@ -5810,27 +5864,27 @@ async function provisionAgentSshKey(homeDir) {
|
|
|
5810
5864
|
const privateKey = decodeProvisionedSshKey(secrets.GITHUB_SSH_KEY);
|
|
5811
5865
|
if (!privateKey) {
|
|
5812
5866
|
const hostKeyPath = resolveHostSshKeyPath(process.env.HOME ?? "");
|
|
5813
|
-
if (!process.env.HOME || !
|
|
5867
|
+
if (!process.env.HOME || !existsSync25(hostKeyPath)) {
|
|
5814
5868
|
return;
|
|
5815
5869
|
}
|
|
5816
|
-
const agentKeyPath2 =
|
|
5817
|
-
if (!
|
|
5870
|
+
const agentKeyPath2 = resolve26(sshDir, "rig-agent-key");
|
|
5871
|
+
if (!existsSync25(agentKeyPath2)) {
|
|
5818
5872
|
copyFileSync5(hostKeyPath, agentKeyPath2);
|
|
5819
5873
|
chmodSync5(agentKeyPath2, 384);
|
|
5820
5874
|
}
|
|
5821
5875
|
const hostPubPath = `${hostKeyPath}.pub`;
|
|
5822
|
-
if (
|
|
5876
|
+
if (existsSync25(hostPubPath)) {
|
|
5823
5877
|
const agentPubPath = `${agentKeyPath2}.pub`;
|
|
5824
|
-
if (!
|
|
5878
|
+
if (!existsSync25(agentPubPath)) {
|
|
5825
5879
|
copyFileSync5(hostPubPath, agentPubPath);
|
|
5826
5880
|
}
|
|
5827
5881
|
}
|
|
5828
5882
|
writeSshConfig(sshDir, agentKeyPath2);
|
|
5829
5883
|
return;
|
|
5830
5884
|
}
|
|
5831
|
-
const agentKeyPath =
|
|
5832
|
-
if (!
|
|
5833
|
-
|
|
5885
|
+
const agentKeyPath = resolve26(sshDir, "rig-agent-key");
|
|
5886
|
+
if (!existsSync25(agentKeyPath)) {
|
|
5887
|
+
writeFileSync10(agentKeyPath, privateKey, { mode: 384 });
|
|
5834
5888
|
}
|
|
5835
5889
|
writeSshConfig(sshDir, agentKeyPath);
|
|
5836
5890
|
}
|
|
@@ -5847,21 +5901,21 @@ function decodeProvisionedSshKey(encodedKey) {
|
|
|
5847
5901
|
`;
|
|
5848
5902
|
}
|
|
5849
5903
|
function resolveHostSshKeyPath(homeDir) {
|
|
5850
|
-
const sshDir =
|
|
5904
|
+
const sshDir = resolve26(homeDir, ".ssh");
|
|
5851
5905
|
const candidates = [
|
|
5852
5906
|
"rig-agent-key",
|
|
5853
5907
|
"id_ed25519",
|
|
5854
5908
|
"id_ecdsa",
|
|
5855
5909
|
"id_rsa"
|
|
5856
|
-
].map((name) =>
|
|
5857
|
-
return candidates.find((candidate) =>
|
|
5910
|
+
].map((name) => resolve26(sshDir, name));
|
|
5911
|
+
return candidates.find((candidate) => existsSync25(candidate)) ?? resolve26(sshDir, "rig-agent-key");
|
|
5858
5912
|
}
|
|
5859
5913
|
function writeSshConfig(sshDir, keyPath) {
|
|
5860
|
-
const configPath =
|
|
5861
|
-
if (
|
|
5914
|
+
const configPath = resolve26(sshDir, "config");
|
|
5915
|
+
if (existsSync25(configPath)) {
|
|
5862
5916
|
return;
|
|
5863
5917
|
}
|
|
5864
|
-
const knownHostsPath =
|
|
5918
|
+
const knownHostsPath = resolve26(sshDir, "known_hosts");
|
|
5865
5919
|
const config = [
|
|
5866
5920
|
"Host github.com",
|
|
5867
5921
|
` IdentityFile ${keyPath}`,
|
|
@@ -5871,10 +5925,10 @@ function writeSshConfig(sshDir, keyPath) {
|
|
|
5871
5925
|
""
|
|
5872
5926
|
].join(`
|
|
5873
5927
|
`);
|
|
5874
|
-
|
|
5928
|
+
writeFileSync10(configPath, config, { mode: 420 });
|
|
5875
5929
|
}
|
|
5876
5930
|
function seedKnownHosts(sshDir) {
|
|
5877
|
-
const knownHostsPath =
|
|
5931
|
+
const knownHostsPath = resolve26(sshDir, "known_hosts");
|
|
5878
5932
|
const existingLines = readKnownHosts(knownHostsPath);
|
|
5879
5933
|
const requiredLines = GITHUB_KNOWN_HOSTS.split(/\r?\n/).map((line) => line.trim()).filter(Boolean);
|
|
5880
5934
|
const missing = requiredLines.filter((line) => !existingLines.has(line));
|
|
@@ -5885,23 +5939,23 @@ function seedKnownHosts(sshDir) {
|
|
|
5885
5939
|
for (const line of missing) {
|
|
5886
5940
|
existingLines.add(line);
|
|
5887
5941
|
}
|
|
5888
|
-
|
|
5942
|
+
writeFileSync10(knownHostsPath, `${Array.from(existingLines).join(`
|
|
5889
5943
|
`)}
|
|
5890
5944
|
`, { mode: 420 });
|
|
5891
5945
|
} catch (err) {
|
|
5892
|
-
const hint =
|
|
5946
|
+
const hint = existsSync25(knownHostsPath) ? "" : " \u2014 known_hosts is missing; git SSH operations may fail";
|
|
5893
5947
|
console.warn(`[rig] Could not update ${knownHostsPath}: ${err instanceof Error ? err.message : String(err)}${hint}`);
|
|
5894
5948
|
}
|
|
5895
5949
|
}
|
|
5896
5950
|
function writeClaudeProjectSettings(claudeHomeDir, workspaceDir, runtimeSettings) {
|
|
5897
5951
|
const projectHash = hashProjectPath(workspaceDir);
|
|
5898
|
-
const projectDir =
|
|
5899
|
-
|
|
5900
|
-
|
|
5952
|
+
const projectDir = resolve26(claudeHomeDir, "projects", projectHash);
|
|
5953
|
+
mkdirSync12(projectDir, { recursive: true });
|
|
5954
|
+
writeFileSync10(resolve26(projectDir, "settings.json"), `${JSON.stringify(runtimeSettings, null, 2)}
|
|
5901
5955
|
`, "utf-8");
|
|
5902
5956
|
}
|
|
5903
5957
|
async function loadRuntimeClaudeSettings(projectSettingsPath) {
|
|
5904
|
-
if (!
|
|
5958
|
+
if (!existsSync25(projectSettingsPath)) {
|
|
5905
5959
|
return {};
|
|
5906
5960
|
}
|
|
5907
5961
|
let parsed;
|
|
@@ -5947,7 +6001,7 @@ async function loadRuntimeClaudeSettings(projectSettingsPath) {
|
|
|
5947
6001
|
return clone;
|
|
5948
6002
|
}
|
|
5949
6003
|
async function injectClaudeCredentials(claudeHomeDir, options = {}) {
|
|
5950
|
-
const credentialsPath =
|
|
6004
|
+
const credentialsPath = resolve26(claudeHomeDir, ".credentials.json");
|
|
5951
6005
|
const platform = options.platform ?? process.platform;
|
|
5952
6006
|
if (platform === "darwin") {
|
|
5953
6007
|
const raw = options.loadKeychainCredentials ? await options.loadKeychainCredentials() : await (async () => {
|
|
@@ -5957,16 +6011,16 @@ async function injectClaudeCredentials(claudeHomeDir, options = {}) {
|
|
|
5957
6011
|
if (raw) {
|
|
5958
6012
|
try {
|
|
5959
6013
|
JSON.parse(raw);
|
|
5960
|
-
|
|
6014
|
+
writeFileSync10(credentialsPath, raw, { mode: 384 });
|
|
5961
6015
|
registerCredentialCleanup(credentialsPath);
|
|
5962
6016
|
return true;
|
|
5963
6017
|
} catch {}
|
|
5964
6018
|
}
|
|
5965
6019
|
}
|
|
5966
|
-
const hostClaudeHome = options.hostClaudeHome ?
|
|
6020
|
+
const hostClaudeHome = options.hostClaudeHome ? resolve26(options.hostClaudeHome) : process.env.CLAUDE_HOME?.trim() ? resolve26(process.env.CLAUDE_HOME) : process.env.HOME ? resolve26(process.env.HOME, ".claude") : "";
|
|
5967
6021
|
if (hostClaudeHome) {
|
|
5968
|
-
const realCredentials =
|
|
5969
|
-
if (
|
|
6022
|
+
const realCredentials = resolve26(hostClaudeHome, ".credentials.json");
|
|
6023
|
+
if (existsSync25(realCredentials)) {
|
|
5970
6024
|
cpSync2(realCredentials, credentialsPath);
|
|
5971
6025
|
return true;
|
|
5972
6026
|
}
|
|
@@ -5974,36 +6028,36 @@ async function injectClaudeCredentials(claudeHomeDir, options = {}) {
|
|
|
5974
6028
|
return false;
|
|
5975
6029
|
}
|
|
5976
6030
|
async function injectCodexAuth(codexHomeDir) {
|
|
5977
|
-
|
|
5978
|
-
const hostCodexHome = process.env.CODEX_HOME?.trim() ?
|
|
6031
|
+
mkdirSync12(codexHomeDir, { recursive: true });
|
|
6032
|
+
const hostCodexHome = process.env.CODEX_HOME?.trim() ? resolve26(process.env.CODEX_HOME) : process.env.HOME ? resolve26(process.env.HOME, ".codex") : "";
|
|
5979
6033
|
if (!hostCodexHome) {
|
|
5980
6034
|
return false;
|
|
5981
6035
|
}
|
|
5982
|
-
const hostAuthPath =
|
|
5983
|
-
if (!
|
|
6036
|
+
const hostAuthPath = resolve26(hostCodexHome, "auth.json");
|
|
6037
|
+
if (!existsSync25(hostAuthPath)) {
|
|
5984
6038
|
return false;
|
|
5985
6039
|
}
|
|
5986
|
-
const runtimeAuthPath =
|
|
6040
|
+
const runtimeAuthPath = resolve26(codexHomeDir, "auth.json");
|
|
5987
6041
|
copyFileSync5(hostAuthPath, runtimeAuthPath);
|
|
5988
6042
|
chmodSync5(runtimeAuthPath, 384);
|
|
5989
6043
|
return true;
|
|
5990
6044
|
}
|
|
5991
6045
|
async function injectPiAgentConfig(piAgentDir) {
|
|
5992
|
-
|
|
5993
|
-
const hostPiAgentDir = process.env.PI_CODING_AGENT_DIR?.trim() ?
|
|
6046
|
+
mkdirSync12(piAgentDir, { recursive: true });
|
|
6047
|
+
const hostPiAgentDir = process.env.PI_CODING_AGENT_DIR?.trim() ? resolve26(process.env.PI_CODING_AGENT_DIR) : process.env.HOME ? resolve26(process.env.HOME, ".pi", "agent") : "";
|
|
5994
6048
|
if (!hostPiAgentDir) {
|
|
5995
6049
|
return false;
|
|
5996
6050
|
}
|
|
5997
|
-
const hostAuthPath =
|
|
5998
|
-
if (!
|
|
6051
|
+
const hostAuthPath = resolve26(hostPiAgentDir, "auth.json");
|
|
6052
|
+
if (!existsSync25(hostAuthPath)) {
|
|
5999
6053
|
return false;
|
|
6000
6054
|
}
|
|
6001
|
-
const runtimeAuthPath =
|
|
6055
|
+
const runtimeAuthPath = resolve26(piAgentDir, "auth.json");
|
|
6002
6056
|
copyFileSync5(hostAuthPath, runtimeAuthPath);
|
|
6003
6057
|
chmodSync5(runtimeAuthPath, 384);
|
|
6004
|
-
const hostSettingsPath =
|
|
6005
|
-
if (
|
|
6006
|
-
const runtimeSettingsPath =
|
|
6058
|
+
const hostSettingsPath = resolve26(hostPiAgentDir, "settings.json");
|
|
6059
|
+
if (existsSync25(hostSettingsPath)) {
|
|
6060
|
+
const runtimeSettingsPath = resolve26(piAgentDir, "settings.json");
|
|
6007
6061
|
copyFileSync5(hostSettingsPath, runtimeSettingsPath);
|
|
6008
6062
|
chmodSync5(runtimeSettingsPath, 384);
|
|
6009
6063
|
}
|
|
@@ -6011,13 +6065,13 @@ async function injectPiAgentConfig(piAgentDir) {
|
|
|
6011
6065
|
}
|
|
6012
6066
|
|
|
6013
6067
|
// packages/runtime/src/control-plane/runtime/tooling/claude-router.ts
|
|
6014
|
-
import { existsSync as
|
|
6015
|
-
import { resolve as
|
|
6068
|
+
import { existsSync as existsSync26, mkdirSync as mkdirSync13, statSync as statSync6, writeFileSync as writeFileSync11 } from "fs";
|
|
6069
|
+
import { resolve as resolve27 } from "path";
|
|
6016
6070
|
var CLAUDE_ROUTER_SERVER_NAME = "rig_runtime_tools";
|
|
6017
6071
|
function buildRuntimeToolRouterServerConfig(options) {
|
|
6018
6072
|
return {
|
|
6019
6073
|
type: "stdio",
|
|
6020
|
-
command:
|
|
6074
|
+
command: resolve27(options.binDir, "rig-tool-router"),
|
|
6021
6075
|
args: [],
|
|
6022
6076
|
env: {
|
|
6023
6077
|
RIG_RUNTIME_CONTEXT_FILE: options.contextFile,
|
|
@@ -6026,26 +6080,26 @@ function buildRuntimeToolRouterServerConfig(options) {
|
|
|
6026
6080
|
};
|
|
6027
6081
|
}
|
|
6028
6082
|
function writeClaudeRuntimeToolRouterConfig(options) {
|
|
6029
|
-
const configPath =
|
|
6030
|
-
|
|
6083
|
+
const configPath = resolve27(options.stateDir, "claude-runtime-tools.mcp.json");
|
|
6084
|
+
mkdirSync13(options.stateDir, { recursive: true });
|
|
6031
6085
|
const payload = {
|
|
6032
6086
|
mcpServers: {
|
|
6033
6087
|
[CLAUDE_ROUTER_SERVER_NAME]: buildRuntimeToolRouterServerConfig(options)
|
|
6034
6088
|
}
|
|
6035
6089
|
};
|
|
6036
|
-
|
|
6090
|
+
writeFileSync11(configPath, `${JSON.stringify(payload, null, 2)}
|
|
6037
6091
|
`, "utf-8");
|
|
6038
6092
|
return configPath;
|
|
6039
6093
|
}
|
|
6040
6094
|
if (false) {}
|
|
6041
6095
|
// packages/runtime/src/control-plane/runtime/isolation/discovery.ts
|
|
6042
6096
|
init_layout();
|
|
6043
|
-
import { existsSync as
|
|
6044
|
-
import { resolve as
|
|
6097
|
+
import { existsSync as existsSync30 } from "fs";
|
|
6098
|
+
import { resolve as resolve31 } from "path";
|
|
6045
6099
|
|
|
6046
6100
|
// packages/runtime/src/control-plane/runtime/isolation/worktree.ts
|
|
6047
|
-
import { existsSync as
|
|
6048
|
-
import { dirname as dirname11, resolve as
|
|
6101
|
+
import { existsSync as existsSync27, mkdirSync as mkdirSync14, rmSync as rmSync10 } from "fs";
|
|
6102
|
+
import { dirname as dirname11, resolve as resolve28 } from "path";
|
|
6049
6103
|
async function resolveMonorepoBaseRef(monorepoRoot) {
|
|
6050
6104
|
const explicit = process.env.RIG_RUNTIME_BASE_REF?.trim();
|
|
6051
6105
|
if (explicit) {
|
|
@@ -6081,12 +6135,12 @@ function ensureProvisioningHostProjectRootEnv(projectRoot) {
|
|
|
6081
6135
|
}
|
|
6082
6136
|
async function provisionRuntimeWorktree(config) {
|
|
6083
6137
|
const branch = runtimeBranchName(config.taskId, config.runtimeId);
|
|
6084
|
-
let hasValidWorktree =
|
|
6085
|
-
if (
|
|
6086
|
-
|
|
6138
|
+
let hasValidWorktree = existsSync27(resolve28(config.workspaceDir, ".git")) && (await runGitCommand(config.workspaceDir, ["rev-parse", "--show-toplevel"])).exitCode === 0;
|
|
6139
|
+
if (existsSync27(config.workspaceDir) && !hasValidWorktree) {
|
|
6140
|
+
rmSync10(config.workspaceDir, { recursive: true, force: true });
|
|
6087
6141
|
}
|
|
6088
6142
|
if (!hasValidWorktree) {
|
|
6089
|
-
|
|
6143
|
+
mkdirSync14(dirname11(config.workspaceDir), { recursive: true });
|
|
6090
6144
|
const branchExists = await runGitCommand(config.monorepoRoot, ["show-ref", "--verify", "--quiet", `refs/heads/${branch}`]);
|
|
6091
6145
|
const add = branchExists.exitCode === 0 ? await runGitCommand(config.monorepoRoot, ["worktree", "add", "--force", config.workspaceDir, branch]) : await runGitCommand(config.monorepoRoot, ["worktree", "add", "--force", "-b", branch, config.workspaceDir, config.baseRef]);
|
|
6092
6146
|
if (add.exitCode !== 0) {
|
|
@@ -6268,31 +6322,31 @@ async function preferredBaseRemotes(repoRoot) {
|
|
|
6268
6322
|
|
|
6269
6323
|
// packages/runtime/src/control-plane/runtime/isolation/toolchain.ts
|
|
6270
6324
|
import {
|
|
6271
|
-
existsSync as
|
|
6325
|
+
existsSync as existsSync29,
|
|
6272
6326
|
lstatSync,
|
|
6273
|
-
mkdirSync as
|
|
6274
|
-
readdirSync as
|
|
6275
|
-
readFileSync as
|
|
6276
|
-
rmSync as
|
|
6327
|
+
mkdirSync as mkdirSync16,
|
|
6328
|
+
readdirSync as readdirSync6,
|
|
6329
|
+
readFileSync as readFileSync14,
|
|
6330
|
+
rmSync as rmSync11,
|
|
6277
6331
|
statSync as statSync8,
|
|
6278
6332
|
symlinkSync as symlinkSync4
|
|
6279
6333
|
} from "fs";
|
|
6280
6334
|
import { mkdir as mkdir2, writeFile } from "fs/promises";
|
|
6281
|
-
import { dirname as dirname13, resolve as
|
|
6335
|
+
import { dirname as dirname13, resolve as resolve30 } from "path";
|
|
6282
6336
|
|
|
6283
6337
|
// packages/runtime/src/control-plane/runtime/tooling/claude-router-binary.ts
|
|
6284
|
-
import { chmodSync as chmodSync6, copyFileSync as copyFileSync6, existsSync as
|
|
6338
|
+
import { chmodSync as chmodSync6, copyFileSync as copyFileSync6, existsSync as existsSync28, mkdirSync as mkdirSync15, statSync as statSync7 } from "fs";
|
|
6285
6339
|
import { tmpdir as tmpdir6 } from "os";
|
|
6286
|
-
import { dirname as dirname12, resolve as
|
|
6287
|
-
var sharedRouterOutputDir =
|
|
6288
|
-
var sharedRouterOutputPath =
|
|
6340
|
+
import { dirname as dirname12, resolve as resolve29 } from "path";
|
|
6341
|
+
var sharedRouterOutputDir = resolve29(tmpdir6(), "rig-native");
|
|
6342
|
+
var sharedRouterOutputPath = resolve29(sharedRouterOutputDir, `rig-tool-router-${process.platform}-${process.arch}${process.platform === "win32" ? ".exe" : ""}`);
|
|
6289
6343
|
function runtimeClaudeToolRouterFileName() {
|
|
6290
6344
|
return `rig-tool-router${process.platform === "win32" ? ".exe" : ""}`;
|
|
6291
6345
|
}
|
|
6292
6346
|
async function ensureClaudeToolRouterBinaryPath(projectRoot, outputPath = sharedRouterOutputPath) {
|
|
6293
|
-
const sourcePath =
|
|
6294
|
-
|
|
6295
|
-
const needsBuild = !
|
|
6347
|
+
const sourcePath = resolve29(projectRoot, "packages/runtime/src/control-plane/runtime/tooling/claude-router.ts");
|
|
6348
|
+
mkdirSync15(dirname12(outputPath), { recursive: true });
|
|
6349
|
+
const needsBuild = !existsSync28(outputPath) || statSync7(sourcePath).mtimeMs > statSync7(outputPath).mtimeMs;
|
|
6296
6350
|
if (!needsBuild) {
|
|
6297
6351
|
return outputPath;
|
|
6298
6352
|
}
|
|
@@ -6306,9 +6360,9 @@ async function ensureClaudeToolRouterBinaryPath(projectRoot, outputPath = shared
|
|
|
6306
6360
|
}
|
|
6307
6361
|
async function materializeClaudeToolRouterBinary(projectRoot, targetDir) {
|
|
6308
6362
|
const sourcePath = await ensureClaudeToolRouterBinaryPath(projectRoot);
|
|
6309
|
-
const targetPath =
|
|
6310
|
-
|
|
6311
|
-
const needsCopy = !
|
|
6363
|
+
const targetPath = resolve29(targetDir, runtimeClaudeToolRouterFileName());
|
|
6364
|
+
mkdirSync15(targetDir, { recursive: true });
|
|
6365
|
+
const needsCopy = !existsSync28(targetPath) || statSync7(sourcePath).mtimeMs > statSync7(targetPath).mtimeMs;
|
|
6312
6366
|
if (needsCopy) {
|
|
6313
6367
|
copyFileSync6(sourcePath, targetPath);
|
|
6314
6368
|
chmodSync6(targetPath, 493);
|
|
@@ -6321,48 +6375,48 @@ var GIT_INDEX_LOCK_RETRY_DELAY_MS = 250;
|
|
|
6321
6375
|
var GIT_INDEX_LOCK_STALE_AFTER_MS = 5000;
|
|
6322
6376
|
function resolveRigSourceRoot(projectRoot) {
|
|
6323
6377
|
const hostProjectRoot = process.env.RIG_HOST_PROJECT_ROOT?.trim();
|
|
6324
|
-
if (hostProjectRoot &&
|
|
6378
|
+
if (hostProjectRoot && existsSync29(resolve30(hostProjectRoot, "packages/runtime/bin/rig-agent.ts"))) {
|
|
6325
6379
|
return hostProjectRoot;
|
|
6326
6380
|
}
|
|
6327
|
-
const fromModule =
|
|
6328
|
-
if (
|
|
6381
|
+
const fromModule = resolve30(import.meta.dir, "../../../../../..");
|
|
6382
|
+
if (existsSync29(resolve30(fromModule, "packages/runtime/bin/rig-agent.ts"))) {
|
|
6329
6383
|
return fromModule;
|
|
6330
6384
|
}
|
|
6331
6385
|
return projectRoot;
|
|
6332
6386
|
}
|
|
6333
6387
|
function prepareTrackedRuntimePaths(logsDir, stateDir, sessionDir) {
|
|
6334
|
-
for (const path of [logsDir, stateDir, sessionDir,
|
|
6388
|
+
for (const path of [logsDir, stateDir, sessionDir, resolve30(sessionDir, "session.json")]) {
|
|
6335
6389
|
removeSymbolicLink(path);
|
|
6336
6390
|
}
|
|
6337
6391
|
runtimePrepareTrackedPathsNative({
|
|
6338
6392
|
logsDir,
|
|
6339
6393
|
stateDir,
|
|
6340
6394
|
sessionDir,
|
|
6341
|
-
controlledBashLogFile:
|
|
6342
|
-
eventsFile:
|
|
6395
|
+
controlledBashLogFile: resolve30(logsDir, "controlled-bash.jsonl"),
|
|
6396
|
+
eventsFile: resolve30(logsDir, "control-plane.events.jsonl")
|
|
6343
6397
|
});
|
|
6344
6398
|
}
|
|
6345
6399
|
async function initializeRuntimeStateFiles(stateDir, sessionDir, taskId) {
|
|
6346
6400
|
await mkdir2(stateDir, { recursive: true });
|
|
6347
6401
|
await mkdir2(sessionDir, { recursive: true });
|
|
6348
|
-
const failedApproachesPath =
|
|
6349
|
-
if (!
|
|
6402
|
+
const failedApproachesPath = resolve30(stateDir, "failed_approaches.md");
|
|
6403
|
+
if (!existsSync29(failedApproachesPath)) {
|
|
6350
6404
|
await writeFile(failedApproachesPath, `# Failed Approaches
|
|
6351
6405
|
|
|
6352
6406
|
`);
|
|
6353
6407
|
}
|
|
6354
|
-
const hookTripsPath =
|
|
6355
|
-
if (!
|
|
6408
|
+
const hookTripsPath = resolve30(stateDir, "hook_trips.log");
|
|
6409
|
+
if (!existsSync29(hookTripsPath)) {
|
|
6356
6410
|
await writeFile(hookTripsPath, "");
|
|
6357
6411
|
}
|
|
6358
|
-
const sessionFile =
|
|
6412
|
+
const sessionFile = resolve30(sessionDir, "session.json");
|
|
6359
6413
|
if (taskId) {
|
|
6360
6414
|
await writeFile(sessionFile, JSON.stringify({ activeTaskIds: [taskId] }));
|
|
6361
6415
|
}
|
|
6362
6416
|
}
|
|
6363
6417
|
async function resetEphemeralTaskArtifacts(workspaceDir, taskId) {
|
|
6364
|
-
const artifactDir =
|
|
6365
|
-
const runtimeSnapshotDir =
|
|
6418
|
+
const artifactDir = resolve30(workspaceDir, "artifacts", taskId);
|
|
6419
|
+
const runtimeSnapshotDir = resolve30(artifactDir, "runtime-snapshots");
|
|
6366
6420
|
let preservedTrackedFiles = false;
|
|
6367
6421
|
for (const file of [
|
|
6368
6422
|
"changed-files.txt",
|
|
@@ -6378,13 +6432,13 @@ async function resetEphemeralTaskArtifacts(workspaceDir, taskId) {
|
|
|
6378
6432
|
preservedTrackedFiles = true;
|
|
6379
6433
|
continue;
|
|
6380
6434
|
}
|
|
6381
|
-
|
|
6435
|
+
rmSync11(resolve30(artifactDir, file), { force: true });
|
|
6382
6436
|
}
|
|
6383
6437
|
const runtimeSnapshotRelativePath = `artifacts/${taskId}/runtime-snapshots`;
|
|
6384
6438
|
if (await resetTrackedArtifactPath(workspaceDir, runtimeSnapshotRelativePath)) {
|
|
6385
6439
|
preservedTrackedFiles = true;
|
|
6386
6440
|
} else {
|
|
6387
|
-
|
|
6441
|
+
rmSync11(runtimeSnapshotDir, { recursive: true, force: true });
|
|
6388
6442
|
}
|
|
6389
6443
|
if (preservedTrackedFiles) {
|
|
6390
6444
|
console.log(`[rig-agent] Preserved tracked runtime artifact files in ${taskId}; skipped ephemeral cleanup for committed paths.`);
|
|
@@ -6417,28 +6471,28 @@ async function buildRuntimeToolchain(options) {
|
|
|
6417
6471
|
throw new Error("Failed to provision the native Zig runtime library.");
|
|
6418
6472
|
}
|
|
6419
6473
|
const rigSourceRoot = resolveRigSourceRoot(options.projectRoot);
|
|
6420
|
-
await buildBinary("packages/cli/bin/rig.ts",
|
|
6421
|
-
await buildBinary("packages/runtime/bin/rig-agent.ts",
|
|
6474
|
+
await buildBinary("packages/cli/bin/rig.ts", resolve30(options.binDir, "rig"), rigSourceRoot);
|
|
6475
|
+
await buildBinary("packages/runtime/bin/rig-agent.ts", resolve30(options.binDir, "rig-agent"), rigSourceRoot, {
|
|
6422
6476
|
...options.runtimeSecretDefines,
|
|
6423
6477
|
AGENT_TASK_ID: options.taskId,
|
|
6424
6478
|
AGENT_PROJECT_ROOT: options.projectRoot,
|
|
6425
6479
|
AGENT_RUNTIME_ID: options.runtimeId,
|
|
6426
6480
|
AGENT_SCOPE_HASH: options.bakedScopeHash,
|
|
6427
6481
|
AGENT_MANIFEST_PATH: options.manifestPath,
|
|
6428
|
-
AGENT_BINARY_PATH:
|
|
6482
|
+
AGENT_BINARY_PATH: resolve30(options.binDir, "rig-agent"),
|
|
6429
6483
|
AGENT_INFO_OUTPUT: options.bakedInfoOutput,
|
|
6430
6484
|
AGENT_DEPS_OUTPUT: options.bakedDepsOutput,
|
|
6431
6485
|
AGENT_STATUS_OUTPUT: options.bakedStatusOutput
|
|
6432
6486
|
});
|
|
6433
|
-
await buildBinary("packages/runtime/src/control-plane/controlled-bash.ts",
|
|
6487
|
+
await buildBinary("packages/runtime/src/control-plane/controlled-bash.ts", resolve30(options.binDir, "controlled-bash"), rigSourceRoot, {
|
|
6434
6488
|
AGENT_PROJECT_ROOT: options.projectRoot,
|
|
6435
6489
|
AGENT_LOGS_DIR: options.logsDir,
|
|
6436
6490
|
AGENT_MONOREPO_ROOT: resolveMonorepoRoot3(options.projectRoot),
|
|
6437
|
-
AGENT_TS_API_TESTS_DIR:
|
|
6438
|
-
AGENT_RIG_AGENT_BIN:
|
|
6491
|
+
AGENT_TS_API_TESTS_DIR: resolve30(options.workspaceDir, "TSAPITests"),
|
|
6492
|
+
AGENT_RIG_AGENT_BIN: resolve30(options.binDir, "rig-agent")
|
|
6439
6493
|
});
|
|
6440
|
-
await buildBinary("packages/runtime/bin/rig-browser-tool.ts",
|
|
6441
|
-
await buildBinary("packages/runtime/src/control-plane/runtime/snapshot/sidecar.ts",
|
|
6494
|
+
await buildBinary("packages/runtime/bin/rig-browser-tool.ts", resolve30(options.binDir, runtimeBrowserToolBinaryName()), rigSourceRoot);
|
|
6495
|
+
await buildBinary("packages/runtime/src/control-plane/runtime/snapshot/sidecar.ts", resolve30(options.binDir, "snapshot-sidecar"), rigSourceRoot, {
|
|
6442
6496
|
AGENT_PROJECT_ROOT: options.projectRoot,
|
|
6443
6497
|
AGENT_BUN_PATH: resolveBunBinaryPath()
|
|
6444
6498
|
});
|
|
@@ -6447,15 +6501,15 @@ async function buildRuntimeToolchain(options) {
|
|
|
6447
6501
|
AGENT_BUN_PATH: resolveBunBinaryPath()
|
|
6448
6502
|
};
|
|
6449
6503
|
for (const hookName of hookNames) {
|
|
6450
|
-
await buildBinary(`packages/runtime/src/control-plane/hooks/${hookName}.ts`,
|
|
6504
|
+
await buildBinary(`packages/runtime/src/control-plane/hooks/${hookName}.ts`, resolve30(runtimeBins.hooksDir, hookName), rigSourceRoot, hookDefines);
|
|
6451
6505
|
}
|
|
6452
|
-
const pluginsDir =
|
|
6453
|
-
if (
|
|
6454
|
-
for (const entry of
|
|
6506
|
+
const pluginsDir = resolve30(options.projectRoot, "rig/plugins");
|
|
6507
|
+
if (existsSync29(pluginsDir)) {
|
|
6508
|
+
for (const entry of readdirSync6(pluginsDir, { withFileTypes: true })) {
|
|
6455
6509
|
const match = entry.name.match(/^(.+)\.plugin\.(ts|js|mjs|cjs)$/);
|
|
6456
6510
|
if (!match)
|
|
6457
6511
|
continue;
|
|
6458
|
-
await buildBinary(`rig/plugins/${entry.name}`,
|
|
6512
|
+
await buildBinary(`rig/plugins/${entry.name}`, resolve30(runtimeBins.pluginsDir, match[1]), options.projectRoot);
|
|
6459
6513
|
}
|
|
6460
6514
|
}
|
|
6461
6515
|
await materializeRigGitBinary(options.binDir);
|
|
@@ -6465,8 +6519,8 @@ async function buildRuntimeToolchain(options) {
|
|
|
6465
6519
|
}
|
|
6466
6520
|
async function writeRuntimeManifest(config) {
|
|
6467
6521
|
const scopeHash = sha256Hex(JSON.stringify(config.scopes));
|
|
6468
|
-
const binarySha256 = sha256Hex(
|
|
6469
|
-
const manifestPath =
|
|
6522
|
+
const binarySha256 = sha256Hex(readFileSync14(config.binaryPath));
|
|
6523
|
+
const manifestPath = resolve30(config.runtimeRoot, "manifest.json");
|
|
6470
6524
|
const manifest = {
|
|
6471
6525
|
runtimeId: config.runtimeId,
|
|
6472
6526
|
taskId: config.taskId,
|
|
@@ -6500,7 +6554,7 @@ function removeSymbolicLink(path) {
|
|
|
6500
6554
|
} catch {
|
|
6501
6555
|
return;
|
|
6502
6556
|
}
|
|
6503
|
-
|
|
6557
|
+
rmSync11(path, { force: true, recursive: true });
|
|
6504
6558
|
}
|
|
6505
6559
|
async function resetTrackedArtifactPath(workspaceDir, relativePath) {
|
|
6506
6560
|
const tracked = await runGitLsFiles(workspaceDir, relativePath);
|
|
@@ -6526,7 +6580,7 @@ async function restoreTrackedArtifactPathWithRetry(workspaceDir, relativePath, r
|
|
|
6526
6580
|
const retryDelayMs = options.retryDelayMs ?? GIT_INDEX_LOCK_RETRY_DELAY_MS;
|
|
6527
6581
|
const now = options.now ?? Date.now;
|
|
6528
6582
|
const statMtimeMs = options.statMtimeMs ?? readFileMtimeMs;
|
|
6529
|
-
const removeFile = options.removeFile ?? ((path) =>
|
|
6583
|
+
const removeFile = options.removeFile ?? ((path) => rmSync11(path, { force: true }));
|
|
6530
6584
|
const log = options.log ?? console.warn;
|
|
6531
6585
|
let lastOutput = "";
|
|
6532
6586
|
for (let attempt = 0;attempt <= maxRetries; attempt += 1) {
|
|
@@ -6586,31 +6640,31 @@ function readFileMtimeMs(path) {
|
|
|
6586
6640
|
}
|
|
6587
6641
|
function linkRuntimeDependencyLayers(monorepoRoot, workspaceDir) {
|
|
6588
6642
|
linkGenericNodeModulesLayers(monorepoRoot, workspaceDir);
|
|
6589
|
-
const sourceNodeModules =
|
|
6590
|
-
if (!
|
|
6591
|
-
const runtimeHumoongate =
|
|
6592
|
-
if (
|
|
6593
|
-
const targetNodeModules =
|
|
6643
|
+
const sourceNodeModules = resolve30(monorepoRoot, "humoongate", "node_modules");
|
|
6644
|
+
if (!existsSync29(sourceNodeModules)) {} else {
|
|
6645
|
+
const runtimeHumoongate = resolve30(workspaceDir, "humoongate");
|
|
6646
|
+
if (existsSync29(resolve30(runtimeHumoongate, "package.json"))) {
|
|
6647
|
+
const targetNodeModules = resolve30(runtimeHumoongate, "node_modules");
|
|
6594
6648
|
runtimeLinkDependencyLayerNative(sourceNodeModules, targetNodeModules);
|
|
6595
6649
|
}
|
|
6596
6650
|
}
|
|
6597
|
-
const runtimeHpNext =
|
|
6598
|
-
if (!
|
|
6651
|
+
const runtimeHpNext = resolve30(workspaceDir, "microservices", "hp-next-frontend", "app");
|
|
6652
|
+
if (!existsSync29(resolve30(runtimeHpNext, "package.json"))) {
|
|
6599
6653
|
return;
|
|
6600
6654
|
}
|
|
6601
|
-
const sourceHpNextNodeModules =
|
|
6602
|
-
const sourceMonorepoNodeModules =
|
|
6603
|
-
const targetHpNextNodeModules =
|
|
6604
|
-
if (
|
|
6655
|
+
const sourceHpNextNodeModules = resolve30(monorepoRoot, "microservices", "hp-next-frontend", "app", "node_modules");
|
|
6656
|
+
const sourceMonorepoNodeModules = resolve30(monorepoRoot, "node_modules");
|
|
6657
|
+
const targetHpNextNodeModules = resolve30(runtimeHpNext, "node_modules");
|
|
6658
|
+
if (existsSync29(sourceHpNextNodeModules)) {
|
|
6605
6659
|
runtimeLinkDependencyLayerNative(sourceHpNextNodeModules, targetHpNextNodeModules);
|
|
6606
6660
|
return;
|
|
6607
6661
|
}
|
|
6608
|
-
if (
|
|
6662
|
+
if (existsSync29(sourceMonorepoNodeModules)) {
|
|
6609
6663
|
runtimeLinkDependencyLayerNative(sourceMonorepoNodeModules, targetHpNextNodeModules);
|
|
6610
6664
|
}
|
|
6611
6665
|
}
|
|
6612
6666
|
function linkGenericNodeModulesLayers(monorepoRoot, workspaceDir) {
|
|
6613
|
-
linkNodeModulesLayer(
|
|
6667
|
+
linkNodeModulesLayer(resolve30(monorepoRoot, "node_modules"), resolve30(workspaceDir, "node_modules"));
|
|
6614
6668
|
for (const relativePackageDir of [
|
|
6615
6669
|
"apps/native-app/apps/marketing",
|
|
6616
6670
|
"apps/native-app/apps/web",
|
|
@@ -6632,15 +6686,15 @@ function linkGenericNodeModulesLayers(monorepoRoot, workspaceDir) {
|
|
|
6632
6686
|
"packages/standard-plugin",
|
|
6633
6687
|
"packages/validator-kit"
|
|
6634
6688
|
]) {
|
|
6635
|
-
const workspacePackageDir =
|
|
6636
|
-
if (!
|
|
6689
|
+
const workspacePackageDir = resolve30(workspaceDir, relativePackageDir);
|
|
6690
|
+
if (!existsSync29(resolve30(workspacePackageDir, "package.json"))) {
|
|
6637
6691
|
continue;
|
|
6638
6692
|
}
|
|
6639
|
-
linkNodeModulesLayer(
|
|
6693
|
+
linkNodeModulesLayer(resolve30(monorepoRoot, relativePackageDir, "node_modules"), resolve30(workspacePackageDir, "node_modules"));
|
|
6640
6694
|
}
|
|
6641
6695
|
}
|
|
6642
6696
|
function linkNodeModulesLayer(sourceDir, targetDir) {
|
|
6643
|
-
if (!
|
|
6697
|
+
if (!existsSync29(sourceDir) || existsSync29(targetDir)) {
|
|
6644
6698
|
return;
|
|
6645
6699
|
}
|
|
6646
6700
|
try {
|
|
@@ -6649,16 +6703,16 @@ function linkNodeModulesLayer(sourceDir, targetDir) {
|
|
|
6649
6703
|
} catch (error) {
|
|
6650
6704
|
console.warn(`[rig-agent] Native dependency-layer linking failed for ${targetDir}; using symlink fallback: ${error instanceof Error ? error.message : String(error)}`);
|
|
6651
6705
|
}
|
|
6652
|
-
|
|
6706
|
+
mkdirSync16(dirname13(targetDir), { recursive: true });
|
|
6653
6707
|
symlinkSync4(sourceDir, targetDir, "dir");
|
|
6654
6708
|
}
|
|
6655
6709
|
function ensureRuntimeBinTrees(runtimeBinDir) {
|
|
6656
|
-
const hooksDir =
|
|
6657
|
-
const pluginsDir =
|
|
6658
|
-
const validatorsDir =
|
|
6659
|
-
|
|
6660
|
-
|
|
6661
|
-
|
|
6710
|
+
const hooksDir = resolve30(runtimeBinDir, "hooks");
|
|
6711
|
+
const pluginsDir = resolve30(runtimeBinDir, "plugins");
|
|
6712
|
+
const validatorsDir = resolve30(runtimeBinDir, "validators");
|
|
6713
|
+
mkdirSync16(hooksDir, { recursive: true });
|
|
6714
|
+
mkdirSync16(pluginsDir, { recursive: true });
|
|
6715
|
+
mkdirSync16(validatorsDir, { recursive: true });
|
|
6662
6716
|
return { hooksDir, pluginsDir, validatorsDir };
|
|
6663
6717
|
}
|
|
6664
6718
|
function runtimeWorktreeId(workspaceDir) {
|
|
@@ -6667,7 +6721,7 @@ function runtimeWorktreeId(workspaceDir) {
|
|
|
6667
6721
|
|
|
6668
6722
|
// packages/runtime/src/control-plane/runtime/isolation/discovery.ts
|
|
6669
6723
|
async function readRuntimeMetadata(metadataPath) {
|
|
6670
|
-
if (!
|
|
6724
|
+
if (!existsSync30(metadataPath)) {
|
|
6671
6725
|
return null;
|
|
6672
6726
|
}
|
|
6673
6727
|
try {
|
|
@@ -6679,8 +6733,8 @@ async function readRuntimeMetadata(metadataPath) {
|
|
|
6679
6733
|
async function listAgentRuntimes(projectRoot) {
|
|
6680
6734
|
const runtimes = [];
|
|
6681
6735
|
const monorepoRoot = resolveMonorepoRoot3(projectRoot);
|
|
6682
|
-
const worktreesRoot =
|
|
6683
|
-
if (!
|
|
6736
|
+
const worktreesRoot = resolve31(monorepoRoot, ".worktrees");
|
|
6737
|
+
if (!existsSync30(worktreesRoot)) {
|
|
6684
6738
|
return [];
|
|
6685
6739
|
}
|
|
6686
6740
|
const workspaces = runtimeScanWorktreesNative(worktreesRoot);
|
|
@@ -6688,7 +6742,7 @@ async function listAgentRuntimes(projectRoot) {
|
|
|
6688
6742
|
let workspacePath = scan.workspaceDir;
|
|
6689
6743
|
const workspaceLayout = resolveRuntimeWorkspaceLayout(workspacePath);
|
|
6690
6744
|
const rootDir = scan.runtimeDir || workspaceLayout.runtimeDir;
|
|
6691
|
-
const metadataPath = scan.metadataPath ||
|
|
6745
|
+
const metadataPath = scan.metadataPath || resolve31(rootDir, "runtime.json");
|
|
6692
6746
|
const contextFile = scan.contextPath || workspaceLayout.contextPath;
|
|
6693
6747
|
let mode = "worktree";
|
|
6694
6748
|
let createdAt = new Date().toISOString();
|
|
@@ -6704,7 +6758,7 @@ async function listAgentRuntimes(projectRoot) {
|
|
|
6704
6758
|
mode = metadata.mode;
|
|
6705
6759
|
createdAt = metadata.createdAt;
|
|
6706
6760
|
}
|
|
6707
|
-
if (
|
|
6761
|
+
if (existsSync30(contextFile)) {
|
|
6708
6762
|
try {
|
|
6709
6763
|
const ctx = loadRuntimeContext(contextFile);
|
|
6710
6764
|
taskId = ctx.taskId;
|
|
@@ -6724,13 +6778,13 @@ async function listAgentRuntimes(projectRoot) {
|
|
|
6724
6778
|
mode,
|
|
6725
6779
|
rootDir,
|
|
6726
6780
|
workspaceDir: workspacePath,
|
|
6727
|
-
homeDir:
|
|
6728
|
-
tmpDir:
|
|
6729
|
-
cacheDir:
|
|
6781
|
+
homeDir: resolve31(rootDir, "home"),
|
|
6782
|
+
tmpDir: resolve31(rootDir, "tmp"),
|
|
6783
|
+
cacheDir: resolve31(rootDir, "cache"),
|
|
6730
6784
|
logsDir,
|
|
6731
6785
|
stateDir,
|
|
6732
6786
|
sessionDir,
|
|
6733
|
-
claudeHomeDir:
|
|
6787
|
+
claudeHomeDir: resolve31(rootDir, "home", ".claude"),
|
|
6734
6788
|
contextFile,
|
|
6735
6789
|
binDir,
|
|
6736
6790
|
createdAt
|
|
@@ -6744,22 +6798,22 @@ function runtimeRootForCleanup(projectRoot, runtimeId) {
|
|
|
6744
6798
|
monorepoRoot = resolveMonorepoRoot3(projectRoot);
|
|
6745
6799
|
} catch {}
|
|
6746
6800
|
const workspaceRootCandidate = monorepoRoot ?? projectRoot;
|
|
6747
|
-
const initialWorkspaceDir =
|
|
6801
|
+
const initialWorkspaceDir = resolve31(workspaceRootCandidate, ".worktrees", runtimeWorktreeNameFromRuntimeId(runtimeId));
|
|
6748
6802
|
const runtimeRoot = resolveRuntimeWorkspaceLayout(initialWorkspaceDir).runtimeDir;
|
|
6749
6803
|
return { monorepoRoot, initialWorkspaceDir, runtimeRoot };
|
|
6750
6804
|
}
|
|
6751
6805
|
|
|
6752
6806
|
// packages/runtime/src/control-plane/runtime/isolation/runner.ts
|
|
6753
|
-
import { existsSync as
|
|
6754
|
-
import { basename as basename9, resolve as
|
|
6807
|
+
import { existsSync as existsSync33, rmSync as rmSync12, writeFileSync as writeFileSync13 } from "fs";
|
|
6808
|
+
import { basename as basename9, resolve as resolve35 } from "path";
|
|
6755
6809
|
|
|
6756
6810
|
// packages/runtime/src/control-plane/runtime/sandbox/backend.ts
|
|
6757
|
-
import { existsSync as
|
|
6811
|
+
import { existsSync as existsSync32 } from "fs";
|
|
6758
6812
|
|
|
6759
6813
|
// packages/runtime/src/control-plane/runtime/guard.ts
|
|
6760
6814
|
import { optimizeNextInvocation } from "bun:jsc";
|
|
6761
|
-
import { existsSync as
|
|
6762
|
-
import { resolve as
|
|
6815
|
+
import { existsSync as existsSync31, readFileSync as readFileSync15, statSync as statSync9 } from "fs";
|
|
6816
|
+
import { resolve as resolve32 } from "path";
|
|
6763
6817
|
|
|
6764
6818
|
// packages/runtime/src/control-plane/runtime/guard-types.ts
|
|
6765
6819
|
var POLICY_VERSION = 1;
|
|
@@ -6822,8 +6876,8 @@ function loadPolicy(projectRoot) {
|
|
|
6822
6876
|
if (seededPolicyConfig) {
|
|
6823
6877
|
return seededPolicyConfig;
|
|
6824
6878
|
}
|
|
6825
|
-
const configPath =
|
|
6826
|
-
if (!
|
|
6879
|
+
const configPath = resolve32(projectRoot, "rig/policy/policy.json");
|
|
6880
|
+
if (!existsSync31(configPath)) {
|
|
6827
6881
|
return defaultPolicy();
|
|
6828
6882
|
}
|
|
6829
6883
|
let mtimeMs;
|
|
@@ -6837,7 +6891,7 @@ function loadPolicy(projectRoot) {
|
|
|
6837
6891
|
}
|
|
6838
6892
|
let parsed;
|
|
6839
6893
|
try {
|
|
6840
|
-
parsed = JSON.parse(
|
|
6894
|
+
parsed = JSON.parse(readFileSync15(configPath, "utf-8"));
|
|
6841
6895
|
} catch {
|
|
6842
6896
|
return defaultPolicy();
|
|
6843
6897
|
}
|
|
@@ -7053,28 +7107,28 @@ function resolveAction(mode, matched) {
|
|
|
7053
7107
|
}
|
|
7054
7108
|
function resolveAbsolutePath(projectRoot, rawPath) {
|
|
7055
7109
|
if (rawPath.startsWith("/"))
|
|
7056
|
-
return
|
|
7057
|
-
return
|
|
7110
|
+
return resolve32(rawPath);
|
|
7111
|
+
return resolve32(projectRoot, rawPath);
|
|
7058
7112
|
}
|
|
7059
7113
|
function isHarnessPath(projectRoot, rawPath) {
|
|
7060
7114
|
const absPath = resolveAbsolutePath(projectRoot, rawPath);
|
|
7061
7115
|
const managedRoots = [
|
|
7062
|
-
|
|
7063
|
-
|
|
7064
|
-
|
|
7116
|
+
resolve32(projectRoot, "rig"),
|
|
7117
|
+
resolve32(projectRoot, ".rig"),
|
|
7118
|
+
resolve32(projectRoot, "artifacts")
|
|
7065
7119
|
];
|
|
7066
7120
|
return managedRoots.some((root) => absPath === root || absPath.startsWith(root + "/"));
|
|
7067
7121
|
}
|
|
7068
7122
|
function isRuntimePath(projectRoot, rawPath, taskWorkspace) {
|
|
7069
7123
|
const absPath = resolveAbsolutePath(projectRoot, rawPath);
|
|
7070
7124
|
if (taskWorkspace) {
|
|
7071
|
-
const workspaceRigRoot =
|
|
7072
|
-
const workspaceArtifactsRoot =
|
|
7125
|
+
const workspaceRigRoot = resolve32(taskWorkspace, ".rig");
|
|
7126
|
+
const workspaceArtifactsRoot = resolve32(taskWorkspace, "artifacts");
|
|
7073
7127
|
if (absPath === workspaceRigRoot || absPath.startsWith(workspaceRigRoot + "/") || absPath === workspaceArtifactsRoot || absPath.startsWith(workspaceArtifactsRoot + "/")) {
|
|
7074
7128
|
return true;
|
|
7075
7129
|
}
|
|
7076
7130
|
}
|
|
7077
|
-
const runtimeRoot =
|
|
7131
|
+
const runtimeRoot = resolve32(projectRoot, ".rig/runtime/agents");
|
|
7078
7132
|
return absPath === runtimeRoot || absPath.startsWith(runtimeRoot + "/");
|
|
7079
7133
|
}
|
|
7080
7134
|
function isTestFile(path) {
|
|
@@ -7122,7 +7176,7 @@ function evaluateScope(policy, context, filePath, access) {
|
|
|
7122
7176
|
return allowed();
|
|
7123
7177
|
}
|
|
7124
7178
|
if (context.taskWorkspace && context.taskWorkspace !== context.projectRoot && filePath.startsWith("/")) {
|
|
7125
|
-
const absPath =
|
|
7179
|
+
const absPath = resolve32(filePath);
|
|
7126
7180
|
if (!absPath.startsWith(context.taskWorkspace + "/") && !isHarnessPath(context.projectRoot, filePath)) {
|
|
7127
7181
|
const reason2 = `Absolute path '${filePath}' is outside task runtime boundary. Allowed root: ${context.taskWorkspace}`;
|
|
7128
7182
|
const matched2 = [{ id: "scope:workspace-boundary", category: "command", reason: reason2 }];
|
|
@@ -7447,13 +7501,13 @@ async function resolveBackend(projectRoot, options) {
|
|
|
7447
7501
|
depRoots
|
|
7448
7502
|
};
|
|
7449
7503
|
const fsContext = {
|
|
7450
|
-
pathExists: (p) =>
|
|
7504
|
+
pathExists: (p) => existsSync32(p),
|
|
7451
7505
|
realPath: toRealPath
|
|
7452
7506
|
};
|
|
7453
7507
|
if (process.platform === "darwin" && (!requestedBackend || requestedBackend === "macos-seatbelt")) {
|
|
7454
7508
|
const seatbelt = Bun.which("sandbox-exec");
|
|
7455
7509
|
probed.push("sandbox-exec");
|
|
7456
|
-
if (seatbelt &&
|
|
7510
|
+
if (seatbelt && existsSync32(seatbelt)) {
|
|
7457
7511
|
const SeatbeltBackendClass = loadSeatbeltBackend();
|
|
7458
7512
|
if (SeatbeltBackendClass) {
|
|
7459
7513
|
return {
|
|
@@ -7574,10 +7628,10 @@ init_layout();
|
|
|
7574
7628
|
var SNAPSHOT_SIDECAR_READY_TIMEOUT_MS = 1e4;
|
|
7575
7629
|
async function startRuntimeSnapshotSidecar(runtime, options = {}) {
|
|
7576
7630
|
const instanceId = sanitizeRuntimeRefSegment(options.instanceId?.trim() || runtime.id);
|
|
7577
|
-
const readyFile =
|
|
7578
|
-
const requestFile =
|
|
7579
|
-
|
|
7580
|
-
|
|
7631
|
+
const readyFile = resolve35(runtime.stateDir, `runtime-snapshot-sidecar-${instanceId}.ready`);
|
|
7632
|
+
const requestFile = resolve35(runtime.stateDir, `runtime-snapshot-sidecar-${instanceId}.request.json`);
|
|
7633
|
+
rmSync12(readyFile, { force: true });
|
|
7634
|
+
rmSync12(requestFile, { force: true });
|
|
7581
7635
|
const sidecarBinary = resolveSnapshotSidecarBinaryPath(runtime.binDir);
|
|
7582
7636
|
const useCompiledSidecar = shouldUseCompiledSnapshotSidecar(sidecarBinary);
|
|
7583
7637
|
const bunCli = useCompiledSidecar ? null : resolveBunCliInvocation();
|
|
@@ -7615,19 +7669,19 @@ async function startRuntimeSnapshotSidecar(runtime, options = {}) {
|
|
|
7615
7669
|
proc.kill("SIGTERM");
|
|
7616
7670
|
} catch {}
|
|
7617
7671
|
await proc.exited;
|
|
7618
|
-
|
|
7619
|
-
|
|
7672
|
+
rmSync12(readyFile, { force: true });
|
|
7673
|
+
rmSync12(requestFile, { force: true });
|
|
7620
7674
|
},
|
|
7621
7675
|
finalize: async (commandParts, exitCode) => {
|
|
7622
|
-
|
|
7676
|
+
writeFileSync13(requestFile, `${JSON.stringify({ command: commandParts, exitCode })}
|
|
7623
7677
|
`, "utf-8");
|
|
7624
7678
|
const [sidecarExitCode, stdout, stderr] = await Promise.all([
|
|
7625
7679
|
proc.exited,
|
|
7626
7680
|
stdoutTextPromise,
|
|
7627
7681
|
stderrTextPromise
|
|
7628
7682
|
]);
|
|
7629
|
-
|
|
7630
|
-
|
|
7683
|
+
rmSync12(readyFile, { force: true });
|
|
7684
|
+
rmSync12(requestFile, { force: true });
|
|
7631
7685
|
if (sidecarExitCode !== 0) {
|
|
7632
7686
|
throw new Error(`snapshot sidecar failed (${sidecarExitCode}): ${stderr || stdout}`);
|
|
7633
7687
|
}
|
|
@@ -7683,8 +7737,8 @@ async function runInAgentRuntime(options) {
|
|
|
7683
7737
|
const stdout = await new Response(proc.stdout).text();
|
|
7684
7738
|
const stderr = await new Response(proc.stderr).text();
|
|
7685
7739
|
try {
|
|
7686
|
-
await Bun.write(
|
|
7687
|
-
await Bun.write(
|
|
7740
|
+
await Bun.write(resolve35(options.runtime.logsDir, "agent-stdout.log"), stdout);
|
|
7741
|
+
await Bun.write(resolve35(options.runtime.logsDir, "agent-stderr.log"), stderr);
|
|
7688
7742
|
} catch {}
|
|
7689
7743
|
await snapshotSidecar.finalize(runtimeCommand, exitCode);
|
|
7690
7744
|
return {
|
|
@@ -7714,18 +7768,18 @@ function resolveInternalRuntimeCommand(command) {
|
|
|
7714
7768
|
}
|
|
7715
7769
|
async function cleanupAgentRuntime(options) {
|
|
7716
7770
|
const { monorepoRoot, initialWorkspaceDir, runtimeRoot } = runtimeRootForCleanup(options.projectRoot, options.id);
|
|
7717
|
-
const metadataPath =
|
|
7718
|
-
if (!
|
|
7771
|
+
const metadataPath = resolve35(runtimeRoot, "runtime.json");
|
|
7772
|
+
if (!existsSync33(runtimeRoot)) {
|
|
7719
7773
|
return;
|
|
7720
7774
|
}
|
|
7721
7775
|
let mode = "worktree";
|
|
7722
7776
|
let workspaceDir = "";
|
|
7723
7777
|
const metadata = await readRuntimeMetadata2(metadataPath);
|
|
7724
|
-
const metadataMatchesRequestedRuntime = metadata !== null && metadata.id === options.id &&
|
|
7778
|
+
const metadataMatchesRequestedRuntime = metadata !== null && metadata.id === options.id && resolve35(metadata.workspaceDir) === resolve35(initialWorkspaceDir);
|
|
7725
7779
|
if (metadata && metadataMatchesRequestedRuntime) {
|
|
7726
7780
|
mode = metadata.mode;
|
|
7727
7781
|
workspaceDir = metadata.workspaceDir;
|
|
7728
|
-
} else if (
|
|
7782
|
+
} else if (existsSync33(initialWorkspaceDir)) {
|
|
7729
7783
|
workspaceDir = initialWorkspaceDir;
|
|
7730
7784
|
}
|
|
7731
7785
|
const preservesTaskWorktree = metadataMatchesRequestedRuntime && metadata ? options.id === taskRuntimeId(metadata.taskId) : false;
|
|
@@ -7734,7 +7788,7 @@ async function cleanupAgentRuntime(options) {
|
|
|
7734
7788
|
} else if (mode === "worktree" && workspaceDir && preservesTaskWorktree) {
|
|
7735
7789
|
cleanupTaskRuntimeOverlay(workspaceDir);
|
|
7736
7790
|
}
|
|
7737
|
-
|
|
7791
|
+
rmSync12(runtimeRoot, { recursive: true, force: true });
|
|
7738
7792
|
}
|
|
7739
7793
|
function cleanupTaskRuntimeOverlay(workspaceDir) {
|
|
7740
7794
|
const layout = resolveRuntimeWorkspaceLayout(workspaceDir);
|
|
@@ -7750,17 +7804,17 @@ function cleanupTaskRuntimeOverlay(workspaceDir) {
|
|
|
7750
7804
|
layout.runtimeDir,
|
|
7751
7805
|
layout.contextPath
|
|
7752
7806
|
]) {
|
|
7753
|
-
|
|
7807
|
+
rmSync12(path, { recursive: true, force: true });
|
|
7754
7808
|
}
|
|
7755
7809
|
}
|
|
7756
7810
|
function resolveSnapshotSidecarScriptPath() {
|
|
7757
7811
|
return resolveRuntimeSourceScriptPath("snapshot-sidecar.ts");
|
|
7758
7812
|
}
|
|
7759
7813
|
function resolveSnapshotSidecarBinaryPath(binDir) {
|
|
7760
|
-
return
|
|
7814
|
+
return resolve35(binDir, "snapshot-sidecar");
|
|
7761
7815
|
}
|
|
7762
7816
|
function shouldUseCompiledSnapshotSidecar(binaryPath) {
|
|
7763
|
-
if (!
|
|
7817
|
+
if (!existsSync33(binaryPath)) {
|
|
7764
7818
|
return false;
|
|
7765
7819
|
}
|
|
7766
7820
|
const preference = process.env.RIG_USE_COMPILED_SNAPSHOT_SIDECAR?.trim().toLowerCase();
|
|
@@ -7775,12 +7829,12 @@ function resolveRuntimeSourceScriptPath(fileName) {
|
|
|
7775
7829
|
process.env.PROJECT_RIG_ROOT?.trim()
|
|
7776
7830
|
].filter((value) => Boolean(value));
|
|
7777
7831
|
for (const root of hostRoots) {
|
|
7778
|
-
const candidate =
|
|
7779
|
-
if (
|
|
7832
|
+
const candidate = resolve35(root, "packages/runtime/src/control-plane/runtime", fileName);
|
|
7833
|
+
if (existsSync33(candidate)) {
|
|
7780
7834
|
return candidate;
|
|
7781
7835
|
}
|
|
7782
7836
|
}
|
|
7783
|
-
return
|
|
7837
|
+
return resolve35(import.meta.dir, "..", fileName);
|
|
7784
7838
|
}
|
|
7785
7839
|
function resolveBunCliInvocation() {
|
|
7786
7840
|
if (process.env.RIG_BUN_PATH?.trim()) {
|
|
@@ -7807,7 +7861,7 @@ function resolveBunCliInvocation() {
|
|
|
7807
7861
|
async function waitForSnapshotSidecarReady(readyFile, proc, stdoutTextPromise, stderrTextPromise) {
|
|
7808
7862
|
const deadline = Date.now() + SNAPSHOT_SIDECAR_READY_TIMEOUT_MS;
|
|
7809
7863
|
while (Date.now() < deadline) {
|
|
7810
|
-
if (
|
|
7864
|
+
if (existsSync33(readyFile)) {
|
|
7811
7865
|
return;
|
|
7812
7866
|
}
|
|
7813
7867
|
const exitCode = proc.exitCode;
|
|
@@ -7820,7 +7874,7 @@ async function waitForSnapshotSidecarReady(readyFile, proc, stdoutTextPromise, s
|
|
|
7820
7874
|
throw new Error(`snapshot sidecar did not become ready within ${SNAPSHOT_SIDECAR_READY_TIMEOUT_MS}ms`);
|
|
7821
7875
|
}
|
|
7822
7876
|
async function readRuntimeMetadata2(metadataPath) {
|
|
7823
|
-
if (!
|
|
7877
|
+
if (!existsSync33(metadataPath)) {
|
|
7824
7878
|
return null;
|
|
7825
7879
|
}
|
|
7826
7880
|
try {
|
|
@@ -7835,9 +7889,9 @@ var CANONICAL_MEMORY_DB_PATH2 = "rig/memory/project-memory.db";
|
|
|
7835
7889
|
async function hydrateRuntimeMemory(options) {
|
|
7836
7890
|
const snapshot = await readCanonicalMemoryDb(options.projectRoot);
|
|
7837
7891
|
const workspaceLayout = resolveRuntimeWorkspaceLayout(options.workspaceDir);
|
|
7838
|
-
const hydratedPath =
|
|
7892
|
+
const hydratedPath = resolve36(workspaceLayout.stateDir, "memory", "project-memory.db");
|
|
7839
7893
|
try {
|
|
7840
|
-
await mkdir3(
|
|
7894
|
+
await mkdir3(resolve36(workspaceLayout.stateDir, "memory"), { recursive: true });
|
|
7841
7895
|
await copyFile(snapshot.dbPath, hydratedPath);
|
|
7842
7896
|
return {
|
|
7843
7897
|
canonicalPath: CANONICAL_MEMORY_DB_PATH2,
|
|
@@ -7852,12 +7906,12 @@ async function hydrateRuntimeMemory(options) {
|
|
|
7852
7906
|
}
|
|
7853
7907
|
}
|
|
7854
7908
|
async function createRuntimeTaskRecordReader(options) {
|
|
7855
|
-
const legacyConfigPath =
|
|
7909
|
+
const legacyConfigPath = resolve36(options.projectRoot, ".rig", "task-config.json");
|
|
7856
7910
|
let pluginHostContext = null;
|
|
7857
7911
|
try {
|
|
7858
7912
|
pluginHostContext = await buildPluginHostContext(options.projectRoot);
|
|
7859
7913
|
} catch (error) {
|
|
7860
|
-
if (!
|
|
7914
|
+
if (!existsSync34(legacyConfigPath)) {
|
|
7861
7915
|
throw error;
|
|
7862
7916
|
}
|
|
7863
7917
|
const message = `Plugin task source unavailable; using source-aware .rig/task-config.json compatibility path: ${error instanceof Error ? error.message : String(error)}`;
|
|
@@ -7877,7 +7931,7 @@ async function createRuntimeTaskRecordReader(options) {
|
|
|
7877
7931
|
source: "plugin"
|
|
7878
7932
|
};
|
|
7879
7933
|
}
|
|
7880
|
-
if (
|
|
7934
|
+
if (existsSync34(legacyConfigPath)) {
|
|
7881
7935
|
const message = "Using source-aware .rig/task-config.json task source compatibility path";
|
|
7882
7936
|
options.diagnostics?.(message);
|
|
7883
7937
|
console.warn(message);
|
|
@@ -7894,10 +7948,10 @@ async function createRuntimeTaskRecordReader(options) {
|
|
|
7894
7948
|
};
|
|
7895
7949
|
}
|
|
7896
7950
|
function readConfiguredTaskSourceKindHint(projectRoot) {
|
|
7897
|
-
const jsonPath =
|
|
7898
|
-
if (
|
|
7951
|
+
const jsonPath = resolve36(projectRoot, "rig.config.json");
|
|
7952
|
+
if (existsSync34(jsonPath)) {
|
|
7899
7953
|
try {
|
|
7900
|
-
const parsed = JSON.parse(
|
|
7954
|
+
const parsed = JSON.parse(readFileSync16(jsonPath, "utf8"));
|
|
7901
7955
|
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
7902
7956
|
const taskSource = parsed.taskSource;
|
|
7903
7957
|
if (taskSource && typeof taskSource === "object" && !Array.isArray(taskSource)) {
|
|
@@ -7909,12 +7963,12 @@ function readConfiguredTaskSourceKindHint(projectRoot) {
|
|
|
7909
7963
|
return null;
|
|
7910
7964
|
}
|
|
7911
7965
|
}
|
|
7912
|
-
const tsPath =
|
|
7913
|
-
if (!
|
|
7966
|
+
const tsPath = resolve36(projectRoot, "rig.config.ts");
|
|
7967
|
+
if (!existsSync34(tsPath)) {
|
|
7914
7968
|
return null;
|
|
7915
7969
|
}
|
|
7916
7970
|
try {
|
|
7917
|
-
const source =
|
|
7971
|
+
const source = readFileSync16(tsPath, "utf8");
|
|
7918
7972
|
const taskSourceBlock = source.match(/taskSource\s*:\s*\{[\s\S]*?\}/m)?.[0] ?? "";
|
|
7919
7973
|
const kind = taskSourceBlock.match(/kind\s*:\s*["']([^"']+)["']/)?.[1];
|
|
7920
7974
|
return kind ?? null;
|
|
@@ -7984,8 +8038,8 @@ async function writeRuntimeTaskConfigProjection(options) {
|
|
|
7984
8038
|
...options.taskEntry.validation && options.taskEntry.validation.length > 0 ? { validation: options.taskEntry.validation } : {},
|
|
7985
8039
|
...options.taskEntry.browser ? { browser: options.taskEntry.browser } : {}
|
|
7986
8040
|
};
|
|
7987
|
-
const configPath =
|
|
7988
|
-
await mkdir3(
|
|
8041
|
+
const configPath = resolve36(options.workspaceDir, ".rig", "task-config.json");
|
|
8042
|
+
await mkdir3(resolve36(options.workspaceDir, ".rig"), { recursive: true });
|
|
7989
8043
|
await writeFile2(configPath, `${JSON.stringify({ [options.task.id]: entry }, null, 2)}
|
|
7990
8044
|
`, "utf-8");
|
|
7991
8045
|
}
|
|
@@ -8049,9 +8103,9 @@ async function ensureAgentRuntime(options) {
|
|
|
8049
8103
|
}
|
|
8050
8104
|
ensureProvisioningHostProjectRootEnv(options.projectRoot);
|
|
8051
8105
|
const monorepoRoot = resolveMonorepoRoot3(options.projectRoot);
|
|
8052
|
-
const workspaceDir =
|
|
8106
|
+
const workspaceDir = resolve36(monorepoRoot, ".worktrees", runtimeWorktreeName(options.taskId, options.id));
|
|
8053
8107
|
const createdAt = new Date().toISOString();
|
|
8054
|
-
if (!
|
|
8108
|
+
if (!existsSync34(resolve36(monorepoRoot, ".git"))) {
|
|
8055
8109
|
throw new Error(`Monorepo root is not a git checkout: ${monorepoRoot}`);
|
|
8056
8110
|
}
|
|
8057
8111
|
const taskResolution = await resolveRuntimeTaskRecord({
|
|
@@ -8086,7 +8140,7 @@ async function ensureAgentRuntime(options) {
|
|
|
8086
8140
|
logsDir: overlay.logsDir,
|
|
8087
8141
|
stateDir: overlay.stateDir,
|
|
8088
8142
|
sessionDir: overlay.sessionDir,
|
|
8089
|
-
claudeHomeDir:
|
|
8143
|
+
claudeHomeDir: resolve36(workspaceLayout.homeDir, ".claude"),
|
|
8090
8144
|
contextFile: overlay.contextPath,
|
|
8091
8145
|
binDir: workspaceLayout.binDir,
|
|
8092
8146
|
createdAt
|
|
@@ -8099,8 +8153,8 @@ async function ensureAgentRuntime(options) {
|
|
|
8099
8153
|
projectRoot: options.projectRoot,
|
|
8100
8154
|
workspaceDir
|
|
8101
8155
|
});
|
|
8102
|
-
|
|
8103
|
-
|
|
8156
|
+
mkdirSync19(runtime.binDir, { recursive: true });
|
|
8157
|
+
mkdirSync19(workspaceLayout.distDir, { recursive: true });
|
|
8104
8158
|
prepareRuntimeWorkspace(options.projectRoot, workspaceDir);
|
|
8105
8159
|
if (options.preserveTaskArtifacts) {
|
|
8106
8160
|
console.log(`[rig-agent] Preserving runtime task artifacts for resume of ${options.taskId}.`);
|
|
@@ -8119,7 +8173,7 @@ async function ensureAgentRuntime(options) {
|
|
|
8119
8173
|
runtimeId: options.id
|
|
8120
8174
|
}),
|
|
8121
8175
|
workspaceDir,
|
|
8122
|
-
artifactRoot:
|
|
8176
|
+
artifactRoot: resolve36(workspaceDir, "artifacts", options.taskId),
|
|
8123
8177
|
hostProjectRoot: options.projectRoot,
|
|
8124
8178
|
monorepoMainRoot: monorepoRoot,
|
|
8125
8179
|
monorepoBaseRef: baseRef,
|
|
@@ -8135,8 +8189,8 @@ async function ensureAgentRuntime(options) {
|
|
|
8135
8189
|
stateDir: overlay.stateDir,
|
|
8136
8190
|
logsDir: overlay.logsDir,
|
|
8137
8191
|
sessionDir: overlay.sessionDir,
|
|
8138
|
-
sessionFile:
|
|
8139
|
-
policyFile:
|
|
8192
|
+
sessionFile: resolve36(overlay.sessionDir, "session.json"),
|
|
8193
|
+
policyFile: resolve36(options.projectRoot, "rig/policy/policy.json"),
|
|
8140
8194
|
binDir: runtime.binDir,
|
|
8141
8195
|
createdAt,
|
|
8142
8196
|
memory
|
|
@@ -8147,9 +8201,9 @@ async function ensureAgentRuntime(options) {
|
|
|
8147
8201
|
task: taskResolution.task,
|
|
8148
8202
|
taskEntry
|
|
8149
8203
|
});
|
|
8150
|
-
const manifestPath =
|
|
8204
|
+
const manifestPath = resolve36(runtimeRoot, "manifest.json");
|
|
8151
8205
|
const bakedScopeHash = sha256Hex(JSON.stringify(taskEntry.scope || []));
|
|
8152
|
-
const runtimeAgentBinary =
|
|
8206
|
+
const runtimeAgentBinary = resolve36(runtime.binDir, "rig-agent");
|
|
8153
8207
|
await ensureRigGitBinaryPath();
|
|
8154
8208
|
const bakedInfoOutput = await captureTaskInfoOutput({
|
|
8155
8209
|
projectRoot: options.projectRoot,
|
|
@@ -8164,10 +8218,10 @@ async function ensureAgentRuntime(options) {
|
|
|
8164
8218
|
const bakedStatusOutput = await captureStdout(async () => {
|
|
8165
8219
|
taskStatus(options.projectRoot);
|
|
8166
8220
|
});
|
|
8167
|
-
|
|
8168
|
-
|
|
8169
|
-
|
|
8170
|
-
|
|
8221
|
+
rmSync13(runtime.binDir, { recursive: true, force: true });
|
|
8222
|
+
rmSync13(workspaceLayout.distDir, { recursive: true, force: true });
|
|
8223
|
+
mkdirSync19(runtime.binDir, { recursive: true });
|
|
8224
|
+
mkdirSync19(workspaceLayout.distDir, { recursive: true });
|
|
8171
8225
|
await buildRuntimeToolchain({
|
|
8172
8226
|
projectRoot: options.projectRoot,
|
|
8173
8227
|
workspaceDir,
|
|
@@ -8204,9 +8258,9 @@ async function ensureAgentRuntime(options) {
|
|
|
8204
8258
|
workspaceDir,
|
|
8205
8259
|
taskEntry
|
|
8206
8260
|
});
|
|
8207
|
-
const sandboxDir =
|
|
8261
|
+
const sandboxDir = resolve36(runtimeRoot, "sandbox");
|
|
8208
8262
|
await mkdir3(sandboxDir, { recursive: true });
|
|
8209
|
-
await writeFile2(
|
|
8263
|
+
await writeFile2(resolve36(runtimeRoot, "runtime.json"), JSON.stringify({
|
|
8210
8264
|
id: options.id,
|
|
8211
8265
|
taskId: options.taskId,
|
|
8212
8266
|
mode: "worktree",
|