@h-rig/runtime 0.0.6-alpha.28 → 0.0.6-alpha.29
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin/rig-agent-dispatch.js +552 -483
- package/dist/bin/rig-agent.js +418 -364
- package/dist/src/control-plane/agent-wrapper.js +557 -488
- package/dist/src/control-plane/harness-main.js +559 -1418
- package/dist/src/control-plane/hooks/completion-verification.js +451 -808
- package/dist/src/control-plane/hooks/inject-context.js +191 -137
- package/dist/src/control-plane/hooks/submodule-branch.js +596 -542
- package/dist/src/control-plane/hooks/task-runtime-start.js +596 -542
- package/dist/src/control-plane/materialize-task-config.js +64 -8
- package/dist/src/control-plane/native/git-ops.js +3 -0
- package/dist/src/control-plane/native/harness-cli.js +544 -496
- package/dist/src/control-plane/native/repo-ops.js +3 -0
- package/dist/src/control-plane/native/run-ops.js +3 -0
- package/dist/src/control-plane/native/task-ops.js +418 -370
- package/dist/src/control-plane/native/validator.js +161 -107
- package/dist/src/control-plane/native/verifier.js +217 -169
- package/dist/src/control-plane/pi-sessiond/launcher.js +12 -2
- package/dist/src/control-plane/plugin-host-context.js +54 -0
- package/dist/src/control-plane/runtime/image/fingerprint-sidecar.js +3 -0
- package/dist/src/control-plane/runtime/image/index.js +3 -0
- package/dist/src/control-plane/runtime/image-fingerprint-sidecar.js +3 -0
- package/dist/src/control-plane/runtime/image.js +3 -0
- package/dist/src/control-plane/runtime/index.js +487 -718
- package/dist/src/control-plane/runtime/isolation/index.js +511 -457
- package/dist/src/control-plane/runtime/isolation.js +511 -457
- package/dist/src/control-plane/runtime/plugin-mode.js +3 -27
- package/dist/src/control-plane/runtime/queue.js +428 -381
- package/dist/src/control-plane/runtime/snapshot/task-run.js +3 -0
- package/dist/src/control-plane/runtime/task-run-snapshot.js +3 -0
- package/dist/src/control-plane/skill-materializer.js +46 -0
- package/dist/src/control-plane/tasks/source-lifecycle.js +84 -30
- package/dist/src/index.js +0 -278
- package/native/darwin-arm64/rig-shell +0 -0
- package/native/darwin-arm64/rig-shell.build-manifest.json +1 -1
- package/native/darwin-arm64/rig-tools +0 -0
- package/native/darwin-arm64/rig-tools.build-manifest.json +1 -1
- package/package.json +8 -7
- package/dist/src/control-plane/runtime/plugins.js +0 -1131
- package/dist/src/plugins.js +0 -329
|
@@ -149,32 +149,32 @@ var RIG_DEFINITION_DIRNAME = "rig", RIG_ARTIFACTS_DIRNAME = "artifacts";
|
|
|
149
149
|
var init_layout = () => {};
|
|
150
150
|
|
|
151
151
|
// packages/runtime/src/control-plane/runtime/sandbox/utils.ts
|
|
152
|
-
import { existsSync as
|
|
153
|
-
import { resolve as
|
|
152
|
+
import { existsSync as 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) {
|
|
@@ -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,16 +6208,16 @@ 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
6214
|
for (const candidate of ["/usr/bin/gh", "/opt/homebrew/bin/gh", "/usr/local/bin/gh"]) {
|
|
6161
|
-
if (
|
|
6215
|
+
if (existsSync25(candidate)) {
|
|
6162
6216
|
return candidate;
|
|
6163
6217
|
}
|
|
6164
6218
|
}
|
|
6165
6219
|
const bunResolved = Bun.which("gh");
|
|
6166
|
-
if (bunResolved &&
|
|
6220
|
+
if (bunResolved && existsSync25(bunResolved) && !isRuntimeGatewayGhPath(bunResolved)) {
|
|
6167
6221
|
return bunResolved;
|
|
6168
6222
|
}
|
|
6169
6223
|
return "";
|
|
@@ -6197,17 +6251,17 @@ function resolveSystemCertBundlePath() {
|
|
|
6197
6251
|
"/opt/homebrew/etc/openssl@3/cert.pem"
|
|
6198
6252
|
];
|
|
6199
6253
|
for (const candidate of candidates) {
|
|
6200
|
-
if (candidate &&
|
|
6201
|
-
return
|
|
6254
|
+
if (candidate && existsSync25(candidate)) {
|
|
6255
|
+
return resolve27(candidate);
|
|
6202
6256
|
}
|
|
6203
6257
|
}
|
|
6204
6258
|
return "";
|
|
6205
6259
|
}
|
|
6206
6260
|
function readKnownHosts(path) {
|
|
6207
|
-
if (!
|
|
6261
|
+
if (!existsSync25(path)) {
|
|
6208
6262
|
return new Set;
|
|
6209
6263
|
}
|
|
6210
|
-
return new Set(
|
|
6264
|
+
return new Set(readFileSync13(path, "utf-8").split(/\r?\n/).map((line) => line.trim()).filter(Boolean));
|
|
6211
6265
|
}
|
|
6212
6266
|
|
|
6213
6267
|
// packages/runtime/src/control-plane/runtime/isolation/home.ts
|
|
@@ -6222,12 +6276,12 @@ function resolveControlPlaneSourceRoot(projectRoot) {
|
|
|
6222
6276
|
const candidates = [
|
|
6223
6277
|
process.env.RIG_CONTROL_PLANE_SOURCE_ROOT?.trim(),
|
|
6224
6278
|
process.env.RIG_HOST_PROJECT_ROOT?.trim(),
|
|
6225
|
-
|
|
6279
|
+
resolve28(import.meta.dir, "../../../../.."),
|
|
6226
6280
|
projectRoot
|
|
6227
6281
|
].filter((value) => Boolean(value));
|
|
6228
6282
|
for (const candidate of candidates) {
|
|
6229
|
-
const root =
|
|
6230
|
-
if (
|
|
6283
|
+
const root = resolve28(candidate);
|
|
6284
|
+
if (existsSync26(resolve28(root, "packages/runtime/src/control-plane/pi-sessiond/bin.ts"))) {
|
|
6231
6285
|
return root;
|
|
6232
6286
|
}
|
|
6233
6287
|
}
|
|
@@ -6247,7 +6301,7 @@ async function runtimeEnv(projectRoot, runtime) {
|
|
|
6247
6301
|
try {
|
|
6248
6302
|
return resolveClaudeInstallDir();
|
|
6249
6303
|
} catch {
|
|
6250
|
-
return
|
|
6304
|
+
return resolve28(claudeBinaryPath, "..");
|
|
6251
6305
|
}
|
|
6252
6306
|
})() : "";
|
|
6253
6307
|
const nodeDir = resolveNodeInstallDir();
|
|
@@ -6262,8 +6316,8 @@ async function runtimeEnv(projectRoot, runtime) {
|
|
|
6262
6316
|
`${bunDir}/bin`,
|
|
6263
6317
|
claudeDir,
|
|
6264
6318
|
nodeDir ? `${nodeDir}/bin` : "",
|
|
6265
|
-
realHome ?
|
|
6266
|
-
realHome ?
|
|
6319
|
+
realHome ? resolve28(realHome, ".local/bin") : "",
|
|
6320
|
+
realHome ? resolve28(realHome, ".cargo/bin") : "",
|
|
6267
6321
|
...inheritedPath,
|
|
6268
6322
|
"/usr/local/bin",
|
|
6269
6323
|
"/usr/local/sbin",
|
|
@@ -6274,9 +6328,9 @@ async function runtimeEnv(projectRoot, runtime) {
|
|
|
6274
6328
|
"/usr/sbin",
|
|
6275
6329
|
"/sbin"
|
|
6276
6330
|
].filter(Boolean);
|
|
6277
|
-
const runtimeBash =
|
|
6278
|
-
const runtimeRigGit =
|
|
6279
|
-
const preferredShell =
|
|
6331
|
+
const runtimeBash = resolve28(runtime.binDir, "bash");
|
|
6332
|
+
const runtimeRigGit = resolve28(runtime.binDir, runtimeRigGitFileName());
|
|
6333
|
+
const preferredShell = existsSync26(runtimeBash) ? runtimeBash : "/bin/bash";
|
|
6280
6334
|
const nativeRuntimeLibraryPath = await materializeNativeRuntimeLibrary(runtime.binDir);
|
|
6281
6335
|
const controlPlaneSourceRoot = resolveControlPlaneSourceRoot(projectRoot);
|
|
6282
6336
|
const env = {
|
|
@@ -6297,30 +6351,30 @@ async function runtimeEnv(projectRoot, runtime) {
|
|
|
6297
6351
|
RIG_RUNTIME_MODE: runtime.mode,
|
|
6298
6352
|
RIG_RUNTIME_HOME: runtime.rootDir,
|
|
6299
6353
|
RIG_RUNTIME_BIN_DIR: runtime.binDir,
|
|
6300
|
-
...
|
|
6354
|
+
...existsSync26(runtimeRigGit) ? { RIG_NATIVE_GIT_BIN: runtimeRigGit } : {},
|
|
6301
6355
|
RIG_BUN_PATH: bunBinaryPath,
|
|
6302
6356
|
...claudeBinaryPath ? { RIG_CLAUDE_PATH: claudeBinaryPath } : {},
|
|
6303
|
-
RIG_AGENT_BIN:
|
|
6357
|
+
RIG_AGENT_BIN: resolve28(runtime.binDir, "rig-agent"),
|
|
6304
6358
|
RIG_HOOKS_ACTIVE: "1",
|
|
6305
6359
|
RIG_AUTO_PR_ON_COMPLETE: "1",
|
|
6306
|
-
RIG_POLICY_FILE:
|
|
6360
|
+
RIG_POLICY_FILE: resolve28(projectRoot, "rig/policy/policy.json"),
|
|
6307
6361
|
RIG_STATE_DIR: runtime.stateDir,
|
|
6308
6362
|
RIG_LOGS_DIR: runtime.logsDir,
|
|
6309
|
-
RIG_SESSION_FILE:
|
|
6363
|
+
RIG_SESSION_FILE: resolve28(runtime.sessionDir, "session.json"),
|
|
6310
6364
|
MONOREPO_ROOT: runtime.workspaceDir,
|
|
6311
6365
|
MONOREPO_MAIN_ROOT: monorepoMainRoot,
|
|
6312
|
-
TS_API_TESTS_DIR:
|
|
6366
|
+
TS_API_TESTS_DIR: resolve28(runtime.workspaceDir, "TSAPITests"),
|
|
6313
6367
|
BASH: preferredShell,
|
|
6314
6368
|
SHELL: preferredShell,
|
|
6315
6369
|
PATH: [...new Set(pathEntries)].join(delimiter2),
|
|
6316
6370
|
LANG: process.env.LANG ?? "en_US.UTF-8",
|
|
6317
6371
|
TERM: process.env.TERM ?? "xterm-256color",
|
|
6318
6372
|
PYTHONDONTWRITEBYTECODE: "1",
|
|
6319
|
-
PYTHONPYCACHEPREFIX:
|
|
6373
|
+
PYTHONPYCACHEPREFIX: resolve28(runtime.cacheDir, "python"),
|
|
6320
6374
|
...process.env.RIG_PR_BASE_PROJECT && { RIG_PR_BASE_PROJECT: process.env.RIG_PR_BASE_PROJECT },
|
|
6321
6375
|
...process.env.RIG_PR_BASE_MONOREPO && { RIG_PR_BASE_MONOREPO: process.env.RIG_PR_BASE_MONOREPO },
|
|
6322
6376
|
CLAUDE_HOME: runtime.claudeHomeDir,
|
|
6323
|
-
PI_CODING_AGENT_DIR:
|
|
6377
|
+
PI_CODING_AGENT_DIR: resolve28(runtime.homeDir, ".pi", "agent"),
|
|
6324
6378
|
[RUNTIME_CONTEXT_ENV]: runtime.contextFile,
|
|
6325
6379
|
...nativeRuntimeLibraryPath ? { RIG_NATIVE_RUNTIME_LIB: nativeRuntimeLibraryPath } : {},
|
|
6326
6380
|
...hostGhBinary ? { RIG_GH_BIN: hostGhBinary } : {},
|
|
@@ -6331,16 +6385,16 @@ async function runtimeEnv(projectRoot, runtime) {
|
|
|
6331
6385
|
NODE_EXTRA_CA_CERTS: runtimeCertBundlePath
|
|
6332
6386
|
} : {}
|
|
6333
6387
|
};
|
|
6334
|
-
const knownHostsPath =
|
|
6335
|
-
if (
|
|
6336
|
-
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");
|
|
6337
6391
|
const sshParts = [
|
|
6338
6392
|
"ssh",
|
|
6339
6393
|
`-o UserKnownHostsFile="${knownHostsPath}"`,
|
|
6340
6394
|
"-o StrictHostKeyChecking=yes",
|
|
6341
6395
|
"-F /dev/null"
|
|
6342
6396
|
];
|
|
6343
|
-
if (
|
|
6397
|
+
if (existsSync26(agentSshKey)) {
|
|
6344
6398
|
sshParts.splice(1, 0, `-i "${agentSshKey}"`, "-o IdentitiesOnly=yes");
|
|
6345
6399
|
}
|
|
6346
6400
|
env.GIT_SSH_COMMAND = sshParts.join(" ");
|
|
@@ -6377,7 +6431,7 @@ async function runtimeEnv(projectRoot, runtime) {
|
|
|
6377
6431
|
if (!env.GREPTILE_GITHUB_TOKEN && env.GITHUB_TOKEN) {
|
|
6378
6432
|
env.GREPTILE_GITHUB_TOKEN = env.GITHUB_TOKEN;
|
|
6379
6433
|
}
|
|
6380
|
-
if (
|
|
6434
|
+
if (existsSync26(runtime.contextFile)) {
|
|
6381
6435
|
const runtimeContext = loadRuntimeContext(runtime.contextFile);
|
|
6382
6436
|
Object.assign(env, runtimeMemoryEnvFromContext(runtimeContext));
|
|
6383
6437
|
Object.assign(env, browserEnvFromContext(runtimeContext.browser));
|
|
@@ -6406,30 +6460,30 @@ async function provisionRuntimeHome(runtime, options = {}) {
|
|
|
6406
6460
|
await mkdir2(runtime.cacheDir, { recursive: true });
|
|
6407
6461
|
await provisionAgentSshKey(runtime.homeDir);
|
|
6408
6462
|
if (options.provider === "codex") {
|
|
6409
|
-
const hasCodexAuth = await injectCodexAuth(
|
|
6463
|
+
const hasCodexAuth = await injectCodexAuth(resolve28(runtime.homeDir, ".codex"));
|
|
6410
6464
|
if (!hasCodexAuth) {
|
|
6411
6465
|
console.warn("[rig] No Codex auth.json found for isolated runtime. " + "Run `codex login` in your host shell, then retry the agent run.");
|
|
6412
6466
|
}
|
|
6413
6467
|
}
|
|
6414
6468
|
if (options.provider === "pi") {
|
|
6415
|
-
const hasPiAuth = await injectPiAgentConfig(
|
|
6469
|
+
const hasPiAuth = await injectPiAgentConfig(resolve28(runtime.homeDir, ".pi", "agent"));
|
|
6416
6470
|
if (!hasPiAuth) {
|
|
6417
6471
|
console.warn("[rig] No Pi auth.json found for isolated runtime. " + "Run `pi /login` in your host shell, then retry the agent run.");
|
|
6418
6472
|
}
|
|
6419
6473
|
}
|
|
6420
6474
|
}
|
|
6421
6475
|
async function provisionClaudeHome(config) {
|
|
6422
|
-
|
|
6423
|
-
const workspaceSettings =
|
|
6424
|
-
const hostSettings =
|
|
6425
|
-
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;
|
|
6426
6480
|
const runtimeSettings = await loadRuntimeClaudeSettings(projectSettings);
|
|
6427
|
-
if (
|
|
6428
|
-
|
|
6481
|
+
if (existsSync26(projectSettings)) {
|
|
6482
|
+
writeFileSync10(resolve28(config.claudeHomeDir, "settings.local.json"), `${JSON.stringify(runtimeSettings, null, 2)}
|
|
6429
6483
|
`, "utf-8");
|
|
6430
6484
|
}
|
|
6431
6485
|
writeClaudeProjectSettings(config.claudeHomeDir, config.workspaceDir, runtimeSettings);
|
|
6432
|
-
|
|
6486
|
+
writeFileSync10(resolve28(config.claudeHomeDir, "settings.json"), JSON.stringify({
|
|
6433
6487
|
permissions: { defaultMode: "bypassPermissions" },
|
|
6434
6488
|
autoMemoryEnabled: false
|
|
6435
6489
|
}, null, 2));
|
|
@@ -6437,12 +6491,12 @@ async function provisionClaudeHome(config) {
|
|
|
6437
6491
|
if (!hasCredentials) {
|
|
6438
6492
|
console.warn("[rig] No Claude credentials found for isolated runtime. " + "Run `claude /login` in your host shell, then retry the agent run.");
|
|
6439
6493
|
}
|
|
6440
|
-
const realClaudeHome =
|
|
6441
|
-
if (process.env.HOME &&
|
|
6442
|
-
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"));
|
|
6443
6497
|
}
|
|
6444
|
-
if (process.env.HOME &&
|
|
6445
|
-
cpSync2(
|
|
6498
|
+
if (process.env.HOME && existsSync26(resolve28(realClaudeHome, "agents"))) {
|
|
6499
|
+
cpSync2(resolve28(realClaudeHome, "agents"), resolve28(config.claudeHomeDir, "agents"), { recursive: true });
|
|
6446
6500
|
}
|
|
6447
6501
|
if (process.platform === "darwin" && process.env.HOME) {
|
|
6448
6502
|
writeClaudeProjectSettings(realClaudeHome, config.workspaceDir, runtimeSettings);
|
|
@@ -6453,10 +6507,10 @@ async function materializeRuntimeCertBundle(runtime) {
|
|
|
6453
6507
|
if (!sourcePath) {
|
|
6454
6508
|
return "";
|
|
6455
6509
|
}
|
|
6456
|
-
const certsDir =
|
|
6457
|
-
const targetPath =
|
|
6510
|
+
const certsDir = resolve28(runtime.rootDir, "certs");
|
|
6511
|
+
const targetPath = resolve28(certsDir, "ca-certificates.pem");
|
|
6458
6512
|
await mkdir2(certsDir, { recursive: true });
|
|
6459
|
-
let shouldCopy = !
|
|
6513
|
+
let shouldCopy = !existsSync26(targetPath);
|
|
6460
6514
|
if (!shouldCopy) {
|
|
6461
6515
|
try {
|
|
6462
6516
|
shouldCopy = statSync6(sourcePath).mtimeMs > statSync6(targetPath).mtimeMs;
|
|
@@ -6478,7 +6532,7 @@ function applyGitHubCredentialHelperEnv(env) {
|
|
|
6478
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';
|
|
6479
6533
|
}
|
|
6480
6534
|
function persistRuntimeSecrets(runtimeRoot, env) {
|
|
6481
|
-
const secretsPath =
|
|
6535
|
+
const secretsPath = resolve28(runtimeRoot, "runtime-secrets.json");
|
|
6482
6536
|
const persisted = {};
|
|
6483
6537
|
for (const key of [
|
|
6484
6538
|
"GITHUB_TOKEN",
|
|
@@ -6497,12 +6551,12 @@ function persistRuntimeSecrets(runtimeRoot, env) {
|
|
|
6497
6551
|
if (Object.keys(persisted).length === 0) {
|
|
6498
6552
|
return;
|
|
6499
6553
|
}
|
|
6500
|
-
|
|
6554
|
+
writeFileSync10(secretsPath, `${JSON.stringify(persisted, null, 2)}
|
|
6501
6555
|
`, "utf-8");
|
|
6502
6556
|
}
|
|
6503
6557
|
async function provisionAgentSshKey(homeDir) {
|
|
6504
|
-
const sshDir =
|
|
6505
|
-
if (!
|
|
6558
|
+
const sshDir = resolve28(homeDir, ".ssh");
|
|
6559
|
+
if (!existsSync26(sshDir)) {
|
|
6506
6560
|
await mkdir2(sshDir, { recursive: true });
|
|
6507
6561
|
}
|
|
6508
6562
|
seedKnownHosts(sshDir);
|
|
@@ -6510,27 +6564,27 @@ async function provisionAgentSshKey(homeDir) {
|
|
|
6510
6564
|
const privateKey = decodeProvisionedSshKey(secrets.GITHUB_SSH_KEY);
|
|
6511
6565
|
if (!privateKey) {
|
|
6512
6566
|
const hostKeyPath = resolveHostSshKeyPath(process.env.HOME ?? "");
|
|
6513
|
-
if (!process.env.HOME || !
|
|
6567
|
+
if (!process.env.HOME || !existsSync26(hostKeyPath)) {
|
|
6514
6568
|
return;
|
|
6515
6569
|
}
|
|
6516
|
-
const agentKeyPath2 =
|
|
6517
|
-
if (!
|
|
6570
|
+
const agentKeyPath2 = resolve28(sshDir, "rig-agent-key");
|
|
6571
|
+
if (!existsSync26(agentKeyPath2)) {
|
|
6518
6572
|
copyFileSync5(hostKeyPath, agentKeyPath2);
|
|
6519
6573
|
chmodSync5(agentKeyPath2, 384);
|
|
6520
6574
|
}
|
|
6521
6575
|
const hostPubPath = `${hostKeyPath}.pub`;
|
|
6522
|
-
if (
|
|
6576
|
+
if (existsSync26(hostPubPath)) {
|
|
6523
6577
|
const agentPubPath = `${agentKeyPath2}.pub`;
|
|
6524
|
-
if (!
|
|
6578
|
+
if (!existsSync26(agentPubPath)) {
|
|
6525
6579
|
copyFileSync5(hostPubPath, agentPubPath);
|
|
6526
6580
|
}
|
|
6527
6581
|
}
|
|
6528
6582
|
writeSshConfig(sshDir, agentKeyPath2);
|
|
6529
6583
|
return;
|
|
6530
6584
|
}
|
|
6531
|
-
const agentKeyPath =
|
|
6532
|
-
if (!
|
|
6533
|
-
|
|
6585
|
+
const agentKeyPath = resolve28(sshDir, "rig-agent-key");
|
|
6586
|
+
if (!existsSync26(agentKeyPath)) {
|
|
6587
|
+
writeFileSync10(agentKeyPath, privateKey, { mode: 384 });
|
|
6534
6588
|
}
|
|
6535
6589
|
writeSshConfig(sshDir, agentKeyPath);
|
|
6536
6590
|
}
|
|
@@ -6547,21 +6601,21 @@ function decodeProvisionedSshKey(encodedKey) {
|
|
|
6547
6601
|
`;
|
|
6548
6602
|
}
|
|
6549
6603
|
function resolveHostSshKeyPath(homeDir) {
|
|
6550
|
-
const sshDir =
|
|
6604
|
+
const sshDir = resolve28(homeDir, ".ssh");
|
|
6551
6605
|
const candidates = [
|
|
6552
6606
|
"rig-agent-key",
|
|
6553
6607
|
"id_ed25519",
|
|
6554
6608
|
"id_ecdsa",
|
|
6555
6609
|
"id_rsa"
|
|
6556
|
-
].map((name) =>
|
|
6557
|
-
return candidates.find((candidate) =>
|
|
6610
|
+
].map((name) => resolve28(sshDir, name));
|
|
6611
|
+
return candidates.find((candidate) => existsSync26(candidate)) ?? resolve28(sshDir, "rig-agent-key");
|
|
6558
6612
|
}
|
|
6559
6613
|
function writeSshConfig(sshDir, keyPath) {
|
|
6560
|
-
const configPath =
|
|
6561
|
-
if (
|
|
6614
|
+
const configPath = resolve28(sshDir, "config");
|
|
6615
|
+
if (existsSync26(configPath)) {
|
|
6562
6616
|
return;
|
|
6563
6617
|
}
|
|
6564
|
-
const knownHostsPath =
|
|
6618
|
+
const knownHostsPath = resolve28(sshDir, "known_hosts");
|
|
6565
6619
|
const config = [
|
|
6566
6620
|
"Host github.com",
|
|
6567
6621
|
` IdentityFile ${keyPath}`,
|
|
@@ -6571,10 +6625,10 @@ function writeSshConfig(sshDir, keyPath) {
|
|
|
6571
6625
|
""
|
|
6572
6626
|
].join(`
|
|
6573
6627
|
`);
|
|
6574
|
-
|
|
6628
|
+
writeFileSync10(configPath, config, { mode: 420 });
|
|
6575
6629
|
}
|
|
6576
6630
|
function seedKnownHosts(sshDir) {
|
|
6577
|
-
const knownHostsPath =
|
|
6631
|
+
const knownHostsPath = resolve28(sshDir, "known_hosts");
|
|
6578
6632
|
const existingLines = readKnownHosts(knownHostsPath);
|
|
6579
6633
|
const requiredLines = GITHUB_KNOWN_HOSTS.split(/\r?\n/).map((line) => line.trim()).filter(Boolean);
|
|
6580
6634
|
const missing = requiredLines.filter((line) => !existingLines.has(line));
|
|
@@ -6585,23 +6639,23 @@ function seedKnownHosts(sshDir) {
|
|
|
6585
6639
|
for (const line of missing) {
|
|
6586
6640
|
existingLines.add(line);
|
|
6587
6641
|
}
|
|
6588
|
-
|
|
6642
|
+
writeFileSync10(knownHostsPath, `${Array.from(existingLines).join(`
|
|
6589
6643
|
`)}
|
|
6590
6644
|
`, { mode: 420 });
|
|
6591
6645
|
} catch (err) {
|
|
6592
|
-
const hint =
|
|
6646
|
+
const hint = existsSync26(knownHostsPath) ? "" : " \u2014 known_hosts is missing; git SSH operations may fail";
|
|
6593
6647
|
console.warn(`[rig] Could not update ${knownHostsPath}: ${err instanceof Error ? err.message : String(err)}${hint}`);
|
|
6594
6648
|
}
|
|
6595
6649
|
}
|
|
6596
6650
|
function writeClaudeProjectSettings(claudeHomeDir, workspaceDir, runtimeSettings) {
|
|
6597
6651
|
const projectHash = hashProjectPath(workspaceDir);
|
|
6598
|
-
const projectDir =
|
|
6599
|
-
|
|
6600
|
-
|
|
6652
|
+
const projectDir = resolve28(claudeHomeDir, "projects", projectHash);
|
|
6653
|
+
mkdirSync12(projectDir, { recursive: true });
|
|
6654
|
+
writeFileSync10(resolve28(projectDir, "settings.json"), `${JSON.stringify(runtimeSettings, null, 2)}
|
|
6601
6655
|
`, "utf-8");
|
|
6602
6656
|
}
|
|
6603
6657
|
async function loadRuntimeClaudeSettings(projectSettingsPath) {
|
|
6604
|
-
if (!
|
|
6658
|
+
if (!existsSync26(projectSettingsPath)) {
|
|
6605
6659
|
return {};
|
|
6606
6660
|
}
|
|
6607
6661
|
let parsed;
|
|
@@ -6647,7 +6701,7 @@ async function loadRuntimeClaudeSettings(projectSettingsPath) {
|
|
|
6647
6701
|
return clone;
|
|
6648
6702
|
}
|
|
6649
6703
|
async function injectClaudeCredentials(claudeHomeDir, options = {}) {
|
|
6650
|
-
const credentialsPath =
|
|
6704
|
+
const credentialsPath = resolve28(claudeHomeDir, ".credentials.json");
|
|
6651
6705
|
const platform = options.platform ?? process.platform;
|
|
6652
6706
|
if (platform === "darwin") {
|
|
6653
6707
|
const raw = options.loadKeychainCredentials ? await options.loadKeychainCredentials() : await (async () => {
|
|
@@ -6657,16 +6711,16 @@ async function injectClaudeCredentials(claudeHomeDir, options = {}) {
|
|
|
6657
6711
|
if (raw) {
|
|
6658
6712
|
try {
|
|
6659
6713
|
JSON.parse(raw);
|
|
6660
|
-
|
|
6714
|
+
writeFileSync10(credentialsPath, raw, { mode: 384 });
|
|
6661
6715
|
registerCredentialCleanup(credentialsPath);
|
|
6662
6716
|
return true;
|
|
6663
6717
|
} catch {}
|
|
6664
6718
|
}
|
|
6665
6719
|
}
|
|
6666
|
-
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") : "";
|
|
6667
6721
|
if (hostClaudeHome) {
|
|
6668
|
-
const realCredentials =
|
|
6669
|
-
if (
|
|
6722
|
+
const realCredentials = resolve28(hostClaudeHome, ".credentials.json");
|
|
6723
|
+
if (existsSync26(realCredentials)) {
|
|
6670
6724
|
cpSync2(realCredentials, credentialsPath);
|
|
6671
6725
|
return true;
|
|
6672
6726
|
}
|
|
@@ -6674,36 +6728,36 @@ async function injectClaudeCredentials(claudeHomeDir, options = {}) {
|
|
|
6674
6728
|
return false;
|
|
6675
6729
|
}
|
|
6676
6730
|
async function injectCodexAuth(codexHomeDir) {
|
|
6677
|
-
|
|
6678
|
-
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") : "";
|
|
6679
6733
|
if (!hostCodexHome) {
|
|
6680
6734
|
return false;
|
|
6681
6735
|
}
|
|
6682
|
-
const hostAuthPath =
|
|
6683
|
-
if (!
|
|
6736
|
+
const hostAuthPath = resolve28(hostCodexHome, "auth.json");
|
|
6737
|
+
if (!existsSync26(hostAuthPath)) {
|
|
6684
6738
|
return false;
|
|
6685
6739
|
}
|
|
6686
|
-
const runtimeAuthPath =
|
|
6740
|
+
const runtimeAuthPath = resolve28(codexHomeDir, "auth.json");
|
|
6687
6741
|
copyFileSync5(hostAuthPath, runtimeAuthPath);
|
|
6688
6742
|
chmodSync5(runtimeAuthPath, 384);
|
|
6689
6743
|
return true;
|
|
6690
6744
|
}
|
|
6691
6745
|
async function injectPiAgentConfig(piAgentDir) {
|
|
6692
|
-
|
|
6693
|
-
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") : "";
|
|
6694
6748
|
if (!hostPiAgentDir) {
|
|
6695
6749
|
return false;
|
|
6696
6750
|
}
|
|
6697
|
-
const hostAuthPath =
|
|
6698
|
-
if (!
|
|
6751
|
+
const hostAuthPath = resolve28(hostPiAgentDir, "auth.json");
|
|
6752
|
+
if (!existsSync26(hostAuthPath)) {
|
|
6699
6753
|
return false;
|
|
6700
6754
|
}
|
|
6701
|
-
const runtimeAuthPath =
|
|
6755
|
+
const runtimeAuthPath = resolve28(piAgentDir, "auth.json");
|
|
6702
6756
|
copyFileSync5(hostAuthPath, runtimeAuthPath);
|
|
6703
6757
|
chmodSync5(runtimeAuthPath, 384);
|
|
6704
|
-
const hostSettingsPath =
|
|
6705
|
-
if (
|
|
6706
|
-
const runtimeSettingsPath =
|
|
6758
|
+
const hostSettingsPath = resolve28(hostPiAgentDir, "settings.json");
|
|
6759
|
+
if (existsSync26(hostSettingsPath)) {
|
|
6760
|
+
const runtimeSettingsPath = resolve28(piAgentDir, "settings.json");
|
|
6707
6761
|
copyFileSync5(hostSettingsPath, runtimeSettingsPath);
|
|
6708
6762
|
chmodSync5(runtimeSettingsPath, 384);
|
|
6709
6763
|
}
|
|
@@ -6711,13 +6765,13 @@ async function injectPiAgentConfig(piAgentDir) {
|
|
|
6711
6765
|
}
|
|
6712
6766
|
|
|
6713
6767
|
// packages/runtime/src/control-plane/runtime/tooling/claude-router.ts
|
|
6714
|
-
import { existsSync as
|
|
6715
|
-
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";
|
|
6716
6770
|
var CLAUDE_ROUTER_SERVER_NAME = "rig_runtime_tools";
|
|
6717
6771
|
function buildRuntimeToolRouterServerConfig(options) {
|
|
6718
6772
|
return {
|
|
6719
6773
|
type: "stdio",
|
|
6720
|
-
command:
|
|
6774
|
+
command: resolve29(options.binDir, "rig-tool-router"),
|
|
6721
6775
|
args: [],
|
|
6722
6776
|
env: {
|
|
6723
6777
|
RIG_RUNTIME_CONTEXT_FILE: options.contextFile,
|
|
@@ -6726,25 +6780,25 @@ function buildRuntimeToolRouterServerConfig(options) {
|
|
|
6726
6780
|
};
|
|
6727
6781
|
}
|
|
6728
6782
|
function writeClaudeRuntimeToolRouterConfig(options) {
|
|
6729
|
-
const configPath =
|
|
6730
|
-
|
|
6783
|
+
const configPath = resolve29(options.stateDir, "claude-runtime-tools.mcp.json");
|
|
6784
|
+
mkdirSync13(options.stateDir, { recursive: true });
|
|
6731
6785
|
const payload = {
|
|
6732
6786
|
mcpServers: {
|
|
6733
6787
|
[CLAUDE_ROUTER_SERVER_NAME]: buildRuntimeToolRouterServerConfig(options)
|
|
6734
6788
|
}
|
|
6735
6789
|
};
|
|
6736
|
-
|
|
6790
|
+
writeFileSync11(configPath, `${JSON.stringify(payload, null, 2)}
|
|
6737
6791
|
`, "utf-8");
|
|
6738
6792
|
return configPath;
|
|
6739
6793
|
}
|
|
6740
6794
|
if (false) {}
|
|
6741
6795
|
// packages/runtime/src/control-plane/runtime/isolation/discovery.ts
|
|
6742
6796
|
init_layout();
|
|
6743
|
-
import { resolve as
|
|
6797
|
+
import { resolve as resolve33 } from "path";
|
|
6744
6798
|
|
|
6745
6799
|
// packages/runtime/src/control-plane/runtime/isolation/worktree.ts
|
|
6746
|
-
import { existsSync as
|
|
6747
|
-
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";
|
|
6748
6802
|
async function resolveMonorepoBaseRef(monorepoRoot) {
|
|
6749
6803
|
const explicit = process.env.RIG_RUNTIME_BASE_REF?.trim();
|
|
6750
6804
|
if (explicit) {
|
|
@@ -6780,12 +6834,12 @@ function ensureProvisioningHostProjectRootEnv(projectRoot) {
|
|
|
6780
6834
|
}
|
|
6781
6835
|
async function provisionRuntimeWorktree(config) {
|
|
6782
6836
|
const branch = runtimeBranchName(config.taskId, config.runtimeId);
|
|
6783
|
-
let hasValidWorktree =
|
|
6784
|
-
if (
|
|
6785
|
-
|
|
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 });
|
|
6786
6840
|
}
|
|
6787
6841
|
if (!hasValidWorktree) {
|
|
6788
|
-
|
|
6842
|
+
mkdirSync14(dirname12(config.workspaceDir), { recursive: true });
|
|
6789
6843
|
const branchExists = await runGitCommand(config.monorepoRoot, ["show-ref", "--verify", "--quiet", `refs/heads/${branch}`]);
|
|
6790
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]);
|
|
6791
6845
|
if (add.exitCode !== 0) {
|
|
@@ -6967,31 +7021,31 @@ async function preferredBaseRemotes(repoRoot) {
|
|
|
6967
7021
|
|
|
6968
7022
|
// packages/runtime/src/control-plane/runtime/isolation/toolchain.ts
|
|
6969
7023
|
import {
|
|
6970
|
-
existsSync as
|
|
7024
|
+
existsSync as existsSync30,
|
|
6971
7025
|
lstatSync,
|
|
6972
|
-
mkdirSync as
|
|
6973
|
-
readdirSync as
|
|
6974
|
-
readFileSync as
|
|
6975
|
-
rmSync as
|
|
7026
|
+
mkdirSync as mkdirSync16,
|
|
7027
|
+
readdirSync as readdirSync6,
|
|
7028
|
+
readFileSync as readFileSync15,
|
|
7029
|
+
rmSync as rmSync11,
|
|
6976
7030
|
statSync as statSync9,
|
|
6977
7031
|
symlinkSync as symlinkSync4
|
|
6978
7032
|
} from "fs";
|
|
6979
7033
|
import { mkdir as mkdir3, writeFile } from "fs/promises";
|
|
6980
|
-
import { dirname as dirname14, resolve as
|
|
7034
|
+
import { dirname as dirname14, resolve as resolve32 } from "path";
|
|
6981
7035
|
|
|
6982
7036
|
// packages/runtime/src/control-plane/runtime/tooling/claude-router-binary.ts
|
|
6983
|
-
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";
|
|
6984
7038
|
import { tmpdir as tmpdir6 } from "os";
|
|
6985
|
-
import { dirname as dirname13, resolve as
|
|
6986
|
-
var sharedRouterOutputDir =
|
|
6987
|
-
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" : ""}`);
|
|
6988
7042
|
function runtimeClaudeToolRouterFileName() {
|
|
6989
7043
|
return `rig-tool-router${process.platform === "win32" ? ".exe" : ""}`;
|
|
6990
7044
|
}
|
|
6991
7045
|
async function ensureClaudeToolRouterBinaryPath(projectRoot, outputPath = sharedRouterOutputPath) {
|
|
6992
|
-
const sourcePath =
|
|
6993
|
-
|
|
6994
|
-
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;
|
|
6995
7049
|
if (!needsBuild) {
|
|
6996
7050
|
return outputPath;
|
|
6997
7051
|
}
|
|
@@ -7005,9 +7059,9 @@ async function ensureClaudeToolRouterBinaryPath(projectRoot, outputPath = shared
|
|
|
7005
7059
|
}
|
|
7006
7060
|
async function materializeClaudeToolRouterBinary(projectRoot, targetDir) {
|
|
7007
7061
|
const sourcePath = await ensureClaudeToolRouterBinaryPath(projectRoot);
|
|
7008
|
-
const targetPath =
|
|
7009
|
-
|
|
7010
|
-
const needsCopy = !
|
|
7062
|
+
const targetPath = resolve31(targetDir, runtimeClaudeToolRouterFileName());
|
|
7063
|
+
mkdirSync15(targetDir, { recursive: true });
|
|
7064
|
+
const needsCopy = !existsSync29(targetPath) || statSync8(sourcePath).mtimeMs > statSync8(targetPath).mtimeMs;
|
|
7011
7065
|
if (needsCopy) {
|
|
7012
7066
|
copyFileSync6(sourcePath, targetPath);
|
|
7013
7067
|
chmodSync6(targetPath, 493);
|
|
@@ -7020,48 +7074,48 @@ var GIT_INDEX_LOCK_RETRY_DELAY_MS = 250;
|
|
|
7020
7074
|
var GIT_INDEX_LOCK_STALE_AFTER_MS = 5000;
|
|
7021
7075
|
function resolveRigSourceRoot(projectRoot) {
|
|
7022
7076
|
const hostProjectRoot = process.env.RIG_HOST_PROJECT_ROOT?.trim();
|
|
7023
|
-
if (hostProjectRoot &&
|
|
7077
|
+
if (hostProjectRoot && existsSync30(resolve32(hostProjectRoot, "packages/runtime/bin/rig-agent.ts"))) {
|
|
7024
7078
|
return hostProjectRoot;
|
|
7025
7079
|
}
|
|
7026
|
-
const fromModule =
|
|
7027
|
-
if (
|
|
7080
|
+
const fromModule = resolve32(import.meta.dir, "../../../../../..");
|
|
7081
|
+
if (existsSync30(resolve32(fromModule, "packages/runtime/bin/rig-agent.ts"))) {
|
|
7028
7082
|
return fromModule;
|
|
7029
7083
|
}
|
|
7030
7084
|
return projectRoot;
|
|
7031
7085
|
}
|
|
7032
7086
|
function prepareTrackedRuntimePaths(logsDir, stateDir, sessionDir) {
|
|
7033
|
-
for (const path of [logsDir, stateDir, sessionDir,
|
|
7087
|
+
for (const path of [logsDir, stateDir, sessionDir, resolve32(sessionDir, "session.json")]) {
|
|
7034
7088
|
removeSymbolicLink(path);
|
|
7035
7089
|
}
|
|
7036
7090
|
runtimePrepareTrackedPathsNative({
|
|
7037
7091
|
logsDir,
|
|
7038
7092
|
stateDir,
|
|
7039
7093
|
sessionDir,
|
|
7040
|
-
controlledBashLogFile:
|
|
7041
|
-
eventsFile:
|
|
7094
|
+
controlledBashLogFile: resolve32(logsDir, "controlled-bash.jsonl"),
|
|
7095
|
+
eventsFile: resolve32(logsDir, "control-plane.events.jsonl")
|
|
7042
7096
|
});
|
|
7043
7097
|
}
|
|
7044
7098
|
async function initializeRuntimeStateFiles(stateDir, sessionDir, taskId) {
|
|
7045
7099
|
await mkdir3(stateDir, { recursive: true });
|
|
7046
7100
|
await mkdir3(sessionDir, { recursive: true });
|
|
7047
|
-
const failedApproachesPath =
|
|
7048
|
-
if (!
|
|
7101
|
+
const failedApproachesPath = resolve32(stateDir, "failed_approaches.md");
|
|
7102
|
+
if (!existsSync30(failedApproachesPath)) {
|
|
7049
7103
|
await writeFile(failedApproachesPath, `# Failed Approaches
|
|
7050
7104
|
|
|
7051
7105
|
`);
|
|
7052
7106
|
}
|
|
7053
|
-
const hookTripsPath =
|
|
7054
|
-
if (!
|
|
7107
|
+
const hookTripsPath = resolve32(stateDir, "hook_trips.log");
|
|
7108
|
+
if (!existsSync30(hookTripsPath)) {
|
|
7055
7109
|
await writeFile(hookTripsPath, "");
|
|
7056
7110
|
}
|
|
7057
|
-
const sessionFile =
|
|
7111
|
+
const sessionFile = resolve32(sessionDir, "session.json");
|
|
7058
7112
|
if (taskId) {
|
|
7059
7113
|
await writeFile(sessionFile, JSON.stringify({ activeTaskIds: [taskId] }));
|
|
7060
7114
|
}
|
|
7061
7115
|
}
|
|
7062
7116
|
async function resetEphemeralTaskArtifacts(workspaceDir, taskId) {
|
|
7063
|
-
const artifactDir =
|
|
7064
|
-
const runtimeSnapshotDir =
|
|
7117
|
+
const artifactDir = resolve32(workspaceDir, "artifacts", taskId);
|
|
7118
|
+
const runtimeSnapshotDir = resolve32(artifactDir, "runtime-snapshots");
|
|
7065
7119
|
let preservedTrackedFiles = false;
|
|
7066
7120
|
for (const file of [
|
|
7067
7121
|
"changed-files.txt",
|
|
@@ -7077,13 +7131,13 @@ async function resetEphemeralTaskArtifacts(workspaceDir, taskId) {
|
|
|
7077
7131
|
preservedTrackedFiles = true;
|
|
7078
7132
|
continue;
|
|
7079
7133
|
}
|
|
7080
|
-
|
|
7134
|
+
rmSync11(resolve32(artifactDir, file), { force: true });
|
|
7081
7135
|
}
|
|
7082
7136
|
const runtimeSnapshotRelativePath = `artifacts/${taskId}/runtime-snapshots`;
|
|
7083
7137
|
if (await resetTrackedArtifactPath(workspaceDir, runtimeSnapshotRelativePath)) {
|
|
7084
7138
|
preservedTrackedFiles = true;
|
|
7085
7139
|
} else {
|
|
7086
|
-
|
|
7140
|
+
rmSync11(runtimeSnapshotDir, { recursive: true, force: true });
|
|
7087
7141
|
}
|
|
7088
7142
|
if (preservedTrackedFiles) {
|
|
7089
7143
|
console.log(`[rig-agent] Preserved tracked runtime artifact files in ${taskId}; skipped ephemeral cleanup for committed paths.`);
|
|
@@ -7116,28 +7170,28 @@ async function buildRuntimeToolchain(options) {
|
|
|
7116
7170
|
throw new Error("Failed to provision the native Zig runtime library.");
|
|
7117
7171
|
}
|
|
7118
7172
|
const rigSourceRoot = resolveRigSourceRoot(options.projectRoot);
|
|
7119
|
-
await buildBinary("packages/cli/bin/rig.ts",
|
|
7120
|
-
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, {
|
|
7121
7175
|
...options.runtimeSecretDefines,
|
|
7122
7176
|
AGENT_TASK_ID: options.taskId,
|
|
7123
7177
|
AGENT_PROJECT_ROOT: options.projectRoot,
|
|
7124
7178
|
AGENT_RUNTIME_ID: options.runtimeId,
|
|
7125
7179
|
AGENT_SCOPE_HASH: options.bakedScopeHash,
|
|
7126
7180
|
AGENT_MANIFEST_PATH: options.manifestPath,
|
|
7127
|
-
AGENT_BINARY_PATH:
|
|
7181
|
+
AGENT_BINARY_PATH: resolve32(options.binDir, "rig-agent"),
|
|
7128
7182
|
AGENT_INFO_OUTPUT: options.bakedInfoOutput,
|
|
7129
7183
|
AGENT_DEPS_OUTPUT: options.bakedDepsOutput,
|
|
7130
7184
|
AGENT_STATUS_OUTPUT: options.bakedStatusOutput
|
|
7131
7185
|
});
|
|
7132
|
-
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, {
|
|
7133
7187
|
AGENT_PROJECT_ROOT: options.projectRoot,
|
|
7134
7188
|
AGENT_LOGS_DIR: options.logsDir,
|
|
7135
7189
|
AGENT_MONOREPO_ROOT: resolveMonorepoRoot3(options.projectRoot),
|
|
7136
|
-
AGENT_TS_API_TESTS_DIR:
|
|
7137
|
-
AGENT_RIG_AGENT_BIN:
|
|
7190
|
+
AGENT_TS_API_TESTS_DIR: resolve32(options.workspaceDir, "TSAPITests"),
|
|
7191
|
+
AGENT_RIG_AGENT_BIN: resolve32(options.binDir, "rig-agent")
|
|
7138
7192
|
});
|
|
7139
|
-
await buildBinary("packages/runtime/bin/rig-browser-tool.ts",
|
|
7140
|
-
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, {
|
|
7141
7195
|
AGENT_PROJECT_ROOT: options.projectRoot,
|
|
7142
7196
|
AGENT_BUN_PATH: resolveBunBinaryPath()
|
|
7143
7197
|
});
|
|
@@ -7146,15 +7200,15 @@ async function buildRuntimeToolchain(options) {
|
|
|
7146
7200
|
AGENT_BUN_PATH: resolveBunBinaryPath()
|
|
7147
7201
|
};
|
|
7148
7202
|
for (const hookName of hookNames) {
|
|
7149
|
-
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);
|
|
7150
7204
|
}
|
|
7151
|
-
const pluginsDir =
|
|
7152
|
-
if (
|
|
7153
|
-
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 })) {
|
|
7154
7208
|
const match = entry.name.match(/^(.+)\.plugin\.(ts|js|mjs|cjs)$/);
|
|
7155
7209
|
if (!match)
|
|
7156
7210
|
continue;
|
|
7157
|
-
await buildBinary(`rig/plugins/${entry.name}`,
|
|
7211
|
+
await buildBinary(`rig/plugins/${entry.name}`, resolve32(runtimeBins.pluginsDir, match[1]), options.projectRoot);
|
|
7158
7212
|
}
|
|
7159
7213
|
}
|
|
7160
7214
|
await materializeRigGitBinary(options.binDir);
|
|
@@ -7164,8 +7218,8 @@ async function buildRuntimeToolchain(options) {
|
|
|
7164
7218
|
}
|
|
7165
7219
|
async function writeRuntimeManifest(config) {
|
|
7166
7220
|
const scopeHash = sha256Hex(JSON.stringify(config.scopes));
|
|
7167
|
-
const binarySha256 = sha256Hex(
|
|
7168
|
-
const manifestPath =
|
|
7221
|
+
const binarySha256 = sha256Hex(readFileSync15(config.binaryPath));
|
|
7222
|
+
const manifestPath = resolve32(config.runtimeRoot, "manifest.json");
|
|
7169
7223
|
const manifest = {
|
|
7170
7224
|
runtimeId: config.runtimeId,
|
|
7171
7225
|
taskId: config.taskId,
|
|
@@ -7199,7 +7253,7 @@ function removeSymbolicLink(path) {
|
|
|
7199
7253
|
} catch {
|
|
7200
7254
|
return;
|
|
7201
7255
|
}
|
|
7202
|
-
|
|
7256
|
+
rmSync11(path, { force: true, recursive: true });
|
|
7203
7257
|
}
|
|
7204
7258
|
async function resetTrackedArtifactPath(workspaceDir, relativePath) {
|
|
7205
7259
|
const tracked = await runGitLsFiles(workspaceDir, relativePath);
|
|
@@ -7225,7 +7279,7 @@ async function restoreTrackedArtifactPathWithRetry(workspaceDir, relativePath, r
|
|
|
7225
7279
|
const retryDelayMs = options.retryDelayMs ?? GIT_INDEX_LOCK_RETRY_DELAY_MS;
|
|
7226
7280
|
const now = options.now ?? Date.now;
|
|
7227
7281
|
const statMtimeMs = options.statMtimeMs ?? readFileMtimeMs;
|
|
7228
|
-
const removeFile = options.removeFile ?? ((path) =>
|
|
7282
|
+
const removeFile = options.removeFile ?? ((path) => rmSync11(path, { force: true }));
|
|
7229
7283
|
const log = options.log ?? console.warn;
|
|
7230
7284
|
let lastOutput = "";
|
|
7231
7285
|
for (let attempt = 0;attempt <= maxRetries; attempt += 1) {
|
|
@@ -7285,31 +7339,31 @@ function readFileMtimeMs(path) {
|
|
|
7285
7339
|
}
|
|
7286
7340
|
function linkRuntimeDependencyLayers(monorepoRoot, workspaceDir) {
|
|
7287
7341
|
linkGenericNodeModulesLayers(monorepoRoot, workspaceDir);
|
|
7288
|
-
const sourceNodeModules =
|
|
7289
|
-
if (!
|
|
7290
|
-
const runtimeHumoongate =
|
|
7291
|
-
if (
|
|
7292
|
-
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");
|
|
7293
7347
|
runtimeLinkDependencyLayerNative(sourceNodeModules, targetNodeModules);
|
|
7294
7348
|
}
|
|
7295
7349
|
}
|
|
7296
|
-
const runtimeHpNext =
|
|
7297
|
-
if (!
|
|
7350
|
+
const runtimeHpNext = resolve32(workspaceDir, "microservices", "hp-next-frontend", "app");
|
|
7351
|
+
if (!existsSync30(resolve32(runtimeHpNext, "package.json"))) {
|
|
7298
7352
|
return;
|
|
7299
7353
|
}
|
|
7300
|
-
const sourceHpNextNodeModules =
|
|
7301
|
-
const sourceMonorepoNodeModules =
|
|
7302
|
-
const targetHpNextNodeModules =
|
|
7303
|
-
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)) {
|
|
7304
7358
|
runtimeLinkDependencyLayerNative(sourceHpNextNodeModules, targetHpNextNodeModules);
|
|
7305
7359
|
return;
|
|
7306
7360
|
}
|
|
7307
|
-
if (
|
|
7361
|
+
if (existsSync30(sourceMonorepoNodeModules)) {
|
|
7308
7362
|
runtimeLinkDependencyLayerNative(sourceMonorepoNodeModules, targetHpNextNodeModules);
|
|
7309
7363
|
}
|
|
7310
7364
|
}
|
|
7311
7365
|
function linkGenericNodeModulesLayers(monorepoRoot, workspaceDir) {
|
|
7312
|
-
linkNodeModulesLayer(
|
|
7366
|
+
linkNodeModulesLayer(resolve32(monorepoRoot, "node_modules"), resolve32(workspaceDir, "node_modules"));
|
|
7313
7367
|
for (const relativePackageDir of [
|
|
7314
7368
|
"apps/native-app/apps/marketing",
|
|
7315
7369
|
"apps/native-app/apps/web",
|
|
@@ -7331,15 +7385,15 @@ function linkGenericNodeModulesLayers(monorepoRoot, workspaceDir) {
|
|
|
7331
7385
|
"packages/standard-plugin",
|
|
7332
7386
|
"packages/validator-kit"
|
|
7333
7387
|
]) {
|
|
7334
|
-
const workspacePackageDir =
|
|
7335
|
-
if (!
|
|
7388
|
+
const workspacePackageDir = resolve32(workspaceDir, relativePackageDir);
|
|
7389
|
+
if (!existsSync30(resolve32(workspacePackageDir, "package.json"))) {
|
|
7336
7390
|
continue;
|
|
7337
7391
|
}
|
|
7338
|
-
linkNodeModulesLayer(
|
|
7392
|
+
linkNodeModulesLayer(resolve32(monorepoRoot, relativePackageDir, "node_modules"), resolve32(workspacePackageDir, "node_modules"));
|
|
7339
7393
|
}
|
|
7340
7394
|
}
|
|
7341
7395
|
function linkNodeModulesLayer(sourceDir, targetDir) {
|
|
7342
|
-
if (!
|
|
7396
|
+
if (!existsSync30(sourceDir) || existsSync30(targetDir)) {
|
|
7343
7397
|
return;
|
|
7344
7398
|
}
|
|
7345
7399
|
try {
|
|
@@ -7348,16 +7402,16 @@ function linkNodeModulesLayer(sourceDir, targetDir) {
|
|
|
7348
7402
|
} catch (error) {
|
|
7349
7403
|
console.warn(`[rig-agent] Native dependency-layer linking failed for ${targetDir}; using symlink fallback: ${error instanceof Error ? error.message : String(error)}`);
|
|
7350
7404
|
}
|
|
7351
|
-
|
|
7405
|
+
mkdirSync16(dirname14(targetDir), { recursive: true });
|
|
7352
7406
|
symlinkSync4(sourceDir, targetDir, "dir");
|
|
7353
7407
|
}
|
|
7354
7408
|
function ensureRuntimeBinTrees(runtimeBinDir) {
|
|
7355
|
-
const hooksDir =
|
|
7356
|
-
const pluginsDir =
|
|
7357
|
-
const validatorsDir =
|
|
7358
|
-
|
|
7359
|
-
|
|
7360
|
-
|
|
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 });
|
|
7361
7415
|
return { hooksDir, pluginsDir, validatorsDir };
|
|
7362
7416
|
}
|
|
7363
7417
|
|
|
@@ -7368,17 +7422,17 @@ function runtimeRootForCleanup(projectRoot, runtimeId) {
|
|
|
7368
7422
|
monorepoRoot = resolveMonorepoRoot3(projectRoot);
|
|
7369
7423
|
} catch {}
|
|
7370
7424
|
const workspaceRootCandidate = monorepoRoot ?? projectRoot;
|
|
7371
|
-
const initialWorkspaceDir =
|
|
7425
|
+
const initialWorkspaceDir = resolve33(workspaceRootCandidate, ".worktrees", runtimeWorktreeNameFromRuntimeId(runtimeId));
|
|
7372
7426
|
const runtimeRoot = resolveRuntimeWorkspaceLayout(initialWorkspaceDir).runtimeDir;
|
|
7373
7427
|
return { monorepoRoot, initialWorkspaceDir, runtimeRoot };
|
|
7374
7428
|
}
|
|
7375
7429
|
|
|
7376
7430
|
// packages/runtime/src/control-plane/runtime/isolation/runner.ts
|
|
7377
|
-
import { existsSync as
|
|
7378
|
-
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";
|
|
7379
7433
|
|
|
7380
7434
|
// packages/runtime/src/control-plane/runtime/sandbox/backend.ts
|
|
7381
|
-
import { existsSync as
|
|
7435
|
+
import { existsSync as existsSync31 } from "fs";
|
|
7382
7436
|
init_utils();
|
|
7383
7437
|
|
|
7384
7438
|
// packages/runtime/src/control-plane/runtime/sandbox/backend-none.ts
|
|
@@ -7478,13 +7532,13 @@ async function resolveBackend(projectRoot, options) {
|
|
|
7478
7532
|
depRoots
|
|
7479
7533
|
};
|
|
7480
7534
|
const fsContext = {
|
|
7481
|
-
pathExists: (p) =>
|
|
7535
|
+
pathExists: (p) => existsSync31(p),
|
|
7482
7536
|
realPath: toRealPath
|
|
7483
7537
|
};
|
|
7484
7538
|
if (process.platform === "darwin" && (!requestedBackend || requestedBackend === "macos-seatbelt")) {
|
|
7485
7539
|
const seatbelt = Bun.which("sandbox-exec");
|
|
7486
7540
|
probed.push("sandbox-exec");
|
|
7487
|
-
if (seatbelt &&
|
|
7541
|
+
if (seatbelt && existsSync31(seatbelt)) {
|
|
7488
7542
|
const SeatbeltBackendClass = loadSeatbeltBackend();
|
|
7489
7543
|
if (SeatbeltBackendClass) {
|
|
7490
7544
|
return {
|
|
@@ -7605,10 +7659,10 @@ init_layout();
|
|
|
7605
7659
|
var SNAPSHOT_SIDECAR_READY_TIMEOUT_MS = 1e4;
|
|
7606
7660
|
async function startRuntimeSnapshotSidecar(runtime, options = {}) {
|
|
7607
7661
|
const instanceId = sanitizeRuntimeRefSegment(options.instanceId?.trim() || runtime.id);
|
|
7608
|
-
const readyFile =
|
|
7609
|
-
const requestFile =
|
|
7610
|
-
|
|
7611
|
-
|
|
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 });
|
|
7612
7666
|
const sidecarBinary = resolveSnapshotSidecarBinaryPath(runtime.binDir);
|
|
7613
7667
|
const useCompiledSidecar = shouldUseCompiledSnapshotSidecar(sidecarBinary);
|
|
7614
7668
|
const bunCli = useCompiledSidecar ? null : resolveBunCliInvocation();
|
|
@@ -7646,19 +7700,19 @@ async function startRuntimeSnapshotSidecar(runtime, options = {}) {
|
|
|
7646
7700
|
proc.kill("SIGTERM");
|
|
7647
7701
|
} catch {}
|
|
7648
7702
|
await proc.exited;
|
|
7649
|
-
|
|
7650
|
-
|
|
7703
|
+
rmSync12(readyFile, { force: true });
|
|
7704
|
+
rmSync12(requestFile, { force: true });
|
|
7651
7705
|
},
|
|
7652
7706
|
finalize: async (commandParts, exitCode) => {
|
|
7653
|
-
|
|
7707
|
+
writeFileSync13(requestFile, `${JSON.stringify({ command: commandParts, exitCode })}
|
|
7654
7708
|
`, "utf-8");
|
|
7655
7709
|
const [sidecarExitCode, stdout, stderr] = await Promise.all([
|
|
7656
7710
|
proc.exited,
|
|
7657
7711
|
stdoutTextPromise,
|
|
7658
7712
|
stderrTextPromise
|
|
7659
7713
|
]);
|
|
7660
|
-
|
|
7661
|
-
|
|
7714
|
+
rmSync12(readyFile, { force: true });
|
|
7715
|
+
rmSync12(requestFile, { force: true });
|
|
7662
7716
|
if (sidecarExitCode !== 0) {
|
|
7663
7717
|
throw new Error(`snapshot sidecar failed (${sidecarExitCode}): ${stderr || stdout}`);
|
|
7664
7718
|
}
|
|
@@ -7714,8 +7768,8 @@ async function runInAgentRuntime(options) {
|
|
|
7714
7768
|
const stdout = await new Response(proc.stdout).text();
|
|
7715
7769
|
const stderr = await new Response(proc.stderr).text();
|
|
7716
7770
|
try {
|
|
7717
|
-
await Bun.write(
|
|
7718
|
-
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);
|
|
7719
7773
|
} catch {}
|
|
7720
7774
|
await snapshotSidecar.finalize(runtimeCommand, exitCode);
|
|
7721
7775
|
return {
|
|
@@ -7745,18 +7799,18 @@ function resolveInternalRuntimeCommand(command) {
|
|
|
7745
7799
|
}
|
|
7746
7800
|
async function cleanupAgentRuntime(options) {
|
|
7747
7801
|
const { monorepoRoot, initialWorkspaceDir, runtimeRoot } = runtimeRootForCleanup(options.projectRoot, options.id);
|
|
7748
|
-
const metadataPath =
|
|
7749
|
-
if (!
|
|
7802
|
+
const metadataPath = resolve36(runtimeRoot, "runtime.json");
|
|
7803
|
+
if (!existsSync32(runtimeRoot)) {
|
|
7750
7804
|
return;
|
|
7751
7805
|
}
|
|
7752
7806
|
let mode = "worktree";
|
|
7753
7807
|
let workspaceDir = "";
|
|
7754
7808
|
const metadata = await readRuntimeMetadata(metadataPath);
|
|
7755
|
-
const metadataMatchesRequestedRuntime = metadata !== null && metadata.id === options.id &&
|
|
7809
|
+
const metadataMatchesRequestedRuntime = metadata !== null && metadata.id === options.id && resolve36(metadata.workspaceDir) === resolve36(initialWorkspaceDir);
|
|
7756
7810
|
if (metadata && metadataMatchesRequestedRuntime) {
|
|
7757
7811
|
mode = metadata.mode;
|
|
7758
7812
|
workspaceDir = metadata.workspaceDir;
|
|
7759
|
-
} else if (
|
|
7813
|
+
} else if (existsSync32(initialWorkspaceDir)) {
|
|
7760
7814
|
workspaceDir = initialWorkspaceDir;
|
|
7761
7815
|
}
|
|
7762
7816
|
const preservesTaskWorktree = metadataMatchesRequestedRuntime && metadata ? options.id === taskRuntimeId(metadata.taskId) : false;
|
|
@@ -7765,7 +7819,7 @@ async function cleanupAgentRuntime(options) {
|
|
|
7765
7819
|
} else if (mode === "worktree" && workspaceDir && preservesTaskWorktree) {
|
|
7766
7820
|
cleanupTaskRuntimeOverlay(workspaceDir);
|
|
7767
7821
|
}
|
|
7768
|
-
|
|
7822
|
+
rmSync12(runtimeRoot, { recursive: true, force: true });
|
|
7769
7823
|
}
|
|
7770
7824
|
function cleanupTaskRuntimeOverlay(workspaceDir) {
|
|
7771
7825
|
const layout = resolveRuntimeWorkspaceLayout(workspaceDir);
|
|
@@ -7781,17 +7835,17 @@ function cleanupTaskRuntimeOverlay(workspaceDir) {
|
|
|
7781
7835
|
layout.runtimeDir,
|
|
7782
7836
|
layout.contextPath
|
|
7783
7837
|
]) {
|
|
7784
|
-
|
|
7838
|
+
rmSync12(path, { recursive: true, force: true });
|
|
7785
7839
|
}
|
|
7786
7840
|
}
|
|
7787
7841
|
function resolveSnapshotSidecarScriptPath() {
|
|
7788
7842
|
return resolveRuntimeSourceScriptPath("snapshot-sidecar.ts");
|
|
7789
7843
|
}
|
|
7790
7844
|
function resolveSnapshotSidecarBinaryPath(binDir) {
|
|
7791
|
-
return
|
|
7845
|
+
return resolve36(binDir, "snapshot-sidecar");
|
|
7792
7846
|
}
|
|
7793
7847
|
function shouldUseCompiledSnapshotSidecar(binaryPath) {
|
|
7794
|
-
if (!
|
|
7848
|
+
if (!existsSync32(binaryPath)) {
|
|
7795
7849
|
return false;
|
|
7796
7850
|
}
|
|
7797
7851
|
const preference = process.env.RIG_USE_COMPILED_SNAPSHOT_SIDECAR?.trim().toLowerCase();
|
|
@@ -7806,12 +7860,12 @@ function resolveRuntimeSourceScriptPath(fileName) {
|
|
|
7806
7860
|
process.env.PROJECT_RIG_ROOT?.trim()
|
|
7807
7861
|
].filter((value) => Boolean(value));
|
|
7808
7862
|
for (const root of hostRoots) {
|
|
7809
|
-
const candidate =
|
|
7810
|
-
if (
|
|
7863
|
+
const candidate = resolve36(root, "packages/runtime/src/control-plane/runtime", fileName);
|
|
7864
|
+
if (existsSync32(candidate)) {
|
|
7811
7865
|
return candidate;
|
|
7812
7866
|
}
|
|
7813
7867
|
}
|
|
7814
|
-
return
|
|
7868
|
+
return resolve36(import.meta.dir, "..", fileName);
|
|
7815
7869
|
}
|
|
7816
7870
|
function resolveBunCliInvocation() {
|
|
7817
7871
|
if (process.env.RIG_BUN_PATH?.trim()) {
|
|
@@ -7838,7 +7892,7 @@ function resolveBunCliInvocation() {
|
|
|
7838
7892
|
async function waitForSnapshotSidecarReady(readyFile, proc, stdoutTextPromise, stderrTextPromise) {
|
|
7839
7893
|
const deadline = Date.now() + SNAPSHOT_SIDECAR_READY_TIMEOUT_MS;
|
|
7840
7894
|
while (Date.now() < deadline) {
|
|
7841
|
-
if (
|
|
7895
|
+
if (existsSync32(readyFile)) {
|
|
7842
7896
|
return;
|
|
7843
7897
|
}
|
|
7844
7898
|
const exitCode = proc.exitCode;
|
|
@@ -7851,7 +7905,7 @@ async function waitForSnapshotSidecarReady(readyFile, proc, stdoutTextPromise, s
|
|
|
7851
7905
|
throw new Error(`snapshot sidecar did not become ready within ${SNAPSHOT_SIDECAR_READY_TIMEOUT_MS}ms`);
|
|
7852
7906
|
}
|
|
7853
7907
|
async function readRuntimeMetadata(metadataPath) {
|
|
7854
|
-
if (!
|
|
7908
|
+
if (!existsSync32(metadataPath)) {
|
|
7855
7909
|
return null;
|
|
7856
7910
|
}
|
|
7857
7911
|
try {
|
|
@@ -7866,9 +7920,9 @@ var CANONICAL_MEMORY_DB_PATH2 = "rig/memory/project-memory.db";
|
|
|
7866
7920
|
async function hydrateRuntimeMemory(options) {
|
|
7867
7921
|
const snapshot = await readCanonicalMemoryDb(options.projectRoot);
|
|
7868
7922
|
const workspaceLayout = resolveRuntimeWorkspaceLayout(options.workspaceDir);
|
|
7869
|
-
const hydratedPath =
|
|
7923
|
+
const hydratedPath = resolve37(workspaceLayout.stateDir, "memory", "project-memory.db");
|
|
7870
7924
|
try {
|
|
7871
|
-
await mkdir4(
|
|
7925
|
+
await mkdir4(resolve37(workspaceLayout.stateDir, "memory"), { recursive: true });
|
|
7872
7926
|
await copyFile(snapshot.dbPath, hydratedPath);
|
|
7873
7927
|
return {
|
|
7874
7928
|
canonicalPath: CANONICAL_MEMORY_DB_PATH2,
|
|
@@ -7883,12 +7937,12 @@ async function hydrateRuntimeMemory(options) {
|
|
|
7883
7937
|
}
|
|
7884
7938
|
}
|
|
7885
7939
|
async function createRuntimeTaskRecordReader(options) {
|
|
7886
|
-
const legacyConfigPath =
|
|
7940
|
+
const legacyConfigPath = resolve37(options.projectRoot, ".rig", "task-config.json");
|
|
7887
7941
|
let pluginHostContext = null;
|
|
7888
7942
|
try {
|
|
7889
7943
|
pluginHostContext = await buildPluginHostContext(options.projectRoot);
|
|
7890
7944
|
} catch (error) {
|
|
7891
|
-
if (!
|
|
7945
|
+
if (!existsSync33(legacyConfigPath)) {
|
|
7892
7946
|
throw error;
|
|
7893
7947
|
}
|
|
7894
7948
|
const message = `Plugin task source unavailable; using source-aware .rig/task-config.json compatibility path: ${error instanceof Error ? error.message : String(error)}`;
|
|
@@ -7908,7 +7962,7 @@ async function createRuntimeTaskRecordReader(options) {
|
|
|
7908
7962
|
source: "plugin"
|
|
7909
7963
|
};
|
|
7910
7964
|
}
|
|
7911
|
-
if (
|
|
7965
|
+
if (existsSync33(legacyConfigPath)) {
|
|
7912
7966
|
const message = "Using source-aware .rig/task-config.json task source compatibility path";
|
|
7913
7967
|
options.diagnostics?.(message);
|
|
7914
7968
|
console.warn(message);
|
|
@@ -7925,10 +7979,10 @@ async function createRuntimeTaskRecordReader(options) {
|
|
|
7925
7979
|
};
|
|
7926
7980
|
}
|
|
7927
7981
|
function readConfiguredTaskSourceKindHint(projectRoot) {
|
|
7928
|
-
const jsonPath =
|
|
7929
|
-
if (
|
|
7982
|
+
const jsonPath = resolve37(projectRoot, "rig.config.json");
|
|
7983
|
+
if (existsSync33(jsonPath)) {
|
|
7930
7984
|
try {
|
|
7931
|
-
const parsed = JSON.parse(
|
|
7985
|
+
const parsed = JSON.parse(readFileSync16(jsonPath, "utf8"));
|
|
7932
7986
|
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
7933
7987
|
const taskSource = parsed.taskSource;
|
|
7934
7988
|
if (taskSource && typeof taskSource === "object" && !Array.isArray(taskSource)) {
|
|
@@ -7940,12 +7994,12 @@ function readConfiguredTaskSourceKindHint(projectRoot) {
|
|
|
7940
7994
|
return null;
|
|
7941
7995
|
}
|
|
7942
7996
|
}
|
|
7943
|
-
const tsPath =
|
|
7944
|
-
if (!
|
|
7997
|
+
const tsPath = resolve37(projectRoot, "rig.config.ts");
|
|
7998
|
+
if (!existsSync33(tsPath)) {
|
|
7945
7999
|
return null;
|
|
7946
8000
|
}
|
|
7947
8001
|
try {
|
|
7948
|
-
const source =
|
|
8002
|
+
const source = readFileSync16(tsPath, "utf8");
|
|
7949
8003
|
const taskSourceBlock = source.match(/taskSource\s*:\s*\{[\s\S]*?\}/m)?.[0] ?? "";
|
|
7950
8004
|
const kind = taskSourceBlock.match(/kind\s*:\s*["']([^"']+)["']/)?.[1];
|
|
7951
8005
|
return kind ?? null;
|
|
@@ -8015,8 +8069,8 @@ async function writeRuntimeTaskConfigProjection(options) {
|
|
|
8015
8069
|
...options.taskEntry.validation && options.taskEntry.validation.length > 0 ? { validation: options.taskEntry.validation } : {},
|
|
8016
8070
|
...options.taskEntry.browser ? { browser: options.taskEntry.browser } : {}
|
|
8017
8071
|
};
|
|
8018
|
-
const configPath =
|
|
8019
|
-
await mkdir4(
|
|
8072
|
+
const configPath = resolve37(options.workspaceDir, ".rig", "task-config.json");
|
|
8073
|
+
await mkdir4(resolve37(options.workspaceDir, ".rig"), { recursive: true });
|
|
8020
8074
|
await writeFile2(configPath, `${JSON.stringify({ [options.task.id]: entry }, null, 2)}
|
|
8021
8075
|
`, "utf-8");
|
|
8022
8076
|
}
|
|
@@ -8080,9 +8134,9 @@ async function ensureAgentRuntime(options) {
|
|
|
8080
8134
|
}
|
|
8081
8135
|
ensureProvisioningHostProjectRootEnv(options.projectRoot);
|
|
8082
8136
|
const monorepoRoot = resolveMonorepoRoot3(options.projectRoot);
|
|
8083
|
-
const workspaceDir =
|
|
8137
|
+
const workspaceDir = resolve37(monorepoRoot, ".worktrees", runtimeWorktreeName(options.taskId, options.id));
|
|
8084
8138
|
const createdAt = new Date().toISOString();
|
|
8085
|
-
if (!
|
|
8139
|
+
if (!existsSync33(resolve37(monorepoRoot, ".git"))) {
|
|
8086
8140
|
throw new Error(`Monorepo root is not a git checkout: ${monorepoRoot}`);
|
|
8087
8141
|
}
|
|
8088
8142
|
const taskResolution = await resolveRuntimeTaskRecord({
|
|
@@ -8117,7 +8171,7 @@ async function ensureAgentRuntime(options) {
|
|
|
8117
8171
|
logsDir: overlay.logsDir,
|
|
8118
8172
|
stateDir: overlay.stateDir,
|
|
8119
8173
|
sessionDir: overlay.sessionDir,
|
|
8120
|
-
claudeHomeDir:
|
|
8174
|
+
claudeHomeDir: resolve37(workspaceLayout.homeDir, ".claude"),
|
|
8121
8175
|
contextFile: overlay.contextPath,
|
|
8122
8176
|
binDir: workspaceLayout.binDir,
|
|
8123
8177
|
createdAt
|
|
@@ -8130,8 +8184,8 @@ async function ensureAgentRuntime(options) {
|
|
|
8130
8184
|
projectRoot: options.projectRoot,
|
|
8131
8185
|
workspaceDir
|
|
8132
8186
|
});
|
|
8133
|
-
|
|
8134
|
-
|
|
8187
|
+
mkdirSync19(runtime.binDir, { recursive: true });
|
|
8188
|
+
mkdirSync19(workspaceLayout.distDir, { recursive: true });
|
|
8135
8189
|
prepareRuntimeWorkspace(options.projectRoot, workspaceDir);
|
|
8136
8190
|
if (options.preserveTaskArtifacts) {
|
|
8137
8191
|
console.log(`[rig-agent] Preserving runtime task artifacts for resume of ${options.taskId}.`);
|
|
@@ -8150,7 +8204,7 @@ async function ensureAgentRuntime(options) {
|
|
|
8150
8204
|
runtimeId: options.id
|
|
8151
8205
|
}),
|
|
8152
8206
|
workspaceDir,
|
|
8153
|
-
artifactRoot:
|
|
8207
|
+
artifactRoot: resolve37(workspaceDir, "artifacts", options.taskId),
|
|
8154
8208
|
hostProjectRoot: options.projectRoot,
|
|
8155
8209
|
monorepoMainRoot: monorepoRoot,
|
|
8156
8210
|
monorepoBaseRef: baseRef,
|
|
@@ -8166,8 +8220,8 @@ async function ensureAgentRuntime(options) {
|
|
|
8166
8220
|
stateDir: overlay.stateDir,
|
|
8167
8221
|
logsDir: overlay.logsDir,
|
|
8168
8222
|
sessionDir: overlay.sessionDir,
|
|
8169
|
-
sessionFile:
|
|
8170
|
-
policyFile:
|
|
8223
|
+
sessionFile: resolve37(overlay.sessionDir, "session.json"),
|
|
8224
|
+
policyFile: resolve37(options.projectRoot, "rig/policy/policy.json"),
|
|
8171
8225
|
binDir: runtime.binDir,
|
|
8172
8226
|
createdAt,
|
|
8173
8227
|
memory
|
|
@@ -8178,9 +8232,9 @@ async function ensureAgentRuntime(options) {
|
|
|
8178
8232
|
task: taskResolution.task,
|
|
8179
8233
|
taskEntry
|
|
8180
8234
|
});
|
|
8181
|
-
const manifestPath =
|
|
8235
|
+
const manifestPath = resolve37(runtimeRoot, "manifest.json");
|
|
8182
8236
|
const bakedScopeHash = sha256Hex(JSON.stringify(taskEntry.scope || []));
|
|
8183
|
-
const runtimeAgentBinary =
|
|
8237
|
+
const runtimeAgentBinary = resolve37(runtime.binDir, "rig-agent");
|
|
8184
8238
|
await ensureRigGitBinaryPath();
|
|
8185
8239
|
const bakedInfoOutput = await captureTaskInfoOutput({
|
|
8186
8240
|
projectRoot: options.projectRoot,
|
|
@@ -8195,10 +8249,10 @@ async function ensureAgentRuntime(options) {
|
|
|
8195
8249
|
const bakedStatusOutput = await captureStdout(async () => {
|
|
8196
8250
|
taskStatus(options.projectRoot);
|
|
8197
8251
|
});
|
|
8198
|
-
|
|
8199
|
-
|
|
8200
|
-
|
|
8201
|
-
|
|
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 });
|
|
8202
8256
|
await buildRuntimeToolchain({
|
|
8203
8257
|
projectRoot: options.projectRoot,
|
|
8204
8258
|
workspaceDir,
|
|
@@ -8235,9 +8289,9 @@ async function ensureAgentRuntime(options) {
|
|
|
8235
8289
|
workspaceDir,
|
|
8236
8290
|
taskEntry
|
|
8237
8291
|
});
|
|
8238
|
-
const sandboxDir =
|
|
8292
|
+
const sandboxDir = resolve37(runtimeRoot, "sandbox");
|
|
8239
8293
|
await mkdir4(sandboxDir, { recursive: true });
|
|
8240
|
-
await writeFile2(
|
|
8294
|
+
await writeFile2(resolve37(runtimeRoot, "runtime.json"), JSON.stringify({
|
|
8241
8295
|
id: options.id,
|
|
8242
8296
|
taskId: options.taskId,
|
|
8243
8297
|
mode: "worktree",
|
|
@@ -8246,290 +8300,6 @@ async function ensureAgentRuntime(options) {
|
|
|
8246
8300
|
}, null, 2), "utf-8");
|
|
8247
8301
|
return runtime;
|
|
8248
8302
|
}
|
|
8249
|
-
// packages/runtime/src/control-plane/runtime/plugins.ts
|
|
8250
|
-
import { existsSync as existsSync33, readdirSync as readdirSync6 } from "fs";
|
|
8251
|
-
import { resolve as resolve37, basename as basename10 } from "path";
|
|
8252
|
-
|
|
8253
|
-
// packages/runtime/src/control-plane/runtime/plugin-mode.ts
|
|
8254
|
-
var LEGACY_PLUGIN_SCAN_ENV = "RIG_LEGACY_PLUGIN_SCAN";
|
|
8255
|
-
function isLegacyPluginScanEnabled(env = process.env) {
|
|
8256
|
-
const value = env[LEGACY_PLUGIN_SCAN_ENV]?.trim().toLowerCase();
|
|
8257
|
-
return value === "1" || value === "true" || value === "yes" || value === "on";
|
|
8258
|
-
}
|
|
8259
|
-
|
|
8260
|
-
// packages/runtime/src/control-plane/runtime/plugins.ts
|
|
8261
|
-
class PluginManager {
|
|
8262
|
-
eventBus;
|
|
8263
|
-
context;
|
|
8264
|
-
pluginDir;
|
|
8265
|
-
pluginFiles;
|
|
8266
|
-
pluginNames;
|
|
8267
|
-
localBinDir;
|
|
8268
|
-
pluginsRequireBinaries;
|
|
8269
|
-
plugins;
|
|
8270
|
-
loadPromise;
|
|
8271
|
-
constructor(options) {
|
|
8272
|
-
this.eventBus = options.eventBus;
|
|
8273
|
-
this.context = options.context;
|
|
8274
|
-
this.pluginDir = options.pluginDir;
|
|
8275
|
-
this.pluginFiles = options.pluginFiles;
|
|
8276
|
-
this.pluginNames = options.pluginNames;
|
|
8277
|
-
this.localBinDir = options.localBinDir;
|
|
8278
|
-
this.pluginsRequireBinaries = options.pluginsRequireBinaries;
|
|
8279
|
-
this.plugins = options.preloadedPlugins ?? null;
|
|
8280
|
-
this.loadPromise = null;
|
|
8281
|
-
}
|
|
8282
|
-
static disabled(options) {
|
|
8283
|
-
const validatorProjectRoot = options.runtimeContext?.workspaceDir || options.projectRoot;
|
|
8284
|
-
return new PluginManager({
|
|
8285
|
-
eventBus: options.eventBus,
|
|
8286
|
-
context: {
|
|
8287
|
-
projectRoot: validatorProjectRoot,
|
|
8288
|
-
runId: options.runId,
|
|
8289
|
-
eventBus: options.eventBus
|
|
8290
|
-
},
|
|
8291
|
-
pluginDir: resolve37(options.projectRoot, "rig/plugins"),
|
|
8292
|
-
pluginFiles: [],
|
|
8293
|
-
pluginNames: [],
|
|
8294
|
-
localBinDir: options.runtimeContext ? resolve37(options.runtimeContext.binDir, "plugins") : resolve37(options.projectRoot, "rig/plugins"),
|
|
8295
|
-
pluginsRequireBinaries: false,
|
|
8296
|
-
preloadedPlugins: []
|
|
8297
|
-
});
|
|
8298
|
-
}
|
|
8299
|
-
static async load(options) {
|
|
8300
|
-
const pluginDir = resolve37(options.projectRoot, "rig/plugins");
|
|
8301
|
-
const runtimeImageConfig = loadRuntimeImageConfig(options.projectRoot);
|
|
8302
|
-
const localBinDir = options.runtimeContext ? resolve37(options.runtimeContext.binDir, "plugins") : resolve37(options.projectRoot, "rig/plugins");
|
|
8303
|
-
const legacyPluginScan = options.legacyPluginScan ?? isLegacyPluginScanEnabled(options.env);
|
|
8304
|
-
const files = legacyPluginScan ? safeReadDir(pluginDir).filter((entry) => /\.(ts|js|mjs|cjs)$/.test(entry)) : [];
|
|
8305
|
-
const pluginNames = files.map((file) => basename10(file).replace(/\.plugin\.(ts|js|mjs|cjs)$/, ""));
|
|
8306
|
-
const validatorProjectRoot = options.runtimeContext?.workspaceDir || options.projectRoot;
|
|
8307
|
-
const context = {
|
|
8308
|
-
projectRoot: validatorProjectRoot,
|
|
8309
|
-
runId: options.runId,
|
|
8310
|
-
eventBus: options.eventBus
|
|
8311
|
-
};
|
|
8312
|
-
return new PluginManager({
|
|
8313
|
-
eventBus: options.eventBus,
|
|
8314
|
-
context,
|
|
8315
|
-
pluginDir,
|
|
8316
|
-
pluginFiles: files,
|
|
8317
|
-
pluginNames,
|
|
8318
|
-
localBinDir,
|
|
8319
|
-
pluginsRequireBinaries: options.pluginsRequireBinaries ?? (runtimeImageConfig.plugins_require_binaries && Boolean(options.runtimeContext))
|
|
8320
|
-
});
|
|
8321
|
-
}
|
|
8322
|
-
list() {
|
|
8323
|
-
if (this.plugins) {
|
|
8324
|
-
return this.plugins.map((plugin) => ({
|
|
8325
|
-
name: plugin.name,
|
|
8326
|
-
validators: plugin.validators?.map((validator) => validator.id) ?? []
|
|
8327
|
-
}));
|
|
8328
|
-
}
|
|
8329
|
-
return this.pluginNames.map((name) => ({
|
|
8330
|
-
name,
|
|
8331
|
-
validators: []
|
|
8332
|
-
}));
|
|
8333
|
-
}
|
|
8334
|
-
async beforeCommand(ctx) {
|
|
8335
|
-
const plugins = await this.ensureLoaded();
|
|
8336
|
-
for (const plugin of plugins) {
|
|
8337
|
-
if (!plugin.beforeCommand) {
|
|
8338
|
-
continue;
|
|
8339
|
-
}
|
|
8340
|
-
await this.safeInvoke(plugin.name, "beforeCommand", () => plugin.beforeCommand?.(ctx, this.context));
|
|
8341
|
-
}
|
|
8342
|
-
}
|
|
8343
|
-
async afterCommand(result) {
|
|
8344
|
-
const plugins = await this.ensureLoaded();
|
|
8345
|
-
for (const plugin of plugins) {
|
|
8346
|
-
if (!plugin.afterCommand) {
|
|
8347
|
-
continue;
|
|
8348
|
-
}
|
|
8349
|
-
await this.safeInvoke(plugin.name, "afterCommand", () => plugin.afterCommand?.(result, this.context));
|
|
8350
|
-
}
|
|
8351
|
-
}
|
|
8352
|
-
async onEvent(event) {
|
|
8353
|
-
const plugins = this.plugins;
|
|
8354
|
-
if (!plugins) {
|
|
8355
|
-
return;
|
|
8356
|
-
}
|
|
8357
|
-
for (const plugin of plugins) {
|
|
8358
|
-
if (!plugin.onEvent) {
|
|
8359
|
-
continue;
|
|
8360
|
-
}
|
|
8361
|
-
await this.safeInvoke(plugin.name, "onEvent", () => plugin.onEvent?.(event, this.context));
|
|
8362
|
-
}
|
|
8363
|
-
}
|
|
8364
|
-
async runValidators(taskId) {
|
|
8365
|
-
const plugins = await this.ensureLoaded();
|
|
8366
|
-
const results = [];
|
|
8367
|
-
for (const plugin of plugins) {
|
|
8368
|
-
for (const validator of plugin.validators ?? []) {
|
|
8369
|
-
await this.eventBus.emit("validator.started", {
|
|
8370
|
-
plugin: plugin.name,
|
|
8371
|
-
validator: validator.id,
|
|
8372
|
-
taskId
|
|
8373
|
-
});
|
|
8374
|
-
try {
|
|
8375
|
-
const result = await validator.run({ taskId, projectRoot: this.context.projectRoot }, this.context);
|
|
8376
|
-
results.push(result);
|
|
8377
|
-
await this.eventBus.emit("validator.finished", {
|
|
8378
|
-
plugin: plugin.name,
|
|
8379
|
-
validator: validator.id,
|
|
8380
|
-
taskId,
|
|
8381
|
-
passed: result.passed,
|
|
8382
|
-
summary: result.summary
|
|
8383
|
-
});
|
|
8384
|
-
} catch (error) {
|
|
8385
|
-
const failed = {
|
|
8386
|
-
id: validator.id,
|
|
8387
|
-
passed: false,
|
|
8388
|
-
summary: `${plugin.name}/${validator.id} failed unexpectedly`,
|
|
8389
|
-
details: `${error}`
|
|
8390
|
-
};
|
|
8391
|
-
results.push(failed);
|
|
8392
|
-
await this.eventBus.emit("validator.finished", {
|
|
8393
|
-
plugin: plugin.name,
|
|
8394
|
-
validator: validator.id,
|
|
8395
|
-
taskId,
|
|
8396
|
-
passed: false,
|
|
8397
|
-
summary: failed.summary,
|
|
8398
|
-
details: failed.details
|
|
8399
|
-
});
|
|
8400
|
-
}
|
|
8401
|
-
}
|
|
8402
|
-
}
|
|
8403
|
-
return results;
|
|
8404
|
-
}
|
|
8405
|
-
async safeInvoke(pluginName, hook, call) {
|
|
8406
|
-
try {
|
|
8407
|
-
await call();
|
|
8408
|
-
} catch (error) {
|
|
8409
|
-
await this.eventBus.emit("plugin.error", {
|
|
8410
|
-
plugin: pluginName,
|
|
8411
|
-
phase: hook,
|
|
8412
|
-
error: `${error}`
|
|
8413
|
-
});
|
|
8414
|
-
}
|
|
8415
|
-
}
|
|
8416
|
-
async ensureLoaded() {
|
|
8417
|
-
if (this.plugins) {
|
|
8418
|
-
return this.plugins;
|
|
8419
|
-
}
|
|
8420
|
-
if (this.loadPromise) {
|
|
8421
|
-
return this.loadPromise;
|
|
8422
|
-
}
|
|
8423
|
-
this.loadPromise = this.loadCompiledPlugins();
|
|
8424
|
-
try {
|
|
8425
|
-
this.plugins = await this.loadPromise;
|
|
8426
|
-
return this.plugins;
|
|
8427
|
-
} finally {
|
|
8428
|
-
this.loadPromise = null;
|
|
8429
|
-
}
|
|
8430
|
-
}
|
|
8431
|
-
resolveBinPath(binName) {
|
|
8432
|
-
const candidates = [this.localBinDir].filter(Boolean).map((dir) => resolve37(dir, binName));
|
|
8433
|
-
return candidates.find((candidate) => existsSync33(candidate));
|
|
8434
|
-
}
|
|
8435
|
-
async loadCompiledPlugins() {
|
|
8436
|
-
const plugins = [];
|
|
8437
|
-
for (const file of this.pluginFiles) {
|
|
8438
|
-
const binName = basename10(file).replace(/\.plugin\.(ts|js|mjs|cjs)$/, "");
|
|
8439
|
-
let binPath = this.resolveBinPath(binName);
|
|
8440
|
-
if (!binPath) {
|
|
8441
|
-
const triedPaths = [this.localBinDir].filter(Boolean).map((dir) => resolve37(dir, binName));
|
|
8442
|
-
const missingError = `Compiled plugin binary not found for '${binName}'. Tried: ${triedPaths.join(", ")}`;
|
|
8443
|
-
await this.eventBus.emit("plugin.error", {
|
|
8444
|
-
file: resolve37(this.pluginDir, file),
|
|
8445
|
-
phase: "load",
|
|
8446
|
-
error: missingError
|
|
8447
|
-
});
|
|
8448
|
-
if (this.pluginsRequireBinaries) {
|
|
8449
|
-
throw new Error(missingError);
|
|
8450
|
-
}
|
|
8451
|
-
plugins.push({
|
|
8452
|
-
name: binName,
|
|
8453
|
-
validators: []
|
|
8454
|
-
});
|
|
8455
|
-
await this.eventBus.emit("plugin.loaded", {
|
|
8456
|
-
plugin: binName,
|
|
8457
|
-
file: resolve37(this.pluginDir, file),
|
|
8458
|
-
source: "metadata-only"
|
|
8459
|
-
});
|
|
8460
|
-
continue;
|
|
8461
|
-
}
|
|
8462
|
-
const wrapper = createBinaryPluginWrapper(binName, binPath, this.context.projectRoot);
|
|
8463
|
-
plugins.push(wrapper);
|
|
8464
|
-
await this.eventBus.emit("plugin.loaded", {
|
|
8465
|
-
plugin: wrapper.name,
|
|
8466
|
-
file: binPath,
|
|
8467
|
-
source: "compiled-binary"
|
|
8468
|
-
});
|
|
8469
|
-
}
|
|
8470
|
-
return plugins;
|
|
8471
|
-
}
|
|
8472
|
-
}
|
|
8473
|
-
function createBinaryPluginWrapper(name, binPath, projectRoot) {
|
|
8474
|
-
return {
|
|
8475
|
-
name,
|
|
8476
|
-
validators: [
|
|
8477
|
-
{
|
|
8478
|
-
id: `${name}:compiled`,
|
|
8479
|
-
async run(ctx) {
|
|
8480
|
-
const proc = Bun.spawn([binPath, "--validate", ctx.taskId, ctx.projectRoot], {
|
|
8481
|
-
cwd: projectRoot,
|
|
8482
|
-
stdout: "pipe",
|
|
8483
|
-
stderr: "pipe"
|
|
8484
|
-
});
|
|
8485
|
-
const exitCode = await proc.exited;
|
|
8486
|
-
const stdout = await new Response(proc.stdout).text();
|
|
8487
|
-
const stderr = await new Response(proc.stderr).text();
|
|
8488
|
-
if (exitCode !== 0) {
|
|
8489
|
-
return {
|
|
8490
|
-
id: `${name}:compiled`,
|
|
8491
|
-
passed: false,
|
|
8492
|
-
summary: `Plugin binary ${name} exited with code ${exitCode}`,
|
|
8493
|
-
details: stderr || stdout
|
|
8494
|
-
};
|
|
8495
|
-
}
|
|
8496
|
-
try {
|
|
8497
|
-
const results = JSON.parse(stdout.trim());
|
|
8498
|
-
const failed = results.filter((r) => !r.passed);
|
|
8499
|
-
if (failed.length > 0) {
|
|
8500
|
-
return {
|
|
8501
|
-
id: `${name}:compiled`,
|
|
8502
|
-
passed: false,
|
|
8503
|
-
summary: `${failed.length} of ${results.length} validator(s) failed`,
|
|
8504
|
-
details: failed.map((f) => `${f.id}: ${f.summary}`).join(`
|
|
8505
|
-
`)
|
|
8506
|
-
};
|
|
8507
|
-
}
|
|
8508
|
-
return {
|
|
8509
|
-
id: `${name}:compiled`,
|
|
8510
|
-
passed: true,
|
|
8511
|
-
summary: `All ${results.length} validator(s) passed`
|
|
8512
|
-
};
|
|
8513
|
-
} catch {
|
|
8514
|
-
return {
|
|
8515
|
-
id: `${name}:compiled`,
|
|
8516
|
-
passed: false,
|
|
8517
|
-
summary: `Failed to parse output from compiled plugin ${name}`,
|
|
8518
|
-
details: stdout.slice(0, 500)
|
|
8519
|
-
};
|
|
8520
|
-
}
|
|
8521
|
-
}
|
|
8522
|
-
}
|
|
8523
|
-
]
|
|
8524
|
-
};
|
|
8525
|
-
}
|
|
8526
|
-
function safeReadDir(path) {
|
|
8527
|
-
try {
|
|
8528
|
-
return readdirSync6(path, { withFileTypes: true }).filter((entry) => entry.isFile()).map((entry) => entry.name).sort();
|
|
8529
|
-
} catch {
|
|
8530
|
-
return [];
|
|
8531
|
-
}
|
|
8532
|
-
}
|
|
8533
8303
|
export {
|
|
8534
8304
|
writeRuntimeContext,
|
|
8535
8305
|
taskRuntimeId,
|
|
@@ -8551,7 +8321,6 @@ export {
|
|
|
8551
8321
|
cleanupAgentRuntime,
|
|
8552
8322
|
agentId,
|
|
8553
8323
|
RUNTIME_CONTEXT_ENV,
|
|
8554
|
-
PluginManager,
|
|
8555
8324
|
POLICY_VERSION,
|
|
8556
8325
|
GeneralCliEventBus as EventBus
|
|
8557
8326
|
};
|