@h-rig/runtime 0.0.6-alpha.3 → 0.0.6-alpha.30
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 +1165 -785
- package/dist/bin/rig-agent.js +458 -389
- package/dist/src/control-plane/agent-wrapper.js +1191 -504
- package/dist/src/control-plane/authority-files.js +12 -6
- package/dist/src/control-plane/harness-main.js +2186 -1786
- package/dist/src/control-plane/hooks/completion-verification.js +2084 -1019
- package/dist/src/control-plane/hooks/inject-context.js +193 -139
- package/dist/src/control-plane/hooks/submodule-branch.js +603 -545
- package/dist/src/control-plane/hooks/task-runtime-start.js +603 -545
- package/dist/src/control-plane/materialize-task-config.js +64 -8
- package/dist/src/control-plane/native/git-ops.js +90 -64
- package/dist/src/control-plane/native/harness-cli.js +1989 -682
- package/dist/src/control-plane/native/pr-automation.js +1657 -54
- package/dist/src/control-plane/native/pr-review-gate.js +1455 -0
- package/dist/src/control-plane/native/repo-ops.js +3 -0
- package/dist/src/control-plane/native/run-ops.js +39 -13
- package/dist/src/control-plane/native/task-ops.js +1819 -527
- package/dist/src/control-plane/native/validator.js +163 -109
- package/dist/src/control-plane/native/verifier.js +1616 -323
- package/dist/src/control-plane/native/workspace-ops.js +12 -6
- package/dist/src/control-plane/pi-sessiond/bin.js +793 -0
- package/dist/src/control-plane/pi-sessiond/client.js +41 -0
- package/dist/src/control-plane/pi-sessiond/event-hub.js +59 -0
- package/dist/src/control-plane/pi-sessiond/extension-ui-context.js +198 -0
- package/dist/src/control-plane/pi-sessiond/launcher.js +173 -0
- package/dist/src/control-plane/pi-sessiond/server.js +802 -0
- package/dist/src/control-plane/pi-sessiond/session-service.js +540 -0
- package/dist/src/control-plane/pi-sessiond/types.js +1 -0
- 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 +517 -722
- package/dist/src/control-plane/runtime/isolation/home.js +28 -6
- package/dist/src/control-plane/runtime/isolation/index.js +541 -461
- package/dist/src/control-plane/runtime/isolation/runner.js +28 -6
- package/dist/src/control-plane/runtime/isolation/shared.js +9 -6
- package/dist/src/control-plane/runtime/isolation.js +541 -461
- package/dist/src/control-plane/runtime/plugin-mode.js +3 -27
- package/dist/src/control-plane/runtime/queue.js +458 -385
- 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-aware-task-config-source.js +14 -2
- package/dist/src/control-plane/tasks/source-lifecycle.js +86 -32
- package/dist/src/index.js +27 -298
- package/dist/src/layout.js +12 -7
- package/dist/src/local-server.js +20 -14
- package/native/darwin-arm64/rig-git +0 -0
- package/native/darwin-arm64/rig-git.build-manifest.json +1 -1
- 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/native/darwin-arm64/runtime-native.dylib +0 -0
- package/package.json +8 -6
- 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 existsSync21, readdirSync as readdirSync4, realpathSync } from "fs";
|
|
153
|
+
import { resolve as resolve22 } from "path";
|
|
154
154
|
function toRealPath(path) {
|
|
155
|
-
if (!
|
|
156
|
-
return
|
|
155
|
+
if (!existsSync21(path)) {
|
|
156
|
+
return resolve22(path);
|
|
157
157
|
}
|
|
158
158
|
try {
|
|
159
159
|
return realpathSync.native(path);
|
|
160
160
|
} catch {
|
|
161
|
-
return
|
|
161
|
+
return resolve22(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 (existsSync21(candidate)) {
|
|
168
168
|
candidates.add(toRealPath(candidate));
|
|
169
169
|
}
|
|
170
170
|
};
|
|
171
|
-
addPath(
|
|
172
|
-
addPath(
|
|
171
|
+
addPath(resolve22(projectRoot, ".git"));
|
|
172
|
+
addPath(resolve22(workspaceDir, "..", "..", ".git"));
|
|
173
173
|
for (const repoRoot of resolveHostRepoRootPaths(projectRoot)) {
|
|
174
|
-
addPath(
|
|
174
|
+
addPath(resolve22(repoRoot, ".git"));
|
|
175
175
|
}
|
|
176
|
-
const workspaceGit =
|
|
177
|
-
if (
|
|
176
|
+
const workspaceGit = resolve22(workspaceDir, ".git");
|
|
177
|
+
if (existsSync21(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 (existsSync21(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 = resolve22(projectRoot, "repos");
|
|
196
|
+
if (existsSync21(reposDir)) {
|
|
197
|
+
for (const entry of readdirSync4(reposDir, { withFileTypes: true })) {
|
|
198
198
|
if (entry.isDirectory() || entry.isSymbolicLink()) {
|
|
199
|
-
addPath(
|
|
199
|
+
addPath(resolve22(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
|
}
|
|
@@ -567,8 +567,8 @@ var init_backend_bwrap = __esm(() => {
|
|
|
567
567
|
|
|
568
568
|
// packages/runtime/src/control-plane/runtime/queue.ts
|
|
569
569
|
init_layout();
|
|
570
|
-
import { existsSync as
|
|
571
|
-
import { resolve as
|
|
570
|
+
import { existsSync as existsSync34 } from "fs";
|
|
571
|
+
import { resolve as resolve37 } from "path";
|
|
572
572
|
|
|
573
573
|
// packages/runtime/src/control-plane/native/task-state.ts
|
|
574
574
|
import { existsSync as existsSync9, readFileSync as readFileSync5, readdirSync, statSync as statSync2, writeFileSync as writeFileSync3 } from "fs";
|
|
@@ -3029,9 +3029,9 @@ function primeGuardHotPaths() {
|
|
|
3029
3029
|
}
|
|
3030
3030
|
primeGuardHotPaths();
|
|
3031
3031
|
// packages/runtime/src/control-plane/runtime/isolation/index.ts
|
|
3032
|
-
import { existsSync as
|
|
3032
|
+
import { existsSync as existsSync33, mkdirSync as mkdirSync19, readFileSync as readFileSync16, rmSync as rmSync13 } from "fs";
|
|
3033
3033
|
import { copyFile, mkdir as mkdir4, writeFile as writeFile2 } from "fs/promises";
|
|
3034
|
-
import { resolve as
|
|
3034
|
+
import { resolve as resolve36 } from "path";
|
|
3035
3035
|
// packages/runtime/src/control-plane/memory-sync/db.ts
|
|
3036
3036
|
import { Database } from "bun:sqlite";
|
|
3037
3037
|
import { mkdirSync as mkdirSync4 } from "fs";
|
|
@@ -3319,8 +3319,8 @@ async function readCanonicalMemoryDb(projectRoot, deps = {}) {
|
|
|
3319
3319
|
var DEFAULT_RESULT_LIMIT = DEFAULT_RUNTIME_MEMORY_RETRIEVAL.topK;
|
|
3320
3320
|
var DAY_MS = 24 * 60 * 60 * 1000;
|
|
3321
3321
|
// packages/runtime/src/control-plane/native/task-ops.ts
|
|
3322
|
-
import { appendFileSync, existsSync as
|
|
3323
|
-
import { resolve as
|
|
3322
|
+
import { appendFileSync, existsSync as existsSync24, mkdirSync as mkdirSync10, readFileSync as readFileSync12, writeFileSync as writeFileSync9 } from "fs";
|
|
3323
|
+
import { resolve as resolve26 } from "path";
|
|
3324
3324
|
|
|
3325
3325
|
// packages/runtime/src/build-time-config.ts
|
|
3326
3326
|
function normalizeBuildConfig(value) {
|
|
@@ -4122,6 +4122,49 @@ function safeReadJson(path) {
|
|
|
4122
4122
|
}
|
|
4123
4123
|
}
|
|
4124
4124
|
|
|
4125
|
+
// packages/runtime/src/control-plane/skill-materializer.ts
|
|
4126
|
+
import { existsSync as existsSync17, mkdirSync as mkdirSync8, readFileSync as readFileSync8, readdirSync as readdirSync2, rmSync as rmSync7, writeFileSync as writeFileSync6 } from "fs";
|
|
4127
|
+
import { resolve as resolve18 } from "path";
|
|
4128
|
+
import { loadSkill } from "@rig/skill-loader";
|
|
4129
|
+
var MARKER_FILENAME = ".rig-plugin";
|
|
4130
|
+
function skillDirName(id) {
|
|
4131
|
+
return id.replace(/[^a-zA-Z0-9._-]+/g, "-");
|
|
4132
|
+
}
|
|
4133
|
+
async function materializeSkills(projectRoot, entries) {
|
|
4134
|
+
const skillsRoot = resolve18(projectRoot, ".pi", "skills");
|
|
4135
|
+
if (existsSync17(skillsRoot)) {
|
|
4136
|
+
for (const name of readdirSync2(skillsRoot)) {
|
|
4137
|
+
const dir = resolve18(skillsRoot, name);
|
|
4138
|
+
if (existsSync17(resolve18(dir, MARKER_FILENAME))) {
|
|
4139
|
+
rmSync7(dir, { recursive: true, force: true });
|
|
4140
|
+
}
|
|
4141
|
+
}
|
|
4142
|
+
}
|
|
4143
|
+
const written = [];
|
|
4144
|
+
for (const { pluginName, skill } of entries) {
|
|
4145
|
+
const sourcePath = resolve18(projectRoot, skill.path);
|
|
4146
|
+
if (!existsSync17(sourcePath)) {
|
|
4147
|
+
console.warn(`[plugin-host] skill "${skill.id}" from plugin "${pluginName}" not materialized: ${sourcePath} does not exist`);
|
|
4148
|
+
continue;
|
|
4149
|
+
}
|
|
4150
|
+
let body;
|
|
4151
|
+
try {
|
|
4152
|
+
await loadSkill(sourcePath);
|
|
4153
|
+
body = readFileSync8(sourcePath, "utf-8");
|
|
4154
|
+
} catch (err) {
|
|
4155
|
+
console.warn(`[plugin-host] skill "${skill.id}" from plugin "${pluginName}" not materialized: ${err instanceof Error ? err.message : err}`);
|
|
4156
|
+
continue;
|
|
4157
|
+
}
|
|
4158
|
+
const dir = resolve18(skillsRoot, skillDirName(skill.id));
|
|
4159
|
+
mkdirSync8(dir, { recursive: true });
|
|
4160
|
+
writeFileSync6(resolve18(dir, "SKILL.md"), body, "utf-8");
|
|
4161
|
+
writeFileSync6(resolve18(dir, MARKER_FILENAME), `${JSON.stringify({ plugin: pluginName, skillId: skill.id }, null, 2)}
|
|
4162
|
+
`, "utf-8");
|
|
4163
|
+
written.push({ id: skill.id, pluginName, directory: dir });
|
|
4164
|
+
}
|
|
4165
|
+
return written;
|
|
4166
|
+
}
|
|
4167
|
+
|
|
4125
4168
|
// packages/runtime/src/control-plane/plugin-host-context.ts
|
|
4126
4169
|
async function buildPluginHostContext(projectRoot) {
|
|
4127
4170
|
let config;
|
|
@@ -4158,6 +4201,17 @@ async function buildPluginHostContext(projectRoot) {
|
|
|
4158
4201
|
} catch (err) {
|
|
4159
4202
|
console.warn(`[plugin-host] hook materialization failed: ${err instanceof Error ? err.message : err}`);
|
|
4160
4203
|
}
|
|
4204
|
+
try {
|
|
4205
|
+
const skillEntries = config.plugins.flatMap((plugin) => (plugin.contributes?.skills ?? []).map((skill) => ({
|
|
4206
|
+
pluginName: plugin.name,
|
|
4207
|
+
skill
|
|
4208
|
+
})));
|
|
4209
|
+
if (skillEntries.length > 0) {
|
|
4210
|
+
await materializeSkills(projectRoot, skillEntries);
|
|
4211
|
+
}
|
|
4212
|
+
} catch (err) {
|
|
4213
|
+
console.warn(`[plugin-host] skill materialization failed: ${err instanceof Error ? err.message : err}`);
|
|
4214
|
+
}
|
|
4161
4215
|
return {
|
|
4162
4216
|
config,
|
|
4163
4217
|
pluginHost,
|
|
@@ -4171,12 +4225,12 @@ async function buildPluginHostContext(projectRoot) {
|
|
|
4171
4225
|
|
|
4172
4226
|
// packages/runtime/src/control-plane/tasks/source-aware-task-config-source.ts
|
|
4173
4227
|
import { spawnSync } from "child_process";
|
|
4174
|
-
import { existsSync as
|
|
4175
|
-
import { basename as basename6, join as join4, resolve as
|
|
4228
|
+
import { existsSync as existsSync19, readFileSync as readFileSync10, readdirSync as readdirSync3, statSync as statSync5, writeFileSync as writeFileSync7 } from "fs";
|
|
4229
|
+
import { basename as basename6, join as join4, resolve as resolve20 } from "path";
|
|
4176
4230
|
|
|
4177
4231
|
// packages/runtime/src/control-plane/tasks/legacy-task-config-source.ts
|
|
4178
|
-
import { existsSync as
|
|
4179
|
-
import { resolve as
|
|
4232
|
+
import { existsSync as existsSync18, readFileSync as readFileSync9 } from "fs";
|
|
4233
|
+
import { resolve as resolve19 } from "path";
|
|
4180
4234
|
|
|
4181
4235
|
// packages/runtime/src/control-plane/tasks/task-record-reader.ts
|
|
4182
4236
|
async function findTaskById(reader, id) {
|
|
@@ -4199,7 +4253,7 @@ class LegacyTaskConfigReadError extends Error {
|
|
|
4199
4253
|
}
|
|
4200
4254
|
}
|
|
4201
4255
|
function createLegacyTaskConfigRecordReader(projectRoot, options = {}) {
|
|
4202
|
-
const configPath = options.configPath ??
|
|
4256
|
+
const configPath = options.configPath ?? resolve19(projectRoot, ".rig", "task-config.json");
|
|
4203
4257
|
const reader = {
|
|
4204
4258
|
async listTasks() {
|
|
4205
4259
|
return readLegacyTaskRecords(projectRoot, configPath);
|
|
@@ -4210,8 +4264,8 @@ function createLegacyTaskConfigRecordReader(projectRoot, options = {}) {
|
|
|
4210
4264
|
};
|
|
4211
4265
|
return reader;
|
|
4212
4266
|
}
|
|
4213
|
-
function readLegacyTaskRecords(projectRoot, configPath =
|
|
4214
|
-
if (!
|
|
4267
|
+
function readLegacyTaskRecords(projectRoot, configPath = resolve19(projectRoot, ".rig", "task-config.json")) {
|
|
4268
|
+
if (!existsSync18(configPath)) {
|
|
4215
4269
|
return [];
|
|
4216
4270
|
}
|
|
4217
4271
|
const rawConfig = readLegacyTaskConfigJson(projectRoot, configPath);
|
|
@@ -4219,7 +4273,7 @@ function readLegacyTaskRecords(projectRoot, configPath = resolve18(projectRoot,
|
|
|
4219
4273
|
}
|
|
4220
4274
|
function readLegacyTaskConfigJson(projectRoot, configPath) {
|
|
4221
4275
|
try {
|
|
4222
|
-
const parsed = JSON.parse(
|
|
4276
|
+
const parsed = JSON.parse(readFileSync9(configPath, "utf8"));
|
|
4223
4277
|
if (isPlainRecord(parsed)) {
|
|
4224
4278
|
return parsed;
|
|
4225
4279
|
}
|
|
@@ -4303,7 +4357,7 @@ function isPlainRecord(candidate) {
|
|
|
4303
4357
|
var STATUS_LABELS = new Set(["ready", "blocked", "in-progress", "under-review", "failed", "cancelled"]);
|
|
4304
4358
|
var FILE_TASK_PATTERN2 = /\.(task\.)?json$/;
|
|
4305
4359
|
function createSourceAwareTaskConfigRecordReader(projectRoot, options = {}) {
|
|
4306
|
-
const configPath = options.configPath ??
|
|
4360
|
+
const configPath = options.configPath ?? resolve20(projectRoot, ".rig", "task-config.json");
|
|
4307
4361
|
const legacy = createLegacyTaskConfigRecordReader(projectRoot, { configPath });
|
|
4308
4362
|
const spawnFn = options.spawn ?? spawnSync;
|
|
4309
4363
|
const ghBinary = options.ghBinary ?? "gh";
|
|
@@ -4386,10 +4440,10 @@ function readMaterializedTaskMetadata(entry) {
|
|
|
4386
4440
|
return metadata;
|
|
4387
4441
|
}
|
|
4388
4442
|
function readConfiguredFilesTaskSourcePath2(projectRoot) {
|
|
4389
|
-
const jsonPath =
|
|
4390
|
-
if (
|
|
4443
|
+
const jsonPath = resolve20(projectRoot, "rig.config.json");
|
|
4444
|
+
if (existsSync19(jsonPath)) {
|
|
4391
4445
|
try {
|
|
4392
|
-
const parsed = JSON.parse(
|
|
4446
|
+
const parsed = JSON.parse(readFileSync10(jsonPath, "utf8"));
|
|
4393
4447
|
if (isPlainRecord2(parsed) && isPlainRecord2(parsed.taskSource)) {
|
|
4394
4448
|
const source = parsed.taskSource;
|
|
4395
4449
|
return source.kind === "files" && typeof source.path === "string" ? source.path : null;
|
|
@@ -4398,12 +4452,12 @@ function readConfiguredFilesTaskSourcePath2(projectRoot) {
|
|
|
4398
4452
|
return null;
|
|
4399
4453
|
}
|
|
4400
4454
|
}
|
|
4401
|
-
const tsPath =
|
|
4402
|
-
if (!
|
|
4455
|
+
const tsPath = resolve20(projectRoot, "rig.config.ts");
|
|
4456
|
+
if (!existsSync19(tsPath)) {
|
|
4403
4457
|
return null;
|
|
4404
4458
|
}
|
|
4405
4459
|
try {
|
|
4406
|
-
const source =
|
|
4460
|
+
const source = readFileSync10(tsPath, "utf8");
|
|
4407
4461
|
const taskSourceBlock = source.match(/taskSource\s*:\s*\{[\s\S]*?\}/m)?.[0] ?? "";
|
|
4408
4462
|
const kind = taskSourceBlock.match(/kind\s*:\s*["']([^"']+)["']/)?.[1];
|
|
4409
4463
|
if (kind !== "files") {
|
|
@@ -4423,10 +4477,10 @@ function readRawTaskEntry(configPath, taskId) {
|
|
|
4423
4477
|
return isPlainRecord2(entry) ? entry : null;
|
|
4424
4478
|
}
|
|
4425
4479
|
function readRawTaskConfig(configPath) {
|
|
4426
|
-
if (!
|
|
4480
|
+
if (!existsSync19(configPath)) {
|
|
4427
4481
|
return null;
|
|
4428
4482
|
}
|
|
4429
|
-
const parsed = JSON.parse(
|
|
4483
|
+
const parsed = JSON.parse(readFileSync10(configPath, "utf8"));
|
|
4430
4484
|
return isPlainRecord2(parsed) ? parsed : null;
|
|
4431
4485
|
}
|
|
4432
4486
|
function stripLegacyTaskConfigMetadata2(raw) {
|
|
@@ -4434,12 +4488,12 @@ function stripLegacyTaskConfigMetadata2(raw) {
|
|
|
4434
4488
|
return tasks;
|
|
4435
4489
|
}
|
|
4436
4490
|
function listFileBackedTasks(projectRoot, sourcePath) {
|
|
4437
|
-
const directory =
|
|
4438
|
-
if (!
|
|
4491
|
+
const directory = resolve20(projectRoot, sourcePath);
|
|
4492
|
+
if (!existsSync19(directory)) {
|
|
4439
4493
|
return [];
|
|
4440
4494
|
}
|
|
4441
4495
|
const tasks = [];
|
|
4442
|
-
for (const name of
|
|
4496
|
+
for (const name of readdirSync3(directory)) {
|
|
4443
4497
|
if (!FILE_TASK_PATTERN2.test(name))
|
|
4444
4498
|
continue;
|
|
4445
4499
|
const inferredId = basename6(name).replace(FILE_TASK_PATTERN2, "");
|
|
@@ -4450,11 +4504,11 @@ function listFileBackedTasks(projectRoot, sourcePath) {
|
|
|
4450
4504
|
return tasks;
|
|
4451
4505
|
}
|
|
4452
4506
|
function readFileBackedTask(projectRoot, sourcePath, taskId, rawEntry) {
|
|
4453
|
-
const file = findFileBackedTaskFile(
|
|
4507
|
+
const file = findFileBackedTaskFile(resolve20(projectRoot, sourcePath), taskId);
|
|
4454
4508
|
if (!file) {
|
|
4455
4509
|
return null;
|
|
4456
4510
|
}
|
|
4457
|
-
const raw = JSON.parse(
|
|
4511
|
+
const raw = JSON.parse(readFileSync10(file, "utf8"));
|
|
4458
4512
|
if (!isPlainRecord2(raw)) {
|
|
4459
4513
|
return null;
|
|
4460
4514
|
}
|
|
@@ -4467,17 +4521,17 @@ function readFileBackedTask(projectRoot, sourcePath, taskId, rawEntry) {
|
|
|
4467
4521
|
};
|
|
4468
4522
|
}
|
|
4469
4523
|
function findFileBackedTaskFile(directory, taskId) {
|
|
4470
|
-
if (!
|
|
4524
|
+
if (!existsSync19(directory)) {
|
|
4471
4525
|
return null;
|
|
4472
4526
|
}
|
|
4473
|
-
for (const name of
|
|
4527
|
+
for (const name of readdirSync3(directory)) {
|
|
4474
4528
|
if (!FILE_TASK_PATTERN2.test(name))
|
|
4475
4529
|
continue;
|
|
4476
4530
|
const file = join4(directory, name);
|
|
4477
4531
|
try {
|
|
4478
4532
|
if (!statSync5(file).isFile())
|
|
4479
4533
|
continue;
|
|
4480
|
-
const raw = JSON.parse(
|
|
4534
|
+
const raw = JSON.parse(readFileSync10(file, "utf8"));
|
|
4481
4535
|
const inferredId = basename6(file).replace(FILE_TASK_PATTERN2, "");
|
|
4482
4536
|
const id = isPlainRecord2(raw) && typeof raw.id === "string" ? raw.id : inferredId;
|
|
4483
4537
|
if (id === taskId) {
|
|
@@ -4560,8 +4614,8 @@ function githubStatusFor(issue) {
|
|
|
4560
4614
|
return "open";
|
|
4561
4615
|
}
|
|
4562
4616
|
function selectedGitHubEnv() {
|
|
4563
|
-
const token = process.env.RIG_GITHUB_SELECTED_TOKEN?.trim()
|
|
4564
|
-
return { GH_TOKEN: token, GITHUB_TOKEN: token };
|
|
4617
|
+
const token = process.env.RIG_GITHUB_SELECTED_TOKEN?.trim() || process.env.RIG_GITHUB_TOKEN?.trim() || "";
|
|
4618
|
+
return { GH_TOKEN: token, GITHUB_TOKEN: token, RIG_GITHUB_TOKEN: token };
|
|
4565
4619
|
}
|
|
4566
4620
|
function ghSpawnOptions() {
|
|
4567
4621
|
return { encoding: "utf-8", env: { ...process.env, ...selectedGitHubEnv() } };
|
|
@@ -4641,8 +4695,8 @@ init_layout();
|
|
|
4641
4695
|
|
|
4642
4696
|
// packages/runtime/src/binary-run.ts
|
|
4643
4697
|
init_layout();
|
|
4644
|
-
import { chmodSync as chmodSync4, cpSync, existsSync as
|
|
4645
|
-
import { basename as basename7, dirname as dirname11, resolve as
|
|
4698
|
+
import { chmodSync as chmodSync4, cpSync, existsSync as existsSync20, mkdirSync as mkdirSync9, renameSync as renameSync3, rmSync as rmSync8, writeFileSync as writeFileSync8 } from "fs";
|
|
4699
|
+
import { basename as basename7, dirname as dirname11, resolve as resolve21 } from "path";
|
|
4646
4700
|
import { fileURLToPath } from "url";
|
|
4647
4701
|
import { drainMicrotasks, gcAndSweep } from "bun:jsc";
|
|
4648
4702
|
var runtimeBinaryBuildQueue = Promise.resolve();
|
|
@@ -4668,9 +4722,9 @@ async function buildRuntimeBinary(options) {
|
|
|
4668
4722
|
});
|
|
4669
4723
|
}
|
|
4670
4724
|
async function buildRuntimeBinaryInProcess(options, manifest) {
|
|
4671
|
-
const tempBuildDir =
|
|
4672
|
-
const tempOutputPath =
|
|
4673
|
-
|
|
4725
|
+
const tempBuildDir = resolve21(dirname11(options.outputPath), `.bun-build-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`);
|
|
4726
|
+
const tempOutputPath = resolve21(tempBuildDir, basename7(options.outputPath));
|
|
4727
|
+
mkdirSync9(tempBuildDir, { recursive: true });
|
|
4674
4728
|
await withTemporaryEnv({
|
|
4675
4729
|
...options.env,
|
|
4676
4730
|
...options.define ? { RIG_BUILD_CONFIG_JSON: JSON.stringify(options.define) } : {}
|
|
@@ -4695,7 +4749,7 @@ async function buildRuntimeBinaryInProcess(options, manifest) {
|
|
|
4695
4749
|
`);
|
|
4696
4750
|
throw new Error(`Failed to build ${options.entrypoint}: ${details || "Bun.build() returned errors"}`);
|
|
4697
4751
|
}
|
|
4698
|
-
if (!
|
|
4752
|
+
if (!existsSync20(tempOutputPath)) {
|
|
4699
4753
|
const emitted = buildResult.outputs.map((output) => output.path).join(", ") || "(none)";
|
|
4700
4754
|
throw new Error(`Failed to build ${options.entrypoint}: Bun.build() did not emit ${tempOutputPath}. Emitted: ${emitted}`);
|
|
4701
4755
|
}
|
|
@@ -4710,7 +4764,7 @@ async function buildRuntimeBinaryInProcess(options, manifest) {
|
|
|
4710
4764
|
});
|
|
4711
4765
|
}
|
|
4712
4766
|
})).finally(() => {
|
|
4713
|
-
|
|
4767
|
+
rmSync8(tempBuildDir, { recursive: true, force: true });
|
|
4714
4768
|
});
|
|
4715
4769
|
}
|
|
4716
4770
|
function runBestEffortBuildGc() {
|
|
@@ -4727,8 +4781,8 @@ function runtimeBinaryCacheManifestPath(outputPath) {
|
|
|
4727
4781
|
function resolveRuntimeBinaryBuildOptions(options) {
|
|
4728
4782
|
return {
|
|
4729
4783
|
...options,
|
|
4730
|
-
entrypoint:
|
|
4731
|
-
outputPath:
|
|
4784
|
+
entrypoint: resolve21(options.cwd, options.sourcePath),
|
|
4785
|
+
outputPath: resolve21(options.outputPath)
|
|
4732
4786
|
};
|
|
4733
4787
|
}
|
|
4734
4788
|
function shouldUseRuntimeBinaryBuildWorker() {
|
|
@@ -4742,7 +4796,7 @@ function shouldUseRuntimeBinaryBuildWorker() {
|
|
|
4742
4796
|
}
|
|
4743
4797
|
async function buildRuntimeBinaryViaWorker(options) {
|
|
4744
4798
|
const workerSourcePath = resolveRuntimeBinaryBuildWorkerSourcePath(options);
|
|
4745
|
-
if (!workerSourcePath || !
|
|
4799
|
+
if (!workerSourcePath || !existsSync20(workerSourcePath)) {
|
|
4746
4800
|
await buildRuntimeBinaryInProcess(options, {
|
|
4747
4801
|
manifestPath: runtimeBinaryCacheManifestPath(options.outputPath),
|
|
4748
4802
|
buildKey: createRuntimeBinaryBuildKey({
|
|
@@ -4773,13 +4827,13 @@ async function buildRuntimeBinaryViaWorker(options) {
|
|
|
4773
4827
|
new Response(build.stdout).text(),
|
|
4774
4828
|
new Response(build.stderr).text()
|
|
4775
4829
|
]);
|
|
4776
|
-
|
|
4830
|
+
rmSync8(payloadPath, { force: true });
|
|
4777
4831
|
if (exitCode !== 0) {
|
|
4778
4832
|
throw new Error(`Failed to build ${options.entrypoint}: ${(stderr || stdout || `worker exited ${exitCode}`).trim()}`);
|
|
4779
4833
|
}
|
|
4780
4834
|
}
|
|
4781
4835
|
function createRuntimeBinaryBuildWorkerPayloadPath(outputPath) {
|
|
4782
|
-
return
|
|
4836
|
+
return resolve21(dirname11(outputPath), `.bun-build-worker-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}.json`);
|
|
4783
4837
|
}
|
|
4784
4838
|
function resolveRuntimeBinaryBuildWorkerSourcePath(options) {
|
|
4785
4839
|
const envRoots = [
|
|
@@ -4788,13 +4842,13 @@ function resolveRuntimeBinaryBuildWorkerSourcePath(options) {
|
|
|
4788
4842
|
process.env.PROJECT_RIG_ROOT?.trim()
|
|
4789
4843
|
].filter(Boolean);
|
|
4790
4844
|
for (const root of envRoots) {
|
|
4791
|
-
const candidate =
|
|
4792
|
-
if (
|
|
4845
|
+
const candidate = resolve21(root, "packages/runtime/src/binary-build-worker.ts");
|
|
4846
|
+
if (existsSync20(candidate)) {
|
|
4793
4847
|
return candidate;
|
|
4794
4848
|
}
|
|
4795
4849
|
}
|
|
4796
|
-
const localCandidate =
|
|
4797
|
-
return
|
|
4850
|
+
const localCandidate = resolve21(import.meta.dir, "binary-build-worker.ts");
|
|
4851
|
+
return existsSync20(localCandidate) ? localCandidate : null;
|
|
4798
4852
|
}
|
|
4799
4853
|
function resolveRuntimeBinaryBuildWorkerInvocation() {
|
|
4800
4854
|
const bunPath = Bun.which("bun");
|
|
@@ -4830,7 +4884,7 @@ function createRuntimeBinaryBuildKey(input) {
|
|
|
4830
4884
|
});
|
|
4831
4885
|
}
|
|
4832
4886
|
async function isRuntimeBinaryBuildFresh(input) {
|
|
4833
|
-
if (!
|
|
4887
|
+
if (!existsSync20(input.outputPath) || !existsSync20(input.manifestPath)) {
|
|
4834
4888
|
return false;
|
|
4835
4889
|
}
|
|
4836
4890
|
let manifest = null;
|
|
@@ -4843,7 +4897,7 @@ async function isRuntimeBinaryBuildFresh(input) {
|
|
|
4843
4897
|
return false;
|
|
4844
4898
|
}
|
|
4845
4899
|
for (const [filePath, expectedDigest] of Object.entries(manifest.inputs || {})) {
|
|
4846
|
-
if (!
|
|
4900
|
+
if (!existsSync20(filePath)) {
|
|
4847
4901
|
return false;
|
|
4848
4902
|
}
|
|
4849
4903
|
if (await sha256File4(filePath) !== expectedDigest) {
|
|
@@ -4856,7 +4910,7 @@ async function writeRuntimeBinaryCacheManifest(input) {
|
|
|
4856
4910
|
const inputs = {};
|
|
4857
4911
|
for (const inputPath of Object.keys(input.metafile?.inputs || {}).sort()) {
|
|
4858
4912
|
const normalized = normalizeBuildInputPath(input.cwd, inputPath);
|
|
4859
|
-
if (!normalized || !
|
|
4913
|
+
if (!normalized || !existsSync20(normalized)) {
|
|
4860
4914
|
continue;
|
|
4861
4915
|
}
|
|
4862
4916
|
inputs[normalized] = await sha256File4(normalized);
|
|
@@ -4879,7 +4933,7 @@ function normalizeBuildInputPath(cwd, inputPath) {
|
|
|
4879
4933
|
if (inputPath.startsWith("<")) {
|
|
4880
4934
|
return null;
|
|
4881
4935
|
}
|
|
4882
|
-
return
|
|
4936
|
+
return resolve21(cwd, inputPath);
|
|
4883
4937
|
}
|
|
4884
4938
|
async function sha256File4(path) {
|
|
4885
4939
|
const hasher = new Bun.CryptoHasher("sha256");
|
|
@@ -4895,8 +4949,8 @@ function sortRecord(value) {
|
|
|
4895
4949
|
async function runSerializedRuntimeBinaryBuild(action) {
|
|
4896
4950
|
const previous = runtimeBinaryBuildQueue;
|
|
4897
4951
|
let release;
|
|
4898
|
-
runtimeBinaryBuildQueue = new Promise((
|
|
4899
|
-
release =
|
|
4952
|
+
runtimeBinaryBuildQueue = new Promise((resolve22) => {
|
|
4953
|
+
release = resolve22;
|
|
4900
4954
|
});
|
|
4901
4955
|
await previous;
|
|
4902
4956
|
try {
|
|
@@ -4941,11 +4995,11 @@ async function withTemporaryCwd(cwd, action) {
|
|
|
4941
4995
|
}
|
|
4942
4996
|
|
|
4943
4997
|
// packages/runtime/src/control-plane/runtime/provisioning-env.ts
|
|
4944
|
-
import { delimiter, resolve as
|
|
4998
|
+
import { delimiter, resolve as resolve24 } from "path";
|
|
4945
4999
|
|
|
4946
5000
|
// packages/runtime/src/control-plane/runtime/runtime-paths.ts
|
|
4947
|
-
import { existsSync as
|
|
4948
|
-
import { resolve as
|
|
5001
|
+
import { existsSync as existsSync22, readdirSync as readdirSync5, realpathSync as realpathSync2 } from "fs";
|
|
5002
|
+
import { resolve as resolve23 } from "path";
|
|
4949
5003
|
|
|
4950
5004
|
// packages/runtime/src/control-plane/runtime/sandbox-utils.ts
|
|
4951
5005
|
init_utils();
|
|
@@ -4962,7 +5016,7 @@ function resolveBunBinaryPath() {
|
|
|
4962
5016
|
}
|
|
4963
5017
|
const home = process.env.HOME?.trim();
|
|
4964
5018
|
const fallbackCandidates = [
|
|
4965
|
-
home ?
|
|
5019
|
+
home ? resolve23(home, ".bun/bin/bun") : "",
|
|
4966
5020
|
"/opt/homebrew/bin/bun",
|
|
4967
5021
|
"/usr/local/bin/bun",
|
|
4968
5022
|
"/usr/bin/bun"
|
|
@@ -4990,8 +5044,8 @@ function resolveClaudeBinaryPath() {
|
|
|
4990
5044
|
}
|
|
4991
5045
|
const home = process.env.HOME?.trim();
|
|
4992
5046
|
const fallbackCandidates = [
|
|
4993
|
-
home ?
|
|
4994
|
-
home ?
|
|
5047
|
+
home ? resolve23(home, ".local/bin/claude") : "",
|
|
5048
|
+
home ? resolve23(home, ".local/share/claude/local/claude") : "",
|
|
4995
5049
|
"/opt/homebrew/bin/claude",
|
|
4996
5050
|
"/usr/local/bin/claude",
|
|
4997
5051
|
"/usr/bin/claude"
|
|
@@ -5005,35 +5059,35 @@ function resolveClaudeBinaryPath() {
|
|
|
5005
5059
|
throw new Error("claude not found in PATH");
|
|
5006
5060
|
}
|
|
5007
5061
|
function resolveBunInstallDir(bunBinaryPath = resolveBunBinaryPath()) {
|
|
5008
|
-
return
|
|
5062
|
+
return resolve23(bunBinaryPath, "../..");
|
|
5009
5063
|
}
|
|
5010
5064
|
function resolveClaudeInstallDir() {
|
|
5011
5065
|
const realPath = resolveClaudeBinaryPath();
|
|
5012
|
-
return
|
|
5066
|
+
return resolve23(realPath, "..");
|
|
5013
5067
|
}
|
|
5014
5068
|
function resolveNodeInstallDir() {
|
|
5015
5069
|
const preferredNode = resolvePreferredNodeBinary();
|
|
5016
5070
|
if (!preferredNode)
|
|
5017
5071
|
return null;
|
|
5018
5072
|
const explicitNode = process.env.RIG_NODE_BIN?.trim();
|
|
5019
|
-
if (explicitNode &&
|
|
5020
|
-
return preferredNode.endsWith("/bin/node") ?
|
|
5073
|
+
if (explicitNode && resolve23(explicitNode) === resolve23(preferredNode)) {
|
|
5074
|
+
return preferredNode.endsWith("/bin/node") ? resolve23(preferredNode, "../..") : resolve23(preferredNode, "..");
|
|
5021
5075
|
}
|
|
5022
5076
|
try {
|
|
5023
5077
|
const realPath = realpathSync2(preferredNode);
|
|
5024
5078
|
if (realPath.endsWith("/bin/node")) {
|
|
5025
|
-
return
|
|
5079
|
+
return resolve23(realPath, "../..");
|
|
5026
5080
|
}
|
|
5027
|
-
return
|
|
5081
|
+
return resolve23(realPath, "..");
|
|
5028
5082
|
} catch {
|
|
5029
|
-
return
|
|
5083
|
+
return resolve23(preferredNode, "..");
|
|
5030
5084
|
}
|
|
5031
5085
|
}
|
|
5032
5086
|
function resolveRuntimeDependencyRoots(runtimeDirs) {
|
|
5033
5087
|
const roots = [];
|
|
5034
5088
|
if (process.platform === "darwin") {
|
|
5035
5089
|
for (const macPath of ["/opt/homebrew", "/opt/homebrew/opt"]) {
|
|
5036
|
-
if (
|
|
5090
|
+
if (existsSync22(macPath)) {
|
|
5037
5091
|
roots.push(macPath);
|
|
5038
5092
|
}
|
|
5039
5093
|
}
|
|
@@ -5051,23 +5105,23 @@ function resolvePreferredNodeBinary() {
|
|
|
5051
5105
|
const candidates = [];
|
|
5052
5106
|
const envNode = process.env.RIG_NODE_BIN?.trim();
|
|
5053
5107
|
if (envNode) {
|
|
5054
|
-
const explicit =
|
|
5055
|
-
if (
|
|
5108
|
+
const explicit = resolve23(envNode);
|
|
5109
|
+
if (existsSync22(explicit)) {
|
|
5056
5110
|
return explicit;
|
|
5057
5111
|
}
|
|
5058
5112
|
}
|
|
5059
5113
|
const nvmBin = process.env.NVM_BIN?.trim();
|
|
5060
5114
|
if (nvmBin) {
|
|
5061
|
-
candidates.push(
|
|
5115
|
+
candidates.push(resolve23(nvmBin, "node"));
|
|
5062
5116
|
}
|
|
5063
5117
|
const home = process.env.HOME?.trim();
|
|
5064
5118
|
if (home) {
|
|
5065
|
-
const nvmVersionsDir =
|
|
5066
|
-
if (
|
|
5119
|
+
const nvmVersionsDir = resolve23(home, ".nvm/versions/node");
|
|
5120
|
+
if (existsSync22(nvmVersionsDir)) {
|
|
5067
5121
|
try {
|
|
5068
|
-
const versionDirs =
|
|
5122
|
+
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/, "")));
|
|
5069
5123
|
for (const versionDir of versionDirs) {
|
|
5070
|
-
candidates.push(
|
|
5124
|
+
candidates.push(resolve23(nvmVersionsDir, versionDir, "bin/node"));
|
|
5071
5125
|
}
|
|
5072
5126
|
} catch {}
|
|
5073
5127
|
}
|
|
@@ -5076,8 +5130,8 @@ function resolvePreferredNodeBinary() {
|
|
|
5076
5130
|
if (whichNode) {
|
|
5077
5131
|
candidates.push(whichNode);
|
|
5078
5132
|
}
|
|
5079
|
-
const deduped = uniq(candidates.map((candidate) =>
|
|
5080
|
-
const existing = deduped.filter((candidate) =>
|
|
5133
|
+
const deduped = uniq(candidates.map((candidate) => resolve23(candidate)));
|
|
5134
|
+
const existing = deduped.filter((candidate) => existsSync22(candidate));
|
|
5081
5135
|
if (existing.length === 0) {
|
|
5082
5136
|
return null;
|
|
5083
5137
|
}
|
|
@@ -5091,7 +5145,7 @@ function resolvePreferredNodeBinary() {
|
|
|
5091
5145
|
return existing[0] ?? null;
|
|
5092
5146
|
}
|
|
5093
5147
|
function inferNodeMajor(nodeBinaryPath) {
|
|
5094
|
-
const normalized =
|
|
5148
|
+
const normalized = resolve23(nodeBinaryPath).replace(/\\/g, "/");
|
|
5095
5149
|
const match = normalized.match(/(?:^|\/)(?:node-)?v?(\d+)\.\d+\.\d+(?:\/|$)/);
|
|
5096
5150
|
if (!match) {
|
|
5097
5151
|
return null;
|
|
@@ -5103,8 +5157,8 @@ function normalizeExecutablePath(candidate) {
|
|
|
5103
5157
|
if (!candidate) {
|
|
5104
5158
|
return "";
|
|
5105
5159
|
}
|
|
5106
|
-
const normalized =
|
|
5107
|
-
if (!
|
|
5160
|
+
const normalized = resolve23(candidate);
|
|
5161
|
+
if (!existsSync22(normalized)) {
|
|
5108
5162
|
return "";
|
|
5109
5163
|
}
|
|
5110
5164
|
try {
|
|
@@ -5114,7 +5168,7 @@ function normalizeExecutablePath(candidate) {
|
|
|
5114
5168
|
}
|
|
5115
5169
|
}
|
|
5116
5170
|
function looksLikeRuntimeGateway(candidate) {
|
|
5117
|
-
const normalized =
|
|
5171
|
+
const normalized = resolve23(candidate).replace(/\\/g, "/");
|
|
5118
5172
|
return normalized.includes("/.rig/bin/") || normalized.endsWith("/rig-shell") || normalized.endsWith("/rig-agent");
|
|
5119
5173
|
}
|
|
5120
5174
|
|
|
@@ -5135,7 +5189,7 @@ function runtimeProvisioningEnv(baseEnv = process.env) {
|
|
|
5135
5189
|
try {
|
|
5136
5190
|
return resolveClaudeInstallDir();
|
|
5137
5191
|
} catch {
|
|
5138
|
-
return
|
|
5192
|
+
return resolve24(claudeBinary, "..");
|
|
5139
5193
|
}
|
|
5140
5194
|
})() : "";
|
|
5141
5195
|
const nodeDir = resolveNodeInstallDir();
|
|
@@ -5145,8 +5199,8 @@ function runtimeProvisioningEnv(baseEnv = process.env) {
|
|
|
5145
5199
|
`${bunDir}/bin`,
|
|
5146
5200
|
claudeDir,
|
|
5147
5201
|
nodeDir ? `${nodeDir}/bin` : "",
|
|
5148
|
-
realHome ?
|
|
5149
|
-
realHome ?
|
|
5202
|
+
realHome ? resolve24(realHome, ".local/bin") : "",
|
|
5203
|
+
realHome ? resolve24(realHome, ".cargo/bin") : "",
|
|
5150
5204
|
...inheritedPath,
|
|
5151
5205
|
"/usr/local/bin",
|
|
5152
5206
|
"/usr/local/sbin",
|
|
@@ -5175,8 +5229,8 @@ function runtimeProvisioningEnv(baseEnv = process.env) {
|
|
|
5175
5229
|
}
|
|
5176
5230
|
|
|
5177
5231
|
// packages/runtime/src/control-plane/runtime/baked-secrets.ts
|
|
5178
|
-
import { existsSync as
|
|
5179
|
-
import { resolve as
|
|
5232
|
+
import { existsSync as existsSync23, readFileSync as readFileSync11 } from "fs";
|
|
5233
|
+
import { resolve as resolve25 } from "path";
|
|
5180
5234
|
var BAKED_RUNTIME_SECRETS = {
|
|
5181
5235
|
ANTHROPIC_API_KEY: typeof RIG_BAKED_ANTHROPIC_API_KEY !== "undefined" ? RIG_BAKED_ANTHROPIC_API_KEY : "",
|
|
5182
5236
|
OPENAI_API_KEY: typeof RIG_BAKED_OPENAI_API_KEY !== "undefined" ? RIG_BAKED_OPENAI_API_KEY : "",
|
|
@@ -5219,12 +5273,12 @@ function resolveRuntimeSecrets(env, baked = BAKED_RUNTIME_SECRETS) {
|
|
|
5219
5273
|
return resolved;
|
|
5220
5274
|
}
|
|
5221
5275
|
function loadDotEnvSecrets(projectRoot, env = process.env) {
|
|
5222
|
-
const dotenvPath =
|
|
5223
|
-
if (!
|
|
5276
|
+
const dotenvPath = resolve25(projectRoot, ".env");
|
|
5277
|
+
if (!existsSync23(dotenvPath)) {
|
|
5224
5278
|
return {};
|
|
5225
5279
|
}
|
|
5226
5280
|
const parsed = {};
|
|
5227
|
-
const lines =
|
|
5281
|
+
const lines = readFileSync11(dotenvPath, "utf-8").split(/\r?\n/);
|
|
5228
5282
|
for (const rawLine of lines) {
|
|
5229
5283
|
const line = rawLine.trim();
|
|
5230
5284
|
if (!line || line.startsWith("#")) {
|
|
@@ -5581,16 +5635,16 @@ async function taskDeps(projectRoot, taskId) {
|
|
|
5581
5635
|
for (const dep of deps) {
|
|
5582
5636
|
const artifactDir = artifactDirForId(projectRoot, dep);
|
|
5583
5637
|
console.log(`=== ${dep} ===`);
|
|
5584
|
-
if (!
|
|
5638
|
+
if (!existsSync24(artifactDir)) {
|
|
5585
5639
|
console.log(` (no artifacts yet)
|
|
5586
5640
|
`);
|
|
5587
5641
|
continue;
|
|
5588
5642
|
}
|
|
5589
|
-
printArtifactSection(
|
|
5590
|
-
printArtifactSection(
|
|
5591
|
-
const changedFiles =
|
|
5592
|
-
if (
|
|
5593
|
-
const lines =
|
|
5643
|
+
printArtifactSection(resolve26(artifactDir, "decision-log.md"), "--- Decisions ---");
|
|
5644
|
+
printArtifactSection(resolve26(artifactDir, "next-actions.md"), "--- Next Actions (for you) ---");
|
|
5645
|
+
const changedFiles = resolve26(artifactDir, "changed-files.txt");
|
|
5646
|
+
if (existsSync24(changedFiles)) {
|
|
5647
|
+
const lines = readFileSync12(changedFiles, "utf-8").split(/\r?\n/).filter(Boolean);
|
|
5594
5648
|
console.log(`--- Changed Files (${lines.length}) ---`);
|
|
5595
5649
|
for (const line of lines) {
|
|
5596
5650
|
console.log(line);
|
|
@@ -5714,12 +5768,12 @@ function printIndented(text) {
|
|
|
5714
5768
|
}
|
|
5715
5769
|
}
|
|
5716
5770
|
function readLocalBeadsTasks(projectRoot) {
|
|
5717
|
-
const issuesPath =
|
|
5718
|
-
if (!
|
|
5771
|
+
const issuesPath = resolve26(resolveMonorepoRoot2(projectRoot), ".beads/issues.jsonl");
|
|
5772
|
+
if (!existsSync24(issuesPath)) {
|
|
5719
5773
|
return [];
|
|
5720
5774
|
}
|
|
5721
5775
|
const tasks = [];
|
|
5722
|
-
for (const line of
|
|
5776
|
+
for (const line of readFileSync12(issuesPath, "utf-8").split(/\r?\n/)) {
|
|
5723
5777
|
const trimmed = line.trim();
|
|
5724
5778
|
if (!trimmed) {
|
|
5725
5779
|
continue;
|
|
@@ -5832,11 +5886,11 @@ function taskDependencies(projectRoot, taskId, tracker) {
|
|
|
5832
5886
|
return [...ids].sort();
|
|
5833
5887
|
}
|
|
5834
5888
|
function printArtifactSection(path, header) {
|
|
5835
|
-
if (!
|
|
5889
|
+
if (!existsSync24(path)) {
|
|
5836
5890
|
return;
|
|
5837
5891
|
}
|
|
5838
5892
|
console.log(header);
|
|
5839
|
-
process.stdout.write(
|
|
5893
|
+
process.stdout.write(readFileSync12(path, "utf-8"));
|
|
5840
5894
|
console.log("");
|
|
5841
5895
|
}
|
|
5842
5896
|
|
|
@@ -5938,7 +5992,7 @@ init_layout();
|
|
|
5938
5992
|
|
|
5939
5993
|
// packages/runtime/src/control-plane/runtime/overlay.ts
|
|
5940
5994
|
init_layout();
|
|
5941
|
-
import { mkdirSync as
|
|
5995
|
+
import { mkdirSync as mkdirSync11 } from "fs";
|
|
5942
5996
|
function ensureRuntimeOverlay(projectRoot, runtimeId, workspaceDir) {
|
|
5943
5997
|
const layout = resolveRuntimeWorkspaceLayout(workspaceDir ?? projectRoot);
|
|
5944
5998
|
const rootDir = layout.rigRoot;
|
|
@@ -5950,14 +6004,14 @@ function ensureRuntimeOverlay(projectRoot, runtimeId, workspaceDir) {
|
|
|
5950
6004
|
const sessionDir = layout.sessionDir;
|
|
5951
6005
|
const runtimeDir = layout.runtimeDir;
|
|
5952
6006
|
const contextPath = layout.contextPath;
|
|
5953
|
-
|
|
5954
|
-
|
|
5955
|
-
|
|
5956
|
-
|
|
5957
|
-
|
|
5958
|
-
|
|
5959
|
-
|
|
5960
|
-
|
|
6007
|
+
mkdirSync11(rootDir, { recursive: true });
|
|
6008
|
+
mkdirSync11(homeDir, { recursive: true });
|
|
6009
|
+
mkdirSync11(tmpDir, { recursive: true });
|
|
6010
|
+
mkdirSync11(cacheDir, { recursive: true });
|
|
6011
|
+
mkdirSync11(logsDir, { recursive: true });
|
|
6012
|
+
mkdirSync11(stateDir, { recursive: true });
|
|
6013
|
+
mkdirSync11(sessionDir, { recursive: true });
|
|
6014
|
+
mkdirSync11(runtimeDir, { recursive: true });
|
|
5961
6015
|
return {
|
|
5962
6016
|
rootDir,
|
|
5963
6017
|
homeDir,
|
|
@@ -5975,17 +6029,17 @@ import {
|
|
|
5975
6029
|
chmodSync as chmodSync5,
|
|
5976
6030
|
copyFileSync as copyFileSync5,
|
|
5977
6031
|
cpSync as cpSync2,
|
|
5978
|
-
existsSync as
|
|
5979
|
-
mkdirSync as
|
|
6032
|
+
existsSync as existsSync26,
|
|
6033
|
+
mkdirSync as mkdirSync12,
|
|
5980
6034
|
statSync as statSync6,
|
|
5981
|
-
writeFileSync as
|
|
6035
|
+
writeFileSync as writeFileSync10
|
|
5982
6036
|
} from "fs";
|
|
5983
6037
|
import { mkdir as mkdir2 } from "fs/promises";
|
|
5984
|
-
import { basename as basename8, delimiter as delimiter2, resolve as
|
|
6038
|
+
import { basename as basename8, delimiter as delimiter2, resolve as resolve28 } from "path";
|
|
5985
6039
|
|
|
5986
6040
|
// packages/runtime/src/control-plane/runtime/isolation/shared.ts
|
|
5987
|
-
import { existsSync as
|
|
5988
|
-
import { resolve as
|
|
6041
|
+
import { existsSync as existsSync25, readFileSync as readFileSync13, rmSync as rmSync9 } from "fs";
|
|
6042
|
+
import { resolve as resolve27 } from "path";
|
|
5989
6043
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
5990
6044
|
var generatedCredentialFiles = new Set;
|
|
5991
6045
|
var credentialCleanupRegistered = false;
|
|
@@ -6010,7 +6064,7 @@ function resolveHostGitBinary() {
|
|
|
6010
6064
|
if (!candidate || isRuntimeGatewayGitPath(candidate)) {
|
|
6011
6065
|
continue;
|
|
6012
6066
|
}
|
|
6013
|
-
if (
|
|
6067
|
+
if (existsSync25(candidate)) {
|
|
6014
6068
|
return candidate;
|
|
6015
6069
|
}
|
|
6016
6070
|
}
|
|
@@ -6076,7 +6130,7 @@ async function refreshRemoteBranch(repoRoot, remote, branch) {
|
|
|
6076
6130
|
}
|
|
6077
6131
|
}
|
|
6078
6132
|
async function tryReadGitHead(repoRoot) {
|
|
6079
|
-
if (!
|
|
6133
|
+
if (!existsSync25(resolve27(repoRoot, ".git"))) {
|
|
6080
6134
|
return;
|
|
6081
6135
|
}
|
|
6082
6136
|
const result = await runGitCommand(repoRoot, ["rev-parse", "HEAD"]);
|
|
@@ -6087,7 +6141,7 @@ async function tryReadGitHead(repoRoot) {
|
|
|
6087
6141
|
return value || undefined;
|
|
6088
6142
|
}
|
|
6089
6143
|
async function captureRepoDirtyFiles(repoRoot) {
|
|
6090
|
-
if (!
|
|
6144
|
+
if (!existsSync25(resolve27(repoRoot, ".git"))) {
|
|
6091
6145
|
return [];
|
|
6092
6146
|
}
|
|
6093
6147
|
const files = new Set;
|
|
@@ -6123,7 +6177,7 @@ function registerCredentialCleanup(path) {
|
|
|
6123
6177
|
const cleanup = () => {
|
|
6124
6178
|
for (const filePath of generatedCredentialFiles) {
|
|
6125
6179
|
try {
|
|
6126
|
-
|
|
6180
|
+
rmSync9(filePath, { force: true });
|
|
6127
6181
|
} catch {}
|
|
6128
6182
|
}
|
|
6129
6183
|
generatedCredentialFiles.clear();
|
|
@@ -6178,20 +6232,23 @@ function hashProjectPath(workspaceDir) {
|
|
|
6178
6232
|
}
|
|
6179
6233
|
function resolveGithubCliBinaryPath() {
|
|
6180
6234
|
const explicit = process.env.RIG_GH_BIN?.trim();
|
|
6181
|
-
if (explicit &&
|
|
6235
|
+
if (explicit && existsSync25(explicit) && !isRuntimeGatewayGhPath(explicit)) {
|
|
6182
6236
|
return explicit;
|
|
6183
6237
|
}
|
|
6184
|
-
const
|
|
6185
|
-
|
|
6186
|
-
return bunResolved;
|
|
6187
|
-
}
|
|
6188
|
-
for (const candidate of ["/opt/homebrew/bin/gh", "/usr/local/bin/gh", "/usr/bin/gh"]) {
|
|
6189
|
-
if (existsSync24(candidate)) {
|
|
6238
|
+
for (const candidate of ["/usr/bin/gh", "/opt/homebrew/bin/gh", "/usr/local/bin/gh"]) {
|
|
6239
|
+
if (existsSync25(candidate)) {
|
|
6190
6240
|
return candidate;
|
|
6191
6241
|
}
|
|
6192
6242
|
}
|
|
6243
|
+
const bunResolved = Bun.which("gh");
|
|
6244
|
+
if (bunResolved && existsSync25(bunResolved) && !isRuntimeGatewayGhPath(bunResolved)) {
|
|
6245
|
+
return bunResolved;
|
|
6246
|
+
}
|
|
6193
6247
|
return "";
|
|
6194
6248
|
}
|
|
6249
|
+
function isRuntimeGatewayGhPath(candidate) {
|
|
6250
|
+
return /\/\.rig\/bin\/gh$/.test(candidate.replace(/\\/g, "/"));
|
|
6251
|
+
}
|
|
6195
6252
|
async function resolveGithubCliAuthToken(ghBinary = "") {
|
|
6196
6253
|
const gh = ghBinary || resolveGithubCliBinaryPath();
|
|
6197
6254
|
if (!gh) {
|
|
@@ -6218,17 +6275,17 @@ function resolveSystemCertBundlePath() {
|
|
|
6218
6275
|
"/opt/homebrew/etc/openssl@3/cert.pem"
|
|
6219
6276
|
];
|
|
6220
6277
|
for (const candidate of candidates) {
|
|
6221
|
-
if (candidate &&
|
|
6222
|
-
return
|
|
6278
|
+
if (candidate && existsSync25(candidate)) {
|
|
6279
|
+
return resolve27(candidate);
|
|
6223
6280
|
}
|
|
6224
6281
|
}
|
|
6225
6282
|
return "";
|
|
6226
6283
|
}
|
|
6227
6284
|
function readKnownHosts(path) {
|
|
6228
|
-
if (!
|
|
6285
|
+
if (!existsSync25(path)) {
|
|
6229
6286
|
return new Set;
|
|
6230
6287
|
}
|
|
6231
|
-
return new Set(
|
|
6288
|
+
return new Set(readFileSync13(path, "utf-8").split(/\r?\n/).map((line) => line.trim()).filter(Boolean));
|
|
6232
6289
|
}
|
|
6233
6290
|
|
|
6234
6291
|
// packages/runtime/src/control-plane/runtime/isolation/home.ts
|
|
@@ -6239,6 +6296,21 @@ var GITHUB_KNOWN_HOSTS = [
|
|
|
6239
6296
|
"github.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCj7ndNxQowgcQnjshcLrqPEiiphnt+VTTvDP6mHBL9j1aNUkY4Ue1gvwnGLVlOhGeYrnZaMgRK6+PKCUXaDbC7qtbW8gIkhL7aGCsOr/C56SJMy/BCZfxd1nWzAOxSDPgVsmerOBYfNqltV9/hWCqBywINIR+5dIg6JTJ72pcEpEjcYgXkE2YEFXV1JHnsKgbLWNlhScqb2UmyRkQyytRLtL+38TGxkxCflmO+5Z8CSSNY7GidjMIZ7Q4zMjA2n1nGrlTDkzwDCsw+wqFPGQA179cnfGWOWRVruj16z6XyvxvjJwbz0wQZ75XK5tKSb7FNyeIEs4TT4jk+S4dhPeAUC5y+bDYirYgM4GC7uEnztnZyaVWQ7B381AK4Qdrwt51ZqExKbQpTUNn+EjqoTwvqNj4kqx5QUCI0ThS/YkOxJCXmPUWZbhjpCg56i+2aB6CmK2JGhn57K5mj0MNdBXA4/WnwH6XoPWJzK5Nyu2zB3nAZp+S5hpQs+p1vN1/wsjk="
|
|
6240
6297
|
].join(`
|
|
6241
6298
|
`);
|
|
6299
|
+
function resolveControlPlaneSourceRoot(projectRoot) {
|
|
6300
|
+
const candidates = [
|
|
6301
|
+
process.env.RIG_CONTROL_PLANE_SOURCE_ROOT?.trim(),
|
|
6302
|
+
process.env.RIG_HOST_PROJECT_ROOT?.trim(),
|
|
6303
|
+
resolve28(import.meta.dir, "../../../../.."),
|
|
6304
|
+
projectRoot
|
|
6305
|
+
].filter((value) => Boolean(value));
|
|
6306
|
+
for (const candidate of candidates) {
|
|
6307
|
+
const root = resolve28(candidate);
|
|
6308
|
+
if (existsSync26(resolve28(root, "packages/runtime/src/control-plane/pi-sessiond/bin.ts"))) {
|
|
6309
|
+
return root;
|
|
6310
|
+
}
|
|
6311
|
+
}
|
|
6312
|
+
return "";
|
|
6313
|
+
}
|
|
6242
6314
|
async function runtimeEnv(projectRoot, runtime) {
|
|
6243
6315
|
const bunBinaryPath = resolveBunBinaryPath();
|
|
6244
6316
|
const bunDir = resolveBunInstallDir(bunBinaryPath);
|
|
@@ -6253,7 +6325,7 @@ async function runtimeEnv(projectRoot, runtime) {
|
|
|
6253
6325
|
try {
|
|
6254
6326
|
return resolveClaudeInstallDir();
|
|
6255
6327
|
} catch {
|
|
6256
|
-
return
|
|
6328
|
+
return resolve28(claudeBinaryPath, "..");
|
|
6257
6329
|
}
|
|
6258
6330
|
})() : "";
|
|
6259
6331
|
const nodeDir = resolveNodeInstallDir();
|
|
@@ -6268,8 +6340,8 @@ async function runtimeEnv(projectRoot, runtime) {
|
|
|
6268
6340
|
`${bunDir}/bin`,
|
|
6269
6341
|
claudeDir,
|
|
6270
6342
|
nodeDir ? `${nodeDir}/bin` : "",
|
|
6271
|
-
realHome ?
|
|
6272
|
-
realHome ?
|
|
6343
|
+
realHome ? resolve28(realHome, ".local/bin") : "",
|
|
6344
|
+
realHome ? resolve28(realHome, ".cargo/bin") : "",
|
|
6273
6345
|
...inheritedPath,
|
|
6274
6346
|
"/usr/local/bin",
|
|
6275
6347
|
"/usr/local/sbin",
|
|
@@ -6280,18 +6352,22 @@ async function runtimeEnv(projectRoot, runtime) {
|
|
|
6280
6352
|
"/usr/sbin",
|
|
6281
6353
|
"/sbin"
|
|
6282
6354
|
].filter(Boolean);
|
|
6283
|
-
const runtimeBash =
|
|
6284
|
-
const runtimeRigGit =
|
|
6285
|
-
const preferredShell =
|
|
6355
|
+
const runtimeBash = resolve28(runtime.binDir, "bash");
|
|
6356
|
+
const runtimeRigGit = resolve28(runtime.binDir, runtimeRigGitFileName());
|
|
6357
|
+
const preferredShell = existsSync26(runtimeBash) ? runtimeBash : "/bin/bash";
|
|
6286
6358
|
const nativeRuntimeLibraryPath = await materializeNativeRuntimeLibrary(runtime.binDir);
|
|
6359
|
+
const controlPlaneSourceRoot = resolveControlPlaneSourceRoot(projectRoot);
|
|
6287
6360
|
const env = {
|
|
6288
6361
|
PROJECT_RIG_ROOT: projectRoot,
|
|
6289
6362
|
RIG_HOST_PROJECT_ROOT: projectRoot,
|
|
6363
|
+
...controlPlaneSourceRoot ? { RIG_CONTROL_PLANE_SOURCE_ROOT: controlPlaneSourceRoot } : {},
|
|
6290
6364
|
HOME: runtime.homeDir,
|
|
6291
6365
|
TMPDIR: runtime.tmpDir,
|
|
6292
6366
|
XDG_CACHE_HOME: runtime.cacheDir,
|
|
6293
6367
|
XDG_STATE_HOME: runtime.stateDir,
|
|
6294
6368
|
RIG_AGENT_ID: runtime.id,
|
|
6369
|
+
...process.env.RIG_RUN_ID?.trim() ? { RIG_RUN_ID: process.env.RIG_RUN_ID.trim() } : {},
|
|
6370
|
+
...process.env.RIG_SERVER_RUN_ID?.trim() ? { RIG_SERVER_RUN_ID: process.env.RIG_SERVER_RUN_ID.trim() } : {},
|
|
6295
6371
|
RIG_TASK_ID: runtime.taskId,
|
|
6296
6372
|
RIG_TASK_RUNTIME_ID: runtime.id,
|
|
6297
6373
|
RIG_TASK_WORKSPACE: runtime.workspaceDir,
|
|
@@ -6299,30 +6375,30 @@ async function runtimeEnv(projectRoot, runtime) {
|
|
|
6299
6375
|
RIG_RUNTIME_MODE: runtime.mode,
|
|
6300
6376
|
RIG_RUNTIME_HOME: runtime.rootDir,
|
|
6301
6377
|
RIG_RUNTIME_BIN_DIR: runtime.binDir,
|
|
6302
|
-
...
|
|
6378
|
+
...existsSync26(runtimeRigGit) ? { RIG_NATIVE_GIT_BIN: runtimeRigGit } : {},
|
|
6303
6379
|
RIG_BUN_PATH: bunBinaryPath,
|
|
6304
6380
|
...claudeBinaryPath ? { RIG_CLAUDE_PATH: claudeBinaryPath } : {},
|
|
6305
|
-
RIG_AGENT_BIN:
|
|
6381
|
+
RIG_AGENT_BIN: resolve28(runtime.binDir, "rig-agent"),
|
|
6306
6382
|
RIG_HOOKS_ACTIVE: "1",
|
|
6307
6383
|
RIG_AUTO_PR_ON_COMPLETE: "1",
|
|
6308
|
-
RIG_POLICY_FILE:
|
|
6384
|
+
RIG_POLICY_FILE: resolve28(projectRoot, "rig/policy/policy.json"),
|
|
6309
6385
|
RIG_STATE_DIR: runtime.stateDir,
|
|
6310
6386
|
RIG_LOGS_DIR: runtime.logsDir,
|
|
6311
|
-
RIG_SESSION_FILE:
|
|
6387
|
+
RIG_SESSION_FILE: resolve28(runtime.sessionDir, "session.json"),
|
|
6312
6388
|
MONOREPO_ROOT: runtime.workspaceDir,
|
|
6313
6389
|
MONOREPO_MAIN_ROOT: monorepoMainRoot,
|
|
6314
|
-
TS_API_TESTS_DIR:
|
|
6390
|
+
TS_API_TESTS_DIR: resolve28(runtime.workspaceDir, "TSAPITests"),
|
|
6315
6391
|
BASH: preferredShell,
|
|
6316
6392
|
SHELL: preferredShell,
|
|
6317
6393
|
PATH: [...new Set(pathEntries)].join(delimiter2),
|
|
6318
6394
|
LANG: process.env.LANG ?? "en_US.UTF-8",
|
|
6319
6395
|
TERM: process.env.TERM ?? "xterm-256color",
|
|
6320
6396
|
PYTHONDONTWRITEBYTECODE: "1",
|
|
6321
|
-
PYTHONPYCACHEPREFIX:
|
|
6397
|
+
PYTHONPYCACHEPREFIX: resolve28(runtime.cacheDir, "python"),
|
|
6322
6398
|
...process.env.RIG_PR_BASE_PROJECT && { RIG_PR_BASE_PROJECT: process.env.RIG_PR_BASE_PROJECT },
|
|
6323
6399
|
...process.env.RIG_PR_BASE_MONOREPO && { RIG_PR_BASE_MONOREPO: process.env.RIG_PR_BASE_MONOREPO },
|
|
6324
6400
|
CLAUDE_HOME: runtime.claudeHomeDir,
|
|
6325
|
-
PI_CODING_AGENT_DIR:
|
|
6401
|
+
PI_CODING_AGENT_DIR: resolve28(runtime.homeDir, ".pi", "agent"),
|
|
6326
6402
|
[RUNTIME_CONTEXT_ENV]: runtime.contextFile,
|
|
6327
6403
|
...nativeRuntimeLibraryPath ? { RIG_NATIVE_RUNTIME_LIB: nativeRuntimeLibraryPath } : {},
|
|
6328
6404
|
...hostGhBinary ? { RIG_GH_BIN: hostGhBinary } : {},
|
|
@@ -6333,16 +6409,16 @@ async function runtimeEnv(projectRoot, runtime) {
|
|
|
6333
6409
|
NODE_EXTRA_CA_CERTS: runtimeCertBundlePath
|
|
6334
6410
|
} : {}
|
|
6335
6411
|
};
|
|
6336
|
-
const knownHostsPath =
|
|
6337
|
-
if (
|
|
6338
|
-
const agentSshKey =
|
|
6412
|
+
const knownHostsPath = resolve28(runtime.homeDir, ".ssh", "known_hosts");
|
|
6413
|
+
if (existsSync26(knownHostsPath)) {
|
|
6414
|
+
const agentSshKey = resolve28(runtime.homeDir, ".ssh", "rig-agent-key");
|
|
6339
6415
|
const sshParts = [
|
|
6340
6416
|
"ssh",
|
|
6341
6417
|
`-o UserKnownHostsFile="${knownHostsPath}"`,
|
|
6342
6418
|
"-o StrictHostKeyChecking=yes",
|
|
6343
6419
|
"-F /dev/null"
|
|
6344
6420
|
];
|
|
6345
|
-
if (
|
|
6421
|
+
if (existsSync26(agentSshKey)) {
|
|
6346
6422
|
sshParts.splice(1, 0, `-i "${agentSshKey}"`, "-o IdentitiesOnly=yes");
|
|
6347
6423
|
}
|
|
6348
6424
|
env.GIT_SSH_COMMAND = sshParts.join(" ");
|
|
@@ -6379,7 +6455,7 @@ async function runtimeEnv(projectRoot, runtime) {
|
|
|
6379
6455
|
if (!env.GREPTILE_GITHUB_TOKEN && env.GITHUB_TOKEN) {
|
|
6380
6456
|
env.GREPTILE_GITHUB_TOKEN = env.GITHUB_TOKEN;
|
|
6381
6457
|
}
|
|
6382
|
-
if (
|
|
6458
|
+
if (existsSync26(runtime.contextFile)) {
|
|
6383
6459
|
const runtimeContext = loadRuntimeContext(runtime.contextFile);
|
|
6384
6460
|
Object.assign(env, runtimeMemoryEnvFromContext(runtimeContext));
|
|
6385
6461
|
Object.assign(env, browserEnvFromContext(runtimeContext.browser));
|
|
@@ -6408,30 +6484,30 @@ async function provisionRuntimeHome(runtime, options = {}) {
|
|
|
6408
6484
|
await mkdir2(runtime.cacheDir, { recursive: true });
|
|
6409
6485
|
await provisionAgentSshKey(runtime.homeDir);
|
|
6410
6486
|
if (options.provider === "codex") {
|
|
6411
|
-
const hasCodexAuth = await injectCodexAuth(
|
|
6487
|
+
const hasCodexAuth = await injectCodexAuth(resolve28(runtime.homeDir, ".codex"));
|
|
6412
6488
|
if (!hasCodexAuth) {
|
|
6413
6489
|
console.warn("[rig] No Codex auth.json found for isolated runtime. " + "Run `codex login` in your host shell, then retry the agent run.");
|
|
6414
6490
|
}
|
|
6415
6491
|
}
|
|
6416
6492
|
if (options.provider === "pi") {
|
|
6417
|
-
const hasPiAuth = await injectPiAgentConfig(
|
|
6493
|
+
const hasPiAuth = await injectPiAgentConfig(resolve28(runtime.homeDir, ".pi", "agent"));
|
|
6418
6494
|
if (!hasPiAuth) {
|
|
6419
6495
|
console.warn("[rig] No Pi auth.json found for isolated runtime. " + "Run `pi /login` in your host shell, then retry the agent run.");
|
|
6420
6496
|
}
|
|
6421
6497
|
}
|
|
6422
6498
|
}
|
|
6423
6499
|
async function provisionClaudeHome(config) {
|
|
6424
|
-
|
|
6425
|
-
const workspaceSettings =
|
|
6426
|
-
const hostSettings =
|
|
6427
|
-
const projectSettings =
|
|
6500
|
+
mkdirSync12(config.claudeHomeDir, { recursive: true });
|
|
6501
|
+
const workspaceSettings = resolve28(config.workspaceDir, ".claude/settings.json");
|
|
6502
|
+
const hostSettings = resolve28(config.hostProjectRoot, ".claude/settings.json");
|
|
6503
|
+
const projectSettings = existsSync26(workspaceSettings) ? workspaceSettings : hostSettings;
|
|
6428
6504
|
const runtimeSettings = await loadRuntimeClaudeSettings(projectSettings);
|
|
6429
|
-
if (
|
|
6430
|
-
|
|
6505
|
+
if (existsSync26(projectSettings)) {
|
|
6506
|
+
writeFileSync10(resolve28(config.claudeHomeDir, "settings.local.json"), `${JSON.stringify(runtimeSettings, null, 2)}
|
|
6431
6507
|
`, "utf-8");
|
|
6432
6508
|
}
|
|
6433
6509
|
writeClaudeProjectSettings(config.claudeHomeDir, config.workspaceDir, runtimeSettings);
|
|
6434
|
-
|
|
6510
|
+
writeFileSync10(resolve28(config.claudeHomeDir, "settings.json"), JSON.stringify({
|
|
6435
6511
|
permissions: { defaultMode: "bypassPermissions" },
|
|
6436
6512
|
autoMemoryEnabled: false
|
|
6437
6513
|
}, null, 2));
|
|
@@ -6439,12 +6515,12 @@ async function provisionClaudeHome(config) {
|
|
|
6439
6515
|
if (!hasCredentials) {
|
|
6440
6516
|
console.warn("[rig] No Claude credentials found for isolated runtime. " + "Run `claude /login` in your host shell, then retry the agent run.");
|
|
6441
6517
|
}
|
|
6442
|
-
const realClaudeHome =
|
|
6443
|
-
if (process.env.HOME &&
|
|
6444
|
-
cpSync2(
|
|
6518
|
+
const realClaudeHome = resolve28(process.env.HOME ?? "", ".claude");
|
|
6519
|
+
if (process.env.HOME && existsSync26(resolve28(realClaudeHome, "CLAUDE.md"))) {
|
|
6520
|
+
cpSync2(resolve28(realClaudeHome, "CLAUDE.md"), resolve28(config.claudeHomeDir, "CLAUDE.md"));
|
|
6445
6521
|
}
|
|
6446
|
-
if (process.env.HOME &&
|
|
6447
|
-
cpSync2(
|
|
6522
|
+
if (process.env.HOME && existsSync26(resolve28(realClaudeHome, "agents"))) {
|
|
6523
|
+
cpSync2(resolve28(realClaudeHome, "agents"), resolve28(config.claudeHomeDir, "agents"), { recursive: true });
|
|
6448
6524
|
}
|
|
6449
6525
|
if (process.platform === "darwin" && process.env.HOME) {
|
|
6450
6526
|
writeClaudeProjectSettings(realClaudeHome, config.workspaceDir, runtimeSettings);
|
|
@@ -6455,10 +6531,10 @@ async function materializeRuntimeCertBundle(runtime) {
|
|
|
6455
6531
|
if (!sourcePath) {
|
|
6456
6532
|
return "";
|
|
6457
6533
|
}
|
|
6458
|
-
const certsDir =
|
|
6459
|
-
const targetPath =
|
|
6534
|
+
const certsDir = resolve28(runtime.rootDir, "certs");
|
|
6535
|
+
const targetPath = resolve28(certsDir, "ca-certificates.pem");
|
|
6460
6536
|
await mkdir2(certsDir, { recursive: true });
|
|
6461
|
-
let shouldCopy = !
|
|
6537
|
+
let shouldCopy = !existsSync26(targetPath);
|
|
6462
6538
|
if (!shouldCopy) {
|
|
6463
6539
|
try {
|
|
6464
6540
|
shouldCopy = statSync6(sourcePath).mtimeMs > statSync6(targetPath).mtimeMs;
|
|
@@ -6480,7 +6556,7 @@ function applyGitHubCredentialHelperEnv(env) {
|
|
|
6480
6556
|
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';
|
|
6481
6557
|
}
|
|
6482
6558
|
function persistRuntimeSecrets(runtimeRoot, env) {
|
|
6483
|
-
const secretsPath =
|
|
6559
|
+
const secretsPath = resolve28(runtimeRoot, "runtime-secrets.json");
|
|
6484
6560
|
const persisted = {};
|
|
6485
6561
|
for (const key of [
|
|
6486
6562
|
"GITHUB_TOKEN",
|
|
@@ -6499,12 +6575,12 @@ function persistRuntimeSecrets(runtimeRoot, env) {
|
|
|
6499
6575
|
if (Object.keys(persisted).length === 0) {
|
|
6500
6576
|
return;
|
|
6501
6577
|
}
|
|
6502
|
-
|
|
6578
|
+
writeFileSync10(secretsPath, `${JSON.stringify(persisted, null, 2)}
|
|
6503
6579
|
`, "utf-8");
|
|
6504
6580
|
}
|
|
6505
6581
|
async function provisionAgentSshKey(homeDir) {
|
|
6506
|
-
const sshDir =
|
|
6507
|
-
if (!
|
|
6582
|
+
const sshDir = resolve28(homeDir, ".ssh");
|
|
6583
|
+
if (!existsSync26(sshDir)) {
|
|
6508
6584
|
await mkdir2(sshDir, { recursive: true });
|
|
6509
6585
|
}
|
|
6510
6586
|
seedKnownHosts(sshDir);
|
|
@@ -6512,27 +6588,27 @@ async function provisionAgentSshKey(homeDir) {
|
|
|
6512
6588
|
const privateKey = decodeProvisionedSshKey(secrets.GITHUB_SSH_KEY);
|
|
6513
6589
|
if (!privateKey) {
|
|
6514
6590
|
const hostKeyPath = resolveHostSshKeyPath(process.env.HOME ?? "");
|
|
6515
|
-
if (!process.env.HOME || !
|
|
6591
|
+
if (!process.env.HOME || !existsSync26(hostKeyPath)) {
|
|
6516
6592
|
return;
|
|
6517
6593
|
}
|
|
6518
|
-
const agentKeyPath2 =
|
|
6519
|
-
if (!
|
|
6594
|
+
const agentKeyPath2 = resolve28(sshDir, "rig-agent-key");
|
|
6595
|
+
if (!existsSync26(agentKeyPath2)) {
|
|
6520
6596
|
copyFileSync5(hostKeyPath, agentKeyPath2);
|
|
6521
6597
|
chmodSync5(agentKeyPath2, 384);
|
|
6522
6598
|
}
|
|
6523
6599
|
const hostPubPath = `${hostKeyPath}.pub`;
|
|
6524
|
-
if (
|
|
6600
|
+
if (existsSync26(hostPubPath)) {
|
|
6525
6601
|
const agentPubPath = `${agentKeyPath2}.pub`;
|
|
6526
|
-
if (!
|
|
6602
|
+
if (!existsSync26(agentPubPath)) {
|
|
6527
6603
|
copyFileSync5(hostPubPath, agentPubPath);
|
|
6528
6604
|
}
|
|
6529
6605
|
}
|
|
6530
6606
|
writeSshConfig(sshDir, agentKeyPath2);
|
|
6531
6607
|
return;
|
|
6532
6608
|
}
|
|
6533
|
-
const agentKeyPath =
|
|
6534
|
-
if (!
|
|
6535
|
-
|
|
6609
|
+
const agentKeyPath = resolve28(sshDir, "rig-agent-key");
|
|
6610
|
+
if (!existsSync26(agentKeyPath)) {
|
|
6611
|
+
writeFileSync10(agentKeyPath, privateKey, { mode: 384 });
|
|
6536
6612
|
}
|
|
6537
6613
|
writeSshConfig(sshDir, agentKeyPath);
|
|
6538
6614
|
}
|
|
@@ -6549,21 +6625,21 @@ function decodeProvisionedSshKey(encodedKey) {
|
|
|
6549
6625
|
`;
|
|
6550
6626
|
}
|
|
6551
6627
|
function resolveHostSshKeyPath(homeDir) {
|
|
6552
|
-
const sshDir =
|
|
6628
|
+
const sshDir = resolve28(homeDir, ".ssh");
|
|
6553
6629
|
const candidates = [
|
|
6554
6630
|
"rig-agent-key",
|
|
6555
6631
|
"id_ed25519",
|
|
6556
6632
|
"id_ecdsa",
|
|
6557
6633
|
"id_rsa"
|
|
6558
|
-
].map((name) =>
|
|
6559
|
-
return candidates.find((candidate) =>
|
|
6634
|
+
].map((name) => resolve28(sshDir, name));
|
|
6635
|
+
return candidates.find((candidate) => existsSync26(candidate)) ?? resolve28(sshDir, "rig-agent-key");
|
|
6560
6636
|
}
|
|
6561
6637
|
function writeSshConfig(sshDir, keyPath) {
|
|
6562
|
-
const configPath =
|
|
6563
|
-
if (
|
|
6638
|
+
const configPath = resolve28(sshDir, "config");
|
|
6639
|
+
if (existsSync26(configPath)) {
|
|
6564
6640
|
return;
|
|
6565
6641
|
}
|
|
6566
|
-
const knownHostsPath =
|
|
6642
|
+
const knownHostsPath = resolve28(sshDir, "known_hosts");
|
|
6567
6643
|
const config = [
|
|
6568
6644
|
"Host github.com",
|
|
6569
6645
|
` IdentityFile ${keyPath}`,
|
|
@@ -6573,10 +6649,10 @@ function writeSshConfig(sshDir, keyPath) {
|
|
|
6573
6649
|
""
|
|
6574
6650
|
].join(`
|
|
6575
6651
|
`);
|
|
6576
|
-
|
|
6652
|
+
writeFileSync10(configPath, config, { mode: 420 });
|
|
6577
6653
|
}
|
|
6578
6654
|
function seedKnownHosts(sshDir) {
|
|
6579
|
-
const knownHostsPath =
|
|
6655
|
+
const knownHostsPath = resolve28(sshDir, "known_hosts");
|
|
6580
6656
|
const existingLines = readKnownHosts(knownHostsPath);
|
|
6581
6657
|
const requiredLines = GITHUB_KNOWN_HOSTS.split(/\r?\n/).map((line) => line.trim()).filter(Boolean);
|
|
6582
6658
|
const missing = requiredLines.filter((line) => !existingLines.has(line));
|
|
@@ -6587,23 +6663,23 @@ function seedKnownHosts(sshDir) {
|
|
|
6587
6663
|
for (const line of missing) {
|
|
6588
6664
|
existingLines.add(line);
|
|
6589
6665
|
}
|
|
6590
|
-
|
|
6666
|
+
writeFileSync10(knownHostsPath, `${Array.from(existingLines).join(`
|
|
6591
6667
|
`)}
|
|
6592
6668
|
`, { mode: 420 });
|
|
6593
6669
|
} catch (err) {
|
|
6594
|
-
const hint =
|
|
6670
|
+
const hint = existsSync26(knownHostsPath) ? "" : " \u2014 known_hosts is missing; git SSH operations may fail";
|
|
6595
6671
|
console.warn(`[rig] Could not update ${knownHostsPath}: ${err instanceof Error ? err.message : String(err)}${hint}`);
|
|
6596
6672
|
}
|
|
6597
6673
|
}
|
|
6598
6674
|
function writeClaudeProjectSettings(claudeHomeDir, workspaceDir, runtimeSettings) {
|
|
6599
6675
|
const projectHash = hashProjectPath(workspaceDir);
|
|
6600
|
-
const projectDir =
|
|
6601
|
-
|
|
6602
|
-
|
|
6676
|
+
const projectDir = resolve28(claudeHomeDir, "projects", projectHash);
|
|
6677
|
+
mkdirSync12(projectDir, { recursive: true });
|
|
6678
|
+
writeFileSync10(resolve28(projectDir, "settings.json"), `${JSON.stringify(runtimeSettings, null, 2)}
|
|
6603
6679
|
`, "utf-8");
|
|
6604
6680
|
}
|
|
6605
6681
|
async function loadRuntimeClaudeSettings(projectSettingsPath) {
|
|
6606
|
-
if (!
|
|
6682
|
+
if (!existsSync26(projectSettingsPath)) {
|
|
6607
6683
|
return {};
|
|
6608
6684
|
}
|
|
6609
6685
|
let parsed;
|
|
@@ -6649,7 +6725,7 @@ async function loadRuntimeClaudeSettings(projectSettingsPath) {
|
|
|
6649
6725
|
return clone;
|
|
6650
6726
|
}
|
|
6651
6727
|
async function injectClaudeCredentials(claudeHomeDir, options = {}) {
|
|
6652
|
-
const credentialsPath =
|
|
6728
|
+
const credentialsPath = resolve28(claudeHomeDir, ".credentials.json");
|
|
6653
6729
|
const platform = options.platform ?? process.platform;
|
|
6654
6730
|
if (platform === "darwin") {
|
|
6655
6731
|
const raw = options.loadKeychainCredentials ? await options.loadKeychainCredentials() : await (async () => {
|
|
@@ -6659,16 +6735,16 @@ async function injectClaudeCredentials(claudeHomeDir, options = {}) {
|
|
|
6659
6735
|
if (raw) {
|
|
6660
6736
|
try {
|
|
6661
6737
|
JSON.parse(raw);
|
|
6662
|
-
|
|
6738
|
+
writeFileSync10(credentialsPath, raw, { mode: 384 });
|
|
6663
6739
|
registerCredentialCleanup(credentialsPath);
|
|
6664
6740
|
return true;
|
|
6665
6741
|
} catch {}
|
|
6666
6742
|
}
|
|
6667
6743
|
}
|
|
6668
|
-
const hostClaudeHome = options.hostClaudeHome ?
|
|
6744
|
+
const hostClaudeHome = options.hostClaudeHome ? resolve28(options.hostClaudeHome) : process.env.CLAUDE_HOME?.trim() ? resolve28(process.env.CLAUDE_HOME) : process.env.HOME ? resolve28(process.env.HOME, ".claude") : "";
|
|
6669
6745
|
if (hostClaudeHome) {
|
|
6670
|
-
const realCredentials =
|
|
6671
|
-
if (
|
|
6746
|
+
const realCredentials = resolve28(hostClaudeHome, ".credentials.json");
|
|
6747
|
+
if (existsSync26(realCredentials)) {
|
|
6672
6748
|
cpSync2(realCredentials, credentialsPath);
|
|
6673
6749
|
return true;
|
|
6674
6750
|
}
|
|
@@ -6676,36 +6752,36 @@ async function injectClaudeCredentials(claudeHomeDir, options = {}) {
|
|
|
6676
6752
|
return false;
|
|
6677
6753
|
}
|
|
6678
6754
|
async function injectCodexAuth(codexHomeDir) {
|
|
6679
|
-
|
|
6680
|
-
const hostCodexHome = process.env.CODEX_HOME?.trim() ?
|
|
6755
|
+
mkdirSync12(codexHomeDir, { recursive: true });
|
|
6756
|
+
const hostCodexHome = process.env.CODEX_HOME?.trim() ? resolve28(process.env.CODEX_HOME) : process.env.HOME ? resolve28(process.env.HOME, ".codex") : "";
|
|
6681
6757
|
if (!hostCodexHome) {
|
|
6682
6758
|
return false;
|
|
6683
6759
|
}
|
|
6684
|
-
const hostAuthPath =
|
|
6685
|
-
if (!
|
|
6760
|
+
const hostAuthPath = resolve28(hostCodexHome, "auth.json");
|
|
6761
|
+
if (!existsSync26(hostAuthPath)) {
|
|
6686
6762
|
return false;
|
|
6687
6763
|
}
|
|
6688
|
-
const runtimeAuthPath =
|
|
6764
|
+
const runtimeAuthPath = resolve28(codexHomeDir, "auth.json");
|
|
6689
6765
|
copyFileSync5(hostAuthPath, runtimeAuthPath);
|
|
6690
6766
|
chmodSync5(runtimeAuthPath, 384);
|
|
6691
6767
|
return true;
|
|
6692
6768
|
}
|
|
6693
6769
|
async function injectPiAgentConfig(piAgentDir) {
|
|
6694
|
-
|
|
6695
|
-
const hostPiAgentDir = process.env.PI_CODING_AGENT_DIR?.trim() ?
|
|
6770
|
+
mkdirSync12(piAgentDir, { recursive: true });
|
|
6771
|
+
const hostPiAgentDir = process.env.PI_CODING_AGENT_DIR?.trim() ? resolve28(process.env.PI_CODING_AGENT_DIR) : process.env.HOME ? resolve28(process.env.HOME, ".pi", "agent") : "";
|
|
6696
6772
|
if (!hostPiAgentDir) {
|
|
6697
6773
|
return false;
|
|
6698
6774
|
}
|
|
6699
|
-
const hostAuthPath =
|
|
6700
|
-
if (!
|
|
6775
|
+
const hostAuthPath = resolve28(hostPiAgentDir, "auth.json");
|
|
6776
|
+
if (!existsSync26(hostAuthPath)) {
|
|
6701
6777
|
return false;
|
|
6702
6778
|
}
|
|
6703
|
-
const runtimeAuthPath =
|
|
6779
|
+
const runtimeAuthPath = resolve28(piAgentDir, "auth.json");
|
|
6704
6780
|
copyFileSync5(hostAuthPath, runtimeAuthPath);
|
|
6705
6781
|
chmodSync5(runtimeAuthPath, 384);
|
|
6706
|
-
const hostSettingsPath =
|
|
6707
|
-
if (
|
|
6708
|
-
const runtimeSettingsPath =
|
|
6782
|
+
const hostSettingsPath = resolve28(hostPiAgentDir, "settings.json");
|
|
6783
|
+
if (existsSync26(hostSettingsPath)) {
|
|
6784
|
+
const runtimeSettingsPath = resolve28(piAgentDir, "settings.json");
|
|
6709
6785
|
copyFileSync5(hostSettingsPath, runtimeSettingsPath);
|
|
6710
6786
|
chmodSync5(runtimeSettingsPath, 384);
|
|
6711
6787
|
}
|
|
@@ -6713,13 +6789,13 @@ async function injectPiAgentConfig(piAgentDir) {
|
|
|
6713
6789
|
}
|
|
6714
6790
|
|
|
6715
6791
|
// packages/runtime/src/control-plane/runtime/tooling/claude-router.ts
|
|
6716
|
-
import { existsSync as
|
|
6717
|
-
import { resolve as
|
|
6792
|
+
import { existsSync as existsSync27, mkdirSync as mkdirSync13, statSync as statSync7, writeFileSync as writeFileSync11 } from "fs";
|
|
6793
|
+
import { resolve as resolve29 } from "path";
|
|
6718
6794
|
var CLAUDE_ROUTER_SERVER_NAME = "rig_runtime_tools";
|
|
6719
6795
|
function buildRuntimeToolRouterServerConfig(options) {
|
|
6720
6796
|
return {
|
|
6721
6797
|
type: "stdio",
|
|
6722
|
-
command:
|
|
6798
|
+
command: resolve29(options.binDir, "rig-tool-router"),
|
|
6723
6799
|
args: [],
|
|
6724
6800
|
env: {
|
|
6725
6801
|
RIG_RUNTIME_CONTEXT_FILE: options.contextFile,
|
|
@@ -6728,14 +6804,14 @@ function buildRuntimeToolRouterServerConfig(options) {
|
|
|
6728
6804
|
};
|
|
6729
6805
|
}
|
|
6730
6806
|
function writeClaudeRuntimeToolRouterConfig(options) {
|
|
6731
|
-
const configPath =
|
|
6732
|
-
|
|
6807
|
+
const configPath = resolve29(options.stateDir, "claude-runtime-tools.mcp.json");
|
|
6808
|
+
mkdirSync13(options.stateDir, { recursive: true });
|
|
6733
6809
|
const payload = {
|
|
6734
6810
|
mcpServers: {
|
|
6735
6811
|
[CLAUDE_ROUTER_SERVER_NAME]: buildRuntimeToolRouterServerConfig(options)
|
|
6736
6812
|
}
|
|
6737
6813
|
};
|
|
6738
|
-
|
|
6814
|
+
writeFileSync11(configPath, `${JSON.stringify(payload, null, 2)}
|
|
6739
6815
|
`, "utf-8");
|
|
6740
6816
|
return configPath;
|
|
6741
6817
|
}
|
|
@@ -6744,8 +6820,8 @@ if (false) {}
|
|
|
6744
6820
|
init_layout();
|
|
6745
6821
|
|
|
6746
6822
|
// packages/runtime/src/control-plane/runtime/isolation/worktree.ts
|
|
6747
|
-
import { existsSync as
|
|
6748
|
-
import { dirname as dirname12, resolve as
|
|
6823
|
+
import { existsSync as existsSync28, mkdirSync as mkdirSync14, rmSync as rmSync10 } from "fs";
|
|
6824
|
+
import { dirname as dirname12, resolve as resolve30 } from "path";
|
|
6749
6825
|
async function resolveMonorepoBaseRef(monorepoRoot) {
|
|
6750
6826
|
const explicit = process.env.RIG_RUNTIME_BASE_REF?.trim();
|
|
6751
6827
|
if (explicit) {
|
|
@@ -6781,12 +6857,12 @@ function ensureProvisioningHostProjectRootEnv(projectRoot) {
|
|
|
6781
6857
|
}
|
|
6782
6858
|
async function provisionRuntimeWorktree(config) {
|
|
6783
6859
|
const branch = runtimeBranchName(config.taskId, config.runtimeId);
|
|
6784
|
-
let hasValidWorktree =
|
|
6785
|
-
if (
|
|
6786
|
-
|
|
6860
|
+
let hasValidWorktree = existsSync28(resolve30(config.workspaceDir, ".git")) && (await runGitCommand(config.workspaceDir, ["rev-parse", "--show-toplevel"])).exitCode === 0;
|
|
6861
|
+
if (existsSync28(config.workspaceDir) && !hasValidWorktree) {
|
|
6862
|
+
rmSync10(config.workspaceDir, { recursive: true, force: true });
|
|
6787
6863
|
}
|
|
6788
6864
|
if (!hasValidWorktree) {
|
|
6789
|
-
|
|
6865
|
+
mkdirSync14(dirname12(config.workspaceDir), { recursive: true });
|
|
6790
6866
|
const branchExists = await runGitCommand(config.monorepoRoot, ["show-ref", "--verify", "--quiet", `refs/heads/${branch}`]);
|
|
6791
6867
|
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]);
|
|
6792
6868
|
if (add.exitCode !== 0) {
|
|
@@ -6962,31 +7038,31 @@ async function preferredBaseRemotes(repoRoot) {
|
|
|
6962
7038
|
|
|
6963
7039
|
// packages/runtime/src/control-plane/runtime/isolation/toolchain.ts
|
|
6964
7040
|
import {
|
|
6965
|
-
existsSync as
|
|
7041
|
+
existsSync as existsSync30,
|
|
6966
7042
|
lstatSync,
|
|
6967
|
-
mkdirSync as
|
|
6968
|
-
readdirSync as
|
|
6969
|
-
readFileSync as
|
|
6970
|
-
rmSync as
|
|
7043
|
+
mkdirSync as mkdirSync16,
|
|
7044
|
+
readdirSync as readdirSync6,
|
|
7045
|
+
readFileSync as readFileSync15,
|
|
7046
|
+
rmSync as rmSync11,
|
|
6971
7047
|
statSync as statSync9,
|
|
6972
7048
|
symlinkSync as symlinkSync4
|
|
6973
7049
|
} from "fs";
|
|
6974
7050
|
import { mkdir as mkdir3, writeFile } from "fs/promises";
|
|
6975
|
-
import { dirname as dirname14, resolve as
|
|
7051
|
+
import { dirname as dirname14, resolve as resolve32 } from "path";
|
|
6976
7052
|
|
|
6977
7053
|
// packages/runtime/src/control-plane/runtime/tooling/claude-router-binary.ts
|
|
6978
|
-
import { chmodSync as chmodSync6, copyFileSync as copyFileSync6, existsSync as
|
|
7054
|
+
import { chmodSync as chmodSync6, copyFileSync as copyFileSync6, existsSync as existsSync29, mkdirSync as mkdirSync15, statSync as statSync8 } from "fs";
|
|
6979
7055
|
import { tmpdir as tmpdir6 } from "os";
|
|
6980
|
-
import { dirname as dirname13, resolve as
|
|
6981
|
-
var sharedRouterOutputDir =
|
|
6982
|
-
var sharedRouterOutputPath =
|
|
7056
|
+
import { dirname as dirname13, resolve as resolve31 } from "path";
|
|
7057
|
+
var sharedRouterOutputDir = resolve31(tmpdir6(), "rig-native");
|
|
7058
|
+
var sharedRouterOutputPath = resolve31(sharedRouterOutputDir, `rig-tool-router-${process.platform}-${process.arch}${process.platform === "win32" ? ".exe" : ""}`);
|
|
6983
7059
|
function runtimeClaudeToolRouterFileName() {
|
|
6984
7060
|
return `rig-tool-router${process.platform === "win32" ? ".exe" : ""}`;
|
|
6985
7061
|
}
|
|
6986
7062
|
async function ensureClaudeToolRouterBinaryPath(projectRoot, outputPath = sharedRouterOutputPath) {
|
|
6987
|
-
const sourcePath =
|
|
6988
|
-
|
|
6989
|
-
const needsBuild = !
|
|
7063
|
+
const sourcePath = resolve31(projectRoot, "packages/runtime/src/control-plane/runtime/tooling/claude-router.ts");
|
|
7064
|
+
mkdirSync15(dirname13(outputPath), { recursive: true });
|
|
7065
|
+
const needsBuild = !existsSync29(outputPath) || statSync8(sourcePath).mtimeMs > statSync8(outputPath).mtimeMs;
|
|
6990
7066
|
if (!needsBuild) {
|
|
6991
7067
|
return outputPath;
|
|
6992
7068
|
}
|
|
@@ -7000,9 +7076,9 @@ async function ensureClaudeToolRouterBinaryPath(projectRoot, outputPath = shared
|
|
|
7000
7076
|
}
|
|
7001
7077
|
async function materializeClaudeToolRouterBinary(projectRoot, targetDir) {
|
|
7002
7078
|
const sourcePath = await ensureClaudeToolRouterBinaryPath(projectRoot);
|
|
7003
|
-
const targetPath =
|
|
7004
|
-
|
|
7005
|
-
const needsCopy = !
|
|
7079
|
+
const targetPath = resolve31(targetDir, runtimeClaudeToolRouterFileName());
|
|
7080
|
+
mkdirSync15(targetDir, { recursive: true });
|
|
7081
|
+
const needsCopy = !existsSync29(targetPath) || statSync8(sourcePath).mtimeMs > statSync8(targetPath).mtimeMs;
|
|
7006
7082
|
if (needsCopy) {
|
|
7007
7083
|
copyFileSync6(sourcePath, targetPath);
|
|
7008
7084
|
chmodSync6(targetPath, 493);
|
|
@@ -7015,48 +7091,48 @@ var GIT_INDEX_LOCK_RETRY_DELAY_MS = 250;
|
|
|
7015
7091
|
var GIT_INDEX_LOCK_STALE_AFTER_MS = 5000;
|
|
7016
7092
|
function resolveRigSourceRoot(projectRoot) {
|
|
7017
7093
|
const hostProjectRoot = process.env.RIG_HOST_PROJECT_ROOT?.trim();
|
|
7018
|
-
if (hostProjectRoot &&
|
|
7094
|
+
if (hostProjectRoot && existsSync30(resolve32(hostProjectRoot, "packages/runtime/bin/rig-agent.ts"))) {
|
|
7019
7095
|
return hostProjectRoot;
|
|
7020
7096
|
}
|
|
7021
|
-
const fromModule =
|
|
7022
|
-
if (
|
|
7097
|
+
const fromModule = resolve32(import.meta.dir, "../../../../../..");
|
|
7098
|
+
if (existsSync30(resolve32(fromModule, "packages/runtime/bin/rig-agent.ts"))) {
|
|
7023
7099
|
return fromModule;
|
|
7024
7100
|
}
|
|
7025
7101
|
return projectRoot;
|
|
7026
7102
|
}
|
|
7027
7103
|
function prepareTrackedRuntimePaths(logsDir, stateDir, sessionDir) {
|
|
7028
|
-
for (const path of [logsDir, stateDir, sessionDir,
|
|
7104
|
+
for (const path of [logsDir, stateDir, sessionDir, resolve32(sessionDir, "session.json")]) {
|
|
7029
7105
|
removeSymbolicLink(path);
|
|
7030
7106
|
}
|
|
7031
7107
|
runtimePrepareTrackedPathsNative({
|
|
7032
7108
|
logsDir,
|
|
7033
7109
|
stateDir,
|
|
7034
7110
|
sessionDir,
|
|
7035
|
-
controlledBashLogFile:
|
|
7036
|
-
eventsFile:
|
|
7111
|
+
controlledBashLogFile: resolve32(logsDir, "controlled-bash.jsonl"),
|
|
7112
|
+
eventsFile: resolve32(logsDir, "control-plane.events.jsonl")
|
|
7037
7113
|
});
|
|
7038
7114
|
}
|
|
7039
7115
|
async function initializeRuntimeStateFiles(stateDir, sessionDir, taskId) {
|
|
7040
7116
|
await mkdir3(stateDir, { recursive: true });
|
|
7041
7117
|
await mkdir3(sessionDir, { recursive: true });
|
|
7042
|
-
const failedApproachesPath =
|
|
7043
|
-
if (!
|
|
7118
|
+
const failedApproachesPath = resolve32(stateDir, "failed_approaches.md");
|
|
7119
|
+
if (!existsSync30(failedApproachesPath)) {
|
|
7044
7120
|
await writeFile(failedApproachesPath, `# Failed Approaches
|
|
7045
7121
|
|
|
7046
7122
|
`);
|
|
7047
7123
|
}
|
|
7048
|
-
const hookTripsPath =
|
|
7049
|
-
if (!
|
|
7124
|
+
const hookTripsPath = resolve32(stateDir, "hook_trips.log");
|
|
7125
|
+
if (!existsSync30(hookTripsPath)) {
|
|
7050
7126
|
await writeFile(hookTripsPath, "");
|
|
7051
7127
|
}
|
|
7052
|
-
const sessionFile =
|
|
7128
|
+
const sessionFile = resolve32(sessionDir, "session.json");
|
|
7053
7129
|
if (taskId) {
|
|
7054
7130
|
await writeFile(sessionFile, JSON.stringify({ activeTaskIds: [taskId] }));
|
|
7055
7131
|
}
|
|
7056
7132
|
}
|
|
7057
7133
|
async function resetEphemeralTaskArtifacts(workspaceDir, taskId) {
|
|
7058
|
-
const artifactDir =
|
|
7059
|
-
const runtimeSnapshotDir =
|
|
7134
|
+
const artifactDir = resolve32(workspaceDir, "artifacts", taskId);
|
|
7135
|
+
const runtimeSnapshotDir = resolve32(artifactDir, "runtime-snapshots");
|
|
7060
7136
|
let preservedTrackedFiles = false;
|
|
7061
7137
|
for (const file of [
|
|
7062
7138
|
"changed-files.txt",
|
|
@@ -7072,13 +7148,13 @@ async function resetEphemeralTaskArtifacts(workspaceDir, taskId) {
|
|
|
7072
7148
|
preservedTrackedFiles = true;
|
|
7073
7149
|
continue;
|
|
7074
7150
|
}
|
|
7075
|
-
|
|
7151
|
+
rmSync11(resolve32(artifactDir, file), { force: true });
|
|
7076
7152
|
}
|
|
7077
7153
|
const runtimeSnapshotRelativePath = `artifacts/${taskId}/runtime-snapshots`;
|
|
7078
7154
|
if (await resetTrackedArtifactPath(workspaceDir, runtimeSnapshotRelativePath)) {
|
|
7079
7155
|
preservedTrackedFiles = true;
|
|
7080
7156
|
} else {
|
|
7081
|
-
|
|
7157
|
+
rmSync11(runtimeSnapshotDir, { recursive: true, force: true });
|
|
7082
7158
|
}
|
|
7083
7159
|
if (preservedTrackedFiles) {
|
|
7084
7160
|
console.log(`[rig-agent] Preserved tracked runtime artifact files in ${taskId}; skipped ephemeral cleanup for committed paths.`);
|
|
@@ -7111,28 +7187,28 @@ async function buildRuntimeToolchain(options) {
|
|
|
7111
7187
|
throw new Error("Failed to provision the native Zig runtime library.");
|
|
7112
7188
|
}
|
|
7113
7189
|
const rigSourceRoot = resolveRigSourceRoot(options.projectRoot);
|
|
7114
|
-
await buildBinary("packages/cli/bin/rig.ts",
|
|
7115
|
-
await buildBinary("packages/runtime/bin/rig-agent.ts",
|
|
7190
|
+
await buildBinary("packages/cli/bin/rig.ts", resolve32(options.binDir, "rig"), rigSourceRoot);
|
|
7191
|
+
await buildBinary("packages/runtime/bin/rig-agent.ts", resolve32(options.binDir, "rig-agent"), rigSourceRoot, {
|
|
7116
7192
|
...options.runtimeSecretDefines,
|
|
7117
7193
|
AGENT_TASK_ID: options.taskId,
|
|
7118
7194
|
AGENT_PROJECT_ROOT: options.projectRoot,
|
|
7119
7195
|
AGENT_RUNTIME_ID: options.runtimeId,
|
|
7120
7196
|
AGENT_SCOPE_HASH: options.bakedScopeHash,
|
|
7121
7197
|
AGENT_MANIFEST_PATH: options.manifestPath,
|
|
7122
|
-
AGENT_BINARY_PATH:
|
|
7198
|
+
AGENT_BINARY_PATH: resolve32(options.binDir, "rig-agent"),
|
|
7123
7199
|
AGENT_INFO_OUTPUT: options.bakedInfoOutput,
|
|
7124
7200
|
AGENT_DEPS_OUTPUT: options.bakedDepsOutput,
|
|
7125
7201
|
AGENT_STATUS_OUTPUT: options.bakedStatusOutput
|
|
7126
7202
|
});
|
|
7127
|
-
await buildBinary("packages/runtime/src/control-plane/controlled-bash.ts",
|
|
7203
|
+
await buildBinary("packages/runtime/src/control-plane/controlled-bash.ts", resolve32(options.binDir, "controlled-bash"), rigSourceRoot, {
|
|
7128
7204
|
AGENT_PROJECT_ROOT: options.projectRoot,
|
|
7129
7205
|
AGENT_LOGS_DIR: options.logsDir,
|
|
7130
7206
|
AGENT_MONOREPO_ROOT: resolveMonorepoRoot3(options.projectRoot),
|
|
7131
|
-
AGENT_TS_API_TESTS_DIR:
|
|
7132
|
-
AGENT_RIG_AGENT_BIN:
|
|
7207
|
+
AGENT_TS_API_TESTS_DIR: resolve32(options.workspaceDir, "TSAPITests"),
|
|
7208
|
+
AGENT_RIG_AGENT_BIN: resolve32(options.binDir, "rig-agent")
|
|
7133
7209
|
});
|
|
7134
|
-
await buildBinary("packages/runtime/bin/rig-browser-tool.ts",
|
|
7135
|
-
await buildBinary("packages/runtime/src/control-plane/runtime/snapshot/sidecar.ts",
|
|
7210
|
+
await buildBinary("packages/runtime/bin/rig-browser-tool.ts", resolve32(options.binDir, runtimeBrowserToolBinaryName()), rigSourceRoot);
|
|
7211
|
+
await buildBinary("packages/runtime/src/control-plane/runtime/snapshot/sidecar.ts", resolve32(options.binDir, "snapshot-sidecar"), rigSourceRoot, {
|
|
7136
7212
|
AGENT_PROJECT_ROOT: options.projectRoot,
|
|
7137
7213
|
AGENT_BUN_PATH: resolveBunBinaryPath()
|
|
7138
7214
|
});
|
|
@@ -7141,15 +7217,15 @@ async function buildRuntimeToolchain(options) {
|
|
|
7141
7217
|
AGENT_BUN_PATH: resolveBunBinaryPath()
|
|
7142
7218
|
};
|
|
7143
7219
|
for (const hookName of hookNames) {
|
|
7144
|
-
await buildBinary(`packages/runtime/src/control-plane/hooks/${hookName}.ts`,
|
|
7220
|
+
await buildBinary(`packages/runtime/src/control-plane/hooks/${hookName}.ts`, resolve32(runtimeBins.hooksDir, hookName), rigSourceRoot, hookDefines);
|
|
7145
7221
|
}
|
|
7146
|
-
const pluginsDir =
|
|
7147
|
-
if (
|
|
7148
|
-
for (const entry of
|
|
7222
|
+
const pluginsDir = resolve32(options.projectRoot, "rig/plugins");
|
|
7223
|
+
if (existsSync30(pluginsDir)) {
|
|
7224
|
+
for (const entry of readdirSync6(pluginsDir, { withFileTypes: true })) {
|
|
7149
7225
|
const match = entry.name.match(/^(.+)\.plugin\.(ts|js|mjs|cjs)$/);
|
|
7150
7226
|
if (!match)
|
|
7151
7227
|
continue;
|
|
7152
|
-
await buildBinary(`rig/plugins/${entry.name}`,
|
|
7228
|
+
await buildBinary(`rig/plugins/${entry.name}`, resolve32(runtimeBins.pluginsDir, match[1]), options.projectRoot);
|
|
7153
7229
|
}
|
|
7154
7230
|
}
|
|
7155
7231
|
await materializeRigGitBinary(options.binDir);
|
|
@@ -7159,8 +7235,8 @@ async function buildRuntimeToolchain(options) {
|
|
|
7159
7235
|
}
|
|
7160
7236
|
async function writeRuntimeManifest(config) {
|
|
7161
7237
|
const scopeHash = sha256Hex(JSON.stringify(config.scopes));
|
|
7162
|
-
const binarySha256 = sha256Hex(
|
|
7163
|
-
const manifestPath =
|
|
7238
|
+
const binarySha256 = sha256Hex(readFileSync15(config.binaryPath));
|
|
7239
|
+
const manifestPath = resolve32(config.runtimeRoot, "manifest.json");
|
|
7164
7240
|
const manifest = {
|
|
7165
7241
|
runtimeId: config.runtimeId,
|
|
7166
7242
|
taskId: config.taskId,
|
|
@@ -7194,7 +7270,7 @@ function removeSymbolicLink(path) {
|
|
|
7194
7270
|
} catch {
|
|
7195
7271
|
return;
|
|
7196
7272
|
}
|
|
7197
|
-
|
|
7273
|
+
rmSync11(path, { force: true, recursive: true });
|
|
7198
7274
|
}
|
|
7199
7275
|
async function resetTrackedArtifactPath(workspaceDir, relativePath) {
|
|
7200
7276
|
const tracked = await runGitLsFiles(workspaceDir, relativePath);
|
|
@@ -7220,7 +7296,7 @@ async function restoreTrackedArtifactPathWithRetry(workspaceDir, relativePath, r
|
|
|
7220
7296
|
const retryDelayMs = options.retryDelayMs ?? GIT_INDEX_LOCK_RETRY_DELAY_MS;
|
|
7221
7297
|
const now = options.now ?? Date.now;
|
|
7222
7298
|
const statMtimeMs = options.statMtimeMs ?? readFileMtimeMs;
|
|
7223
|
-
const removeFile = options.removeFile ?? ((path) =>
|
|
7299
|
+
const removeFile = options.removeFile ?? ((path) => rmSync11(path, { force: true }));
|
|
7224
7300
|
const log = options.log ?? console.warn;
|
|
7225
7301
|
let lastOutput = "";
|
|
7226
7302
|
for (let attempt = 0;attempt <= maxRetries; attempt += 1) {
|
|
@@ -7280,31 +7356,31 @@ function readFileMtimeMs(path) {
|
|
|
7280
7356
|
}
|
|
7281
7357
|
function linkRuntimeDependencyLayers(monorepoRoot, workspaceDir) {
|
|
7282
7358
|
linkGenericNodeModulesLayers(monorepoRoot, workspaceDir);
|
|
7283
|
-
const sourceNodeModules =
|
|
7284
|
-
if (!
|
|
7285
|
-
const runtimeHumoongate =
|
|
7286
|
-
if (
|
|
7287
|
-
const targetNodeModules =
|
|
7359
|
+
const sourceNodeModules = resolve32(monorepoRoot, "humoongate", "node_modules");
|
|
7360
|
+
if (!existsSync30(sourceNodeModules)) {} else {
|
|
7361
|
+
const runtimeHumoongate = resolve32(workspaceDir, "humoongate");
|
|
7362
|
+
if (existsSync30(resolve32(runtimeHumoongate, "package.json"))) {
|
|
7363
|
+
const targetNodeModules = resolve32(runtimeHumoongate, "node_modules");
|
|
7288
7364
|
runtimeLinkDependencyLayerNative(sourceNodeModules, targetNodeModules);
|
|
7289
7365
|
}
|
|
7290
7366
|
}
|
|
7291
|
-
const runtimeHpNext =
|
|
7292
|
-
if (!
|
|
7367
|
+
const runtimeHpNext = resolve32(workspaceDir, "microservices", "hp-next-frontend", "app");
|
|
7368
|
+
if (!existsSync30(resolve32(runtimeHpNext, "package.json"))) {
|
|
7293
7369
|
return;
|
|
7294
7370
|
}
|
|
7295
|
-
const sourceHpNextNodeModules =
|
|
7296
|
-
const sourceMonorepoNodeModules =
|
|
7297
|
-
const targetHpNextNodeModules =
|
|
7298
|
-
if (
|
|
7371
|
+
const sourceHpNextNodeModules = resolve32(monorepoRoot, "microservices", "hp-next-frontend", "app", "node_modules");
|
|
7372
|
+
const sourceMonorepoNodeModules = resolve32(monorepoRoot, "node_modules");
|
|
7373
|
+
const targetHpNextNodeModules = resolve32(runtimeHpNext, "node_modules");
|
|
7374
|
+
if (existsSync30(sourceHpNextNodeModules)) {
|
|
7299
7375
|
runtimeLinkDependencyLayerNative(sourceHpNextNodeModules, targetHpNextNodeModules);
|
|
7300
7376
|
return;
|
|
7301
7377
|
}
|
|
7302
|
-
if (
|
|
7378
|
+
if (existsSync30(sourceMonorepoNodeModules)) {
|
|
7303
7379
|
runtimeLinkDependencyLayerNative(sourceMonorepoNodeModules, targetHpNextNodeModules);
|
|
7304
7380
|
}
|
|
7305
7381
|
}
|
|
7306
7382
|
function linkGenericNodeModulesLayers(monorepoRoot, workspaceDir) {
|
|
7307
|
-
linkNodeModulesLayer(
|
|
7383
|
+
linkNodeModulesLayer(resolve32(monorepoRoot, "node_modules"), resolve32(workspaceDir, "node_modules"));
|
|
7308
7384
|
for (const relativePackageDir of [
|
|
7309
7385
|
"apps/native-app/apps/marketing",
|
|
7310
7386
|
"apps/native-app/apps/web",
|
|
@@ -7326,15 +7402,15 @@ function linkGenericNodeModulesLayers(monorepoRoot, workspaceDir) {
|
|
|
7326
7402
|
"packages/standard-plugin",
|
|
7327
7403
|
"packages/validator-kit"
|
|
7328
7404
|
]) {
|
|
7329
|
-
const workspacePackageDir =
|
|
7330
|
-
if (!
|
|
7405
|
+
const workspacePackageDir = resolve32(workspaceDir, relativePackageDir);
|
|
7406
|
+
if (!existsSync30(resolve32(workspacePackageDir, "package.json"))) {
|
|
7331
7407
|
continue;
|
|
7332
7408
|
}
|
|
7333
|
-
linkNodeModulesLayer(
|
|
7409
|
+
linkNodeModulesLayer(resolve32(monorepoRoot, relativePackageDir, "node_modules"), resolve32(workspacePackageDir, "node_modules"));
|
|
7334
7410
|
}
|
|
7335
7411
|
}
|
|
7336
7412
|
function linkNodeModulesLayer(sourceDir, targetDir) {
|
|
7337
|
-
if (!
|
|
7413
|
+
if (!existsSync30(sourceDir) || existsSync30(targetDir)) {
|
|
7338
7414
|
return;
|
|
7339
7415
|
}
|
|
7340
7416
|
try {
|
|
@@ -7343,25 +7419,25 @@ function linkNodeModulesLayer(sourceDir, targetDir) {
|
|
|
7343
7419
|
} catch (error) {
|
|
7344
7420
|
console.warn(`[rig-agent] Native dependency-layer linking failed for ${targetDir}; using symlink fallback: ${error instanceof Error ? error.message : String(error)}`);
|
|
7345
7421
|
}
|
|
7346
|
-
|
|
7422
|
+
mkdirSync16(dirname14(targetDir), { recursive: true });
|
|
7347
7423
|
symlinkSync4(sourceDir, targetDir, "dir");
|
|
7348
7424
|
}
|
|
7349
7425
|
function ensureRuntimeBinTrees(runtimeBinDir) {
|
|
7350
|
-
const hooksDir =
|
|
7351
|
-
const pluginsDir =
|
|
7352
|
-
const validatorsDir =
|
|
7353
|
-
|
|
7354
|
-
|
|
7355
|
-
|
|
7426
|
+
const hooksDir = resolve32(runtimeBinDir, "hooks");
|
|
7427
|
+
const pluginsDir = resolve32(runtimeBinDir, "plugins");
|
|
7428
|
+
const validatorsDir = resolve32(runtimeBinDir, "validators");
|
|
7429
|
+
mkdirSync16(hooksDir, { recursive: true });
|
|
7430
|
+
mkdirSync16(pluginsDir, { recursive: true });
|
|
7431
|
+
mkdirSync16(validatorsDir, { recursive: true });
|
|
7356
7432
|
return { hooksDir, pluginsDir, validatorsDir };
|
|
7357
7433
|
}
|
|
7358
7434
|
|
|
7359
7435
|
// packages/runtime/src/control-plane/runtime/isolation/runner.ts
|
|
7360
|
-
import { existsSync as
|
|
7361
|
-
import { basename as basename9, resolve as
|
|
7436
|
+
import { existsSync as existsSync32, rmSync as rmSync12, writeFileSync as writeFileSync13 } from "fs";
|
|
7437
|
+
import { basename as basename9, resolve as resolve35 } from "path";
|
|
7362
7438
|
|
|
7363
7439
|
// packages/runtime/src/control-plane/runtime/sandbox/backend.ts
|
|
7364
|
-
import { existsSync as
|
|
7440
|
+
import { existsSync as existsSync31 } from "fs";
|
|
7365
7441
|
init_utils();
|
|
7366
7442
|
|
|
7367
7443
|
// packages/runtime/src/control-plane/runtime/sandbox/backend-none.ts
|
|
@@ -7461,13 +7537,13 @@ async function resolveBackend(projectRoot, options) {
|
|
|
7461
7537
|
depRoots
|
|
7462
7538
|
};
|
|
7463
7539
|
const fsContext = {
|
|
7464
|
-
pathExists: (p) =>
|
|
7540
|
+
pathExists: (p) => existsSync31(p),
|
|
7465
7541
|
realPath: toRealPath
|
|
7466
7542
|
};
|
|
7467
7543
|
if (process.platform === "darwin" && (!requestedBackend || requestedBackend === "macos-seatbelt")) {
|
|
7468
7544
|
const seatbelt = Bun.which("sandbox-exec");
|
|
7469
7545
|
probed.push("sandbox-exec");
|
|
7470
|
-
if (seatbelt &&
|
|
7546
|
+
if (seatbelt && existsSync31(seatbelt)) {
|
|
7471
7547
|
const SeatbeltBackendClass = loadSeatbeltBackend();
|
|
7472
7548
|
if (SeatbeltBackendClass) {
|
|
7473
7549
|
return {
|
|
@@ -7588,10 +7664,10 @@ init_layout();
|
|
|
7588
7664
|
var SNAPSHOT_SIDECAR_READY_TIMEOUT_MS = 1e4;
|
|
7589
7665
|
async function startRuntimeSnapshotSidecar(runtime, options = {}) {
|
|
7590
7666
|
const instanceId = sanitizeRuntimeRefSegment(options.instanceId?.trim() || runtime.id);
|
|
7591
|
-
const readyFile =
|
|
7592
|
-
const requestFile =
|
|
7593
|
-
|
|
7594
|
-
|
|
7667
|
+
const readyFile = resolve35(runtime.stateDir, `runtime-snapshot-sidecar-${instanceId}.ready`);
|
|
7668
|
+
const requestFile = resolve35(runtime.stateDir, `runtime-snapshot-sidecar-${instanceId}.request.json`);
|
|
7669
|
+
rmSync12(readyFile, { force: true });
|
|
7670
|
+
rmSync12(requestFile, { force: true });
|
|
7595
7671
|
const sidecarBinary = resolveSnapshotSidecarBinaryPath(runtime.binDir);
|
|
7596
7672
|
const useCompiledSidecar = shouldUseCompiledSnapshotSidecar(sidecarBinary);
|
|
7597
7673
|
const bunCli = useCompiledSidecar ? null : resolveBunCliInvocation();
|
|
@@ -7629,19 +7705,19 @@ async function startRuntimeSnapshotSidecar(runtime, options = {}) {
|
|
|
7629
7705
|
proc.kill("SIGTERM");
|
|
7630
7706
|
} catch {}
|
|
7631
7707
|
await proc.exited;
|
|
7632
|
-
|
|
7633
|
-
|
|
7708
|
+
rmSync12(readyFile, { force: true });
|
|
7709
|
+
rmSync12(requestFile, { force: true });
|
|
7634
7710
|
},
|
|
7635
7711
|
finalize: async (commandParts, exitCode) => {
|
|
7636
|
-
|
|
7712
|
+
writeFileSync13(requestFile, `${JSON.stringify({ command: commandParts, exitCode })}
|
|
7637
7713
|
`, "utf-8");
|
|
7638
7714
|
const [sidecarExitCode, stdout, stderr] = await Promise.all([
|
|
7639
7715
|
proc.exited,
|
|
7640
7716
|
stdoutTextPromise,
|
|
7641
7717
|
stderrTextPromise
|
|
7642
7718
|
]);
|
|
7643
|
-
|
|
7644
|
-
|
|
7719
|
+
rmSync12(readyFile, { force: true });
|
|
7720
|
+
rmSync12(requestFile, { force: true });
|
|
7645
7721
|
if (sidecarExitCode !== 0) {
|
|
7646
7722
|
throw new Error(`snapshot sidecar failed (${sidecarExitCode}): ${stderr || stdout}`);
|
|
7647
7723
|
}
|
|
@@ -7697,8 +7773,8 @@ async function runInAgentRuntime(options) {
|
|
|
7697
7773
|
const stdout = await new Response(proc.stdout).text();
|
|
7698
7774
|
const stderr = await new Response(proc.stderr).text();
|
|
7699
7775
|
try {
|
|
7700
|
-
await Bun.write(
|
|
7701
|
-
await Bun.write(
|
|
7776
|
+
await Bun.write(resolve35(options.runtime.logsDir, "agent-stdout.log"), stdout);
|
|
7777
|
+
await Bun.write(resolve35(options.runtime.logsDir, "agent-stderr.log"), stderr);
|
|
7702
7778
|
} catch {}
|
|
7703
7779
|
await snapshotSidecar.finalize(runtimeCommand, exitCode);
|
|
7704
7780
|
return {
|
|
@@ -7730,10 +7806,10 @@ function resolveSnapshotSidecarScriptPath() {
|
|
|
7730
7806
|
return resolveRuntimeSourceScriptPath("snapshot-sidecar.ts");
|
|
7731
7807
|
}
|
|
7732
7808
|
function resolveSnapshotSidecarBinaryPath(binDir) {
|
|
7733
|
-
return
|
|
7809
|
+
return resolve35(binDir, "snapshot-sidecar");
|
|
7734
7810
|
}
|
|
7735
7811
|
function shouldUseCompiledSnapshotSidecar(binaryPath) {
|
|
7736
|
-
if (!
|
|
7812
|
+
if (!existsSync32(binaryPath)) {
|
|
7737
7813
|
return false;
|
|
7738
7814
|
}
|
|
7739
7815
|
const preference = process.env.RIG_USE_COMPILED_SNAPSHOT_SIDECAR?.trim().toLowerCase();
|
|
@@ -7748,12 +7824,12 @@ function resolveRuntimeSourceScriptPath(fileName) {
|
|
|
7748
7824
|
process.env.PROJECT_RIG_ROOT?.trim()
|
|
7749
7825
|
].filter((value) => Boolean(value));
|
|
7750
7826
|
for (const root of hostRoots) {
|
|
7751
|
-
const candidate =
|
|
7752
|
-
if (
|
|
7827
|
+
const candidate = resolve35(root, "packages/runtime/src/control-plane/runtime", fileName);
|
|
7828
|
+
if (existsSync32(candidate)) {
|
|
7753
7829
|
return candidate;
|
|
7754
7830
|
}
|
|
7755
7831
|
}
|
|
7756
|
-
return
|
|
7832
|
+
return resolve35(import.meta.dir, "..", fileName);
|
|
7757
7833
|
}
|
|
7758
7834
|
function resolveBunCliInvocation() {
|
|
7759
7835
|
if (process.env.RIG_BUN_PATH?.trim()) {
|
|
@@ -7780,7 +7856,7 @@ function resolveBunCliInvocation() {
|
|
|
7780
7856
|
async function waitForSnapshotSidecarReady(readyFile, proc, stdoutTextPromise, stderrTextPromise) {
|
|
7781
7857
|
const deadline = Date.now() + SNAPSHOT_SIDECAR_READY_TIMEOUT_MS;
|
|
7782
7858
|
while (Date.now() < deadline) {
|
|
7783
|
-
if (
|
|
7859
|
+
if (existsSync32(readyFile)) {
|
|
7784
7860
|
return;
|
|
7785
7861
|
}
|
|
7786
7862
|
const exitCode = proc.exitCode;
|
|
@@ -7798,9 +7874,9 @@ var CANONICAL_MEMORY_DB_PATH2 = "rig/memory/project-memory.db";
|
|
|
7798
7874
|
async function hydrateRuntimeMemory(options) {
|
|
7799
7875
|
const snapshot = await readCanonicalMemoryDb(options.projectRoot);
|
|
7800
7876
|
const workspaceLayout = resolveRuntimeWorkspaceLayout(options.workspaceDir);
|
|
7801
|
-
const hydratedPath =
|
|
7877
|
+
const hydratedPath = resolve36(workspaceLayout.stateDir, "memory", "project-memory.db");
|
|
7802
7878
|
try {
|
|
7803
|
-
await mkdir4(
|
|
7879
|
+
await mkdir4(resolve36(workspaceLayout.stateDir, "memory"), { recursive: true });
|
|
7804
7880
|
await copyFile(snapshot.dbPath, hydratedPath);
|
|
7805
7881
|
return {
|
|
7806
7882
|
canonicalPath: CANONICAL_MEMORY_DB_PATH2,
|
|
@@ -7815,12 +7891,12 @@ async function hydrateRuntimeMemory(options) {
|
|
|
7815
7891
|
}
|
|
7816
7892
|
}
|
|
7817
7893
|
async function createRuntimeTaskRecordReader(options) {
|
|
7818
|
-
const legacyConfigPath =
|
|
7894
|
+
const legacyConfigPath = resolve36(options.projectRoot, ".rig", "task-config.json");
|
|
7819
7895
|
let pluginHostContext = null;
|
|
7820
7896
|
try {
|
|
7821
7897
|
pluginHostContext = await buildPluginHostContext(options.projectRoot);
|
|
7822
7898
|
} catch (error) {
|
|
7823
|
-
if (!
|
|
7899
|
+
if (!existsSync33(legacyConfigPath)) {
|
|
7824
7900
|
throw error;
|
|
7825
7901
|
}
|
|
7826
7902
|
const message = `Plugin task source unavailable; using source-aware .rig/task-config.json compatibility path: ${error instanceof Error ? error.message : String(error)}`;
|
|
@@ -7840,7 +7916,7 @@ async function createRuntimeTaskRecordReader(options) {
|
|
|
7840
7916
|
source: "plugin"
|
|
7841
7917
|
};
|
|
7842
7918
|
}
|
|
7843
|
-
if (
|
|
7919
|
+
if (existsSync33(legacyConfigPath)) {
|
|
7844
7920
|
const message = "Using source-aware .rig/task-config.json task source compatibility path";
|
|
7845
7921
|
options.diagnostics?.(message);
|
|
7846
7922
|
console.warn(message);
|
|
@@ -7857,10 +7933,10 @@ async function createRuntimeTaskRecordReader(options) {
|
|
|
7857
7933
|
};
|
|
7858
7934
|
}
|
|
7859
7935
|
function readConfiguredTaskSourceKindHint(projectRoot) {
|
|
7860
|
-
const jsonPath =
|
|
7861
|
-
if (
|
|
7936
|
+
const jsonPath = resolve36(projectRoot, "rig.config.json");
|
|
7937
|
+
if (existsSync33(jsonPath)) {
|
|
7862
7938
|
try {
|
|
7863
|
-
const parsed = JSON.parse(
|
|
7939
|
+
const parsed = JSON.parse(readFileSync16(jsonPath, "utf8"));
|
|
7864
7940
|
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
7865
7941
|
const taskSource = parsed.taskSource;
|
|
7866
7942
|
if (taskSource && typeof taskSource === "object" && !Array.isArray(taskSource)) {
|
|
@@ -7872,12 +7948,12 @@ function readConfiguredTaskSourceKindHint(projectRoot) {
|
|
|
7872
7948
|
return null;
|
|
7873
7949
|
}
|
|
7874
7950
|
}
|
|
7875
|
-
const tsPath =
|
|
7876
|
-
if (!
|
|
7951
|
+
const tsPath = resolve36(projectRoot, "rig.config.ts");
|
|
7952
|
+
if (!existsSync33(tsPath)) {
|
|
7877
7953
|
return null;
|
|
7878
7954
|
}
|
|
7879
7955
|
try {
|
|
7880
|
-
const source =
|
|
7956
|
+
const source = readFileSync16(tsPath, "utf8");
|
|
7881
7957
|
const taskSourceBlock = source.match(/taskSource\s*:\s*\{[\s\S]*?\}/m)?.[0] ?? "";
|
|
7882
7958
|
const kind = taskSourceBlock.match(/kind\s*:\s*["']([^"']+)["']/)?.[1];
|
|
7883
7959
|
return kind ?? null;
|
|
@@ -7947,8 +8023,8 @@ async function writeRuntimeTaskConfigProjection(options) {
|
|
|
7947
8023
|
...options.taskEntry.validation && options.taskEntry.validation.length > 0 ? { validation: options.taskEntry.validation } : {},
|
|
7948
8024
|
...options.taskEntry.browser ? { browser: options.taskEntry.browser } : {}
|
|
7949
8025
|
};
|
|
7950
|
-
const configPath =
|
|
7951
|
-
await mkdir4(
|
|
8026
|
+
const configPath = resolve36(options.workspaceDir, ".rig", "task-config.json");
|
|
8027
|
+
await mkdir4(resolve36(options.workspaceDir, ".rig"), { recursive: true });
|
|
7952
8028
|
await writeFile2(configPath, `${JSON.stringify({ [options.task.id]: entry }, null, 2)}
|
|
7953
8029
|
`, "utf-8");
|
|
7954
8030
|
}
|
|
@@ -8012,9 +8088,9 @@ async function ensureAgentRuntime(options) {
|
|
|
8012
8088
|
}
|
|
8013
8089
|
ensureProvisioningHostProjectRootEnv(options.projectRoot);
|
|
8014
8090
|
const monorepoRoot = resolveMonorepoRoot3(options.projectRoot);
|
|
8015
|
-
const workspaceDir =
|
|
8091
|
+
const workspaceDir = resolve36(monorepoRoot, ".worktrees", runtimeWorktreeName(options.taskId, options.id));
|
|
8016
8092
|
const createdAt = new Date().toISOString();
|
|
8017
|
-
if (!
|
|
8093
|
+
if (!existsSync33(resolve36(monorepoRoot, ".git"))) {
|
|
8018
8094
|
throw new Error(`Monorepo root is not a git checkout: ${monorepoRoot}`);
|
|
8019
8095
|
}
|
|
8020
8096
|
const taskResolution = await resolveRuntimeTaskRecord({
|
|
@@ -8049,7 +8125,7 @@ async function ensureAgentRuntime(options) {
|
|
|
8049
8125
|
logsDir: overlay.logsDir,
|
|
8050
8126
|
stateDir: overlay.stateDir,
|
|
8051
8127
|
sessionDir: overlay.sessionDir,
|
|
8052
|
-
claudeHomeDir:
|
|
8128
|
+
claudeHomeDir: resolve36(workspaceLayout.homeDir, ".claude"),
|
|
8053
8129
|
contextFile: overlay.contextPath,
|
|
8054
8130
|
binDir: workspaceLayout.binDir,
|
|
8055
8131
|
createdAt
|
|
@@ -8062,10 +8138,14 @@ async function ensureAgentRuntime(options) {
|
|
|
8062
8138
|
projectRoot: options.projectRoot,
|
|
8063
8139
|
workspaceDir
|
|
8064
8140
|
});
|
|
8065
|
-
|
|
8066
|
-
|
|
8141
|
+
mkdirSync19(runtime.binDir, { recursive: true });
|
|
8142
|
+
mkdirSync19(workspaceLayout.distDir, { recursive: true });
|
|
8067
8143
|
prepareRuntimeWorkspace(options.projectRoot, workspaceDir);
|
|
8068
|
-
|
|
8144
|
+
if (options.preserveTaskArtifacts) {
|
|
8145
|
+
console.log(`[rig-agent] Preserving runtime task artifacts for resume of ${options.taskId}.`);
|
|
8146
|
+
} else {
|
|
8147
|
+
await resetEphemeralTaskArtifacts(workspaceDir, options.taskId);
|
|
8148
|
+
}
|
|
8069
8149
|
const ctx = {
|
|
8070
8150
|
runtimeId: options.id,
|
|
8071
8151
|
taskId: options.taskId,
|
|
@@ -8078,7 +8158,7 @@ async function ensureAgentRuntime(options) {
|
|
|
8078
8158
|
runtimeId: options.id
|
|
8079
8159
|
}),
|
|
8080
8160
|
workspaceDir,
|
|
8081
|
-
artifactRoot:
|
|
8161
|
+
artifactRoot: resolve36(workspaceDir, "artifacts", options.taskId),
|
|
8082
8162
|
hostProjectRoot: options.projectRoot,
|
|
8083
8163
|
monorepoMainRoot: monorepoRoot,
|
|
8084
8164
|
monorepoBaseRef: baseRef,
|
|
@@ -8094,8 +8174,8 @@ async function ensureAgentRuntime(options) {
|
|
|
8094
8174
|
stateDir: overlay.stateDir,
|
|
8095
8175
|
logsDir: overlay.logsDir,
|
|
8096
8176
|
sessionDir: overlay.sessionDir,
|
|
8097
|
-
sessionFile:
|
|
8098
|
-
policyFile:
|
|
8177
|
+
sessionFile: resolve36(overlay.sessionDir, "session.json"),
|
|
8178
|
+
policyFile: resolve36(options.projectRoot, "rig/policy/policy.json"),
|
|
8099
8179
|
binDir: runtime.binDir,
|
|
8100
8180
|
createdAt,
|
|
8101
8181
|
memory
|
|
@@ -8106,9 +8186,9 @@ async function ensureAgentRuntime(options) {
|
|
|
8106
8186
|
task: taskResolution.task,
|
|
8107
8187
|
taskEntry
|
|
8108
8188
|
});
|
|
8109
|
-
const manifestPath =
|
|
8189
|
+
const manifestPath = resolve36(runtimeRoot, "manifest.json");
|
|
8110
8190
|
const bakedScopeHash = sha256Hex(JSON.stringify(taskEntry.scope || []));
|
|
8111
|
-
const runtimeAgentBinary =
|
|
8191
|
+
const runtimeAgentBinary = resolve36(runtime.binDir, "rig-agent");
|
|
8112
8192
|
await ensureRigGitBinaryPath();
|
|
8113
8193
|
const bakedInfoOutput = await captureTaskInfoOutput({
|
|
8114
8194
|
projectRoot: options.projectRoot,
|
|
@@ -8123,10 +8203,10 @@ async function ensureAgentRuntime(options) {
|
|
|
8123
8203
|
const bakedStatusOutput = await captureStdout(async () => {
|
|
8124
8204
|
taskStatus(options.projectRoot);
|
|
8125
8205
|
});
|
|
8126
|
-
|
|
8127
|
-
|
|
8128
|
-
|
|
8129
|
-
|
|
8206
|
+
rmSync13(runtime.binDir, { recursive: true, force: true });
|
|
8207
|
+
rmSync13(workspaceLayout.distDir, { recursive: true, force: true });
|
|
8208
|
+
mkdirSync19(runtime.binDir, { recursive: true });
|
|
8209
|
+
mkdirSync19(workspaceLayout.distDir, { recursive: true });
|
|
8130
8210
|
await buildRuntimeToolchain({
|
|
8131
8211
|
projectRoot: options.projectRoot,
|
|
8132
8212
|
workspaceDir,
|
|
@@ -8163,9 +8243,9 @@ async function ensureAgentRuntime(options) {
|
|
|
8163
8243
|
workspaceDir,
|
|
8164
8244
|
taskEntry
|
|
8165
8245
|
});
|
|
8166
|
-
const sandboxDir =
|
|
8246
|
+
const sandboxDir = resolve36(runtimeRoot, "sandbox");
|
|
8167
8247
|
await mkdir4(sandboxDir, { recursive: true });
|
|
8168
|
-
await writeFile2(
|
|
8248
|
+
await writeFile2(resolve36(runtimeRoot, "runtime.json"), JSON.stringify({
|
|
8169
8249
|
id: options.id,
|
|
8170
8250
|
taskId: options.taskId,
|
|
8171
8251
|
mode: "worktree",
|
|
@@ -8221,13 +8301,6 @@ async function runPriorityQueue(context, options) {
|
|
|
8221
8301
|
let result;
|
|
8222
8302
|
if (options.action === "pipeline") {
|
|
8223
8303
|
result = await runTaskStep(context, task.id, "validate", effectiveIsolation, workerRuntime);
|
|
8224
|
-
if (!context.dryRun) {
|
|
8225
|
-
const validatorResults = await context.plugins.runValidators(task.id);
|
|
8226
|
-
const failedValidators = validatorResults.filter((item) => !item.passed);
|
|
8227
|
-
if (failedValidators.length > 0) {
|
|
8228
|
-
throw new Error(`Plugin validators failed for ${task.id}: ${failedValidators.map((item) => item.id).join(", ")}`);
|
|
8229
|
-
}
|
|
8230
|
-
}
|
|
8231
8304
|
result = await runTaskStep(context, task.id, "verify", effectiveIsolation, workerRuntime);
|
|
8232
8305
|
} else {
|
|
8233
8306
|
result = await runTaskStep(context, task.id, options.action, effectiveIsolation, workerRuntime);
|
|
@@ -8326,12 +8399,12 @@ ${result.stderr.trim()}` : ""}`);
|
|
|
8326
8399
|
}
|
|
8327
8400
|
function resolveTaskCommand(projectRoot, action, taskId, hostProjectRoot = projectRoot) {
|
|
8328
8401
|
try {
|
|
8329
|
-
const compiledRig =
|
|
8330
|
-
if (
|
|
8402
|
+
const compiledRig = resolve37(resolveRigLayout(projectRoot).binDir, "rig");
|
|
8403
|
+
if (existsSync34(compiledRig)) {
|
|
8331
8404
|
return [compiledRig, "task", action, "--task", taskId];
|
|
8332
8405
|
}
|
|
8333
8406
|
} catch {}
|
|
8334
|
-
return ["bun", "run",
|
|
8407
|
+
return ["bun", "run", resolve37(hostProjectRoot, "packages/cli/bin/rig.ts"), "task", action, "--task", taskId];
|
|
8335
8408
|
}
|
|
8336
8409
|
function rankTasks(projectRoot, snapshot) {
|
|
8337
8410
|
const readyTaskIds = listReadyTaskIdsFromTracker(snapshot);
|