@h-rig/runtime 0.0.6-alpha.3 → 0.0.6-alpha.31
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 resolve34 } 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 = resolve34(options.runtime.rootDir, "sandbox");
|
|
269
|
+
mkdirSync17(sandboxDir, { recursive: true });
|
|
270
|
+
const profilePath = resolve34(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 = resolve34(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 resolve35 } 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(resolve35(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 = resolve35(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 = resolve35(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
|
}
|
|
@@ -1671,9 +1671,9 @@ function primeGuardHotPaths() {
|
|
|
1671
1671
|
}
|
|
1672
1672
|
primeGuardHotPaths();
|
|
1673
1673
|
// packages/runtime/src/control-plane/runtime/isolation/index.ts
|
|
1674
|
-
import { existsSync as
|
|
1674
|
+
import { existsSync as existsSync33, mkdirSync as mkdirSync19, readFileSync as readFileSync16, rmSync as rmSync13 } from "fs";
|
|
1675
1675
|
import { copyFile, mkdir as mkdir4, writeFile as writeFile2 } from "fs/promises";
|
|
1676
|
-
import { resolve as
|
|
1676
|
+
import { resolve as resolve37 } from "path";
|
|
1677
1677
|
|
|
1678
1678
|
// packages/runtime/src/control-plane/native/git-native.ts
|
|
1679
1679
|
import { chmodSync, copyFileSync as copyFileSync2, existsSync as existsSync5, mkdirSync as mkdirSync2, readFileSync as readFileSync3, renameSync as renameSync2, rmSync as rmSync2, writeFileSync } from "fs";
|
|
@@ -2558,8 +2558,8 @@ function isAgentRuntimeContextPath(path) {
|
|
|
2558
2558
|
var DEFAULT_RESULT_LIMIT = DEFAULT_RUNTIME_MEMORY_RETRIEVAL.topK;
|
|
2559
2559
|
var DAY_MS = 24 * 60 * 60 * 1000;
|
|
2560
2560
|
// packages/runtime/src/control-plane/native/task-ops.ts
|
|
2561
|
-
import { appendFileSync, existsSync as
|
|
2562
|
-
import { resolve as
|
|
2561
|
+
import { appendFileSync, existsSync as existsSync24, mkdirSync as mkdirSync10, readFileSync as readFileSync12, writeFileSync as writeFileSync9 } from "fs";
|
|
2562
|
+
import { resolve as resolve26 } from "path";
|
|
2563
2563
|
|
|
2564
2564
|
// packages/runtime/src/build-time-config.ts
|
|
2565
2565
|
function normalizeBuildConfig(value) {
|
|
@@ -3410,6 +3410,49 @@ function safeReadJson(path) {
|
|
|
3410
3410
|
}
|
|
3411
3411
|
}
|
|
3412
3412
|
|
|
3413
|
+
// packages/runtime/src/control-plane/skill-materializer.ts
|
|
3414
|
+
import { existsSync as existsSync13, mkdirSync as mkdirSync8, readFileSync as readFileSync6, readdirSync, rmSync as rmSync7, writeFileSync as writeFileSync5 } from "fs";
|
|
3415
|
+
import { resolve as resolve14 } from "path";
|
|
3416
|
+
import { loadSkill } from "@rig/skill-loader";
|
|
3417
|
+
var MARKER_FILENAME = ".rig-plugin";
|
|
3418
|
+
function skillDirName(id) {
|
|
3419
|
+
return id.replace(/[^a-zA-Z0-9._-]+/g, "-");
|
|
3420
|
+
}
|
|
3421
|
+
async function materializeSkills(projectRoot, entries) {
|
|
3422
|
+
const skillsRoot = resolve14(projectRoot, ".pi", "skills");
|
|
3423
|
+
if (existsSync13(skillsRoot)) {
|
|
3424
|
+
for (const name of readdirSync(skillsRoot)) {
|
|
3425
|
+
const dir = resolve14(skillsRoot, name);
|
|
3426
|
+
if (existsSync13(resolve14(dir, MARKER_FILENAME))) {
|
|
3427
|
+
rmSync7(dir, { recursive: true, force: true });
|
|
3428
|
+
}
|
|
3429
|
+
}
|
|
3430
|
+
}
|
|
3431
|
+
const written = [];
|
|
3432
|
+
for (const { pluginName, skill } of entries) {
|
|
3433
|
+
const sourcePath = resolve14(projectRoot, skill.path);
|
|
3434
|
+
if (!existsSync13(sourcePath)) {
|
|
3435
|
+
console.warn(`[plugin-host] skill "${skill.id}" from plugin "${pluginName}" not materialized: ${sourcePath} does not exist`);
|
|
3436
|
+
continue;
|
|
3437
|
+
}
|
|
3438
|
+
let body;
|
|
3439
|
+
try {
|
|
3440
|
+
await loadSkill(sourcePath);
|
|
3441
|
+
body = readFileSync6(sourcePath, "utf-8");
|
|
3442
|
+
} catch (err) {
|
|
3443
|
+
console.warn(`[plugin-host] skill "${skill.id}" from plugin "${pluginName}" not materialized: ${err instanceof Error ? err.message : err}`);
|
|
3444
|
+
continue;
|
|
3445
|
+
}
|
|
3446
|
+
const dir = resolve14(skillsRoot, skillDirName(skill.id));
|
|
3447
|
+
mkdirSync8(dir, { recursive: true });
|
|
3448
|
+
writeFileSync5(resolve14(dir, "SKILL.md"), body, "utf-8");
|
|
3449
|
+
writeFileSync5(resolve14(dir, MARKER_FILENAME), `${JSON.stringify({ plugin: pluginName, skillId: skill.id }, null, 2)}
|
|
3450
|
+
`, "utf-8");
|
|
3451
|
+
written.push({ id: skill.id, pluginName, directory: dir });
|
|
3452
|
+
}
|
|
3453
|
+
return written;
|
|
3454
|
+
}
|
|
3455
|
+
|
|
3413
3456
|
// packages/runtime/src/control-plane/plugin-host-context.ts
|
|
3414
3457
|
async function buildPluginHostContext(projectRoot) {
|
|
3415
3458
|
let config;
|
|
@@ -3446,6 +3489,17 @@ async function buildPluginHostContext(projectRoot) {
|
|
|
3446
3489
|
} catch (err) {
|
|
3447
3490
|
console.warn(`[plugin-host] hook materialization failed: ${err instanceof Error ? err.message : err}`);
|
|
3448
3491
|
}
|
|
3492
|
+
try {
|
|
3493
|
+
const skillEntries = config.plugins.flatMap((plugin) => (plugin.contributes?.skills ?? []).map((skill) => ({
|
|
3494
|
+
pluginName: plugin.name,
|
|
3495
|
+
skill
|
|
3496
|
+
})));
|
|
3497
|
+
if (skillEntries.length > 0) {
|
|
3498
|
+
await materializeSkills(projectRoot, skillEntries);
|
|
3499
|
+
}
|
|
3500
|
+
} catch (err) {
|
|
3501
|
+
console.warn(`[plugin-host] skill materialization failed: ${err instanceof Error ? err.message : err}`);
|
|
3502
|
+
}
|
|
3449
3503
|
return {
|
|
3450
3504
|
config,
|
|
3451
3505
|
pluginHost,
|
|
@@ -3459,12 +3513,12 @@ async function buildPluginHostContext(projectRoot) {
|
|
|
3459
3513
|
|
|
3460
3514
|
// packages/runtime/src/control-plane/tasks/source-aware-task-config-source.ts
|
|
3461
3515
|
import { spawnSync } from "child_process";
|
|
3462
|
-
import { existsSync as
|
|
3463
|
-
import { basename as basename4, join as join3, resolve as
|
|
3516
|
+
import { existsSync as existsSync15, readFileSync as readFileSync8, readdirSync as readdirSync2, statSync as statSync4, writeFileSync as writeFileSync6 } from "fs";
|
|
3517
|
+
import { basename as basename4, join as join3, resolve as resolve16 } from "path";
|
|
3464
3518
|
|
|
3465
3519
|
// packages/runtime/src/control-plane/tasks/legacy-task-config-source.ts
|
|
3466
|
-
import { existsSync as
|
|
3467
|
-
import { resolve as
|
|
3520
|
+
import { existsSync as existsSync14, readFileSync as readFileSync7 } from "fs";
|
|
3521
|
+
import { resolve as resolve15 } from "path";
|
|
3468
3522
|
|
|
3469
3523
|
// packages/runtime/src/control-plane/tasks/task-record-reader.ts
|
|
3470
3524
|
async function findTaskById(reader, id) {
|
|
@@ -3487,7 +3541,7 @@ class LegacyTaskConfigReadError extends Error {
|
|
|
3487
3541
|
}
|
|
3488
3542
|
}
|
|
3489
3543
|
function createLegacyTaskConfigRecordReader(projectRoot, options = {}) {
|
|
3490
|
-
const configPath = options.configPath ??
|
|
3544
|
+
const configPath = options.configPath ?? resolve15(projectRoot, ".rig", "task-config.json");
|
|
3491
3545
|
const reader = {
|
|
3492
3546
|
async listTasks() {
|
|
3493
3547
|
return readLegacyTaskRecords(projectRoot, configPath);
|
|
@@ -3498,8 +3552,8 @@ function createLegacyTaskConfigRecordReader(projectRoot, options = {}) {
|
|
|
3498
3552
|
};
|
|
3499
3553
|
return reader;
|
|
3500
3554
|
}
|
|
3501
|
-
function readLegacyTaskRecords(projectRoot, configPath =
|
|
3502
|
-
if (!
|
|
3555
|
+
function readLegacyTaskRecords(projectRoot, configPath = resolve15(projectRoot, ".rig", "task-config.json")) {
|
|
3556
|
+
if (!existsSync14(configPath)) {
|
|
3503
3557
|
return [];
|
|
3504
3558
|
}
|
|
3505
3559
|
const rawConfig = readLegacyTaskConfigJson(projectRoot, configPath);
|
|
@@ -3507,7 +3561,7 @@ function readLegacyTaskRecords(projectRoot, configPath = resolve14(projectRoot,
|
|
|
3507
3561
|
}
|
|
3508
3562
|
function readLegacyTaskConfigJson(projectRoot, configPath) {
|
|
3509
3563
|
try {
|
|
3510
|
-
const parsed = JSON.parse(
|
|
3564
|
+
const parsed = JSON.parse(readFileSync7(configPath, "utf8"));
|
|
3511
3565
|
if (isPlainRecord(parsed)) {
|
|
3512
3566
|
return parsed;
|
|
3513
3567
|
}
|
|
@@ -3591,7 +3645,7 @@ function isPlainRecord(candidate) {
|
|
|
3591
3645
|
var STATUS_LABELS = new Set(["ready", "blocked", "in-progress", "under-review", "failed", "cancelled"]);
|
|
3592
3646
|
var FILE_TASK_PATTERN = /\.(task\.)?json$/;
|
|
3593
3647
|
function createSourceAwareTaskConfigRecordReader(projectRoot, options = {}) {
|
|
3594
|
-
const configPath = options.configPath ??
|
|
3648
|
+
const configPath = options.configPath ?? resolve16(projectRoot, ".rig", "task-config.json");
|
|
3595
3649
|
const legacy = createLegacyTaskConfigRecordReader(projectRoot, { configPath });
|
|
3596
3650
|
const spawnFn = options.spawn ?? spawnSync;
|
|
3597
3651
|
const ghBinary = options.ghBinary ?? "gh";
|
|
@@ -3674,10 +3728,10 @@ function readMaterializedTaskMetadata(entry) {
|
|
|
3674
3728
|
return metadata;
|
|
3675
3729
|
}
|
|
3676
3730
|
function readConfiguredFilesTaskSourcePath(projectRoot) {
|
|
3677
|
-
const jsonPath =
|
|
3678
|
-
if (
|
|
3731
|
+
const jsonPath = resolve16(projectRoot, "rig.config.json");
|
|
3732
|
+
if (existsSync15(jsonPath)) {
|
|
3679
3733
|
try {
|
|
3680
|
-
const parsed = JSON.parse(
|
|
3734
|
+
const parsed = JSON.parse(readFileSync8(jsonPath, "utf8"));
|
|
3681
3735
|
if (isPlainRecord2(parsed) && isPlainRecord2(parsed.taskSource)) {
|
|
3682
3736
|
const source = parsed.taskSource;
|
|
3683
3737
|
return source.kind === "files" && typeof source.path === "string" ? source.path : null;
|
|
@@ -3686,12 +3740,12 @@ function readConfiguredFilesTaskSourcePath(projectRoot) {
|
|
|
3686
3740
|
return null;
|
|
3687
3741
|
}
|
|
3688
3742
|
}
|
|
3689
|
-
const tsPath =
|
|
3690
|
-
if (!
|
|
3743
|
+
const tsPath = resolve16(projectRoot, "rig.config.ts");
|
|
3744
|
+
if (!existsSync15(tsPath)) {
|
|
3691
3745
|
return null;
|
|
3692
3746
|
}
|
|
3693
3747
|
try {
|
|
3694
|
-
const source =
|
|
3748
|
+
const source = readFileSync8(tsPath, "utf8");
|
|
3695
3749
|
const taskSourceBlock = source.match(/taskSource\s*:\s*\{[\s\S]*?\}/m)?.[0] ?? "";
|
|
3696
3750
|
const kind = taskSourceBlock.match(/kind\s*:\s*["']([^"']+)["']/)?.[1];
|
|
3697
3751
|
if (kind !== "files") {
|
|
@@ -3711,10 +3765,10 @@ function readRawTaskEntry(configPath, taskId) {
|
|
|
3711
3765
|
return isPlainRecord2(entry) ? entry : null;
|
|
3712
3766
|
}
|
|
3713
3767
|
function readRawTaskConfig(configPath) {
|
|
3714
|
-
if (!
|
|
3768
|
+
if (!existsSync15(configPath)) {
|
|
3715
3769
|
return null;
|
|
3716
3770
|
}
|
|
3717
|
-
const parsed = JSON.parse(
|
|
3771
|
+
const parsed = JSON.parse(readFileSync8(configPath, "utf8"));
|
|
3718
3772
|
return isPlainRecord2(parsed) ? parsed : null;
|
|
3719
3773
|
}
|
|
3720
3774
|
function stripLegacyTaskConfigMetadata2(raw) {
|
|
@@ -3722,12 +3776,12 @@ function stripLegacyTaskConfigMetadata2(raw) {
|
|
|
3722
3776
|
return tasks;
|
|
3723
3777
|
}
|
|
3724
3778
|
function listFileBackedTasks(projectRoot, sourcePath) {
|
|
3725
|
-
const directory =
|
|
3726
|
-
if (!
|
|
3779
|
+
const directory = resolve16(projectRoot, sourcePath);
|
|
3780
|
+
if (!existsSync15(directory)) {
|
|
3727
3781
|
return [];
|
|
3728
3782
|
}
|
|
3729
3783
|
const tasks = [];
|
|
3730
|
-
for (const name of
|
|
3784
|
+
for (const name of readdirSync2(directory)) {
|
|
3731
3785
|
if (!FILE_TASK_PATTERN.test(name))
|
|
3732
3786
|
continue;
|
|
3733
3787
|
const inferredId = basename4(name).replace(FILE_TASK_PATTERN, "");
|
|
@@ -3738,11 +3792,11 @@ function listFileBackedTasks(projectRoot, sourcePath) {
|
|
|
3738
3792
|
return tasks;
|
|
3739
3793
|
}
|
|
3740
3794
|
function readFileBackedTask(projectRoot, sourcePath, taskId, rawEntry) {
|
|
3741
|
-
const file = findFileBackedTaskFile(
|
|
3795
|
+
const file = findFileBackedTaskFile(resolve16(projectRoot, sourcePath), taskId);
|
|
3742
3796
|
if (!file) {
|
|
3743
3797
|
return null;
|
|
3744
3798
|
}
|
|
3745
|
-
const raw = JSON.parse(
|
|
3799
|
+
const raw = JSON.parse(readFileSync8(file, "utf8"));
|
|
3746
3800
|
if (!isPlainRecord2(raw)) {
|
|
3747
3801
|
return null;
|
|
3748
3802
|
}
|
|
@@ -3755,17 +3809,17 @@ function readFileBackedTask(projectRoot, sourcePath, taskId, rawEntry) {
|
|
|
3755
3809
|
};
|
|
3756
3810
|
}
|
|
3757
3811
|
function findFileBackedTaskFile(directory, taskId) {
|
|
3758
|
-
if (!
|
|
3812
|
+
if (!existsSync15(directory)) {
|
|
3759
3813
|
return null;
|
|
3760
3814
|
}
|
|
3761
|
-
for (const name of
|
|
3815
|
+
for (const name of readdirSync2(directory)) {
|
|
3762
3816
|
if (!FILE_TASK_PATTERN.test(name))
|
|
3763
3817
|
continue;
|
|
3764
3818
|
const file = join3(directory, name);
|
|
3765
3819
|
try {
|
|
3766
3820
|
if (!statSync4(file).isFile())
|
|
3767
3821
|
continue;
|
|
3768
|
-
const raw = JSON.parse(
|
|
3822
|
+
const raw = JSON.parse(readFileSync8(file, "utf8"));
|
|
3769
3823
|
const inferredId = basename4(file).replace(FILE_TASK_PATTERN, "");
|
|
3770
3824
|
const id = isPlainRecord2(raw) && typeof raw.id === "string" ? raw.id : inferredId;
|
|
3771
3825
|
if (id === taskId) {
|
|
@@ -3848,8 +3902,8 @@ function githubStatusFor(issue) {
|
|
|
3848
3902
|
return "open";
|
|
3849
3903
|
}
|
|
3850
3904
|
function selectedGitHubEnv() {
|
|
3851
|
-
const token = process.env.RIG_GITHUB_SELECTED_TOKEN?.trim()
|
|
3852
|
-
return { GH_TOKEN: token, GITHUB_TOKEN: token };
|
|
3905
|
+
const token = process.env.RIG_GITHUB_SELECTED_TOKEN?.trim() || process.env.RIG_GITHUB_TOKEN?.trim() || "";
|
|
3906
|
+
return { GH_TOKEN: token, GITHUB_TOKEN: token, RIG_GITHUB_TOKEN: token };
|
|
3853
3907
|
}
|
|
3854
3908
|
function ghSpawnOptions() {
|
|
3855
3909
|
return { encoding: "utf-8", env: { ...process.env, ...selectedGitHubEnv() } };
|
|
@@ -3925,8 +3979,8 @@ async function readConfiguredTaskSourceTask(projectRoot, taskId) {
|
|
|
3925
3979
|
}
|
|
3926
3980
|
|
|
3927
3981
|
// packages/runtime/src/control-plane/native/task-state.ts
|
|
3928
|
-
import { existsSync as
|
|
3929
|
-
import { basename as basename6, resolve as
|
|
3982
|
+
import { existsSync as existsSync19, readFileSync as readFileSync10, readdirSync as readdirSync3, statSync as statSync5, writeFileSync as writeFileSync7 } from "fs";
|
|
3983
|
+
import { basename as basename6, resolve as resolve20 } from "path";
|
|
3930
3984
|
|
|
3931
3985
|
// packages/runtime/src/control-plane/state-sync/types.ts
|
|
3932
3986
|
var SUPPORTED_TASK_STATE_SCHEMA_VERSION = 1;
|
|
@@ -4034,39 +4088,39 @@ function readTaskStateMetadataEnvelope(raw) {
|
|
|
4034
4088
|
};
|
|
4035
4089
|
}
|
|
4036
4090
|
// packages/runtime/src/control-plane/state-sync/read.ts
|
|
4037
|
-
import { existsSync as
|
|
4038
|
-
import { resolve as
|
|
4091
|
+
import { existsSync as existsSync18, readFileSync as readFileSync9 } from "fs";
|
|
4092
|
+
import { resolve as resolve19 } from "path";
|
|
4039
4093
|
|
|
4040
4094
|
// packages/runtime/src/control-plane/state-sync/repo.ts
|
|
4041
|
-
import { existsSync as
|
|
4042
|
-
import { resolve as
|
|
4095
|
+
import { existsSync as existsSync17 } from "fs";
|
|
4096
|
+
import { resolve as resolve18 } from "path";
|
|
4043
4097
|
|
|
4044
4098
|
// packages/runtime/src/control-plane/repos/layout.ts
|
|
4045
4099
|
init_layout();
|
|
4046
|
-
import { existsSync as
|
|
4047
|
-
import { basename as basename5, dirname as dirname10, join as join4, resolve as
|
|
4100
|
+
import { existsSync as existsSync16 } from "fs";
|
|
4101
|
+
import { basename as basename5, dirname as dirname10, join as join4, resolve as resolve17 } from "path";
|
|
4048
4102
|
function resolveRepoStateDir(projectRoot) {
|
|
4049
|
-
const normalizedProjectRoot =
|
|
4103
|
+
const normalizedProjectRoot = resolve17(projectRoot);
|
|
4050
4104
|
const projectParent = dirname10(normalizedProjectRoot);
|
|
4051
4105
|
if (basename5(projectParent) === ".worktrees") {
|
|
4052
4106
|
const ownerRoot = dirname10(projectParent);
|
|
4053
|
-
const ownerHasRepoMarkers =
|
|
4107
|
+
const ownerHasRepoMarkers = existsSync16(resolve17(ownerRoot, ".git")) || existsSync16(resolve17(ownerRoot, ".rig", "state"));
|
|
4054
4108
|
if (ownerHasRepoMarkers) {
|
|
4055
|
-
return
|
|
4109
|
+
return resolve17(ownerRoot, ".rig", "state");
|
|
4056
4110
|
}
|
|
4057
4111
|
}
|
|
4058
|
-
return
|
|
4112
|
+
return resolve17(projectRoot, ".rig", "state");
|
|
4059
4113
|
}
|
|
4060
4114
|
function resolveManagedRepoLayout(projectRoot, repoId) {
|
|
4061
|
-
const normalizedProjectRoot =
|
|
4115
|
+
const normalizedProjectRoot = resolve17(projectRoot);
|
|
4062
4116
|
const entry = getManagedRepoEntry(repoId);
|
|
4063
4117
|
const stateDir = resolveRepoStateDir(normalizedProjectRoot);
|
|
4064
4118
|
const metadataRelativePath = join4("repos", entry.id);
|
|
4065
|
-
const metadataRoot =
|
|
4119
|
+
const metadataRoot = resolve17(stateDir, metadataRelativePath);
|
|
4066
4120
|
const runtimeWorkspace = process.env.RIG_TASK_WORKSPACE?.trim();
|
|
4067
|
-
const runsInsideTaskWorktree = runtimeWorkspace &&
|
|
4121
|
+
const runsInsideTaskWorktree = runtimeWorkspace && resolve17(runtimeWorkspace) === normalizedProjectRoot || basename5(dirname10(normalizedProjectRoot)) === ".worktrees";
|
|
4068
4122
|
const isPrimaryManagedRepo = listManagedRepoEntries()[0]?.id === repoId;
|
|
4069
|
-
const checkoutRoot = isPrimaryManagedRepo && runsInsideTaskWorktree ? resolveMonorepoRoot(normalizedProjectRoot) : entry.checkoutEnvVar && process.env[entry.checkoutEnvVar]?.trim() ?
|
|
4123
|
+
const checkoutRoot = isPrimaryManagedRepo && runsInsideTaskWorktree ? resolveMonorepoRoot(normalizedProjectRoot) : entry.checkoutEnvVar && process.env[entry.checkoutEnvVar]?.trim() ? resolve17(process.env[entry.checkoutEnvVar].trim()) : resolve17(normalizedProjectRoot, entry.alias);
|
|
4070
4124
|
return {
|
|
4071
4125
|
projectRoot: normalizedProjectRoot,
|
|
4072
4126
|
repoId: entry.id,
|
|
@@ -4074,12 +4128,12 @@ function resolveManagedRepoLayout(projectRoot, repoId) {
|
|
|
4074
4128
|
defaultBranch: entry.defaultBranch,
|
|
4075
4129
|
remoteUrl: entry.remoteEnvVar && process.env[entry.remoteEnvVar]?.trim() ? process.env[entry.remoteEnvVar].trim() : entry.defaultRemoteUrl,
|
|
4076
4130
|
checkoutRoot,
|
|
4077
|
-
worktreesRoot:
|
|
4131
|
+
worktreesRoot: resolve17(checkoutRoot, ".worktrees"),
|
|
4078
4132
|
stateDir,
|
|
4079
4133
|
metadataRoot,
|
|
4080
4134
|
metadataRelativePath,
|
|
4081
|
-
mirrorRoot:
|
|
4082
|
-
mirrorStatePath:
|
|
4135
|
+
mirrorRoot: resolve17(metadataRoot, "mirror.git"),
|
|
4136
|
+
mirrorStatePath: resolve17(metadataRoot, "mirror-state.json"),
|
|
4083
4137
|
mirrorStateRelativePath: join4(metadataRelativePath, "mirror-state.json")
|
|
4084
4138
|
};
|
|
4085
4139
|
}
|
|
@@ -4097,7 +4151,7 @@ function resolveTrackerRepoPath(projectRoot) {
|
|
|
4097
4151
|
const monorepoRoot = resolveMonorepoRoot2(projectRoot);
|
|
4098
4152
|
try {
|
|
4099
4153
|
const layout = resolveMonorepoRepoLayout(projectRoot);
|
|
4100
|
-
if (
|
|
4154
|
+
if (existsSync17(resolve18(layout.mirrorRoot, "HEAD"))) {
|
|
4101
4155
|
return layout.mirrorRoot;
|
|
4102
4156
|
}
|
|
4103
4157
|
} catch {}
|
|
@@ -4108,8 +4162,8 @@ function resolveTrackerRepoPath(projectRoot) {
|
|
|
4108
4162
|
var DEFAULT_READ_DEPS2 = {
|
|
4109
4163
|
fetchRef: nativeFetchRef,
|
|
4110
4164
|
readBlobAtRef: nativeReadBlobAtRef,
|
|
4111
|
-
exists:
|
|
4112
|
-
readFile: (path) =>
|
|
4165
|
+
exists: existsSync18,
|
|
4166
|
+
readFile: (path) => readFileSync9(path, "utf8")
|
|
4113
4167
|
};
|
|
4114
4168
|
function parseIssueStatus(rawStatus) {
|
|
4115
4169
|
const normalized = normalizeTaskLifecycleStatus(rawStatus);
|
|
@@ -4190,12 +4244,12 @@ function shouldPreferLocalTrackerState(options) {
|
|
|
4190
4244
|
if (runtimeContextPath) {
|
|
4191
4245
|
return true;
|
|
4192
4246
|
}
|
|
4193
|
-
return
|
|
4247
|
+
return existsSync18(resolve19(runtimeWorkspace, ".rig", "runtime-context.json"));
|
|
4194
4248
|
}
|
|
4195
4249
|
function readLocalTrackerState(projectRoot, deps) {
|
|
4196
4250
|
const monorepoRoot = resolveMonorepoRoot2(projectRoot);
|
|
4197
|
-
const issuesPath =
|
|
4198
|
-
const taskStatePath =
|
|
4251
|
+
const issuesPath = resolve19(monorepoRoot, ".beads", "issues.jsonl");
|
|
4252
|
+
const taskStatePath = resolve19(monorepoRoot, ".beads", "task-state.json");
|
|
4199
4253
|
return projectSyncedTrackerSnapshot({
|
|
4200
4254
|
source: "local",
|
|
4201
4255
|
issuesBaseOid: null,
|
|
@@ -4257,7 +4311,7 @@ function readValidationDescriptions(projectRoot) {
|
|
|
4257
4311
|
return readValidationDescriptionMap(raw);
|
|
4258
4312
|
}
|
|
4259
4313
|
function readSourceValidationDescriptions(projectRoot) {
|
|
4260
|
-
const rootRaw = readJsonFile(
|
|
4314
|
+
const rootRaw = readJsonFile(resolve20(projectRoot, "rig", "task-config.json"), {});
|
|
4261
4315
|
const sourcePath = findSourceTaskConfigPath(projectRoot);
|
|
4262
4316
|
const sourceRaw = sourcePath ? readJsonFile(sourcePath, {}) : {};
|
|
4263
4317
|
const rootDescriptions = readValidationDescriptionMap(rootRaw);
|
|
@@ -4333,15 +4387,15 @@ function readValidationDescriptionsFromMeta(meta) {
|
|
|
4333
4387
|
return meta.validation_descriptions;
|
|
4334
4388
|
}
|
|
4335
4389
|
function readLocalSourceTaskStateEnvelope(projectRoot) {
|
|
4336
|
-
const taskStatePath =
|
|
4390
|
+
const taskStatePath = resolve20(resolveMonorepoRoot2(projectRoot), ".beads", "task-state.json");
|
|
4337
4391
|
return readTaskStateMetadataEnvelope(readJsonFile(taskStatePath, {}));
|
|
4338
4392
|
}
|
|
4339
4393
|
function readLocalSourceTaskLifecycleStatus(projectRoot, taskId) {
|
|
4340
|
-
const issuesPath =
|
|
4341
|
-
if (!
|
|
4394
|
+
const issuesPath = resolve20(resolveMonorepoRoot2(projectRoot), ".beads", "issues.jsonl");
|
|
4395
|
+
if (!existsSync19(issuesPath)) {
|
|
4342
4396
|
return null;
|
|
4343
4397
|
}
|
|
4344
|
-
for (const line of
|
|
4398
|
+
for (const line of readFileSync10(issuesPath, "utf8").split(/\r?\n/)) {
|
|
4345
4399
|
const trimmed = line.trim();
|
|
4346
4400
|
if (!trimmed) {
|
|
4347
4401
|
continue;
|
|
@@ -4366,25 +4420,25 @@ function inferTaskIdFromRuntimePath(path) {
|
|
|
4366
4420
|
function artifactDirForId(projectRoot, id) {
|
|
4367
4421
|
const workspaceDir = process.env.RIG_TASK_WORKSPACE?.trim();
|
|
4368
4422
|
if (workspaceDir) {
|
|
4369
|
-
const worktreeArtifacts =
|
|
4370
|
-
if (
|
|
4423
|
+
const worktreeArtifacts = resolve20(workspaceDir, "artifacts", id);
|
|
4424
|
+
if (existsSync19(worktreeArtifacts) || existsSync19(resolve20(workspaceDir, "artifacts"))) {
|
|
4371
4425
|
return worktreeArtifacts;
|
|
4372
4426
|
}
|
|
4373
4427
|
}
|
|
4374
4428
|
try {
|
|
4375
4429
|
const paths = resolveHarnessPaths(projectRoot);
|
|
4376
|
-
return
|
|
4430
|
+
return resolve20(paths.artifactsDir, id);
|
|
4377
4431
|
} catch {
|
|
4378
|
-
return
|
|
4432
|
+
return resolve20(resolveMonorepoRoot2(projectRoot), "artifacts", id);
|
|
4379
4433
|
}
|
|
4380
4434
|
}
|
|
4381
4435
|
function resolveTaskConfigPath(projectRoot) {
|
|
4382
4436
|
const paths = resolveHarnessPaths(projectRoot);
|
|
4383
|
-
if (
|
|
4437
|
+
if (existsSync19(paths.taskConfigPath)) {
|
|
4384
4438
|
return paths.taskConfigPath;
|
|
4385
4439
|
}
|
|
4386
4440
|
for (const candidate of sourceTaskConfigCandidates(projectRoot)) {
|
|
4387
|
-
if (
|
|
4441
|
+
if (existsSync19(candidate)) {
|
|
4388
4442
|
return candidate;
|
|
4389
4443
|
}
|
|
4390
4444
|
}
|
|
@@ -4392,7 +4446,7 @@ function resolveTaskConfigPath(projectRoot) {
|
|
|
4392
4446
|
}
|
|
4393
4447
|
function findSourceTaskConfigPath(projectRoot) {
|
|
4394
4448
|
for (const candidate of sourceTaskConfigCandidates(projectRoot)) {
|
|
4395
|
-
if (
|
|
4449
|
+
if (existsSync19(candidate)) {
|
|
4396
4450
|
return candidate;
|
|
4397
4451
|
}
|
|
4398
4452
|
}
|
|
@@ -4405,7 +4459,7 @@ function readAndSyncSourceTaskConfig(projectRoot) {
|
|
|
4405
4459
|
const synced = synchronizeTaskConfigWithTracker(projectRoot, raw);
|
|
4406
4460
|
if (sourcePath && synced.updated) {
|
|
4407
4461
|
try {
|
|
4408
|
-
|
|
4462
|
+
writeFileSync7(sourcePath, `${JSON.stringify(synced.config, null, 2)}
|
|
4409
4463
|
`, "utf-8");
|
|
4410
4464
|
} catch {}
|
|
4411
4465
|
}
|
|
@@ -4457,12 +4511,12 @@ function shouldRefreshAutoSyncedTaskConfigEntry(entry) {
|
|
|
4457
4511
|
return !candidate.role;
|
|
4458
4512
|
}
|
|
4459
4513
|
function readSourceIssueRecords(projectRoot) {
|
|
4460
|
-
const issuesPath =
|
|
4461
|
-
if (!
|
|
4514
|
+
const issuesPath = resolve20(resolveMonorepoRoot2(projectRoot), ".beads", "issues.jsonl");
|
|
4515
|
+
if (!existsSync19(issuesPath)) {
|
|
4462
4516
|
return [];
|
|
4463
4517
|
}
|
|
4464
4518
|
const records = [];
|
|
4465
|
-
for (const line of
|
|
4519
|
+
for (const line of readFileSync10(issuesPath, "utf-8").split(/\r?\n/)) {
|
|
4466
4520
|
const trimmed = line.trim();
|
|
4467
4521
|
if (!trimmed) {
|
|
4468
4522
|
continue;
|
|
@@ -4518,19 +4572,19 @@ function readConfiguredFileTaskConfig(projectRoot) {
|
|
|
4518
4572
|
if (!sourcePath) {
|
|
4519
4573
|
return {};
|
|
4520
4574
|
}
|
|
4521
|
-
const directory =
|
|
4522
|
-
if (!
|
|
4575
|
+
const directory = resolve20(projectRoot, sourcePath);
|
|
4576
|
+
if (!existsSync19(directory)) {
|
|
4523
4577
|
return {};
|
|
4524
4578
|
}
|
|
4525
4579
|
const config = {};
|
|
4526
|
-
for (const name of
|
|
4580
|
+
for (const name of readdirSync3(directory)) {
|
|
4527
4581
|
if (!FILE_TASK_PATTERN2.test(name))
|
|
4528
4582
|
continue;
|
|
4529
|
-
const file =
|
|
4583
|
+
const file = resolve20(directory, name);
|
|
4530
4584
|
try {
|
|
4531
4585
|
if (!statSync5(file).isFile())
|
|
4532
4586
|
continue;
|
|
4533
|
-
const raw = JSON.parse(
|
|
4587
|
+
const raw = JSON.parse(readFileSync10(file, "utf8"));
|
|
4534
4588
|
if (!raw || typeof raw !== "object" || Array.isArray(raw))
|
|
4535
4589
|
continue;
|
|
4536
4590
|
const record = raw;
|
|
@@ -4572,10 +4626,10 @@ function firstStringList2(...candidates) {
|
|
|
4572
4626
|
return [];
|
|
4573
4627
|
}
|
|
4574
4628
|
function readConfiguredFilesTaskSourcePath2(projectRoot) {
|
|
4575
|
-
const jsonPath =
|
|
4576
|
-
if (
|
|
4629
|
+
const jsonPath = resolve20(projectRoot, "rig.config.json");
|
|
4630
|
+
if (existsSync19(jsonPath)) {
|
|
4577
4631
|
try {
|
|
4578
|
-
const parsed = JSON.parse(
|
|
4632
|
+
const parsed = JSON.parse(readFileSync10(jsonPath, "utf8"));
|
|
4579
4633
|
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
4580
4634
|
const taskSource = parsed.taskSource;
|
|
4581
4635
|
if (taskSource && typeof taskSource === "object" && !Array.isArray(taskSource)) {
|
|
@@ -4587,12 +4641,12 @@ function readConfiguredFilesTaskSourcePath2(projectRoot) {
|
|
|
4587
4641
|
return null;
|
|
4588
4642
|
}
|
|
4589
4643
|
}
|
|
4590
|
-
const tsPath =
|
|
4591
|
-
if (!
|
|
4644
|
+
const tsPath = resolve20(projectRoot, "rig.config.ts");
|
|
4645
|
+
if (!existsSync19(tsPath)) {
|
|
4592
4646
|
return null;
|
|
4593
4647
|
}
|
|
4594
4648
|
try {
|
|
4595
|
-
const source =
|
|
4649
|
+
const source = readFileSync10(tsPath, "utf8");
|
|
4596
4650
|
const taskSourceBlock = source.match(/taskSource\s*:\s*\{[\s\S]*?\}/m)?.[0] ?? "";
|
|
4597
4651
|
const kind = taskSourceBlock.match(/kind\s*:\s*["']([^"']+)["']/)?.[1];
|
|
4598
4652
|
if (kind !== "files") {
|
|
@@ -4606,9 +4660,9 @@ function readConfiguredFilesTaskSourcePath2(projectRoot) {
|
|
|
4606
4660
|
function sourceTaskConfigCandidates(projectRoot) {
|
|
4607
4661
|
const runtimeContext = loadRuntimeContextFromEnv();
|
|
4608
4662
|
return [
|
|
4609
|
-
runtimeContext?.monorepoMainRoot ?
|
|
4610
|
-
process.env.MONOREPO_MAIN_ROOT?.trim() ?
|
|
4611
|
-
|
|
4663
|
+
runtimeContext?.monorepoMainRoot ? resolve20(runtimeContext.monorepoMainRoot, ".rig", "task-config.json") : "",
|
|
4664
|
+
process.env.MONOREPO_MAIN_ROOT?.trim() ? resolve20(process.env.MONOREPO_MAIN_ROOT.trim(), ".rig", "task-config.json") : "",
|
|
4665
|
+
resolve20(resolveMonorepoRoot2(projectRoot), ".rig", "task-config.json")
|
|
4612
4666
|
].filter(Boolean);
|
|
4613
4667
|
}
|
|
4614
4668
|
|
|
@@ -4617,8 +4671,8 @@ init_layout();
|
|
|
4617
4671
|
|
|
4618
4672
|
// packages/runtime/src/binary-run.ts
|
|
4619
4673
|
init_layout();
|
|
4620
|
-
import { chmodSync as chmodSync4, cpSync, existsSync as
|
|
4621
|
-
import { basename as basename7, dirname as dirname11, resolve as
|
|
4674
|
+
import { chmodSync as chmodSync4, cpSync, existsSync as existsSync20, mkdirSync as mkdirSync9, renameSync as renameSync3, rmSync as rmSync8, writeFileSync as writeFileSync8 } from "fs";
|
|
4675
|
+
import { basename as basename7, dirname as dirname11, resolve as resolve21 } from "path";
|
|
4622
4676
|
import { fileURLToPath } from "url";
|
|
4623
4677
|
import { drainMicrotasks, gcAndSweep } from "bun:jsc";
|
|
4624
4678
|
var runtimeBinaryBuildQueue = Promise.resolve();
|
|
@@ -4644,9 +4698,9 @@ async function buildRuntimeBinary(options) {
|
|
|
4644
4698
|
});
|
|
4645
4699
|
}
|
|
4646
4700
|
async function buildRuntimeBinaryInProcess(options, manifest) {
|
|
4647
|
-
const tempBuildDir =
|
|
4648
|
-
const tempOutputPath =
|
|
4649
|
-
|
|
4701
|
+
const tempBuildDir = resolve21(dirname11(options.outputPath), `.bun-build-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`);
|
|
4702
|
+
const tempOutputPath = resolve21(tempBuildDir, basename7(options.outputPath));
|
|
4703
|
+
mkdirSync9(tempBuildDir, { recursive: true });
|
|
4650
4704
|
await withTemporaryEnv({
|
|
4651
4705
|
...options.env,
|
|
4652
4706
|
...options.define ? { RIG_BUILD_CONFIG_JSON: JSON.stringify(options.define) } : {}
|
|
@@ -4671,7 +4725,7 @@ async function buildRuntimeBinaryInProcess(options, manifest) {
|
|
|
4671
4725
|
`);
|
|
4672
4726
|
throw new Error(`Failed to build ${options.entrypoint}: ${details || "Bun.build() returned errors"}`);
|
|
4673
4727
|
}
|
|
4674
|
-
if (!
|
|
4728
|
+
if (!existsSync20(tempOutputPath)) {
|
|
4675
4729
|
const emitted = buildResult.outputs.map((output) => output.path).join(", ") || "(none)";
|
|
4676
4730
|
throw new Error(`Failed to build ${options.entrypoint}: Bun.build() did not emit ${tempOutputPath}. Emitted: ${emitted}`);
|
|
4677
4731
|
}
|
|
@@ -4686,7 +4740,7 @@ async function buildRuntimeBinaryInProcess(options, manifest) {
|
|
|
4686
4740
|
});
|
|
4687
4741
|
}
|
|
4688
4742
|
})).finally(() => {
|
|
4689
|
-
|
|
4743
|
+
rmSync8(tempBuildDir, { recursive: true, force: true });
|
|
4690
4744
|
});
|
|
4691
4745
|
}
|
|
4692
4746
|
function runBestEffortBuildGc() {
|
|
@@ -4703,8 +4757,8 @@ function runtimeBinaryCacheManifestPath(outputPath) {
|
|
|
4703
4757
|
function resolveRuntimeBinaryBuildOptions(options) {
|
|
4704
4758
|
return {
|
|
4705
4759
|
...options,
|
|
4706
|
-
entrypoint:
|
|
4707
|
-
outputPath:
|
|
4760
|
+
entrypoint: resolve21(options.cwd, options.sourcePath),
|
|
4761
|
+
outputPath: resolve21(options.outputPath)
|
|
4708
4762
|
};
|
|
4709
4763
|
}
|
|
4710
4764
|
function shouldUseRuntimeBinaryBuildWorker() {
|
|
@@ -4718,7 +4772,7 @@ function shouldUseRuntimeBinaryBuildWorker() {
|
|
|
4718
4772
|
}
|
|
4719
4773
|
async function buildRuntimeBinaryViaWorker(options) {
|
|
4720
4774
|
const workerSourcePath = resolveRuntimeBinaryBuildWorkerSourcePath(options);
|
|
4721
|
-
if (!workerSourcePath || !
|
|
4775
|
+
if (!workerSourcePath || !existsSync20(workerSourcePath)) {
|
|
4722
4776
|
await buildRuntimeBinaryInProcess(options, {
|
|
4723
4777
|
manifestPath: runtimeBinaryCacheManifestPath(options.outputPath),
|
|
4724
4778
|
buildKey: createRuntimeBinaryBuildKey({
|
|
@@ -4749,13 +4803,13 @@ async function buildRuntimeBinaryViaWorker(options) {
|
|
|
4749
4803
|
new Response(build.stdout).text(),
|
|
4750
4804
|
new Response(build.stderr).text()
|
|
4751
4805
|
]);
|
|
4752
|
-
|
|
4806
|
+
rmSync8(payloadPath, { force: true });
|
|
4753
4807
|
if (exitCode !== 0) {
|
|
4754
4808
|
throw new Error(`Failed to build ${options.entrypoint}: ${(stderr || stdout || `worker exited ${exitCode}`).trim()}`);
|
|
4755
4809
|
}
|
|
4756
4810
|
}
|
|
4757
4811
|
function createRuntimeBinaryBuildWorkerPayloadPath(outputPath) {
|
|
4758
|
-
return
|
|
4812
|
+
return resolve21(dirname11(outputPath), `.bun-build-worker-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}.json`);
|
|
4759
4813
|
}
|
|
4760
4814
|
function resolveRuntimeBinaryBuildWorkerSourcePath(options) {
|
|
4761
4815
|
const envRoots = [
|
|
@@ -4764,13 +4818,13 @@ function resolveRuntimeBinaryBuildWorkerSourcePath(options) {
|
|
|
4764
4818
|
process.env.PROJECT_RIG_ROOT?.trim()
|
|
4765
4819
|
].filter(Boolean);
|
|
4766
4820
|
for (const root of envRoots) {
|
|
4767
|
-
const candidate =
|
|
4768
|
-
if (
|
|
4821
|
+
const candidate = resolve21(root, "packages/runtime/src/binary-build-worker.ts");
|
|
4822
|
+
if (existsSync20(candidate)) {
|
|
4769
4823
|
return candidate;
|
|
4770
4824
|
}
|
|
4771
4825
|
}
|
|
4772
|
-
const localCandidate =
|
|
4773
|
-
return
|
|
4826
|
+
const localCandidate = resolve21(import.meta.dir, "binary-build-worker.ts");
|
|
4827
|
+
return existsSync20(localCandidate) ? localCandidate : null;
|
|
4774
4828
|
}
|
|
4775
4829
|
function resolveRuntimeBinaryBuildWorkerInvocation() {
|
|
4776
4830
|
const bunPath = Bun.which("bun");
|
|
@@ -4806,7 +4860,7 @@ function createRuntimeBinaryBuildKey(input) {
|
|
|
4806
4860
|
});
|
|
4807
4861
|
}
|
|
4808
4862
|
async function isRuntimeBinaryBuildFresh(input) {
|
|
4809
|
-
if (!
|
|
4863
|
+
if (!existsSync20(input.outputPath) || !existsSync20(input.manifestPath)) {
|
|
4810
4864
|
return false;
|
|
4811
4865
|
}
|
|
4812
4866
|
let manifest = null;
|
|
@@ -4819,7 +4873,7 @@ async function isRuntimeBinaryBuildFresh(input) {
|
|
|
4819
4873
|
return false;
|
|
4820
4874
|
}
|
|
4821
4875
|
for (const [filePath, expectedDigest] of Object.entries(manifest.inputs || {})) {
|
|
4822
|
-
if (!
|
|
4876
|
+
if (!existsSync20(filePath)) {
|
|
4823
4877
|
return false;
|
|
4824
4878
|
}
|
|
4825
4879
|
if (await sha256File4(filePath) !== expectedDigest) {
|
|
@@ -4832,7 +4886,7 @@ async function writeRuntimeBinaryCacheManifest(input) {
|
|
|
4832
4886
|
const inputs = {};
|
|
4833
4887
|
for (const inputPath of Object.keys(input.metafile?.inputs || {}).sort()) {
|
|
4834
4888
|
const normalized = normalizeBuildInputPath(input.cwd, inputPath);
|
|
4835
|
-
if (!normalized || !
|
|
4889
|
+
if (!normalized || !existsSync20(normalized)) {
|
|
4836
4890
|
continue;
|
|
4837
4891
|
}
|
|
4838
4892
|
inputs[normalized] = await sha256File4(normalized);
|
|
@@ -4855,7 +4909,7 @@ function normalizeBuildInputPath(cwd, inputPath) {
|
|
|
4855
4909
|
if (inputPath.startsWith("<")) {
|
|
4856
4910
|
return null;
|
|
4857
4911
|
}
|
|
4858
|
-
return
|
|
4912
|
+
return resolve21(cwd, inputPath);
|
|
4859
4913
|
}
|
|
4860
4914
|
async function sha256File4(path) {
|
|
4861
4915
|
const hasher = new Bun.CryptoHasher("sha256");
|
|
@@ -4871,8 +4925,8 @@ function sortRecord(value) {
|
|
|
4871
4925
|
async function runSerializedRuntimeBinaryBuild(action) {
|
|
4872
4926
|
const previous = runtimeBinaryBuildQueue;
|
|
4873
4927
|
let release;
|
|
4874
|
-
runtimeBinaryBuildQueue = new Promise((
|
|
4875
|
-
release =
|
|
4928
|
+
runtimeBinaryBuildQueue = new Promise((resolve22) => {
|
|
4929
|
+
release = resolve22;
|
|
4876
4930
|
});
|
|
4877
4931
|
await previous;
|
|
4878
4932
|
try {
|
|
@@ -4917,11 +4971,11 @@ async function withTemporaryCwd(cwd, action) {
|
|
|
4917
4971
|
}
|
|
4918
4972
|
|
|
4919
4973
|
// packages/runtime/src/control-plane/runtime/provisioning-env.ts
|
|
4920
|
-
import { delimiter, resolve as
|
|
4974
|
+
import { delimiter, resolve as resolve24 } from "path";
|
|
4921
4975
|
|
|
4922
4976
|
// packages/runtime/src/control-plane/runtime/runtime-paths.ts
|
|
4923
|
-
import { existsSync as
|
|
4924
|
-
import { resolve as
|
|
4977
|
+
import { existsSync as existsSync22, readdirSync as readdirSync5, realpathSync as realpathSync2 } from "fs";
|
|
4978
|
+
import { resolve as resolve23 } from "path";
|
|
4925
4979
|
|
|
4926
4980
|
// packages/runtime/src/control-plane/runtime/sandbox-utils.ts
|
|
4927
4981
|
init_utils();
|
|
@@ -4938,7 +4992,7 @@ function resolveBunBinaryPath() {
|
|
|
4938
4992
|
}
|
|
4939
4993
|
const home = process.env.HOME?.trim();
|
|
4940
4994
|
const fallbackCandidates = [
|
|
4941
|
-
home ?
|
|
4995
|
+
home ? resolve23(home, ".bun/bin/bun") : "",
|
|
4942
4996
|
"/opt/homebrew/bin/bun",
|
|
4943
4997
|
"/usr/local/bin/bun",
|
|
4944
4998
|
"/usr/bin/bun"
|
|
@@ -4966,8 +5020,8 @@ function resolveClaudeBinaryPath() {
|
|
|
4966
5020
|
}
|
|
4967
5021
|
const home = process.env.HOME?.trim();
|
|
4968
5022
|
const fallbackCandidates = [
|
|
4969
|
-
home ?
|
|
4970
|
-
home ?
|
|
5023
|
+
home ? resolve23(home, ".local/bin/claude") : "",
|
|
5024
|
+
home ? resolve23(home, ".local/share/claude/local/claude") : "",
|
|
4971
5025
|
"/opt/homebrew/bin/claude",
|
|
4972
5026
|
"/usr/local/bin/claude",
|
|
4973
5027
|
"/usr/bin/claude"
|
|
@@ -4981,35 +5035,35 @@ function resolveClaudeBinaryPath() {
|
|
|
4981
5035
|
throw new Error("claude not found in PATH");
|
|
4982
5036
|
}
|
|
4983
5037
|
function resolveBunInstallDir(bunBinaryPath = resolveBunBinaryPath()) {
|
|
4984
|
-
return
|
|
5038
|
+
return resolve23(bunBinaryPath, "../..");
|
|
4985
5039
|
}
|
|
4986
5040
|
function resolveClaudeInstallDir() {
|
|
4987
5041
|
const realPath = resolveClaudeBinaryPath();
|
|
4988
|
-
return
|
|
5042
|
+
return resolve23(realPath, "..");
|
|
4989
5043
|
}
|
|
4990
5044
|
function resolveNodeInstallDir() {
|
|
4991
5045
|
const preferredNode = resolvePreferredNodeBinary();
|
|
4992
5046
|
if (!preferredNode)
|
|
4993
5047
|
return null;
|
|
4994
5048
|
const explicitNode = process.env.RIG_NODE_BIN?.trim();
|
|
4995
|
-
if (explicitNode &&
|
|
4996
|
-
return preferredNode.endsWith("/bin/node") ?
|
|
5049
|
+
if (explicitNode && resolve23(explicitNode) === resolve23(preferredNode)) {
|
|
5050
|
+
return preferredNode.endsWith("/bin/node") ? resolve23(preferredNode, "../..") : resolve23(preferredNode, "..");
|
|
4997
5051
|
}
|
|
4998
5052
|
try {
|
|
4999
5053
|
const realPath = realpathSync2(preferredNode);
|
|
5000
5054
|
if (realPath.endsWith("/bin/node")) {
|
|
5001
|
-
return
|
|
5055
|
+
return resolve23(realPath, "../..");
|
|
5002
5056
|
}
|
|
5003
|
-
return
|
|
5057
|
+
return resolve23(realPath, "..");
|
|
5004
5058
|
} catch {
|
|
5005
|
-
return
|
|
5059
|
+
return resolve23(preferredNode, "..");
|
|
5006
5060
|
}
|
|
5007
5061
|
}
|
|
5008
5062
|
function resolveRuntimeDependencyRoots(runtimeDirs) {
|
|
5009
5063
|
const roots = [];
|
|
5010
5064
|
if (process.platform === "darwin") {
|
|
5011
5065
|
for (const macPath of ["/opt/homebrew", "/opt/homebrew/opt"]) {
|
|
5012
|
-
if (
|
|
5066
|
+
if (existsSync22(macPath)) {
|
|
5013
5067
|
roots.push(macPath);
|
|
5014
5068
|
}
|
|
5015
5069
|
}
|
|
@@ -5027,23 +5081,23 @@ function resolvePreferredNodeBinary() {
|
|
|
5027
5081
|
const candidates = [];
|
|
5028
5082
|
const envNode = process.env.RIG_NODE_BIN?.trim();
|
|
5029
5083
|
if (envNode) {
|
|
5030
|
-
const explicit =
|
|
5031
|
-
if (
|
|
5084
|
+
const explicit = resolve23(envNode);
|
|
5085
|
+
if (existsSync22(explicit)) {
|
|
5032
5086
|
return explicit;
|
|
5033
5087
|
}
|
|
5034
5088
|
}
|
|
5035
5089
|
const nvmBin = process.env.NVM_BIN?.trim();
|
|
5036
5090
|
if (nvmBin) {
|
|
5037
|
-
candidates.push(
|
|
5091
|
+
candidates.push(resolve23(nvmBin, "node"));
|
|
5038
5092
|
}
|
|
5039
5093
|
const home = process.env.HOME?.trim();
|
|
5040
5094
|
if (home) {
|
|
5041
|
-
const nvmVersionsDir =
|
|
5042
|
-
if (
|
|
5095
|
+
const nvmVersionsDir = resolve23(home, ".nvm/versions/node");
|
|
5096
|
+
if (existsSync22(nvmVersionsDir)) {
|
|
5043
5097
|
try {
|
|
5044
|
-
const versionDirs =
|
|
5098
|
+
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/, "")));
|
|
5045
5099
|
for (const versionDir of versionDirs) {
|
|
5046
|
-
candidates.push(
|
|
5100
|
+
candidates.push(resolve23(nvmVersionsDir, versionDir, "bin/node"));
|
|
5047
5101
|
}
|
|
5048
5102
|
} catch {}
|
|
5049
5103
|
}
|
|
@@ -5052,8 +5106,8 @@ function resolvePreferredNodeBinary() {
|
|
|
5052
5106
|
if (whichNode) {
|
|
5053
5107
|
candidates.push(whichNode);
|
|
5054
5108
|
}
|
|
5055
|
-
const deduped = uniq(candidates.map((candidate) =>
|
|
5056
|
-
const existing = deduped.filter((candidate) =>
|
|
5109
|
+
const deduped = uniq(candidates.map((candidate) => resolve23(candidate)));
|
|
5110
|
+
const existing = deduped.filter((candidate) => existsSync22(candidate));
|
|
5057
5111
|
if (existing.length === 0) {
|
|
5058
5112
|
return null;
|
|
5059
5113
|
}
|
|
@@ -5067,7 +5121,7 @@ function resolvePreferredNodeBinary() {
|
|
|
5067
5121
|
return existing[0] ?? null;
|
|
5068
5122
|
}
|
|
5069
5123
|
function inferNodeMajor(nodeBinaryPath) {
|
|
5070
|
-
const normalized =
|
|
5124
|
+
const normalized = resolve23(nodeBinaryPath).replace(/\\/g, "/");
|
|
5071
5125
|
const match = normalized.match(/(?:^|\/)(?:node-)?v?(\d+)\.\d+\.\d+(?:\/|$)/);
|
|
5072
5126
|
if (!match) {
|
|
5073
5127
|
return null;
|
|
@@ -5079,8 +5133,8 @@ function normalizeExecutablePath(candidate) {
|
|
|
5079
5133
|
if (!candidate) {
|
|
5080
5134
|
return "";
|
|
5081
5135
|
}
|
|
5082
|
-
const normalized =
|
|
5083
|
-
if (!
|
|
5136
|
+
const normalized = resolve23(candidate);
|
|
5137
|
+
if (!existsSync22(normalized)) {
|
|
5084
5138
|
return "";
|
|
5085
5139
|
}
|
|
5086
5140
|
try {
|
|
@@ -5090,7 +5144,7 @@ function normalizeExecutablePath(candidate) {
|
|
|
5090
5144
|
}
|
|
5091
5145
|
}
|
|
5092
5146
|
function looksLikeRuntimeGateway(candidate) {
|
|
5093
|
-
const normalized =
|
|
5147
|
+
const normalized = resolve23(candidate).replace(/\\/g, "/");
|
|
5094
5148
|
return normalized.includes("/.rig/bin/") || normalized.endsWith("/rig-shell") || normalized.endsWith("/rig-agent");
|
|
5095
5149
|
}
|
|
5096
5150
|
|
|
@@ -5111,7 +5165,7 @@ function runtimeProvisioningEnv(baseEnv = process.env) {
|
|
|
5111
5165
|
try {
|
|
5112
5166
|
return resolveClaudeInstallDir();
|
|
5113
5167
|
} catch {
|
|
5114
|
-
return
|
|
5168
|
+
return resolve24(claudeBinary, "..");
|
|
5115
5169
|
}
|
|
5116
5170
|
})() : "";
|
|
5117
5171
|
const nodeDir = resolveNodeInstallDir();
|
|
@@ -5121,8 +5175,8 @@ function runtimeProvisioningEnv(baseEnv = process.env) {
|
|
|
5121
5175
|
`${bunDir}/bin`,
|
|
5122
5176
|
claudeDir,
|
|
5123
5177
|
nodeDir ? `${nodeDir}/bin` : "",
|
|
5124
|
-
realHome ?
|
|
5125
|
-
realHome ?
|
|
5178
|
+
realHome ? resolve24(realHome, ".local/bin") : "",
|
|
5179
|
+
realHome ? resolve24(realHome, ".cargo/bin") : "",
|
|
5126
5180
|
...inheritedPath,
|
|
5127
5181
|
"/usr/local/bin",
|
|
5128
5182
|
"/usr/local/sbin",
|
|
@@ -5151,8 +5205,8 @@ function runtimeProvisioningEnv(baseEnv = process.env) {
|
|
|
5151
5205
|
}
|
|
5152
5206
|
|
|
5153
5207
|
// packages/runtime/src/control-plane/runtime/baked-secrets.ts
|
|
5154
|
-
import { existsSync as
|
|
5155
|
-
import { resolve as
|
|
5208
|
+
import { existsSync as existsSync23, readFileSync as readFileSync11 } from "fs";
|
|
5209
|
+
import { resolve as resolve25 } from "path";
|
|
5156
5210
|
var BAKED_RUNTIME_SECRETS = {
|
|
5157
5211
|
ANTHROPIC_API_KEY: typeof RIG_BAKED_ANTHROPIC_API_KEY !== "undefined" ? RIG_BAKED_ANTHROPIC_API_KEY : "",
|
|
5158
5212
|
OPENAI_API_KEY: typeof RIG_BAKED_OPENAI_API_KEY !== "undefined" ? RIG_BAKED_OPENAI_API_KEY : "",
|
|
@@ -5195,12 +5249,12 @@ function resolveRuntimeSecrets(env, baked = BAKED_RUNTIME_SECRETS) {
|
|
|
5195
5249
|
return resolved;
|
|
5196
5250
|
}
|
|
5197
5251
|
function loadDotEnvSecrets(projectRoot, env = process.env) {
|
|
5198
|
-
const dotenvPath =
|
|
5199
|
-
if (!
|
|
5252
|
+
const dotenvPath = resolve25(projectRoot, ".env");
|
|
5253
|
+
if (!existsSync23(dotenvPath)) {
|
|
5200
5254
|
return {};
|
|
5201
5255
|
}
|
|
5202
5256
|
const parsed = {};
|
|
5203
|
-
const lines =
|
|
5257
|
+
const lines = readFileSync11(dotenvPath, "utf-8").split(/\r?\n/);
|
|
5204
5258
|
for (const rawLine of lines) {
|
|
5205
5259
|
const line = rawLine.trim();
|
|
5206
5260
|
if (!line || line.startsWith("#")) {
|
|
@@ -5557,16 +5611,16 @@ async function taskDeps(projectRoot, taskId) {
|
|
|
5557
5611
|
for (const dep of deps) {
|
|
5558
5612
|
const artifactDir = artifactDirForId(projectRoot, dep);
|
|
5559
5613
|
console.log(`=== ${dep} ===`);
|
|
5560
|
-
if (!
|
|
5614
|
+
if (!existsSync24(artifactDir)) {
|
|
5561
5615
|
console.log(` (no artifacts yet)
|
|
5562
5616
|
`);
|
|
5563
5617
|
continue;
|
|
5564
5618
|
}
|
|
5565
|
-
printArtifactSection(
|
|
5566
|
-
printArtifactSection(
|
|
5567
|
-
const changedFiles =
|
|
5568
|
-
if (
|
|
5569
|
-
const lines =
|
|
5619
|
+
printArtifactSection(resolve26(artifactDir, "decision-log.md"), "--- Decisions ---");
|
|
5620
|
+
printArtifactSection(resolve26(artifactDir, "next-actions.md"), "--- Next Actions (for you) ---");
|
|
5621
|
+
const changedFiles = resolve26(artifactDir, "changed-files.txt");
|
|
5622
|
+
if (existsSync24(changedFiles)) {
|
|
5623
|
+
const lines = readFileSync12(changedFiles, "utf-8").split(/\r?\n/).filter(Boolean);
|
|
5570
5624
|
console.log(`--- Changed Files (${lines.length}) ---`);
|
|
5571
5625
|
for (const line of lines) {
|
|
5572
5626
|
console.log(line);
|
|
@@ -5690,12 +5744,12 @@ function printIndented(text) {
|
|
|
5690
5744
|
}
|
|
5691
5745
|
}
|
|
5692
5746
|
function readLocalBeadsTasks(projectRoot) {
|
|
5693
|
-
const issuesPath =
|
|
5694
|
-
if (!
|
|
5747
|
+
const issuesPath = resolve26(resolveMonorepoRoot2(projectRoot), ".beads/issues.jsonl");
|
|
5748
|
+
if (!existsSync24(issuesPath)) {
|
|
5695
5749
|
return [];
|
|
5696
5750
|
}
|
|
5697
5751
|
const tasks = [];
|
|
5698
|
-
for (const line of
|
|
5752
|
+
for (const line of readFileSync12(issuesPath, "utf-8").split(/\r?\n/)) {
|
|
5699
5753
|
const trimmed = line.trim();
|
|
5700
5754
|
if (!trimmed) {
|
|
5701
5755
|
continue;
|
|
@@ -5808,11 +5862,11 @@ function taskDependencies(projectRoot, taskId, tracker) {
|
|
|
5808
5862
|
return [...ids].sort();
|
|
5809
5863
|
}
|
|
5810
5864
|
function printArtifactSection(path, header) {
|
|
5811
|
-
if (!
|
|
5865
|
+
if (!existsSync24(path)) {
|
|
5812
5866
|
return;
|
|
5813
5867
|
}
|
|
5814
5868
|
console.log(header);
|
|
5815
|
-
process.stdout.write(
|
|
5869
|
+
process.stdout.write(readFileSync12(path, "utf-8"));
|
|
5816
5870
|
console.log("");
|
|
5817
5871
|
}
|
|
5818
5872
|
|
|
@@ -5914,7 +5968,7 @@ init_layout();
|
|
|
5914
5968
|
|
|
5915
5969
|
// packages/runtime/src/control-plane/runtime/overlay.ts
|
|
5916
5970
|
init_layout();
|
|
5917
|
-
import { mkdirSync as
|
|
5971
|
+
import { mkdirSync as mkdirSync11 } from "fs";
|
|
5918
5972
|
function ensureRuntimeOverlay(projectRoot, runtimeId, workspaceDir) {
|
|
5919
5973
|
const layout = resolveRuntimeWorkspaceLayout(workspaceDir ?? projectRoot);
|
|
5920
5974
|
const rootDir = layout.rigRoot;
|
|
@@ -5926,14 +5980,14 @@ function ensureRuntimeOverlay(projectRoot, runtimeId, workspaceDir) {
|
|
|
5926
5980
|
const sessionDir = layout.sessionDir;
|
|
5927
5981
|
const runtimeDir = layout.runtimeDir;
|
|
5928
5982
|
const contextPath = layout.contextPath;
|
|
5929
|
-
|
|
5930
|
-
|
|
5931
|
-
|
|
5932
|
-
|
|
5933
|
-
|
|
5934
|
-
|
|
5935
|
-
|
|
5936
|
-
|
|
5983
|
+
mkdirSync11(rootDir, { recursive: true });
|
|
5984
|
+
mkdirSync11(homeDir, { recursive: true });
|
|
5985
|
+
mkdirSync11(tmpDir, { recursive: true });
|
|
5986
|
+
mkdirSync11(cacheDir, { recursive: true });
|
|
5987
|
+
mkdirSync11(logsDir, { recursive: true });
|
|
5988
|
+
mkdirSync11(stateDir, { recursive: true });
|
|
5989
|
+
mkdirSync11(sessionDir, { recursive: true });
|
|
5990
|
+
mkdirSync11(runtimeDir, { recursive: true });
|
|
5937
5991
|
return {
|
|
5938
5992
|
rootDir,
|
|
5939
5993
|
homeDir,
|
|
@@ -5951,17 +6005,17 @@ import {
|
|
|
5951
6005
|
chmodSync as chmodSync5,
|
|
5952
6006
|
copyFileSync as copyFileSync5,
|
|
5953
6007
|
cpSync as cpSync2,
|
|
5954
|
-
existsSync as
|
|
5955
|
-
mkdirSync as
|
|
6008
|
+
existsSync as existsSync26,
|
|
6009
|
+
mkdirSync as mkdirSync12,
|
|
5956
6010
|
statSync as statSync6,
|
|
5957
|
-
writeFileSync as
|
|
6011
|
+
writeFileSync as writeFileSync10
|
|
5958
6012
|
} from "fs";
|
|
5959
6013
|
import { mkdir as mkdir2 } from "fs/promises";
|
|
5960
|
-
import { basename as basename8, delimiter as delimiter2, resolve as
|
|
6014
|
+
import { basename as basename8, delimiter as delimiter2, resolve as resolve28 } from "path";
|
|
5961
6015
|
|
|
5962
6016
|
// packages/runtime/src/control-plane/runtime/isolation/shared.ts
|
|
5963
|
-
import { existsSync as
|
|
5964
|
-
import { resolve as
|
|
6017
|
+
import { existsSync as existsSync25, readFileSync as readFileSync13, rmSync as rmSync9 } from "fs";
|
|
6018
|
+
import { resolve as resolve27 } from "path";
|
|
5965
6019
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
5966
6020
|
var generatedCredentialFiles = new Set;
|
|
5967
6021
|
var credentialCleanupRegistered = false;
|
|
@@ -5986,7 +6040,7 @@ function resolveHostGitBinary() {
|
|
|
5986
6040
|
if (!candidate || isRuntimeGatewayGitPath(candidate)) {
|
|
5987
6041
|
continue;
|
|
5988
6042
|
}
|
|
5989
|
-
if (
|
|
6043
|
+
if (existsSync25(candidate)) {
|
|
5990
6044
|
return candidate;
|
|
5991
6045
|
}
|
|
5992
6046
|
}
|
|
@@ -6052,7 +6106,7 @@ async function refreshRemoteBranch(repoRoot, remote, branch) {
|
|
|
6052
6106
|
}
|
|
6053
6107
|
}
|
|
6054
6108
|
async function tryReadGitHead(repoRoot) {
|
|
6055
|
-
if (!
|
|
6109
|
+
if (!existsSync25(resolve27(repoRoot, ".git"))) {
|
|
6056
6110
|
return;
|
|
6057
6111
|
}
|
|
6058
6112
|
const result = await runGitCommand(repoRoot, ["rev-parse", "HEAD"]);
|
|
@@ -6063,7 +6117,7 @@ async function tryReadGitHead(repoRoot) {
|
|
|
6063
6117
|
return value || undefined;
|
|
6064
6118
|
}
|
|
6065
6119
|
async function captureRepoDirtyFiles(repoRoot) {
|
|
6066
|
-
if (!
|
|
6120
|
+
if (!existsSync25(resolve27(repoRoot, ".git"))) {
|
|
6067
6121
|
return [];
|
|
6068
6122
|
}
|
|
6069
6123
|
const files = new Set;
|
|
@@ -6099,7 +6153,7 @@ function registerCredentialCleanup(path) {
|
|
|
6099
6153
|
const cleanup = () => {
|
|
6100
6154
|
for (const filePath of generatedCredentialFiles) {
|
|
6101
6155
|
try {
|
|
6102
|
-
|
|
6156
|
+
rmSync9(filePath, { force: true });
|
|
6103
6157
|
} catch {}
|
|
6104
6158
|
}
|
|
6105
6159
|
generatedCredentialFiles.clear();
|
|
@@ -6154,20 +6208,23 @@ function hashProjectPath(workspaceDir) {
|
|
|
6154
6208
|
}
|
|
6155
6209
|
function resolveGithubCliBinaryPath() {
|
|
6156
6210
|
const explicit = process.env.RIG_GH_BIN?.trim();
|
|
6157
|
-
if (explicit &&
|
|
6211
|
+
if (explicit && existsSync25(explicit) && !isRuntimeGatewayGhPath(explicit)) {
|
|
6158
6212
|
return explicit;
|
|
6159
6213
|
}
|
|
6160
|
-
const
|
|
6161
|
-
|
|
6162
|
-
return bunResolved;
|
|
6163
|
-
}
|
|
6164
|
-
for (const candidate of ["/opt/homebrew/bin/gh", "/usr/local/bin/gh", "/usr/bin/gh"]) {
|
|
6165
|
-
if (existsSync24(candidate)) {
|
|
6214
|
+
for (const candidate of ["/usr/bin/gh", "/opt/homebrew/bin/gh", "/usr/local/bin/gh"]) {
|
|
6215
|
+
if (existsSync25(candidate)) {
|
|
6166
6216
|
return candidate;
|
|
6167
6217
|
}
|
|
6168
6218
|
}
|
|
6219
|
+
const bunResolved = Bun.which("gh");
|
|
6220
|
+
if (bunResolved && existsSync25(bunResolved) && !isRuntimeGatewayGhPath(bunResolved)) {
|
|
6221
|
+
return bunResolved;
|
|
6222
|
+
}
|
|
6169
6223
|
return "";
|
|
6170
6224
|
}
|
|
6225
|
+
function isRuntimeGatewayGhPath(candidate) {
|
|
6226
|
+
return /\/\.rig\/bin\/gh$/.test(candidate.replace(/\\/g, "/"));
|
|
6227
|
+
}
|
|
6171
6228
|
async function resolveGithubCliAuthToken(ghBinary = "") {
|
|
6172
6229
|
const gh = ghBinary || resolveGithubCliBinaryPath();
|
|
6173
6230
|
if (!gh) {
|
|
@@ -6194,17 +6251,17 @@ function resolveSystemCertBundlePath() {
|
|
|
6194
6251
|
"/opt/homebrew/etc/openssl@3/cert.pem"
|
|
6195
6252
|
];
|
|
6196
6253
|
for (const candidate of candidates) {
|
|
6197
|
-
if (candidate &&
|
|
6198
|
-
return
|
|
6254
|
+
if (candidate && existsSync25(candidate)) {
|
|
6255
|
+
return resolve27(candidate);
|
|
6199
6256
|
}
|
|
6200
6257
|
}
|
|
6201
6258
|
return "";
|
|
6202
6259
|
}
|
|
6203
6260
|
function readKnownHosts(path) {
|
|
6204
|
-
if (!
|
|
6261
|
+
if (!existsSync25(path)) {
|
|
6205
6262
|
return new Set;
|
|
6206
6263
|
}
|
|
6207
|
-
return new Set(
|
|
6264
|
+
return new Set(readFileSync13(path, "utf-8").split(/\r?\n/).map((line) => line.trim()).filter(Boolean));
|
|
6208
6265
|
}
|
|
6209
6266
|
|
|
6210
6267
|
// packages/runtime/src/control-plane/runtime/isolation/home.ts
|
|
@@ -6215,6 +6272,21 @@ var GITHUB_KNOWN_HOSTS = [
|
|
|
6215
6272
|
"github.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCj7ndNxQowgcQnjshcLrqPEiiphnt+VTTvDP6mHBL9j1aNUkY4Ue1gvwnGLVlOhGeYrnZaMgRK6+PKCUXaDbC7qtbW8gIkhL7aGCsOr/C56SJMy/BCZfxd1nWzAOxSDPgVsmerOBYfNqltV9/hWCqBywINIR+5dIg6JTJ72pcEpEjcYgXkE2YEFXV1JHnsKgbLWNlhScqb2UmyRkQyytRLtL+38TGxkxCflmO+5Z8CSSNY7GidjMIZ7Q4zMjA2n1nGrlTDkzwDCsw+wqFPGQA179cnfGWOWRVruj16z6XyvxvjJwbz0wQZ75XK5tKSb7FNyeIEs4TT4jk+S4dhPeAUC5y+bDYirYgM4GC7uEnztnZyaVWQ7B381AK4Qdrwt51ZqExKbQpTUNn+EjqoTwvqNj4kqx5QUCI0ThS/YkOxJCXmPUWZbhjpCg56i+2aB6CmK2JGhn57K5mj0MNdBXA4/WnwH6XoPWJzK5Nyu2zB3nAZp+S5hpQs+p1vN1/wsjk="
|
|
6216
6273
|
].join(`
|
|
6217
6274
|
`);
|
|
6275
|
+
function resolveControlPlaneSourceRoot(projectRoot) {
|
|
6276
|
+
const candidates = [
|
|
6277
|
+
process.env.RIG_CONTROL_PLANE_SOURCE_ROOT?.trim(),
|
|
6278
|
+
process.env.RIG_HOST_PROJECT_ROOT?.trim(),
|
|
6279
|
+
resolve28(import.meta.dir, "../../../../.."),
|
|
6280
|
+
projectRoot
|
|
6281
|
+
].filter((value) => Boolean(value));
|
|
6282
|
+
for (const candidate of candidates) {
|
|
6283
|
+
const root = resolve28(candidate);
|
|
6284
|
+
if (existsSync26(resolve28(root, "packages/runtime/src/control-plane/pi-sessiond/bin.ts"))) {
|
|
6285
|
+
return root;
|
|
6286
|
+
}
|
|
6287
|
+
}
|
|
6288
|
+
return "";
|
|
6289
|
+
}
|
|
6218
6290
|
async function runtimeEnv(projectRoot, runtime) {
|
|
6219
6291
|
const bunBinaryPath = resolveBunBinaryPath();
|
|
6220
6292
|
const bunDir = resolveBunInstallDir(bunBinaryPath);
|
|
@@ -6229,7 +6301,7 @@ async function runtimeEnv(projectRoot, runtime) {
|
|
|
6229
6301
|
try {
|
|
6230
6302
|
return resolveClaudeInstallDir();
|
|
6231
6303
|
} catch {
|
|
6232
|
-
return
|
|
6304
|
+
return resolve28(claudeBinaryPath, "..");
|
|
6233
6305
|
}
|
|
6234
6306
|
})() : "";
|
|
6235
6307
|
const nodeDir = resolveNodeInstallDir();
|
|
@@ -6244,8 +6316,8 @@ async function runtimeEnv(projectRoot, runtime) {
|
|
|
6244
6316
|
`${bunDir}/bin`,
|
|
6245
6317
|
claudeDir,
|
|
6246
6318
|
nodeDir ? `${nodeDir}/bin` : "",
|
|
6247
|
-
realHome ?
|
|
6248
|
-
realHome ?
|
|
6319
|
+
realHome ? resolve28(realHome, ".local/bin") : "",
|
|
6320
|
+
realHome ? resolve28(realHome, ".cargo/bin") : "",
|
|
6249
6321
|
...inheritedPath,
|
|
6250
6322
|
"/usr/local/bin",
|
|
6251
6323
|
"/usr/local/sbin",
|
|
@@ -6256,18 +6328,22 @@ async function runtimeEnv(projectRoot, runtime) {
|
|
|
6256
6328
|
"/usr/sbin",
|
|
6257
6329
|
"/sbin"
|
|
6258
6330
|
].filter(Boolean);
|
|
6259
|
-
const runtimeBash =
|
|
6260
|
-
const runtimeRigGit =
|
|
6261
|
-
const preferredShell =
|
|
6331
|
+
const runtimeBash = resolve28(runtime.binDir, "bash");
|
|
6332
|
+
const runtimeRigGit = resolve28(runtime.binDir, runtimeRigGitFileName());
|
|
6333
|
+
const preferredShell = existsSync26(runtimeBash) ? runtimeBash : "/bin/bash";
|
|
6262
6334
|
const nativeRuntimeLibraryPath = await materializeNativeRuntimeLibrary(runtime.binDir);
|
|
6335
|
+
const controlPlaneSourceRoot = resolveControlPlaneSourceRoot(projectRoot);
|
|
6263
6336
|
const env = {
|
|
6264
6337
|
PROJECT_RIG_ROOT: projectRoot,
|
|
6265
6338
|
RIG_HOST_PROJECT_ROOT: projectRoot,
|
|
6339
|
+
...controlPlaneSourceRoot ? { RIG_CONTROL_PLANE_SOURCE_ROOT: controlPlaneSourceRoot } : {},
|
|
6266
6340
|
HOME: runtime.homeDir,
|
|
6267
6341
|
TMPDIR: runtime.tmpDir,
|
|
6268
6342
|
XDG_CACHE_HOME: runtime.cacheDir,
|
|
6269
6343
|
XDG_STATE_HOME: runtime.stateDir,
|
|
6270
6344
|
RIG_AGENT_ID: runtime.id,
|
|
6345
|
+
...process.env.RIG_RUN_ID?.trim() ? { RIG_RUN_ID: process.env.RIG_RUN_ID.trim() } : {},
|
|
6346
|
+
...process.env.RIG_SERVER_RUN_ID?.trim() ? { RIG_SERVER_RUN_ID: process.env.RIG_SERVER_RUN_ID.trim() } : {},
|
|
6271
6347
|
RIG_TASK_ID: runtime.taskId,
|
|
6272
6348
|
RIG_TASK_RUNTIME_ID: runtime.id,
|
|
6273
6349
|
RIG_TASK_WORKSPACE: runtime.workspaceDir,
|
|
@@ -6275,30 +6351,30 @@ async function runtimeEnv(projectRoot, runtime) {
|
|
|
6275
6351
|
RIG_RUNTIME_MODE: runtime.mode,
|
|
6276
6352
|
RIG_RUNTIME_HOME: runtime.rootDir,
|
|
6277
6353
|
RIG_RUNTIME_BIN_DIR: runtime.binDir,
|
|
6278
|
-
...
|
|
6354
|
+
...existsSync26(runtimeRigGit) ? { RIG_NATIVE_GIT_BIN: runtimeRigGit } : {},
|
|
6279
6355
|
RIG_BUN_PATH: bunBinaryPath,
|
|
6280
6356
|
...claudeBinaryPath ? { RIG_CLAUDE_PATH: claudeBinaryPath } : {},
|
|
6281
|
-
RIG_AGENT_BIN:
|
|
6357
|
+
RIG_AGENT_BIN: resolve28(runtime.binDir, "rig-agent"),
|
|
6282
6358
|
RIG_HOOKS_ACTIVE: "1",
|
|
6283
6359
|
RIG_AUTO_PR_ON_COMPLETE: "1",
|
|
6284
|
-
RIG_POLICY_FILE:
|
|
6360
|
+
RIG_POLICY_FILE: resolve28(projectRoot, "rig/policy/policy.json"),
|
|
6285
6361
|
RIG_STATE_DIR: runtime.stateDir,
|
|
6286
6362
|
RIG_LOGS_DIR: runtime.logsDir,
|
|
6287
|
-
RIG_SESSION_FILE:
|
|
6363
|
+
RIG_SESSION_FILE: resolve28(runtime.sessionDir, "session.json"),
|
|
6288
6364
|
MONOREPO_ROOT: runtime.workspaceDir,
|
|
6289
6365
|
MONOREPO_MAIN_ROOT: monorepoMainRoot,
|
|
6290
|
-
TS_API_TESTS_DIR:
|
|
6366
|
+
TS_API_TESTS_DIR: resolve28(runtime.workspaceDir, "TSAPITests"),
|
|
6291
6367
|
BASH: preferredShell,
|
|
6292
6368
|
SHELL: preferredShell,
|
|
6293
6369
|
PATH: [...new Set(pathEntries)].join(delimiter2),
|
|
6294
6370
|
LANG: process.env.LANG ?? "en_US.UTF-8",
|
|
6295
6371
|
TERM: process.env.TERM ?? "xterm-256color",
|
|
6296
6372
|
PYTHONDONTWRITEBYTECODE: "1",
|
|
6297
|
-
PYTHONPYCACHEPREFIX:
|
|
6373
|
+
PYTHONPYCACHEPREFIX: resolve28(runtime.cacheDir, "python"),
|
|
6298
6374
|
...process.env.RIG_PR_BASE_PROJECT && { RIG_PR_BASE_PROJECT: process.env.RIG_PR_BASE_PROJECT },
|
|
6299
6375
|
...process.env.RIG_PR_BASE_MONOREPO && { RIG_PR_BASE_MONOREPO: process.env.RIG_PR_BASE_MONOREPO },
|
|
6300
6376
|
CLAUDE_HOME: runtime.claudeHomeDir,
|
|
6301
|
-
PI_CODING_AGENT_DIR:
|
|
6377
|
+
PI_CODING_AGENT_DIR: resolve28(runtime.homeDir, ".pi", "agent"),
|
|
6302
6378
|
[RUNTIME_CONTEXT_ENV]: runtime.contextFile,
|
|
6303
6379
|
...nativeRuntimeLibraryPath ? { RIG_NATIVE_RUNTIME_LIB: nativeRuntimeLibraryPath } : {},
|
|
6304
6380
|
...hostGhBinary ? { RIG_GH_BIN: hostGhBinary } : {},
|
|
@@ -6309,16 +6385,16 @@ async function runtimeEnv(projectRoot, runtime) {
|
|
|
6309
6385
|
NODE_EXTRA_CA_CERTS: runtimeCertBundlePath
|
|
6310
6386
|
} : {}
|
|
6311
6387
|
};
|
|
6312
|
-
const knownHostsPath =
|
|
6313
|
-
if (
|
|
6314
|
-
const agentSshKey =
|
|
6388
|
+
const knownHostsPath = resolve28(runtime.homeDir, ".ssh", "known_hosts");
|
|
6389
|
+
if (existsSync26(knownHostsPath)) {
|
|
6390
|
+
const agentSshKey = resolve28(runtime.homeDir, ".ssh", "rig-agent-key");
|
|
6315
6391
|
const sshParts = [
|
|
6316
6392
|
"ssh",
|
|
6317
6393
|
`-o UserKnownHostsFile="${knownHostsPath}"`,
|
|
6318
6394
|
"-o StrictHostKeyChecking=yes",
|
|
6319
6395
|
"-F /dev/null"
|
|
6320
6396
|
];
|
|
6321
|
-
if (
|
|
6397
|
+
if (existsSync26(agentSshKey)) {
|
|
6322
6398
|
sshParts.splice(1, 0, `-i "${agentSshKey}"`, "-o IdentitiesOnly=yes");
|
|
6323
6399
|
}
|
|
6324
6400
|
env.GIT_SSH_COMMAND = sshParts.join(" ");
|
|
@@ -6355,7 +6431,7 @@ async function runtimeEnv(projectRoot, runtime) {
|
|
|
6355
6431
|
if (!env.GREPTILE_GITHUB_TOKEN && env.GITHUB_TOKEN) {
|
|
6356
6432
|
env.GREPTILE_GITHUB_TOKEN = env.GITHUB_TOKEN;
|
|
6357
6433
|
}
|
|
6358
|
-
if (
|
|
6434
|
+
if (existsSync26(runtime.contextFile)) {
|
|
6359
6435
|
const runtimeContext = loadRuntimeContext(runtime.contextFile);
|
|
6360
6436
|
Object.assign(env, runtimeMemoryEnvFromContext(runtimeContext));
|
|
6361
6437
|
Object.assign(env, browserEnvFromContext(runtimeContext.browser));
|
|
@@ -6384,30 +6460,30 @@ async function provisionRuntimeHome(runtime, options = {}) {
|
|
|
6384
6460
|
await mkdir2(runtime.cacheDir, { recursive: true });
|
|
6385
6461
|
await provisionAgentSshKey(runtime.homeDir);
|
|
6386
6462
|
if (options.provider === "codex") {
|
|
6387
|
-
const hasCodexAuth = await injectCodexAuth(
|
|
6463
|
+
const hasCodexAuth = await injectCodexAuth(resolve28(runtime.homeDir, ".codex"));
|
|
6388
6464
|
if (!hasCodexAuth) {
|
|
6389
6465
|
console.warn("[rig] No Codex auth.json found for isolated runtime. " + "Run `codex login` in your host shell, then retry the agent run.");
|
|
6390
6466
|
}
|
|
6391
6467
|
}
|
|
6392
6468
|
if (options.provider === "pi") {
|
|
6393
|
-
const hasPiAuth = await injectPiAgentConfig(
|
|
6469
|
+
const hasPiAuth = await injectPiAgentConfig(resolve28(runtime.homeDir, ".pi", "agent"));
|
|
6394
6470
|
if (!hasPiAuth) {
|
|
6395
6471
|
console.warn("[rig] No Pi auth.json found for isolated runtime. " + "Run `pi /login` in your host shell, then retry the agent run.");
|
|
6396
6472
|
}
|
|
6397
6473
|
}
|
|
6398
6474
|
}
|
|
6399
6475
|
async function provisionClaudeHome(config) {
|
|
6400
|
-
|
|
6401
|
-
const workspaceSettings =
|
|
6402
|
-
const hostSettings =
|
|
6403
|
-
const projectSettings =
|
|
6476
|
+
mkdirSync12(config.claudeHomeDir, { recursive: true });
|
|
6477
|
+
const workspaceSettings = resolve28(config.workspaceDir, ".claude/settings.json");
|
|
6478
|
+
const hostSettings = resolve28(config.hostProjectRoot, ".claude/settings.json");
|
|
6479
|
+
const projectSettings = existsSync26(workspaceSettings) ? workspaceSettings : hostSettings;
|
|
6404
6480
|
const runtimeSettings = await loadRuntimeClaudeSettings(projectSettings);
|
|
6405
|
-
if (
|
|
6406
|
-
|
|
6481
|
+
if (existsSync26(projectSettings)) {
|
|
6482
|
+
writeFileSync10(resolve28(config.claudeHomeDir, "settings.local.json"), `${JSON.stringify(runtimeSettings, null, 2)}
|
|
6407
6483
|
`, "utf-8");
|
|
6408
6484
|
}
|
|
6409
6485
|
writeClaudeProjectSettings(config.claudeHomeDir, config.workspaceDir, runtimeSettings);
|
|
6410
|
-
|
|
6486
|
+
writeFileSync10(resolve28(config.claudeHomeDir, "settings.json"), JSON.stringify({
|
|
6411
6487
|
permissions: { defaultMode: "bypassPermissions" },
|
|
6412
6488
|
autoMemoryEnabled: false
|
|
6413
6489
|
}, null, 2));
|
|
@@ -6415,12 +6491,12 @@ async function provisionClaudeHome(config) {
|
|
|
6415
6491
|
if (!hasCredentials) {
|
|
6416
6492
|
console.warn("[rig] No Claude credentials found for isolated runtime. " + "Run `claude /login` in your host shell, then retry the agent run.");
|
|
6417
6493
|
}
|
|
6418
|
-
const realClaudeHome =
|
|
6419
|
-
if (process.env.HOME &&
|
|
6420
|
-
cpSync2(
|
|
6494
|
+
const realClaudeHome = resolve28(process.env.HOME ?? "", ".claude");
|
|
6495
|
+
if (process.env.HOME && existsSync26(resolve28(realClaudeHome, "CLAUDE.md"))) {
|
|
6496
|
+
cpSync2(resolve28(realClaudeHome, "CLAUDE.md"), resolve28(config.claudeHomeDir, "CLAUDE.md"));
|
|
6421
6497
|
}
|
|
6422
|
-
if (process.env.HOME &&
|
|
6423
|
-
cpSync2(
|
|
6498
|
+
if (process.env.HOME && existsSync26(resolve28(realClaudeHome, "agents"))) {
|
|
6499
|
+
cpSync2(resolve28(realClaudeHome, "agents"), resolve28(config.claudeHomeDir, "agents"), { recursive: true });
|
|
6424
6500
|
}
|
|
6425
6501
|
if (process.platform === "darwin" && process.env.HOME) {
|
|
6426
6502
|
writeClaudeProjectSettings(realClaudeHome, config.workspaceDir, runtimeSettings);
|
|
@@ -6431,10 +6507,10 @@ async function materializeRuntimeCertBundle(runtime) {
|
|
|
6431
6507
|
if (!sourcePath) {
|
|
6432
6508
|
return "";
|
|
6433
6509
|
}
|
|
6434
|
-
const certsDir =
|
|
6435
|
-
const targetPath =
|
|
6510
|
+
const certsDir = resolve28(runtime.rootDir, "certs");
|
|
6511
|
+
const targetPath = resolve28(certsDir, "ca-certificates.pem");
|
|
6436
6512
|
await mkdir2(certsDir, { recursive: true });
|
|
6437
|
-
let shouldCopy = !
|
|
6513
|
+
let shouldCopy = !existsSync26(targetPath);
|
|
6438
6514
|
if (!shouldCopy) {
|
|
6439
6515
|
try {
|
|
6440
6516
|
shouldCopy = statSync6(sourcePath).mtimeMs > statSync6(targetPath).mtimeMs;
|
|
@@ -6456,7 +6532,7 @@ function applyGitHubCredentialHelperEnv(env) {
|
|
|
6456
6532
|
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';
|
|
6457
6533
|
}
|
|
6458
6534
|
function persistRuntimeSecrets(runtimeRoot, env) {
|
|
6459
|
-
const secretsPath =
|
|
6535
|
+
const secretsPath = resolve28(runtimeRoot, "runtime-secrets.json");
|
|
6460
6536
|
const persisted = {};
|
|
6461
6537
|
for (const key of [
|
|
6462
6538
|
"GITHUB_TOKEN",
|
|
@@ -6475,12 +6551,12 @@ function persistRuntimeSecrets(runtimeRoot, env) {
|
|
|
6475
6551
|
if (Object.keys(persisted).length === 0) {
|
|
6476
6552
|
return;
|
|
6477
6553
|
}
|
|
6478
|
-
|
|
6554
|
+
writeFileSync10(secretsPath, `${JSON.stringify(persisted, null, 2)}
|
|
6479
6555
|
`, "utf-8");
|
|
6480
6556
|
}
|
|
6481
6557
|
async function provisionAgentSshKey(homeDir) {
|
|
6482
|
-
const sshDir =
|
|
6483
|
-
if (!
|
|
6558
|
+
const sshDir = resolve28(homeDir, ".ssh");
|
|
6559
|
+
if (!existsSync26(sshDir)) {
|
|
6484
6560
|
await mkdir2(sshDir, { recursive: true });
|
|
6485
6561
|
}
|
|
6486
6562
|
seedKnownHosts(sshDir);
|
|
@@ -6488,27 +6564,27 @@ async function provisionAgentSshKey(homeDir) {
|
|
|
6488
6564
|
const privateKey = decodeProvisionedSshKey(secrets.GITHUB_SSH_KEY);
|
|
6489
6565
|
if (!privateKey) {
|
|
6490
6566
|
const hostKeyPath = resolveHostSshKeyPath(process.env.HOME ?? "");
|
|
6491
|
-
if (!process.env.HOME || !
|
|
6567
|
+
if (!process.env.HOME || !existsSync26(hostKeyPath)) {
|
|
6492
6568
|
return;
|
|
6493
6569
|
}
|
|
6494
|
-
const agentKeyPath2 =
|
|
6495
|
-
if (!
|
|
6570
|
+
const agentKeyPath2 = resolve28(sshDir, "rig-agent-key");
|
|
6571
|
+
if (!existsSync26(agentKeyPath2)) {
|
|
6496
6572
|
copyFileSync5(hostKeyPath, agentKeyPath2);
|
|
6497
6573
|
chmodSync5(agentKeyPath2, 384);
|
|
6498
6574
|
}
|
|
6499
6575
|
const hostPubPath = `${hostKeyPath}.pub`;
|
|
6500
|
-
if (
|
|
6576
|
+
if (existsSync26(hostPubPath)) {
|
|
6501
6577
|
const agentPubPath = `${agentKeyPath2}.pub`;
|
|
6502
|
-
if (!
|
|
6578
|
+
if (!existsSync26(agentPubPath)) {
|
|
6503
6579
|
copyFileSync5(hostPubPath, agentPubPath);
|
|
6504
6580
|
}
|
|
6505
6581
|
}
|
|
6506
6582
|
writeSshConfig(sshDir, agentKeyPath2);
|
|
6507
6583
|
return;
|
|
6508
6584
|
}
|
|
6509
|
-
const agentKeyPath =
|
|
6510
|
-
if (!
|
|
6511
|
-
|
|
6585
|
+
const agentKeyPath = resolve28(sshDir, "rig-agent-key");
|
|
6586
|
+
if (!existsSync26(agentKeyPath)) {
|
|
6587
|
+
writeFileSync10(agentKeyPath, privateKey, { mode: 384 });
|
|
6512
6588
|
}
|
|
6513
6589
|
writeSshConfig(sshDir, agentKeyPath);
|
|
6514
6590
|
}
|
|
@@ -6525,21 +6601,21 @@ function decodeProvisionedSshKey(encodedKey) {
|
|
|
6525
6601
|
`;
|
|
6526
6602
|
}
|
|
6527
6603
|
function resolveHostSshKeyPath(homeDir) {
|
|
6528
|
-
const sshDir =
|
|
6604
|
+
const sshDir = resolve28(homeDir, ".ssh");
|
|
6529
6605
|
const candidates = [
|
|
6530
6606
|
"rig-agent-key",
|
|
6531
6607
|
"id_ed25519",
|
|
6532
6608
|
"id_ecdsa",
|
|
6533
6609
|
"id_rsa"
|
|
6534
|
-
].map((name) =>
|
|
6535
|
-
return candidates.find((candidate) =>
|
|
6610
|
+
].map((name) => resolve28(sshDir, name));
|
|
6611
|
+
return candidates.find((candidate) => existsSync26(candidate)) ?? resolve28(sshDir, "rig-agent-key");
|
|
6536
6612
|
}
|
|
6537
6613
|
function writeSshConfig(sshDir, keyPath) {
|
|
6538
|
-
const configPath =
|
|
6539
|
-
if (
|
|
6614
|
+
const configPath = resolve28(sshDir, "config");
|
|
6615
|
+
if (existsSync26(configPath)) {
|
|
6540
6616
|
return;
|
|
6541
6617
|
}
|
|
6542
|
-
const knownHostsPath =
|
|
6618
|
+
const knownHostsPath = resolve28(sshDir, "known_hosts");
|
|
6543
6619
|
const config = [
|
|
6544
6620
|
"Host github.com",
|
|
6545
6621
|
` IdentityFile ${keyPath}`,
|
|
@@ -6549,10 +6625,10 @@ function writeSshConfig(sshDir, keyPath) {
|
|
|
6549
6625
|
""
|
|
6550
6626
|
].join(`
|
|
6551
6627
|
`);
|
|
6552
|
-
|
|
6628
|
+
writeFileSync10(configPath, config, { mode: 420 });
|
|
6553
6629
|
}
|
|
6554
6630
|
function seedKnownHosts(sshDir) {
|
|
6555
|
-
const knownHostsPath =
|
|
6631
|
+
const knownHostsPath = resolve28(sshDir, "known_hosts");
|
|
6556
6632
|
const existingLines = readKnownHosts(knownHostsPath);
|
|
6557
6633
|
const requiredLines = GITHUB_KNOWN_HOSTS.split(/\r?\n/).map((line) => line.trim()).filter(Boolean);
|
|
6558
6634
|
const missing = requiredLines.filter((line) => !existingLines.has(line));
|
|
@@ -6563,23 +6639,23 @@ function seedKnownHosts(sshDir) {
|
|
|
6563
6639
|
for (const line of missing) {
|
|
6564
6640
|
existingLines.add(line);
|
|
6565
6641
|
}
|
|
6566
|
-
|
|
6642
|
+
writeFileSync10(knownHostsPath, `${Array.from(existingLines).join(`
|
|
6567
6643
|
`)}
|
|
6568
6644
|
`, { mode: 420 });
|
|
6569
6645
|
} catch (err) {
|
|
6570
|
-
const hint =
|
|
6646
|
+
const hint = existsSync26(knownHostsPath) ? "" : " \u2014 known_hosts is missing; git SSH operations may fail";
|
|
6571
6647
|
console.warn(`[rig] Could not update ${knownHostsPath}: ${err instanceof Error ? err.message : String(err)}${hint}`);
|
|
6572
6648
|
}
|
|
6573
6649
|
}
|
|
6574
6650
|
function writeClaudeProjectSettings(claudeHomeDir, workspaceDir, runtimeSettings) {
|
|
6575
6651
|
const projectHash = hashProjectPath(workspaceDir);
|
|
6576
|
-
const projectDir =
|
|
6577
|
-
|
|
6578
|
-
|
|
6652
|
+
const projectDir = resolve28(claudeHomeDir, "projects", projectHash);
|
|
6653
|
+
mkdirSync12(projectDir, { recursive: true });
|
|
6654
|
+
writeFileSync10(resolve28(projectDir, "settings.json"), `${JSON.stringify(runtimeSettings, null, 2)}
|
|
6579
6655
|
`, "utf-8");
|
|
6580
6656
|
}
|
|
6581
6657
|
async function loadRuntimeClaudeSettings(projectSettingsPath) {
|
|
6582
|
-
if (!
|
|
6658
|
+
if (!existsSync26(projectSettingsPath)) {
|
|
6583
6659
|
return {};
|
|
6584
6660
|
}
|
|
6585
6661
|
let parsed;
|
|
@@ -6625,7 +6701,7 @@ async function loadRuntimeClaudeSettings(projectSettingsPath) {
|
|
|
6625
6701
|
return clone;
|
|
6626
6702
|
}
|
|
6627
6703
|
async function injectClaudeCredentials(claudeHomeDir, options = {}) {
|
|
6628
|
-
const credentialsPath =
|
|
6704
|
+
const credentialsPath = resolve28(claudeHomeDir, ".credentials.json");
|
|
6629
6705
|
const platform = options.platform ?? process.platform;
|
|
6630
6706
|
if (platform === "darwin") {
|
|
6631
6707
|
const raw = options.loadKeychainCredentials ? await options.loadKeychainCredentials() : await (async () => {
|
|
@@ -6635,16 +6711,16 @@ async function injectClaudeCredentials(claudeHomeDir, options = {}) {
|
|
|
6635
6711
|
if (raw) {
|
|
6636
6712
|
try {
|
|
6637
6713
|
JSON.parse(raw);
|
|
6638
|
-
|
|
6714
|
+
writeFileSync10(credentialsPath, raw, { mode: 384 });
|
|
6639
6715
|
registerCredentialCleanup(credentialsPath);
|
|
6640
6716
|
return true;
|
|
6641
6717
|
} catch {}
|
|
6642
6718
|
}
|
|
6643
6719
|
}
|
|
6644
|
-
const hostClaudeHome = options.hostClaudeHome ?
|
|
6720
|
+
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") : "";
|
|
6645
6721
|
if (hostClaudeHome) {
|
|
6646
|
-
const realCredentials =
|
|
6647
|
-
if (
|
|
6722
|
+
const realCredentials = resolve28(hostClaudeHome, ".credentials.json");
|
|
6723
|
+
if (existsSync26(realCredentials)) {
|
|
6648
6724
|
cpSync2(realCredentials, credentialsPath);
|
|
6649
6725
|
return true;
|
|
6650
6726
|
}
|
|
@@ -6652,36 +6728,36 @@ async function injectClaudeCredentials(claudeHomeDir, options = {}) {
|
|
|
6652
6728
|
return false;
|
|
6653
6729
|
}
|
|
6654
6730
|
async function injectCodexAuth(codexHomeDir) {
|
|
6655
|
-
|
|
6656
|
-
const hostCodexHome = process.env.CODEX_HOME?.trim() ?
|
|
6731
|
+
mkdirSync12(codexHomeDir, { recursive: true });
|
|
6732
|
+
const hostCodexHome = process.env.CODEX_HOME?.trim() ? resolve28(process.env.CODEX_HOME) : process.env.HOME ? resolve28(process.env.HOME, ".codex") : "";
|
|
6657
6733
|
if (!hostCodexHome) {
|
|
6658
6734
|
return false;
|
|
6659
6735
|
}
|
|
6660
|
-
const hostAuthPath =
|
|
6661
|
-
if (!
|
|
6736
|
+
const hostAuthPath = resolve28(hostCodexHome, "auth.json");
|
|
6737
|
+
if (!existsSync26(hostAuthPath)) {
|
|
6662
6738
|
return false;
|
|
6663
6739
|
}
|
|
6664
|
-
const runtimeAuthPath =
|
|
6740
|
+
const runtimeAuthPath = resolve28(codexHomeDir, "auth.json");
|
|
6665
6741
|
copyFileSync5(hostAuthPath, runtimeAuthPath);
|
|
6666
6742
|
chmodSync5(runtimeAuthPath, 384);
|
|
6667
6743
|
return true;
|
|
6668
6744
|
}
|
|
6669
6745
|
async function injectPiAgentConfig(piAgentDir) {
|
|
6670
|
-
|
|
6671
|
-
const hostPiAgentDir = process.env.PI_CODING_AGENT_DIR?.trim() ?
|
|
6746
|
+
mkdirSync12(piAgentDir, { recursive: true });
|
|
6747
|
+
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") : "";
|
|
6672
6748
|
if (!hostPiAgentDir) {
|
|
6673
6749
|
return false;
|
|
6674
6750
|
}
|
|
6675
|
-
const hostAuthPath =
|
|
6676
|
-
if (!
|
|
6751
|
+
const hostAuthPath = resolve28(hostPiAgentDir, "auth.json");
|
|
6752
|
+
if (!existsSync26(hostAuthPath)) {
|
|
6677
6753
|
return false;
|
|
6678
6754
|
}
|
|
6679
|
-
const runtimeAuthPath =
|
|
6755
|
+
const runtimeAuthPath = resolve28(piAgentDir, "auth.json");
|
|
6680
6756
|
copyFileSync5(hostAuthPath, runtimeAuthPath);
|
|
6681
6757
|
chmodSync5(runtimeAuthPath, 384);
|
|
6682
|
-
const hostSettingsPath =
|
|
6683
|
-
if (
|
|
6684
|
-
const runtimeSettingsPath =
|
|
6758
|
+
const hostSettingsPath = resolve28(hostPiAgentDir, "settings.json");
|
|
6759
|
+
if (existsSync26(hostSettingsPath)) {
|
|
6760
|
+
const runtimeSettingsPath = resolve28(piAgentDir, "settings.json");
|
|
6685
6761
|
copyFileSync5(hostSettingsPath, runtimeSettingsPath);
|
|
6686
6762
|
chmodSync5(runtimeSettingsPath, 384);
|
|
6687
6763
|
}
|
|
@@ -6689,13 +6765,13 @@ async function injectPiAgentConfig(piAgentDir) {
|
|
|
6689
6765
|
}
|
|
6690
6766
|
|
|
6691
6767
|
// packages/runtime/src/control-plane/runtime/tooling/claude-router.ts
|
|
6692
|
-
import { existsSync as
|
|
6693
|
-
import { resolve as
|
|
6768
|
+
import { existsSync as existsSync27, mkdirSync as mkdirSync13, statSync as statSync7, writeFileSync as writeFileSync11 } from "fs";
|
|
6769
|
+
import { resolve as resolve29 } from "path";
|
|
6694
6770
|
var CLAUDE_ROUTER_SERVER_NAME = "rig_runtime_tools";
|
|
6695
6771
|
function buildRuntimeToolRouterServerConfig(options) {
|
|
6696
6772
|
return {
|
|
6697
6773
|
type: "stdio",
|
|
6698
|
-
command:
|
|
6774
|
+
command: resolve29(options.binDir, "rig-tool-router"),
|
|
6699
6775
|
args: [],
|
|
6700
6776
|
env: {
|
|
6701
6777
|
RIG_RUNTIME_CONTEXT_FILE: options.contextFile,
|
|
@@ -6704,25 +6780,25 @@ function buildRuntimeToolRouterServerConfig(options) {
|
|
|
6704
6780
|
};
|
|
6705
6781
|
}
|
|
6706
6782
|
function writeClaudeRuntimeToolRouterConfig(options) {
|
|
6707
|
-
const configPath =
|
|
6708
|
-
|
|
6783
|
+
const configPath = resolve29(options.stateDir, "claude-runtime-tools.mcp.json");
|
|
6784
|
+
mkdirSync13(options.stateDir, { recursive: true });
|
|
6709
6785
|
const payload = {
|
|
6710
6786
|
mcpServers: {
|
|
6711
6787
|
[CLAUDE_ROUTER_SERVER_NAME]: buildRuntimeToolRouterServerConfig(options)
|
|
6712
6788
|
}
|
|
6713
6789
|
};
|
|
6714
|
-
|
|
6790
|
+
writeFileSync11(configPath, `${JSON.stringify(payload, null, 2)}
|
|
6715
6791
|
`, "utf-8");
|
|
6716
6792
|
return configPath;
|
|
6717
6793
|
}
|
|
6718
6794
|
if (false) {}
|
|
6719
6795
|
// packages/runtime/src/control-plane/runtime/isolation/discovery.ts
|
|
6720
6796
|
init_layout();
|
|
6721
|
-
import { resolve as
|
|
6797
|
+
import { resolve as resolve33 } from "path";
|
|
6722
6798
|
|
|
6723
6799
|
// packages/runtime/src/control-plane/runtime/isolation/worktree.ts
|
|
6724
|
-
import { existsSync as
|
|
6725
|
-
import { dirname as dirname12, resolve as
|
|
6800
|
+
import { existsSync as existsSync28, mkdirSync as mkdirSync14, rmSync as rmSync10 } from "fs";
|
|
6801
|
+
import { dirname as dirname12, resolve as resolve30 } from "path";
|
|
6726
6802
|
async function resolveMonorepoBaseRef(monorepoRoot) {
|
|
6727
6803
|
const explicit = process.env.RIG_RUNTIME_BASE_REF?.trim();
|
|
6728
6804
|
if (explicit) {
|
|
@@ -6758,12 +6834,12 @@ function ensureProvisioningHostProjectRootEnv(projectRoot) {
|
|
|
6758
6834
|
}
|
|
6759
6835
|
async function provisionRuntimeWorktree(config) {
|
|
6760
6836
|
const branch = runtimeBranchName(config.taskId, config.runtimeId);
|
|
6761
|
-
let hasValidWorktree =
|
|
6762
|
-
if (
|
|
6763
|
-
|
|
6837
|
+
let hasValidWorktree = existsSync28(resolve30(config.workspaceDir, ".git")) && (await runGitCommand(config.workspaceDir, ["rev-parse", "--show-toplevel"])).exitCode === 0;
|
|
6838
|
+
if (existsSync28(config.workspaceDir) && !hasValidWorktree) {
|
|
6839
|
+
rmSync10(config.workspaceDir, { recursive: true, force: true });
|
|
6764
6840
|
}
|
|
6765
6841
|
if (!hasValidWorktree) {
|
|
6766
|
-
|
|
6842
|
+
mkdirSync14(dirname12(config.workspaceDir), { recursive: true });
|
|
6767
6843
|
const branchExists = await runGitCommand(config.monorepoRoot, ["show-ref", "--verify", "--quiet", `refs/heads/${branch}`]);
|
|
6768
6844
|
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]);
|
|
6769
6845
|
if (add.exitCode !== 0) {
|
|
@@ -6945,31 +7021,31 @@ async function preferredBaseRemotes(repoRoot) {
|
|
|
6945
7021
|
|
|
6946
7022
|
// packages/runtime/src/control-plane/runtime/isolation/toolchain.ts
|
|
6947
7023
|
import {
|
|
6948
|
-
existsSync as
|
|
7024
|
+
existsSync as existsSync30,
|
|
6949
7025
|
lstatSync,
|
|
6950
|
-
mkdirSync as
|
|
6951
|
-
readdirSync as
|
|
6952
|
-
readFileSync as
|
|
6953
|
-
rmSync as
|
|
7026
|
+
mkdirSync as mkdirSync16,
|
|
7027
|
+
readdirSync as readdirSync6,
|
|
7028
|
+
readFileSync as readFileSync15,
|
|
7029
|
+
rmSync as rmSync11,
|
|
6954
7030
|
statSync as statSync9,
|
|
6955
7031
|
symlinkSync as symlinkSync4
|
|
6956
7032
|
} from "fs";
|
|
6957
7033
|
import { mkdir as mkdir3, writeFile } from "fs/promises";
|
|
6958
|
-
import { dirname as dirname14, resolve as
|
|
7034
|
+
import { dirname as dirname14, resolve as resolve32 } from "path";
|
|
6959
7035
|
|
|
6960
7036
|
// packages/runtime/src/control-plane/runtime/tooling/claude-router-binary.ts
|
|
6961
|
-
import { chmodSync as chmodSync6, copyFileSync as copyFileSync6, existsSync as
|
|
7037
|
+
import { chmodSync as chmodSync6, copyFileSync as copyFileSync6, existsSync as existsSync29, mkdirSync as mkdirSync15, statSync as statSync8 } from "fs";
|
|
6962
7038
|
import { tmpdir as tmpdir6 } from "os";
|
|
6963
|
-
import { dirname as dirname13, resolve as
|
|
6964
|
-
var sharedRouterOutputDir =
|
|
6965
|
-
var sharedRouterOutputPath =
|
|
7039
|
+
import { dirname as dirname13, resolve as resolve31 } from "path";
|
|
7040
|
+
var sharedRouterOutputDir = resolve31(tmpdir6(), "rig-native");
|
|
7041
|
+
var sharedRouterOutputPath = resolve31(sharedRouterOutputDir, `rig-tool-router-${process.platform}-${process.arch}${process.platform === "win32" ? ".exe" : ""}`);
|
|
6966
7042
|
function runtimeClaudeToolRouterFileName() {
|
|
6967
7043
|
return `rig-tool-router${process.platform === "win32" ? ".exe" : ""}`;
|
|
6968
7044
|
}
|
|
6969
7045
|
async function ensureClaudeToolRouterBinaryPath(projectRoot, outputPath = sharedRouterOutputPath) {
|
|
6970
|
-
const sourcePath =
|
|
6971
|
-
|
|
6972
|
-
const needsBuild = !
|
|
7046
|
+
const sourcePath = resolve31(projectRoot, "packages/runtime/src/control-plane/runtime/tooling/claude-router.ts");
|
|
7047
|
+
mkdirSync15(dirname13(outputPath), { recursive: true });
|
|
7048
|
+
const needsBuild = !existsSync29(outputPath) || statSync8(sourcePath).mtimeMs > statSync8(outputPath).mtimeMs;
|
|
6973
7049
|
if (!needsBuild) {
|
|
6974
7050
|
return outputPath;
|
|
6975
7051
|
}
|
|
@@ -6983,9 +7059,9 @@ async function ensureClaudeToolRouterBinaryPath(projectRoot, outputPath = shared
|
|
|
6983
7059
|
}
|
|
6984
7060
|
async function materializeClaudeToolRouterBinary(projectRoot, targetDir) {
|
|
6985
7061
|
const sourcePath = await ensureClaudeToolRouterBinaryPath(projectRoot);
|
|
6986
|
-
const targetPath =
|
|
6987
|
-
|
|
6988
|
-
const needsCopy = !
|
|
7062
|
+
const targetPath = resolve31(targetDir, runtimeClaudeToolRouterFileName());
|
|
7063
|
+
mkdirSync15(targetDir, { recursive: true });
|
|
7064
|
+
const needsCopy = !existsSync29(targetPath) || statSync8(sourcePath).mtimeMs > statSync8(targetPath).mtimeMs;
|
|
6989
7065
|
if (needsCopy) {
|
|
6990
7066
|
copyFileSync6(sourcePath, targetPath);
|
|
6991
7067
|
chmodSync6(targetPath, 493);
|
|
@@ -6998,48 +7074,48 @@ var GIT_INDEX_LOCK_RETRY_DELAY_MS = 250;
|
|
|
6998
7074
|
var GIT_INDEX_LOCK_STALE_AFTER_MS = 5000;
|
|
6999
7075
|
function resolveRigSourceRoot(projectRoot) {
|
|
7000
7076
|
const hostProjectRoot = process.env.RIG_HOST_PROJECT_ROOT?.trim();
|
|
7001
|
-
if (hostProjectRoot &&
|
|
7077
|
+
if (hostProjectRoot && existsSync30(resolve32(hostProjectRoot, "packages/runtime/bin/rig-agent.ts"))) {
|
|
7002
7078
|
return hostProjectRoot;
|
|
7003
7079
|
}
|
|
7004
|
-
const fromModule =
|
|
7005
|
-
if (
|
|
7080
|
+
const fromModule = resolve32(import.meta.dir, "../../../../../..");
|
|
7081
|
+
if (existsSync30(resolve32(fromModule, "packages/runtime/bin/rig-agent.ts"))) {
|
|
7006
7082
|
return fromModule;
|
|
7007
7083
|
}
|
|
7008
7084
|
return projectRoot;
|
|
7009
7085
|
}
|
|
7010
7086
|
function prepareTrackedRuntimePaths(logsDir, stateDir, sessionDir) {
|
|
7011
|
-
for (const path of [logsDir, stateDir, sessionDir,
|
|
7087
|
+
for (const path of [logsDir, stateDir, sessionDir, resolve32(sessionDir, "session.json")]) {
|
|
7012
7088
|
removeSymbolicLink(path);
|
|
7013
7089
|
}
|
|
7014
7090
|
runtimePrepareTrackedPathsNative({
|
|
7015
7091
|
logsDir,
|
|
7016
7092
|
stateDir,
|
|
7017
7093
|
sessionDir,
|
|
7018
|
-
controlledBashLogFile:
|
|
7019
|
-
eventsFile:
|
|
7094
|
+
controlledBashLogFile: resolve32(logsDir, "controlled-bash.jsonl"),
|
|
7095
|
+
eventsFile: resolve32(logsDir, "control-plane.events.jsonl")
|
|
7020
7096
|
});
|
|
7021
7097
|
}
|
|
7022
7098
|
async function initializeRuntimeStateFiles(stateDir, sessionDir, taskId) {
|
|
7023
7099
|
await mkdir3(stateDir, { recursive: true });
|
|
7024
7100
|
await mkdir3(sessionDir, { recursive: true });
|
|
7025
|
-
const failedApproachesPath =
|
|
7026
|
-
if (!
|
|
7101
|
+
const failedApproachesPath = resolve32(stateDir, "failed_approaches.md");
|
|
7102
|
+
if (!existsSync30(failedApproachesPath)) {
|
|
7027
7103
|
await writeFile(failedApproachesPath, `# Failed Approaches
|
|
7028
7104
|
|
|
7029
7105
|
`);
|
|
7030
7106
|
}
|
|
7031
|
-
const hookTripsPath =
|
|
7032
|
-
if (!
|
|
7107
|
+
const hookTripsPath = resolve32(stateDir, "hook_trips.log");
|
|
7108
|
+
if (!existsSync30(hookTripsPath)) {
|
|
7033
7109
|
await writeFile(hookTripsPath, "");
|
|
7034
7110
|
}
|
|
7035
|
-
const sessionFile =
|
|
7111
|
+
const sessionFile = resolve32(sessionDir, "session.json");
|
|
7036
7112
|
if (taskId) {
|
|
7037
7113
|
await writeFile(sessionFile, JSON.stringify({ activeTaskIds: [taskId] }));
|
|
7038
7114
|
}
|
|
7039
7115
|
}
|
|
7040
7116
|
async function resetEphemeralTaskArtifacts(workspaceDir, taskId) {
|
|
7041
|
-
const artifactDir =
|
|
7042
|
-
const runtimeSnapshotDir =
|
|
7117
|
+
const artifactDir = resolve32(workspaceDir, "artifacts", taskId);
|
|
7118
|
+
const runtimeSnapshotDir = resolve32(artifactDir, "runtime-snapshots");
|
|
7043
7119
|
let preservedTrackedFiles = false;
|
|
7044
7120
|
for (const file of [
|
|
7045
7121
|
"changed-files.txt",
|
|
@@ -7055,13 +7131,13 @@ async function resetEphemeralTaskArtifacts(workspaceDir, taskId) {
|
|
|
7055
7131
|
preservedTrackedFiles = true;
|
|
7056
7132
|
continue;
|
|
7057
7133
|
}
|
|
7058
|
-
|
|
7134
|
+
rmSync11(resolve32(artifactDir, file), { force: true });
|
|
7059
7135
|
}
|
|
7060
7136
|
const runtimeSnapshotRelativePath = `artifacts/${taskId}/runtime-snapshots`;
|
|
7061
7137
|
if (await resetTrackedArtifactPath(workspaceDir, runtimeSnapshotRelativePath)) {
|
|
7062
7138
|
preservedTrackedFiles = true;
|
|
7063
7139
|
} else {
|
|
7064
|
-
|
|
7140
|
+
rmSync11(runtimeSnapshotDir, { recursive: true, force: true });
|
|
7065
7141
|
}
|
|
7066
7142
|
if (preservedTrackedFiles) {
|
|
7067
7143
|
console.log(`[rig-agent] Preserved tracked runtime artifact files in ${taskId}; skipped ephemeral cleanup for committed paths.`);
|
|
@@ -7094,28 +7170,28 @@ async function buildRuntimeToolchain(options) {
|
|
|
7094
7170
|
throw new Error("Failed to provision the native Zig runtime library.");
|
|
7095
7171
|
}
|
|
7096
7172
|
const rigSourceRoot = resolveRigSourceRoot(options.projectRoot);
|
|
7097
|
-
await buildBinary("packages/cli/bin/rig.ts",
|
|
7098
|
-
await buildBinary("packages/runtime/bin/rig-agent.ts",
|
|
7173
|
+
await buildBinary("packages/cli/bin/rig.ts", resolve32(options.binDir, "rig"), rigSourceRoot);
|
|
7174
|
+
await buildBinary("packages/runtime/bin/rig-agent.ts", resolve32(options.binDir, "rig-agent"), rigSourceRoot, {
|
|
7099
7175
|
...options.runtimeSecretDefines,
|
|
7100
7176
|
AGENT_TASK_ID: options.taskId,
|
|
7101
7177
|
AGENT_PROJECT_ROOT: options.projectRoot,
|
|
7102
7178
|
AGENT_RUNTIME_ID: options.runtimeId,
|
|
7103
7179
|
AGENT_SCOPE_HASH: options.bakedScopeHash,
|
|
7104
7180
|
AGENT_MANIFEST_PATH: options.manifestPath,
|
|
7105
|
-
AGENT_BINARY_PATH:
|
|
7181
|
+
AGENT_BINARY_PATH: resolve32(options.binDir, "rig-agent"),
|
|
7106
7182
|
AGENT_INFO_OUTPUT: options.bakedInfoOutput,
|
|
7107
7183
|
AGENT_DEPS_OUTPUT: options.bakedDepsOutput,
|
|
7108
7184
|
AGENT_STATUS_OUTPUT: options.bakedStatusOutput
|
|
7109
7185
|
});
|
|
7110
|
-
await buildBinary("packages/runtime/src/control-plane/controlled-bash.ts",
|
|
7186
|
+
await buildBinary("packages/runtime/src/control-plane/controlled-bash.ts", resolve32(options.binDir, "controlled-bash"), rigSourceRoot, {
|
|
7111
7187
|
AGENT_PROJECT_ROOT: options.projectRoot,
|
|
7112
7188
|
AGENT_LOGS_DIR: options.logsDir,
|
|
7113
7189
|
AGENT_MONOREPO_ROOT: resolveMonorepoRoot3(options.projectRoot),
|
|
7114
|
-
AGENT_TS_API_TESTS_DIR:
|
|
7115
|
-
AGENT_RIG_AGENT_BIN:
|
|
7190
|
+
AGENT_TS_API_TESTS_DIR: resolve32(options.workspaceDir, "TSAPITests"),
|
|
7191
|
+
AGENT_RIG_AGENT_BIN: resolve32(options.binDir, "rig-agent")
|
|
7116
7192
|
});
|
|
7117
|
-
await buildBinary("packages/runtime/bin/rig-browser-tool.ts",
|
|
7118
|
-
await buildBinary("packages/runtime/src/control-plane/runtime/snapshot/sidecar.ts",
|
|
7193
|
+
await buildBinary("packages/runtime/bin/rig-browser-tool.ts", resolve32(options.binDir, runtimeBrowserToolBinaryName()), rigSourceRoot);
|
|
7194
|
+
await buildBinary("packages/runtime/src/control-plane/runtime/snapshot/sidecar.ts", resolve32(options.binDir, "snapshot-sidecar"), rigSourceRoot, {
|
|
7119
7195
|
AGENT_PROJECT_ROOT: options.projectRoot,
|
|
7120
7196
|
AGENT_BUN_PATH: resolveBunBinaryPath()
|
|
7121
7197
|
});
|
|
@@ -7124,15 +7200,15 @@ async function buildRuntimeToolchain(options) {
|
|
|
7124
7200
|
AGENT_BUN_PATH: resolveBunBinaryPath()
|
|
7125
7201
|
};
|
|
7126
7202
|
for (const hookName of hookNames) {
|
|
7127
|
-
await buildBinary(`packages/runtime/src/control-plane/hooks/${hookName}.ts`,
|
|
7203
|
+
await buildBinary(`packages/runtime/src/control-plane/hooks/${hookName}.ts`, resolve32(runtimeBins.hooksDir, hookName), rigSourceRoot, hookDefines);
|
|
7128
7204
|
}
|
|
7129
|
-
const pluginsDir =
|
|
7130
|
-
if (
|
|
7131
|
-
for (const entry of
|
|
7205
|
+
const pluginsDir = resolve32(options.projectRoot, "rig/plugins");
|
|
7206
|
+
if (existsSync30(pluginsDir)) {
|
|
7207
|
+
for (const entry of readdirSync6(pluginsDir, { withFileTypes: true })) {
|
|
7132
7208
|
const match = entry.name.match(/^(.+)\.plugin\.(ts|js|mjs|cjs)$/);
|
|
7133
7209
|
if (!match)
|
|
7134
7210
|
continue;
|
|
7135
|
-
await buildBinary(`rig/plugins/${entry.name}`,
|
|
7211
|
+
await buildBinary(`rig/plugins/${entry.name}`, resolve32(runtimeBins.pluginsDir, match[1]), options.projectRoot);
|
|
7136
7212
|
}
|
|
7137
7213
|
}
|
|
7138
7214
|
await materializeRigGitBinary(options.binDir);
|
|
@@ -7142,8 +7218,8 @@ async function buildRuntimeToolchain(options) {
|
|
|
7142
7218
|
}
|
|
7143
7219
|
async function writeRuntimeManifest(config) {
|
|
7144
7220
|
const scopeHash = sha256Hex(JSON.stringify(config.scopes));
|
|
7145
|
-
const binarySha256 = sha256Hex(
|
|
7146
|
-
const manifestPath =
|
|
7221
|
+
const binarySha256 = sha256Hex(readFileSync15(config.binaryPath));
|
|
7222
|
+
const manifestPath = resolve32(config.runtimeRoot, "manifest.json");
|
|
7147
7223
|
const manifest = {
|
|
7148
7224
|
runtimeId: config.runtimeId,
|
|
7149
7225
|
taskId: config.taskId,
|
|
@@ -7177,7 +7253,7 @@ function removeSymbolicLink(path) {
|
|
|
7177
7253
|
} catch {
|
|
7178
7254
|
return;
|
|
7179
7255
|
}
|
|
7180
|
-
|
|
7256
|
+
rmSync11(path, { force: true, recursive: true });
|
|
7181
7257
|
}
|
|
7182
7258
|
async function resetTrackedArtifactPath(workspaceDir, relativePath) {
|
|
7183
7259
|
const tracked = await runGitLsFiles(workspaceDir, relativePath);
|
|
@@ -7203,7 +7279,7 @@ async function restoreTrackedArtifactPathWithRetry(workspaceDir, relativePath, r
|
|
|
7203
7279
|
const retryDelayMs = options.retryDelayMs ?? GIT_INDEX_LOCK_RETRY_DELAY_MS;
|
|
7204
7280
|
const now = options.now ?? Date.now;
|
|
7205
7281
|
const statMtimeMs = options.statMtimeMs ?? readFileMtimeMs;
|
|
7206
|
-
const removeFile = options.removeFile ?? ((path) =>
|
|
7282
|
+
const removeFile = options.removeFile ?? ((path) => rmSync11(path, { force: true }));
|
|
7207
7283
|
const log = options.log ?? console.warn;
|
|
7208
7284
|
let lastOutput = "";
|
|
7209
7285
|
for (let attempt = 0;attempt <= maxRetries; attempt += 1) {
|
|
@@ -7263,31 +7339,31 @@ function readFileMtimeMs(path) {
|
|
|
7263
7339
|
}
|
|
7264
7340
|
function linkRuntimeDependencyLayers(monorepoRoot, workspaceDir) {
|
|
7265
7341
|
linkGenericNodeModulesLayers(monorepoRoot, workspaceDir);
|
|
7266
|
-
const sourceNodeModules =
|
|
7267
|
-
if (!
|
|
7268
|
-
const runtimeHumoongate =
|
|
7269
|
-
if (
|
|
7270
|
-
const targetNodeModules =
|
|
7342
|
+
const sourceNodeModules = resolve32(monorepoRoot, "humoongate", "node_modules");
|
|
7343
|
+
if (!existsSync30(sourceNodeModules)) {} else {
|
|
7344
|
+
const runtimeHumoongate = resolve32(workspaceDir, "humoongate");
|
|
7345
|
+
if (existsSync30(resolve32(runtimeHumoongate, "package.json"))) {
|
|
7346
|
+
const targetNodeModules = resolve32(runtimeHumoongate, "node_modules");
|
|
7271
7347
|
runtimeLinkDependencyLayerNative(sourceNodeModules, targetNodeModules);
|
|
7272
7348
|
}
|
|
7273
7349
|
}
|
|
7274
|
-
const runtimeHpNext =
|
|
7275
|
-
if (!
|
|
7350
|
+
const runtimeHpNext = resolve32(workspaceDir, "microservices", "hp-next-frontend", "app");
|
|
7351
|
+
if (!existsSync30(resolve32(runtimeHpNext, "package.json"))) {
|
|
7276
7352
|
return;
|
|
7277
7353
|
}
|
|
7278
|
-
const sourceHpNextNodeModules =
|
|
7279
|
-
const sourceMonorepoNodeModules =
|
|
7280
|
-
const targetHpNextNodeModules =
|
|
7281
|
-
if (
|
|
7354
|
+
const sourceHpNextNodeModules = resolve32(monorepoRoot, "microservices", "hp-next-frontend", "app", "node_modules");
|
|
7355
|
+
const sourceMonorepoNodeModules = resolve32(monorepoRoot, "node_modules");
|
|
7356
|
+
const targetHpNextNodeModules = resolve32(runtimeHpNext, "node_modules");
|
|
7357
|
+
if (existsSync30(sourceHpNextNodeModules)) {
|
|
7282
7358
|
runtimeLinkDependencyLayerNative(sourceHpNextNodeModules, targetHpNextNodeModules);
|
|
7283
7359
|
return;
|
|
7284
7360
|
}
|
|
7285
|
-
if (
|
|
7361
|
+
if (existsSync30(sourceMonorepoNodeModules)) {
|
|
7286
7362
|
runtimeLinkDependencyLayerNative(sourceMonorepoNodeModules, targetHpNextNodeModules);
|
|
7287
7363
|
}
|
|
7288
7364
|
}
|
|
7289
7365
|
function linkGenericNodeModulesLayers(monorepoRoot, workspaceDir) {
|
|
7290
|
-
linkNodeModulesLayer(
|
|
7366
|
+
linkNodeModulesLayer(resolve32(monorepoRoot, "node_modules"), resolve32(workspaceDir, "node_modules"));
|
|
7291
7367
|
for (const relativePackageDir of [
|
|
7292
7368
|
"apps/native-app/apps/marketing",
|
|
7293
7369
|
"apps/native-app/apps/web",
|
|
@@ -7309,15 +7385,15 @@ function linkGenericNodeModulesLayers(monorepoRoot, workspaceDir) {
|
|
|
7309
7385
|
"packages/standard-plugin",
|
|
7310
7386
|
"packages/validator-kit"
|
|
7311
7387
|
]) {
|
|
7312
|
-
const workspacePackageDir =
|
|
7313
|
-
if (!
|
|
7388
|
+
const workspacePackageDir = resolve32(workspaceDir, relativePackageDir);
|
|
7389
|
+
if (!existsSync30(resolve32(workspacePackageDir, "package.json"))) {
|
|
7314
7390
|
continue;
|
|
7315
7391
|
}
|
|
7316
|
-
linkNodeModulesLayer(
|
|
7392
|
+
linkNodeModulesLayer(resolve32(monorepoRoot, relativePackageDir, "node_modules"), resolve32(workspacePackageDir, "node_modules"));
|
|
7317
7393
|
}
|
|
7318
7394
|
}
|
|
7319
7395
|
function linkNodeModulesLayer(sourceDir, targetDir) {
|
|
7320
|
-
if (!
|
|
7396
|
+
if (!existsSync30(sourceDir) || existsSync30(targetDir)) {
|
|
7321
7397
|
return;
|
|
7322
7398
|
}
|
|
7323
7399
|
try {
|
|
@@ -7326,16 +7402,16 @@ function linkNodeModulesLayer(sourceDir, targetDir) {
|
|
|
7326
7402
|
} catch (error) {
|
|
7327
7403
|
console.warn(`[rig-agent] Native dependency-layer linking failed for ${targetDir}; using symlink fallback: ${error instanceof Error ? error.message : String(error)}`);
|
|
7328
7404
|
}
|
|
7329
|
-
|
|
7405
|
+
mkdirSync16(dirname14(targetDir), { recursive: true });
|
|
7330
7406
|
symlinkSync4(sourceDir, targetDir, "dir");
|
|
7331
7407
|
}
|
|
7332
7408
|
function ensureRuntimeBinTrees(runtimeBinDir) {
|
|
7333
|
-
const hooksDir =
|
|
7334
|
-
const pluginsDir =
|
|
7335
|
-
const validatorsDir =
|
|
7336
|
-
|
|
7337
|
-
|
|
7338
|
-
|
|
7409
|
+
const hooksDir = resolve32(runtimeBinDir, "hooks");
|
|
7410
|
+
const pluginsDir = resolve32(runtimeBinDir, "plugins");
|
|
7411
|
+
const validatorsDir = resolve32(runtimeBinDir, "validators");
|
|
7412
|
+
mkdirSync16(hooksDir, { recursive: true });
|
|
7413
|
+
mkdirSync16(pluginsDir, { recursive: true });
|
|
7414
|
+
mkdirSync16(validatorsDir, { recursive: true });
|
|
7339
7415
|
return { hooksDir, pluginsDir, validatorsDir };
|
|
7340
7416
|
}
|
|
7341
7417
|
|
|
@@ -7346,17 +7422,17 @@ function runtimeRootForCleanup(projectRoot, runtimeId) {
|
|
|
7346
7422
|
monorepoRoot = resolveMonorepoRoot3(projectRoot);
|
|
7347
7423
|
} catch {}
|
|
7348
7424
|
const workspaceRootCandidate = monorepoRoot ?? projectRoot;
|
|
7349
|
-
const initialWorkspaceDir =
|
|
7425
|
+
const initialWorkspaceDir = resolve33(workspaceRootCandidate, ".worktrees", runtimeWorktreeNameFromRuntimeId(runtimeId));
|
|
7350
7426
|
const runtimeRoot = resolveRuntimeWorkspaceLayout(initialWorkspaceDir).runtimeDir;
|
|
7351
7427
|
return { monorepoRoot, initialWorkspaceDir, runtimeRoot };
|
|
7352
7428
|
}
|
|
7353
7429
|
|
|
7354
7430
|
// packages/runtime/src/control-plane/runtime/isolation/runner.ts
|
|
7355
|
-
import { existsSync as
|
|
7356
|
-
import { basename as basename9, resolve as
|
|
7431
|
+
import { existsSync as existsSync32, rmSync as rmSync12, writeFileSync as writeFileSync13 } from "fs";
|
|
7432
|
+
import { basename as basename9, resolve as resolve36 } from "path";
|
|
7357
7433
|
|
|
7358
7434
|
// packages/runtime/src/control-plane/runtime/sandbox/backend.ts
|
|
7359
|
-
import { existsSync as
|
|
7435
|
+
import { existsSync as existsSync31 } from "fs";
|
|
7360
7436
|
init_utils();
|
|
7361
7437
|
|
|
7362
7438
|
// packages/runtime/src/control-plane/runtime/sandbox/backend-none.ts
|
|
@@ -7456,13 +7532,13 @@ async function resolveBackend(projectRoot, options) {
|
|
|
7456
7532
|
depRoots
|
|
7457
7533
|
};
|
|
7458
7534
|
const fsContext = {
|
|
7459
|
-
pathExists: (p) =>
|
|
7535
|
+
pathExists: (p) => existsSync31(p),
|
|
7460
7536
|
realPath: toRealPath
|
|
7461
7537
|
};
|
|
7462
7538
|
if (process.platform === "darwin" && (!requestedBackend || requestedBackend === "macos-seatbelt")) {
|
|
7463
7539
|
const seatbelt = Bun.which("sandbox-exec");
|
|
7464
7540
|
probed.push("sandbox-exec");
|
|
7465
|
-
if (seatbelt &&
|
|
7541
|
+
if (seatbelt && existsSync31(seatbelt)) {
|
|
7466
7542
|
const SeatbeltBackendClass = loadSeatbeltBackend();
|
|
7467
7543
|
if (SeatbeltBackendClass) {
|
|
7468
7544
|
return {
|
|
@@ -7583,10 +7659,10 @@ init_layout();
|
|
|
7583
7659
|
var SNAPSHOT_SIDECAR_READY_TIMEOUT_MS = 1e4;
|
|
7584
7660
|
async function startRuntimeSnapshotSidecar(runtime, options = {}) {
|
|
7585
7661
|
const instanceId = sanitizeRuntimeRefSegment(options.instanceId?.trim() || runtime.id);
|
|
7586
|
-
const readyFile =
|
|
7587
|
-
const requestFile =
|
|
7588
|
-
|
|
7589
|
-
|
|
7662
|
+
const readyFile = resolve36(runtime.stateDir, `runtime-snapshot-sidecar-${instanceId}.ready`);
|
|
7663
|
+
const requestFile = resolve36(runtime.stateDir, `runtime-snapshot-sidecar-${instanceId}.request.json`);
|
|
7664
|
+
rmSync12(readyFile, { force: true });
|
|
7665
|
+
rmSync12(requestFile, { force: true });
|
|
7590
7666
|
const sidecarBinary = resolveSnapshotSidecarBinaryPath(runtime.binDir);
|
|
7591
7667
|
const useCompiledSidecar = shouldUseCompiledSnapshotSidecar(sidecarBinary);
|
|
7592
7668
|
const bunCli = useCompiledSidecar ? null : resolveBunCliInvocation();
|
|
@@ -7624,19 +7700,19 @@ async function startRuntimeSnapshotSidecar(runtime, options = {}) {
|
|
|
7624
7700
|
proc.kill("SIGTERM");
|
|
7625
7701
|
} catch {}
|
|
7626
7702
|
await proc.exited;
|
|
7627
|
-
|
|
7628
|
-
|
|
7703
|
+
rmSync12(readyFile, { force: true });
|
|
7704
|
+
rmSync12(requestFile, { force: true });
|
|
7629
7705
|
},
|
|
7630
7706
|
finalize: async (commandParts, exitCode) => {
|
|
7631
|
-
|
|
7707
|
+
writeFileSync13(requestFile, `${JSON.stringify({ command: commandParts, exitCode })}
|
|
7632
7708
|
`, "utf-8");
|
|
7633
7709
|
const [sidecarExitCode, stdout, stderr] = await Promise.all([
|
|
7634
7710
|
proc.exited,
|
|
7635
7711
|
stdoutTextPromise,
|
|
7636
7712
|
stderrTextPromise
|
|
7637
7713
|
]);
|
|
7638
|
-
|
|
7639
|
-
|
|
7714
|
+
rmSync12(readyFile, { force: true });
|
|
7715
|
+
rmSync12(requestFile, { force: true });
|
|
7640
7716
|
if (sidecarExitCode !== 0) {
|
|
7641
7717
|
throw new Error(`snapshot sidecar failed (${sidecarExitCode}): ${stderr || stdout}`);
|
|
7642
7718
|
}
|
|
@@ -7692,8 +7768,8 @@ async function runInAgentRuntime(options) {
|
|
|
7692
7768
|
const stdout = await new Response(proc.stdout).text();
|
|
7693
7769
|
const stderr = await new Response(proc.stderr).text();
|
|
7694
7770
|
try {
|
|
7695
|
-
await Bun.write(
|
|
7696
|
-
await Bun.write(
|
|
7771
|
+
await Bun.write(resolve36(options.runtime.logsDir, "agent-stdout.log"), stdout);
|
|
7772
|
+
await Bun.write(resolve36(options.runtime.logsDir, "agent-stderr.log"), stderr);
|
|
7697
7773
|
} catch {}
|
|
7698
7774
|
await snapshotSidecar.finalize(runtimeCommand, exitCode);
|
|
7699
7775
|
return {
|
|
@@ -7723,18 +7799,18 @@ function resolveInternalRuntimeCommand(command) {
|
|
|
7723
7799
|
}
|
|
7724
7800
|
async function cleanupAgentRuntime(options) {
|
|
7725
7801
|
const { monorepoRoot, initialWorkspaceDir, runtimeRoot } = runtimeRootForCleanup(options.projectRoot, options.id);
|
|
7726
|
-
const metadataPath =
|
|
7727
|
-
if (!
|
|
7802
|
+
const metadataPath = resolve36(runtimeRoot, "runtime.json");
|
|
7803
|
+
if (!existsSync32(runtimeRoot)) {
|
|
7728
7804
|
return;
|
|
7729
7805
|
}
|
|
7730
7806
|
let mode = "worktree";
|
|
7731
7807
|
let workspaceDir = "";
|
|
7732
7808
|
const metadata = await readRuntimeMetadata(metadataPath);
|
|
7733
|
-
const metadataMatchesRequestedRuntime = metadata !== null && metadata.id === options.id &&
|
|
7809
|
+
const metadataMatchesRequestedRuntime = metadata !== null && metadata.id === options.id && resolve36(metadata.workspaceDir) === resolve36(initialWorkspaceDir);
|
|
7734
7810
|
if (metadata && metadataMatchesRequestedRuntime) {
|
|
7735
7811
|
mode = metadata.mode;
|
|
7736
7812
|
workspaceDir = metadata.workspaceDir;
|
|
7737
|
-
} else if (
|
|
7813
|
+
} else if (existsSync32(initialWorkspaceDir)) {
|
|
7738
7814
|
workspaceDir = initialWorkspaceDir;
|
|
7739
7815
|
}
|
|
7740
7816
|
const preservesTaskWorktree = metadataMatchesRequestedRuntime && metadata ? options.id === taskRuntimeId(metadata.taskId) : false;
|
|
@@ -7743,7 +7819,7 @@ async function cleanupAgentRuntime(options) {
|
|
|
7743
7819
|
} else if (mode === "worktree" && workspaceDir && preservesTaskWorktree) {
|
|
7744
7820
|
cleanupTaskRuntimeOverlay(workspaceDir);
|
|
7745
7821
|
}
|
|
7746
|
-
|
|
7822
|
+
rmSync12(runtimeRoot, { recursive: true, force: true });
|
|
7747
7823
|
}
|
|
7748
7824
|
function cleanupTaskRuntimeOverlay(workspaceDir) {
|
|
7749
7825
|
const layout = resolveRuntimeWorkspaceLayout(workspaceDir);
|
|
@@ -7759,17 +7835,17 @@ function cleanupTaskRuntimeOverlay(workspaceDir) {
|
|
|
7759
7835
|
layout.runtimeDir,
|
|
7760
7836
|
layout.contextPath
|
|
7761
7837
|
]) {
|
|
7762
|
-
|
|
7838
|
+
rmSync12(path, { recursive: true, force: true });
|
|
7763
7839
|
}
|
|
7764
7840
|
}
|
|
7765
7841
|
function resolveSnapshotSidecarScriptPath() {
|
|
7766
7842
|
return resolveRuntimeSourceScriptPath("snapshot-sidecar.ts");
|
|
7767
7843
|
}
|
|
7768
7844
|
function resolveSnapshotSidecarBinaryPath(binDir) {
|
|
7769
|
-
return
|
|
7845
|
+
return resolve36(binDir, "snapshot-sidecar");
|
|
7770
7846
|
}
|
|
7771
7847
|
function shouldUseCompiledSnapshotSidecar(binaryPath) {
|
|
7772
|
-
if (!
|
|
7848
|
+
if (!existsSync32(binaryPath)) {
|
|
7773
7849
|
return false;
|
|
7774
7850
|
}
|
|
7775
7851
|
const preference = process.env.RIG_USE_COMPILED_SNAPSHOT_SIDECAR?.trim().toLowerCase();
|
|
@@ -7784,12 +7860,12 @@ function resolveRuntimeSourceScriptPath(fileName) {
|
|
|
7784
7860
|
process.env.PROJECT_RIG_ROOT?.trim()
|
|
7785
7861
|
].filter((value) => Boolean(value));
|
|
7786
7862
|
for (const root of hostRoots) {
|
|
7787
|
-
const candidate =
|
|
7788
|
-
if (
|
|
7863
|
+
const candidate = resolve36(root, "packages/runtime/src/control-plane/runtime", fileName);
|
|
7864
|
+
if (existsSync32(candidate)) {
|
|
7789
7865
|
return candidate;
|
|
7790
7866
|
}
|
|
7791
7867
|
}
|
|
7792
|
-
return
|
|
7868
|
+
return resolve36(import.meta.dir, "..", fileName);
|
|
7793
7869
|
}
|
|
7794
7870
|
function resolveBunCliInvocation() {
|
|
7795
7871
|
if (process.env.RIG_BUN_PATH?.trim()) {
|
|
@@ -7816,7 +7892,7 @@ function resolveBunCliInvocation() {
|
|
|
7816
7892
|
async function waitForSnapshotSidecarReady(readyFile, proc, stdoutTextPromise, stderrTextPromise) {
|
|
7817
7893
|
const deadline = Date.now() + SNAPSHOT_SIDECAR_READY_TIMEOUT_MS;
|
|
7818
7894
|
while (Date.now() < deadline) {
|
|
7819
|
-
if (
|
|
7895
|
+
if (existsSync32(readyFile)) {
|
|
7820
7896
|
return;
|
|
7821
7897
|
}
|
|
7822
7898
|
const exitCode = proc.exitCode;
|
|
@@ -7829,7 +7905,7 @@ async function waitForSnapshotSidecarReady(readyFile, proc, stdoutTextPromise, s
|
|
|
7829
7905
|
throw new Error(`snapshot sidecar did not become ready within ${SNAPSHOT_SIDECAR_READY_TIMEOUT_MS}ms`);
|
|
7830
7906
|
}
|
|
7831
7907
|
async function readRuntimeMetadata(metadataPath) {
|
|
7832
|
-
if (!
|
|
7908
|
+
if (!existsSync32(metadataPath)) {
|
|
7833
7909
|
return null;
|
|
7834
7910
|
}
|
|
7835
7911
|
try {
|
|
@@ -7844,9 +7920,9 @@ var CANONICAL_MEMORY_DB_PATH2 = "rig/memory/project-memory.db";
|
|
|
7844
7920
|
async function hydrateRuntimeMemory(options) {
|
|
7845
7921
|
const snapshot = await readCanonicalMemoryDb(options.projectRoot);
|
|
7846
7922
|
const workspaceLayout = resolveRuntimeWorkspaceLayout(options.workspaceDir);
|
|
7847
|
-
const hydratedPath =
|
|
7923
|
+
const hydratedPath = resolve37(workspaceLayout.stateDir, "memory", "project-memory.db");
|
|
7848
7924
|
try {
|
|
7849
|
-
await mkdir4(
|
|
7925
|
+
await mkdir4(resolve37(workspaceLayout.stateDir, "memory"), { recursive: true });
|
|
7850
7926
|
await copyFile(snapshot.dbPath, hydratedPath);
|
|
7851
7927
|
return {
|
|
7852
7928
|
canonicalPath: CANONICAL_MEMORY_DB_PATH2,
|
|
@@ -7861,12 +7937,12 @@ async function hydrateRuntimeMemory(options) {
|
|
|
7861
7937
|
}
|
|
7862
7938
|
}
|
|
7863
7939
|
async function createRuntimeTaskRecordReader(options) {
|
|
7864
|
-
const legacyConfigPath =
|
|
7940
|
+
const legacyConfigPath = resolve37(options.projectRoot, ".rig", "task-config.json");
|
|
7865
7941
|
let pluginHostContext = null;
|
|
7866
7942
|
try {
|
|
7867
7943
|
pluginHostContext = await buildPluginHostContext(options.projectRoot);
|
|
7868
7944
|
} catch (error) {
|
|
7869
|
-
if (!
|
|
7945
|
+
if (!existsSync33(legacyConfigPath)) {
|
|
7870
7946
|
throw error;
|
|
7871
7947
|
}
|
|
7872
7948
|
const message = `Plugin task source unavailable; using source-aware .rig/task-config.json compatibility path: ${error instanceof Error ? error.message : String(error)}`;
|
|
@@ -7886,7 +7962,7 @@ async function createRuntimeTaskRecordReader(options) {
|
|
|
7886
7962
|
source: "plugin"
|
|
7887
7963
|
};
|
|
7888
7964
|
}
|
|
7889
|
-
if (
|
|
7965
|
+
if (existsSync33(legacyConfigPath)) {
|
|
7890
7966
|
const message = "Using source-aware .rig/task-config.json task source compatibility path";
|
|
7891
7967
|
options.diagnostics?.(message);
|
|
7892
7968
|
console.warn(message);
|
|
@@ -7903,10 +7979,10 @@ async function createRuntimeTaskRecordReader(options) {
|
|
|
7903
7979
|
};
|
|
7904
7980
|
}
|
|
7905
7981
|
function readConfiguredTaskSourceKindHint(projectRoot) {
|
|
7906
|
-
const jsonPath =
|
|
7907
|
-
if (
|
|
7982
|
+
const jsonPath = resolve37(projectRoot, "rig.config.json");
|
|
7983
|
+
if (existsSync33(jsonPath)) {
|
|
7908
7984
|
try {
|
|
7909
|
-
const parsed = JSON.parse(
|
|
7985
|
+
const parsed = JSON.parse(readFileSync16(jsonPath, "utf8"));
|
|
7910
7986
|
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
7911
7987
|
const taskSource = parsed.taskSource;
|
|
7912
7988
|
if (taskSource && typeof taskSource === "object" && !Array.isArray(taskSource)) {
|
|
@@ -7918,12 +7994,12 @@ function readConfiguredTaskSourceKindHint(projectRoot) {
|
|
|
7918
7994
|
return null;
|
|
7919
7995
|
}
|
|
7920
7996
|
}
|
|
7921
|
-
const tsPath =
|
|
7922
|
-
if (!
|
|
7997
|
+
const tsPath = resolve37(projectRoot, "rig.config.ts");
|
|
7998
|
+
if (!existsSync33(tsPath)) {
|
|
7923
7999
|
return null;
|
|
7924
8000
|
}
|
|
7925
8001
|
try {
|
|
7926
|
-
const source =
|
|
8002
|
+
const source = readFileSync16(tsPath, "utf8");
|
|
7927
8003
|
const taskSourceBlock = source.match(/taskSource\s*:\s*\{[\s\S]*?\}/m)?.[0] ?? "";
|
|
7928
8004
|
const kind = taskSourceBlock.match(/kind\s*:\s*["']([^"']+)["']/)?.[1];
|
|
7929
8005
|
return kind ?? null;
|
|
@@ -7993,8 +8069,8 @@ async function writeRuntimeTaskConfigProjection(options) {
|
|
|
7993
8069
|
...options.taskEntry.validation && options.taskEntry.validation.length > 0 ? { validation: options.taskEntry.validation } : {},
|
|
7994
8070
|
...options.taskEntry.browser ? { browser: options.taskEntry.browser } : {}
|
|
7995
8071
|
};
|
|
7996
|
-
const configPath =
|
|
7997
|
-
await mkdir4(
|
|
8072
|
+
const configPath = resolve37(options.workspaceDir, ".rig", "task-config.json");
|
|
8073
|
+
await mkdir4(resolve37(options.workspaceDir, ".rig"), { recursive: true });
|
|
7998
8074
|
await writeFile2(configPath, `${JSON.stringify({ [options.task.id]: entry }, null, 2)}
|
|
7999
8075
|
`, "utf-8");
|
|
8000
8076
|
}
|
|
@@ -8058,9 +8134,9 @@ async function ensureAgentRuntime(options) {
|
|
|
8058
8134
|
}
|
|
8059
8135
|
ensureProvisioningHostProjectRootEnv(options.projectRoot);
|
|
8060
8136
|
const monorepoRoot = resolveMonorepoRoot3(options.projectRoot);
|
|
8061
|
-
const workspaceDir =
|
|
8137
|
+
const workspaceDir = resolve37(monorepoRoot, ".worktrees", runtimeWorktreeName(options.taskId, options.id));
|
|
8062
8138
|
const createdAt = new Date().toISOString();
|
|
8063
|
-
if (!
|
|
8139
|
+
if (!existsSync33(resolve37(monorepoRoot, ".git"))) {
|
|
8064
8140
|
throw new Error(`Monorepo root is not a git checkout: ${monorepoRoot}`);
|
|
8065
8141
|
}
|
|
8066
8142
|
const taskResolution = await resolveRuntimeTaskRecord({
|
|
@@ -8095,7 +8171,7 @@ async function ensureAgentRuntime(options) {
|
|
|
8095
8171
|
logsDir: overlay.logsDir,
|
|
8096
8172
|
stateDir: overlay.stateDir,
|
|
8097
8173
|
sessionDir: overlay.sessionDir,
|
|
8098
|
-
claudeHomeDir:
|
|
8174
|
+
claudeHomeDir: resolve37(workspaceLayout.homeDir, ".claude"),
|
|
8099
8175
|
contextFile: overlay.contextPath,
|
|
8100
8176
|
binDir: workspaceLayout.binDir,
|
|
8101
8177
|
createdAt
|
|
@@ -8108,10 +8184,14 @@ async function ensureAgentRuntime(options) {
|
|
|
8108
8184
|
projectRoot: options.projectRoot,
|
|
8109
8185
|
workspaceDir
|
|
8110
8186
|
});
|
|
8111
|
-
|
|
8112
|
-
|
|
8187
|
+
mkdirSync19(runtime.binDir, { recursive: true });
|
|
8188
|
+
mkdirSync19(workspaceLayout.distDir, { recursive: true });
|
|
8113
8189
|
prepareRuntimeWorkspace(options.projectRoot, workspaceDir);
|
|
8114
|
-
|
|
8190
|
+
if (options.preserveTaskArtifacts) {
|
|
8191
|
+
console.log(`[rig-agent] Preserving runtime task artifacts for resume of ${options.taskId}.`);
|
|
8192
|
+
} else {
|
|
8193
|
+
await resetEphemeralTaskArtifacts(workspaceDir, options.taskId);
|
|
8194
|
+
}
|
|
8115
8195
|
const ctx = {
|
|
8116
8196
|
runtimeId: options.id,
|
|
8117
8197
|
taskId: options.taskId,
|
|
@@ -8124,7 +8204,7 @@ async function ensureAgentRuntime(options) {
|
|
|
8124
8204
|
runtimeId: options.id
|
|
8125
8205
|
}),
|
|
8126
8206
|
workspaceDir,
|
|
8127
|
-
artifactRoot:
|
|
8207
|
+
artifactRoot: resolve37(workspaceDir, "artifacts", options.taskId),
|
|
8128
8208
|
hostProjectRoot: options.projectRoot,
|
|
8129
8209
|
monorepoMainRoot: monorepoRoot,
|
|
8130
8210
|
monorepoBaseRef: baseRef,
|
|
@@ -8140,8 +8220,8 @@ async function ensureAgentRuntime(options) {
|
|
|
8140
8220
|
stateDir: overlay.stateDir,
|
|
8141
8221
|
logsDir: overlay.logsDir,
|
|
8142
8222
|
sessionDir: overlay.sessionDir,
|
|
8143
|
-
sessionFile:
|
|
8144
|
-
policyFile:
|
|
8223
|
+
sessionFile: resolve37(overlay.sessionDir, "session.json"),
|
|
8224
|
+
policyFile: resolve37(options.projectRoot, "rig/policy/policy.json"),
|
|
8145
8225
|
binDir: runtime.binDir,
|
|
8146
8226
|
createdAt,
|
|
8147
8227
|
memory
|
|
@@ -8152,9 +8232,9 @@ async function ensureAgentRuntime(options) {
|
|
|
8152
8232
|
task: taskResolution.task,
|
|
8153
8233
|
taskEntry
|
|
8154
8234
|
});
|
|
8155
|
-
const manifestPath =
|
|
8235
|
+
const manifestPath = resolve37(runtimeRoot, "manifest.json");
|
|
8156
8236
|
const bakedScopeHash = sha256Hex(JSON.stringify(taskEntry.scope || []));
|
|
8157
|
-
const runtimeAgentBinary =
|
|
8237
|
+
const runtimeAgentBinary = resolve37(runtime.binDir, "rig-agent");
|
|
8158
8238
|
await ensureRigGitBinaryPath();
|
|
8159
8239
|
const bakedInfoOutput = await captureTaskInfoOutput({
|
|
8160
8240
|
projectRoot: options.projectRoot,
|
|
@@ -8169,10 +8249,10 @@ async function ensureAgentRuntime(options) {
|
|
|
8169
8249
|
const bakedStatusOutput = await captureStdout(async () => {
|
|
8170
8250
|
taskStatus(options.projectRoot);
|
|
8171
8251
|
});
|
|
8172
|
-
|
|
8173
|
-
|
|
8174
|
-
|
|
8175
|
-
|
|
8252
|
+
rmSync13(runtime.binDir, { recursive: true, force: true });
|
|
8253
|
+
rmSync13(workspaceLayout.distDir, { recursive: true, force: true });
|
|
8254
|
+
mkdirSync19(runtime.binDir, { recursive: true });
|
|
8255
|
+
mkdirSync19(workspaceLayout.distDir, { recursive: true });
|
|
8176
8256
|
await buildRuntimeToolchain({
|
|
8177
8257
|
projectRoot: options.projectRoot,
|
|
8178
8258
|
workspaceDir,
|
|
@@ -8209,9 +8289,9 @@ async function ensureAgentRuntime(options) {
|
|
|
8209
8289
|
workspaceDir,
|
|
8210
8290
|
taskEntry
|
|
8211
8291
|
});
|
|
8212
|
-
const sandboxDir =
|
|
8292
|
+
const sandboxDir = resolve37(runtimeRoot, "sandbox");
|
|
8213
8293
|
await mkdir4(sandboxDir, { recursive: true });
|
|
8214
|
-
await writeFile2(
|
|
8294
|
+
await writeFile2(resolve37(runtimeRoot, "runtime.json"), JSON.stringify({
|
|
8215
8295
|
id: options.id,
|
|
8216
8296
|
taskId: options.taskId,
|
|
8217
8297
|
mode: "worktree",
|
|
@@ -8220,290 +8300,6 @@ async function ensureAgentRuntime(options) {
|
|
|
8220
8300
|
}, null, 2), "utf-8");
|
|
8221
8301
|
return runtime;
|
|
8222
8302
|
}
|
|
8223
|
-
// packages/runtime/src/control-plane/runtime/plugins.ts
|
|
8224
|
-
import { existsSync as existsSync33, readdirSync as readdirSync6 } from "fs";
|
|
8225
|
-
import { resolve as resolve37, basename as basename10 } from "path";
|
|
8226
|
-
|
|
8227
|
-
// packages/runtime/src/control-plane/runtime/plugin-mode.ts
|
|
8228
|
-
var LEGACY_PLUGIN_SCAN_ENV = "RIG_LEGACY_PLUGIN_SCAN";
|
|
8229
|
-
function isLegacyPluginScanEnabled(env = process.env) {
|
|
8230
|
-
const value = env[LEGACY_PLUGIN_SCAN_ENV]?.trim().toLowerCase();
|
|
8231
|
-
return value === "1" || value === "true" || value === "yes" || value === "on";
|
|
8232
|
-
}
|
|
8233
|
-
|
|
8234
|
-
// packages/runtime/src/control-plane/runtime/plugins.ts
|
|
8235
|
-
class PluginManager {
|
|
8236
|
-
eventBus;
|
|
8237
|
-
context;
|
|
8238
|
-
pluginDir;
|
|
8239
|
-
pluginFiles;
|
|
8240
|
-
pluginNames;
|
|
8241
|
-
localBinDir;
|
|
8242
|
-
pluginsRequireBinaries;
|
|
8243
|
-
plugins;
|
|
8244
|
-
loadPromise;
|
|
8245
|
-
constructor(options) {
|
|
8246
|
-
this.eventBus = options.eventBus;
|
|
8247
|
-
this.context = options.context;
|
|
8248
|
-
this.pluginDir = options.pluginDir;
|
|
8249
|
-
this.pluginFiles = options.pluginFiles;
|
|
8250
|
-
this.pluginNames = options.pluginNames;
|
|
8251
|
-
this.localBinDir = options.localBinDir;
|
|
8252
|
-
this.pluginsRequireBinaries = options.pluginsRequireBinaries;
|
|
8253
|
-
this.plugins = options.preloadedPlugins ?? null;
|
|
8254
|
-
this.loadPromise = null;
|
|
8255
|
-
}
|
|
8256
|
-
static disabled(options) {
|
|
8257
|
-
const validatorProjectRoot = options.runtimeContext?.workspaceDir || options.projectRoot;
|
|
8258
|
-
return new PluginManager({
|
|
8259
|
-
eventBus: options.eventBus,
|
|
8260
|
-
context: {
|
|
8261
|
-
projectRoot: validatorProjectRoot,
|
|
8262
|
-
runId: options.runId,
|
|
8263
|
-
eventBus: options.eventBus
|
|
8264
|
-
},
|
|
8265
|
-
pluginDir: resolve37(options.projectRoot, "rig/plugins"),
|
|
8266
|
-
pluginFiles: [],
|
|
8267
|
-
pluginNames: [],
|
|
8268
|
-
localBinDir: options.runtimeContext ? resolve37(options.runtimeContext.binDir, "plugins") : resolve37(options.projectRoot, "rig/plugins"),
|
|
8269
|
-
pluginsRequireBinaries: false,
|
|
8270
|
-
preloadedPlugins: []
|
|
8271
|
-
});
|
|
8272
|
-
}
|
|
8273
|
-
static async load(options) {
|
|
8274
|
-
const pluginDir = resolve37(options.projectRoot, "rig/plugins");
|
|
8275
|
-
const runtimeImageConfig = loadRuntimeImageConfig(options.projectRoot);
|
|
8276
|
-
const localBinDir = options.runtimeContext ? resolve37(options.runtimeContext.binDir, "plugins") : resolve37(options.projectRoot, "rig/plugins");
|
|
8277
|
-
const legacyPluginScan = options.legacyPluginScan ?? isLegacyPluginScanEnabled(options.env);
|
|
8278
|
-
const files = legacyPluginScan ? safeReadDir(pluginDir).filter((entry) => /\.(ts|js|mjs|cjs)$/.test(entry)) : [];
|
|
8279
|
-
const pluginNames = files.map((file) => basename10(file).replace(/\.plugin\.(ts|js|mjs|cjs)$/, ""));
|
|
8280
|
-
const validatorProjectRoot = options.runtimeContext?.workspaceDir || options.projectRoot;
|
|
8281
|
-
const context = {
|
|
8282
|
-
projectRoot: validatorProjectRoot,
|
|
8283
|
-
runId: options.runId,
|
|
8284
|
-
eventBus: options.eventBus
|
|
8285
|
-
};
|
|
8286
|
-
return new PluginManager({
|
|
8287
|
-
eventBus: options.eventBus,
|
|
8288
|
-
context,
|
|
8289
|
-
pluginDir,
|
|
8290
|
-
pluginFiles: files,
|
|
8291
|
-
pluginNames,
|
|
8292
|
-
localBinDir,
|
|
8293
|
-
pluginsRequireBinaries: options.pluginsRequireBinaries ?? (runtimeImageConfig.plugins_require_binaries && Boolean(options.runtimeContext))
|
|
8294
|
-
});
|
|
8295
|
-
}
|
|
8296
|
-
list() {
|
|
8297
|
-
if (this.plugins) {
|
|
8298
|
-
return this.plugins.map((plugin) => ({
|
|
8299
|
-
name: plugin.name,
|
|
8300
|
-
validators: plugin.validators?.map((validator) => validator.id) ?? []
|
|
8301
|
-
}));
|
|
8302
|
-
}
|
|
8303
|
-
return this.pluginNames.map((name) => ({
|
|
8304
|
-
name,
|
|
8305
|
-
validators: []
|
|
8306
|
-
}));
|
|
8307
|
-
}
|
|
8308
|
-
async beforeCommand(ctx) {
|
|
8309
|
-
const plugins = await this.ensureLoaded();
|
|
8310
|
-
for (const plugin of plugins) {
|
|
8311
|
-
if (!plugin.beforeCommand) {
|
|
8312
|
-
continue;
|
|
8313
|
-
}
|
|
8314
|
-
await this.safeInvoke(plugin.name, "beforeCommand", () => plugin.beforeCommand?.(ctx, this.context));
|
|
8315
|
-
}
|
|
8316
|
-
}
|
|
8317
|
-
async afterCommand(result) {
|
|
8318
|
-
const plugins = await this.ensureLoaded();
|
|
8319
|
-
for (const plugin of plugins) {
|
|
8320
|
-
if (!plugin.afterCommand) {
|
|
8321
|
-
continue;
|
|
8322
|
-
}
|
|
8323
|
-
await this.safeInvoke(plugin.name, "afterCommand", () => plugin.afterCommand?.(result, this.context));
|
|
8324
|
-
}
|
|
8325
|
-
}
|
|
8326
|
-
async onEvent(event) {
|
|
8327
|
-
const plugins = this.plugins;
|
|
8328
|
-
if (!plugins) {
|
|
8329
|
-
return;
|
|
8330
|
-
}
|
|
8331
|
-
for (const plugin of plugins) {
|
|
8332
|
-
if (!plugin.onEvent) {
|
|
8333
|
-
continue;
|
|
8334
|
-
}
|
|
8335
|
-
await this.safeInvoke(plugin.name, "onEvent", () => plugin.onEvent?.(event, this.context));
|
|
8336
|
-
}
|
|
8337
|
-
}
|
|
8338
|
-
async runValidators(taskId) {
|
|
8339
|
-
const plugins = await this.ensureLoaded();
|
|
8340
|
-
const results = [];
|
|
8341
|
-
for (const plugin of plugins) {
|
|
8342
|
-
for (const validator of plugin.validators ?? []) {
|
|
8343
|
-
await this.eventBus.emit("validator.started", {
|
|
8344
|
-
plugin: plugin.name,
|
|
8345
|
-
validator: validator.id,
|
|
8346
|
-
taskId
|
|
8347
|
-
});
|
|
8348
|
-
try {
|
|
8349
|
-
const result = await validator.run({ taskId, projectRoot: this.context.projectRoot }, this.context);
|
|
8350
|
-
results.push(result);
|
|
8351
|
-
await this.eventBus.emit("validator.finished", {
|
|
8352
|
-
plugin: plugin.name,
|
|
8353
|
-
validator: validator.id,
|
|
8354
|
-
taskId,
|
|
8355
|
-
passed: result.passed,
|
|
8356
|
-
summary: result.summary
|
|
8357
|
-
});
|
|
8358
|
-
} catch (error) {
|
|
8359
|
-
const failed = {
|
|
8360
|
-
id: validator.id,
|
|
8361
|
-
passed: false,
|
|
8362
|
-
summary: `${plugin.name}/${validator.id} failed unexpectedly`,
|
|
8363
|
-
details: `${error}`
|
|
8364
|
-
};
|
|
8365
|
-
results.push(failed);
|
|
8366
|
-
await this.eventBus.emit("validator.finished", {
|
|
8367
|
-
plugin: plugin.name,
|
|
8368
|
-
validator: validator.id,
|
|
8369
|
-
taskId,
|
|
8370
|
-
passed: false,
|
|
8371
|
-
summary: failed.summary,
|
|
8372
|
-
details: failed.details
|
|
8373
|
-
});
|
|
8374
|
-
}
|
|
8375
|
-
}
|
|
8376
|
-
}
|
|
8377
|
-
return results;
|
|
8378
|
-
}
|
|
8379
|
-
async safeInvoke(pluginName, hook, call) {
|
|
8380
|
-
try {
|
|
8381
|
-
await call();
|
|
8382
|
-
} catch (error) {
|
|
8383
|
-
await this.eventBus.emit("plugin.error", {
|
|
8384
|
-
plugin: pluginName,
|
|
8385
|
-
phase: hook,
|
|
8386
|
-
error: `${error}`
|
|
8387
|
-
});
|
|
8388
|
-
}
|
|
8389
|
-
}
|
|
8390
|
-
async ensureLoaded() {
|
|
8391
|
-
if (this.plugins) {
|
|
8392
|
-
return this.plugins;
|
|
8393
|
-
}
|
|
8394
|
-
if (this.loadPromise) {
|
|
8395
|
-
return this.loadPromise;
|
|
8396
|
-
}
|
|
8397
|
-
this.loadPromise = this.loadCompiledPlugins();
|
|
8398
|
-
try {
|
|
8399
|
-
this.plugins = await this.loadPromise;
|
|
8400
|
-
return this.plugins;
|
|
8401
|
-
} finally {
|
|
8402
|
-
this.loadPromise = null;
|
|
8403
|
-
}
|
|
8404
|
-
}
|
|
8405
|
-
resolveBinPath(binName) {
|
|
8406
|
-
const candidates = [this.localBinDir].filter(Boolean).map((dir) => resolve37(dir, binName));
|
|
8407
|
-
return candidates.find((candidate) => existsSync33(candidate));
|
|
8408
|
-
}
|
|
8409
|
-
async loadCompiledPlugins() {
|
|
8410
|
-
const plugins = [];
|
|
8411
|
-
for (const file of this.pluginFiles) {
|
|
8412
|
-
const binName = basename10(file).replace(/\.plugin\.(ts|js|mjs|cjs)$/, "");
|
|
8413
|
-
let binPath = this.resolveBinPath(binName);
|
|
8414
|
-
if (!binPath) {
|
|
8415
|
-
const triedPaths = [this.localBinDir].filter(Boolean).map((dir) => resolve37(dir, binName));
|
|
8416
|
-
const missingError = `Compiled plugin binary not found for '${binName}'. Tried: ${triedPaths.join(", ")}`;
|
|
8417
|
-
await this.eventBus.emit("plugin.error", {
|
|
8418
|
-
file: resolve37(this.pluginDir, file),
|
|
8419
|
-
phase: "load",
|
|
8420
|
-
error: missingError
|
|
8421
|
-
});
|
|
8422
|
-
if (this.pluginsRequireBinaries) {
|
|
8423
|
-
throw new Error(missingError);
|
|
8424
|
-
}
|
|
8425
|
-
plugins.push({
|
|
8426
|
-
name: binName,
|
|
8427
|
-
validators: []
|
|
8428
|
-
});
|
|
8429
|
-
await this.eventBus.emit("plugin.loaded", {
|
|
8430
|
-
plugin: binName,
|
|
8431
|
-
file: resolve37(this.pluginDir, file),
|
|
8432
|
-
source: "metadata-only"
|
|
8433
|
-
});
|
|
8434
|
-
continue;
|
|
8435
|
-
}
|
|
8436
|
-
const wrapper = createBinaryPluginWrapper(binName, binPath, this.context.projectRoot);
|
|
8437
|
-
plugins.push(wrapper);
|
|
8438
|
-
await this.eventBus.emit("plugin.loaded", {
|
|
8439
|
-
plugin: wrapper.name,
|
|
8440
|
-
file: binPath,
|
|
8441
|
-
source: "compiled-binary"
|
|
8442
|
-
});
|
|
8443
|
-
}
|
|
8444
|
-
return plugins;
|
|
8445
|
-
}
|
|
8446
|
-
}
|
|
8447
|
-
function createBinaryPluginWrapper(name, binPath, projectRoot) {
|
|
8448
|
-
return {
|
|
8449
|
-
name,
|
|
8450
|
-
validators: [
|
|
8451
|
-
{
|
|
8452
|
-
id: `${name}:compiled`,
|
|
8453
|
-
async run(ctx) {
|
|
8454
|
-
const proc = Bun.spawn([binPath, "--validate", ctx.taskId, ctx.projectRoot], {
|
|
8455
|
-
cwd: projectRoot,
|
|
8456
|
-
stdout: "pipe",
|
|
8457
|
-
stderr: "pipe"
|
|
8458
|
-
});
|
|
8459
|
-
const exitCode = await proc.exited;
|
|
8460
|
-
const stdout = await new Response(proc.stdout).text();
|
|
8461
|
-
const stderr = await new Response(proc.stderr).text();
|
|
8462
|
-
if (exitCode !== 0) {
|
|
8463
|
-
return {
|
|
8464
|
-
id: `${name}:compiled`,
|
|
8465
|
-
passed: false,
|
|
8466
|
-
summary: `Plugin binary ${name} exited with code ${exitCode}`,
|
|
8467
|
-
details: stderr || stdout
|
|
8468
|
-
};
|
|
8469
|
-
}
|
|
8470
|
-
try {
|
|
8471
|
-
const results = JSON.parse(stdout.trim());
|
|
8472
|
-
const failed = results.filter((r) => !r.passed);
|
|
8473
|
-
if (failed.length > 0) {
|
|
8474
|
-
return {
|
|
8475
|
-
id: `${name}:compiled`,
|
|
8476
|
-
passed: false,
|
|
8477
|
-
summary: `${failed.length} of ${results.length} validator(s) failed`,
|
|
8478
|
-
details: failed.map((f) => `${f.id}: ${f.summary}`).join(`
|
|
8479
|
-
`)
|
|
8480
|
-
};
|
|
8481
|
-
}
|
|
8482
|
-
return {
|
|
8483
|
-
id: `${name}:compiled`,
|
|
8484
|
-
passed: true,
|
|
8485
|
-
summary: `All ${results.length} validator(s) passed`
|
|
8486
|
-
};
|
|
8487
|
-
} catch {
|
|
8488
|
-
return {
|
|
8489
|
-
id: `${name}:compiled`,
|
|
8490
|
-
passed: false,
|
|
8491
|
-
summary: `Failed to parse output from compiled plugin ${name}`,
|
|
8492
|
-
details: stdout.slice(0, 500)
|
|
8493
|
-
};
|
|
8494
|
-
}
|
|
8495
|
-
}
|
|
8496
|
-
}
|
|
8497
|
-
]
|
|
8498
|
-
};
|
|
8499
|
-
}
|
|
8500
|
-
function safeReadDir(path) {
|
|
8501
|
-
try {
|
|
8502
|
-
return readdirSync6(path, { withFileTypes: true }).filter((entry) => entry.isFile()).map((entry) => entry.name).sort();
|
|
8503
|
-
} catch {
|
|
8504
|
-
return [];
|
|
8505
|
-
}
|
|
8506
|
-
}
|
|
8507
8303
|
export {
|
|
8508
8304
|
writeRuntimeContext,
|
|
8509
8305
|
taskRuntimeId,
|
|
@@ -8525,7 +8321,6 @@ export {
|
|
|
8525
8321
|
cleanupAgentRuntime,
|
|
8526
8322
|
agentId,
|
|
8527
8323
|
RUNTIME_CONTEXT_ENV,
|
|
8528
|
-
PluginManager,
|
|
8529
8324
|
POLICY_VERSION,
|
|
8530
8325
|
GeneralCliEventBus as EventBus
|
|
8531
8326
|
};
|