@h-rig/cli 0.0.6-alpha.60 → 0.0.6-alpha.62
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.js +316 -134
- package/dist/src/commands/_authority-runs.js +2 -3
- package/dist/src/commands/_help-catalog.js +1 -0
- package/dist/src/commands/_run-driver-helpers.js +12 -17
- package/dist/src/commands/_run-replay.js +142 -0
- package/dist/src/commands/agent.js +2 -3
- package/dist/src/commands/run.js +216 -38
- package/dist/src/commands/server.js +4 -5
- package/dist/src/commands/task-run-driver.js +29 -26
- package/dist/src/commands/task.js +4 -4
- package/dist/src/commands.js +308 -126
- package/dist/src/index.js +316 -134
- package/package.json +7 -7
package/dist/src/index.js
CHANGED
|
@@ -527,10 +527,10 @@ var init_plugin = __esm(() => {
|
|
|
527
527
|
// packages/cli/src/commands.ts
|
|
528
528
|
init_runner();
|
|
529
529
|
import {
|
|
530
|
-
existsSync as
|
|
530
|
+
existsSync as existsSync17,
|
|
531
531
|
readFileSync as readFileSync12
|
|
532
532
|
} from "fs";
|
|
533
|
-
import { resolve as
|
|
533
|
+
import { resolve as resolve26 } from "path";
|
|
534
534
|
import { readBuildConfig } from "@rig/runtime/build-time-config";
|
|
535
535
|
|
|
536
536
|
// packages/cli/src/commands/browser.ts
|
|
@@ -3617,8 +3617,7 @@ import { resolve as resolve12 } from "path";
|
|
|
3617
3617
|
import {
|
|
3618
3618
|
readAuthorityRun,
|
|
3619
3619
|
readJsonlFile as readJsonlFile2,
|
|
3620
|
-
|
|
3621
|
-
writeJsonFile as writeJsonFile3
|
|
3620
|
+
writeAuthorityRunRecord
|
|
3622
3621
|
} from "@rig/runtime/control-plane/authority-files";
|
|
3623
3622
|
var RIG_WORKSPACE_ID = "rig-local-workspace";
|
|
3624
3623
|
function normalizeRuntimeAdapter(value) {
|
|
@@ -3704,7 +3703,7 @@ function upsertAgentAuthorityRun(projectRoot, input) {
|
|
|
3704
3703
|
} else if ("errorText" in next) {
|
|
3705
3704
|
delete next.errorText;
|
|
3706
3705
|
}
|
|
3707
|
-
|
|
3706
|
+
writeAuthorityRunRecord(projectRoot, input.runId, next);
|
|
3708
3707
|
return next;
|
|
3709
3708
|
}
|
|
3710
3709
|
|
|
@@ -4268,7 +4267,7 @@ import { resolve as resolve15 } from "path";
|
|
|
4268
4267
|
import {
|
|
4269
4268
|
listAuthorityRuns,
|
|
4270
4269
|
readJsonlFile as readJsonlFile3,
|
|
4271
|
-
resolveAuthorityRunDir
|
|
4270
|
+
resolveAuthorityRunDir
|
|
4272
4271
|
} from "@rig/runtime/control-plane/authority-files";
|
|
4273
4272
|
|
|
4274
4273
|
// packages/cli/src/commands/_cli-format.ts
|
|
@@ -4666,7 +4665,7 @@ async function listRemoteInboxRecords(context, kind, filters) {
|
|
|
4666
4665
|
function listLocalInboxRecords(context, kind, filters) {
|
|
4667
4666
|
const fileName = kind === "approvals" ? "approvals.jsonl" : "user-input.jsonl";
|
|
4668
4667
|
const runs = listAuthorityRuns(context.projectRoot).filter((entry) => (!filters.run || entry.runId === filters.run) && (!filters.task || entry.taskId === filters.task));
|
|
4669
|
-
return runs.flatMap((entry) => readJsonlFile3(resolve15(
|
|
4668
|
+
return runs.flatMap((entry) => readJsonlFile3(resolve15(resolveAuthorityRunDir(context.projectRoot, entry.runId), fileName)).map((record) => ({
|
|
4670
4669
|
runId: entry.runId,
|
|
4671
4670
|
taskId: entry.taskId ?? undefined,
|
|
4672
4671
|
record
|
|
@@ -4714,7 +4713,7 @@ async function executeInbox(context, args) {
|
|
|
4714
4713
|
if (isRemoteConnectionSelected(context.projectRoot)) {
|
|
4715
4714
|
throw new CliError2("Remote approval resolution is not available from this CLI yet; use the server UI/API or switch to local state for direct JSONL edits.", 2);
|
|
4716
4715
|
}
|
|
4717
|
-
const approvalsPath = resolve15(
|
|
4716
|
+
const approvalsPath = resolve15(resolveAuthorityRunDir(context.projectRoot, run.value), "approvals.jsonl");
|
|
4718
4717
|
const approvals = readJsonlFile3(approvalsPath);
|
|
4719
4718
|
const resolvedAt = new Date().toISOString();
|
|
4720
4719
|
const next = approvals.map((entry) => entry.requestId === request.value || entry.id === request.value ? { ...entry, status: "resolved", decision: decision.value, note: note4.value ?? null, resolvedAt } : entry);
|
|
@@ -4770,7 +4769,7 @@ async function executeInbox(context, args) {
|
|
|
4770
4769
|
const [key, ...restValue] = entry.split("=");
|
|
4771
4770
|
return [key, restValue.join("=")];
|
|
4772
4771
|
}));
|
|
4773
|
-
const requestsPath = resolve15(
|
|
4772
|
+
const requestsPath = resolve15(resolveAuthorityRunDir(context.projectRoot, run.value), "user-input.jsonl");
|
|
4774
4773
|
const requests = readJsonlFile3(requestsPath);
|
|
4775
4774
|
const resolvedAt = new Date().toISOString();
|
|
4776
4775
|
const next = requests.map((entry) => entry.requestId === request.value || entry.id === request.value ? { ...entry, status: "resolved", answers: parsedAnswers, respondedAt: resolvedAt, resolvedAt } : entry);
|
|
@@ -6237,27 +6236,23 @@ init_runner();
|
|
|
6237
6236
|
import { readFileSync as readFileSync8 } from "fs";
|
|
6238
6237
|
import { resolve as resolve20 } from "path";
|
|
6239
6238
|
import {
|
|
6240
|
-
appendJsonlRecord as appendJsonlRecord2,
|
|
6241
6239
|
appendRunLifecycleEvent,
|
|
6240
|
+
appendRunLogEntry,
|
|
6241
|
+
appendRunTimelineEntry,
|
|
6242
|
+
patchAuthorityRunRecord,
|
|
6242
6243
|
readAuthorityRun as readAuthorityRun2,
|
|
6243
|
-
resolveAuthorityRunDir as
|
|
6244
|
-
writeJsonFile as
|
|
6244
|
+
resolveAuthorityRunDir as resolveAuthorityRunDir2,
|
|
6245
|
+
writeJsonFile as writeJsonFile3
|
|
6245
6246
|
} from "@rig/runtime/control-plane/authority-files";
|
|
6246
6247
|
import { taskLookup } from "@rig/runtime/control-plane/native/task-ops";
|
|
6247
6248
|
import { readPriorPrProgressPromptSection } from "@rig/runtime/control-plane/prompt-context";
|
|
6248
6249
|
import { buildProviderTaskRunInstructionLines } from "@rig/runtime/control-plane/provider/runtime-instructions";
|
|
6249
6250
|
import { loadRigTaskRunSkillBody } from "@rig/runtime/control-plane/provider/rig-task-run-skill";
|
|
6250
6251
|
function patchAuthorityRun(projectRoot, runId, patch) {
|
|
6251
|
-
const
|
|
6252
|
-
if (!
|
|
6252
|
+
const next = patchAuthorityRunRecord(projectRoot, runId, patch);
|
|
6253
|
+
if (!next) {
|
|
6253
6254
|
throw new CliError2(`Run not found: ${runId}`, 2);
|
|
6254
6255
|
}
|
|
6255
|
-
const next = {
|
|
6256
|
-
...current,
|
|
6257
|
-
...patch,
|
|
6258
|
-
updatedAt: new Date().toISOString()
|
|
6259
|
-
};
|
|
6260
|
-
writeJsonFile4(resolve20(resolveAuthorityRunDir3(projectRoot, runId), "run.json"), next);
|
|
6261
6256
|
return next;
|
|
6262
6257
|
}
|
|
6263
6258
|
function touchAuthorityRun(projectRoot, runId) {
|
|
@@ -6265,21 +6260,21 @@ function touchAuthorityRun(projectRoot, runId) {
|
|
|
6265
6260
|
if (!current) {
|
|
6266
6261
|
return;
|
|
6267
6262
|
}
|
|
6268
|
-
|
|
6263
|
+
writeJsonFile3(resolve20(resolveAuthorityRunDir2(projectRoot, runId), "run.json"), {
|
|
6269
6264
|
...current,
|
|
6270
6265
|
updatedAt: new Date().toISOString()
|
|
6271
6266
|
});
|
|
6272
6267
|
}
|
|
6273
6268
|
function appendRunTimeline(projectRoot, runId, value) {
|
|
6274
|
-
|
|
6269
|
+
appendRunTimelineEntry(projectRoot, runId, value);
|
|
6275
6270
|
touchAuthorityRun(projectRoot, runId);
|
|
6276
6271
|
}
|
|
6277
6272
|
function appendRunLog(projectRoot, runId, value) {
|
|
6278
|
-
|
|
6273
|
+
appendRunLogEntry(projectRoot, runId, value);
|
|
6279
6274
|
touchAuthorityRun(projectRoot, runId);
|
|
6280
6275
|
}
|
|
6281
6276
|
function appendRunAction(projectRoot, runId, value) {
|
|
6282
|
-
|
|
6277
|
+
appendRunTimelineEntry(projectRoot, runId, {
|
|
6283
6278
|
id: value.id,
|
|
6284
6279
|
type: "action",
|
|
6285
6280
|
actionType: value.actionType,
|
|
@@ -6500,7 +6495,7 @@ import { resolve as resolve21 } from "path";
|
|
|
6500
6495
|
import {
|
|
6501
6496
|
listAuthorityRuns as listAuthorityRuns2,
|
|
6502
6497
|
readAuthorityRun as readAuthorityRun3,
|
|
6503
|
-
resolveAuthorityRunDir as
|
|
6498
|
+
resolveAuthorityRunDir as resolveAuthorityRunDir3,
|
|
6504
6499
|
resolveTaskArtifactDirs
|
|
6505
6500
|
} from "@rig/runtime/control-plane/authority-files";
|
|
6506
6501
|
import { changedFilesForTask } from "@rig/runtime/control-plane/native/task-ops";
|
|
@@ -6534,7 +6529,7 @@ async function executeInspect(context, args) {
|
|
|
6534
6529
|
}
|
|
6535
6530
|
return { ok: true, group: "inspect", command, details: { task: requiredTask, runId: serverRun.runId, source: "server", entries } };
|
|
6536
6531
|
}
|
|
6537
|
-
const logsPath = resolve21(
|
|
6532
|
+
const logsPath = resolve21(resolveAuthorityRunDir3(context.projectRoot, latestRun.runId), "logs.jsonl");
|
|
6538
6533
|
if (!existsSync13(logsPath)) {
|
|
6539
6534
|
throw new CliError2(`No logs found for run ${latestRun.runId}.`);
|
|
6540
6535
|
}
|
|
@@ -7264,7 +7259,7 @@ init__parsers();
|
|
|
7264
7259
|
import { createInterface as createInterface2 } from "readline/promises";
|
|
7265
7260
|
import {
|
|
7266
7261
|
listAuthorityRuns as listAuthorityRuns3,
|
|
7267
|
-
readAuthorityRun as
|
|
7262
|
+
readAuthorityRun as readAuthorityRun5
|
|
7268
7263
|
} from "@rig/runtime/control-plane/authority-files";
|
|
7269
7264
|
import {
|
|
7270
7265
|
cleanupRunState,
|
|
@@ -7280,6 +7275,144 @@ import {
|
|
|
7280
7275
|
} from "@rig/runtime/control-plane/native/run-ops";
|
|
7281
7276
|
import { loadRuntimeContextFromEnv } from "@rig/runtime/control-plane/runtime/context";
|
|
7282
7277
|
|
|
7278
|
+
// packages/cli/src/commands/_run-replay.ts
|
|
7279
|
+
import { existsSync as existsSync14, readdirSync as readdirSync2 } from "fs";
|
|
7280
|
+
import { join as join2, resolve as resolve22 } from "path";
|
|
7281
|
+
import {
|
|
7282
|
+
readAuthorityRun as readAuthorityRun4,
|
|
7283
|
+
readJsonlFile as readJsonlFile4,
|
|
7284
|
+
runLifecycleLogPath
|
|
7285
|
+
} from "@rig/runtime/control-plane/authority-files";
|
|
7286
|
+
function asRecord(value) {
|
|
7287
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
7288
|
+
}
|
|
7289
|
+
function text2(value) {
|
|
7290
|
+
return typeof value === "string" && value.trim().length > 0 ? value.trim() : null;
|
|
7291
|
+
}
|
|
7292
|
+
function snippet(value, max = 120) {
|
|
7293
|
+
const raw = text2(value);
|
|
7294
|
+
if (!raw)
|
|
7295
|
+
return null;
|
|
7296
|
+
const flat = raw.replace(/\s+/g, " ");
|
|
7297
|
+
return flat.length > max ? `${flat.slice(0, max - 1)}\u2026` : flat;
|
|
7298
|
+
}
|
|
7299
|
+
function summarizeLifecycleEntry(entry) {
|
|
7300
|
+
const type = text2(entry.type) ?? "event";
|
|
7301
|
+
switch (type) {
|
|
7302
|
+
case "status": {
|
|
7303
|
+
const anchor = text2(entry.sessionId);
|
|
7304
|
+
return [
|
|
7305
|
+
`status \u2192 ${text2(entry.status) ?? "(unknown)"}`,
|
|
7306
|
+
snippet(entry.detail) ? `\u2014 ${snippet(entry.detail)}` : null,
|
|
7307
|
+
anchor ? `[session ${anchor}]` : null
|
|
7308
|
+
].filter(Boolean).join(" ");
|
|
7309
|
+
}
|
|
7310
|
+
case "timeline-entry": {
|
|
7311
|
+
const payload = asRecord(entry.payload) ?? {};
|
|
7312
|
+
const kind = text2(payload.type) ?? "entry";
|
|
7313
|
+
const body = snippet(payload.title) ?? snippet(payload.text) ?? snippet(payload.detail);
|
|
7314
|
+
const state = text2(payload.state);
|
|
7315
|
+
return [`timeline ${kind}`, body ? `\u2014 ${body}` : null, state ? `(${state})` : null].filter(Boolean).join(" ");
|
|
7316
|
+
}
|
|
7317
|
+
case "log-entry": {
|
|
7318
|
+
const payload = asRecord(entry.payload) ?? {};
|
|
7319
|
+
const title = snippet(payload.title) ?? "log";
|
|
7320
|
+
const detail = snippet(payload.detail);
|
|
7321
|
+
return [`log ${title}`, detail ? `\u2014 ${detail}` : null].filter(Boolean).join(" ");
|
|
7322
|
+
}
|
|
7323
|
+
case "record-patch": {
|
|
7324
|
+
const patch = asRecord(entry.patch) ?? {};
|
|
7325
|
+
const keys = Object.keys(patch);
|
|
7326
|
+
const shown = keys.slice(0, 8).join(", ");
|
|
7327
|
+
return `record-patch {${shown}${keys.length > 8 ? `, +${keys.length - 8} more` : ""}}`;
|
|
7328
|
+
}
|
|
7329
|
+
case "timeline":
|
|
7330
|
+
return "timeline updated (signal)";
|
|
7331
|
+
case "log":
|
|
7332
|
+
return `log signal${snippet(entry.title) ? ` \u2014 ${snippet(entry.title)}` : ""}`;
|
|
7333
|
+
case "completed":
|
|
7334
|
+
return "run completed";
|
|
7335
|
+
case "failed":
|
|
7336
|
+
return `run failed${snippet(entry.error) ? ` \u2014 ${snippet(entry.error)}` : ""}`;
|
|
7337
|
+
default:
|
|
7338
|
+
return type;
|
|
7339
|
+
}
|
|
7340
|
+
}
|
|
7341
|
+
function summarizeSessionEntry(entry) {
|
|
7342
|
+
const type = text2(entry.type) ?? "entry";
|
|
7343
|
+
const message2 = asRecord(entry.message);
|
|
7344
|
+
const role = text2(message2?.role);
|
|
7345
|
+
const content = message2?.content;
|
|
7346
|
+
let body = null;
|
|
7347
|
+
if (typeof content === "string") {
|
|
7348
|
+
body = snippet(content);
|
|
7349
|
+
} else if (Array.isArray(content)) {
|
|
7350
|
+
body = snippet(content.map((part) => text2(asRecord(part)?.text) ?? "").filter(Boolean).join(" "));
|
|
7351
|
+
}
|
|
7352
|
+
return [
|
|
7353
|
+
`pi ${type}`,
|
|
7354
|
+
role ? `(${role})` : null,
|
|
7355
|
+
body ? `\u2014 ${body}` : null
|
|
7356
|
+
].filter(Boolean).join(" ");
|
|
7357
|
+
}
|
|
7358
|
+
function sessionEntryTimestamp(entry) {
|
|
7359
|
+
return text2(entry.timestamp) ?? text2(entry.at) ?? text2(entry.createdAt) ?? null;
|
|
7360
|
+
}
|
|
7361
|
+
function resolveRunSessionFile(record) {
|
|
7362
|
+
const piSession = record?.piSession ?? null;
|
|
7363
|
+
if (!piSession)
|
|
7364
|
+
return null;
|
|
7365
|
+
const recorded = text2(piSession.sessionFile);
|
|
7366
|
+
if (recorded && existsSync14(recorded)) {
|
|
7367
|
+
return recorded;
|
|
7368
|
+
}
|
|
7369
|
+
const cwd = text2(piSession.cwd);
|
|
7370
|
+
const sessionId = text2(piSession.sessionId);
|
|
7371
|
+
if (!cwd || !sessionId)
|
|
7372
|
+
return null;
|
|
7373
|
+
const sessionDir = resolve22(cwd, ".rig", "session");
|
|
7374
|
+
try {
|
|
7375
|
+
const match = readdirSync2(sessionDir).find((name) => name.endsWith(`_${sessionId}.jsonl`));
|
|
7376
|
+
return match ? join2(sessionDir, match) : null;
|
|
7377
|
+
} catch {
|
|
7378
|
+
return null;
|
|
7379
|
+
}
|
|
7380
|
+
}
|
|
7381
|
+
function buildRunReplay(projectRoot, runId, options = {}) {
|
|
7382
|
+
const logPath = runLifecycleLogPath(projectRoot, runId);
|
|
7383
|
+
const record = readAuthorityRun4(projectRoot, runId);
|
|
7384
|
+
const lifecycleEntries = readJsonlFile4(logPath).map((entry) => asRecord(entry)).filter((entry) => entry !== null);
|
|
7385
|
+
const merged = lifecycleEntries.map((entry) => ({
|
|
7386
|
+
at: text2(entry.at),
|
|
7387
|
+
source: "run",
|
|
7388
|
+
summary: summarizeLifecycleEntry(entry)
|
|
7389
|
+
}));
|
|
7390
|
+
let sessionFile = null;
|
|
7391
|
+
let sessionEntryCount = 0;
|
|
7392
|
+
if (options.withSession) {
|
|
7393
|
+
sessionFile = resolveRunSessionFile(record);
|
|
7394
|
+
if (sessionFile) {
|
|
7395
|
+
let lastSeenAt = null;
|
|
7396
|
+
const sessionLines = readJsonlFile4(sessionFile).map((entry) => asRecord(entry)).filter((entry) => entry !== null).map((entry) => {
|
|
7397
|
+
lastSeenAt = sessionEntryTimestamp(entry) ?? lastSeenAt;
|
|
7398
|
+
return { at: lastSeenAt, source: "session", summary: summarizeSessionEntry(entry) };
|
|
7399
|
+
});
|
|
7400
|
+
sessionEntryCount = sessionLines.length;
|
|
7401
|
+
merged.push(...sessionLines);
|
|
7402
|
+
merged.sort((left, right) => (left.at ?? "").localeCompare(right.at ?? ""));
|
|
7403
|
+
}
|
|
7404
|
+
}
|
|
7405
|
+
const lines = merged.map((line) => `${line.at ?? "(no timestamp) "} ${line.source === "run" ? "run " : "session"} ${line.summary}`);
|
|
7406
|
+
return {
|
|
7407
|
+
runId,
|
|
7408
|
+
logPath,
|
|
7409
|
+
sessionFile,
|
|
7410
|
+
entryCount: lifecycleEntries.length,
|
|
7411
|
+
sessionEntryCount,
|
|
7412
|
+
lines
|
|
7413
|
+
};
|
|
7414
|
+
}
|
|
7415
|
+
|
|
7283
7416
|
// packages/cli/src/commands/_operator-surface.ts
|
|
7284
7417
|
import { createInterface } from "readline";
|
|
7285
7418
|
import { createInterface as createPromptInterface } from "readline/promises";
|
|
@@ -7378,22 +7511,22 @@ function createPiRunStreamRenderer(output = process.stdout) {
|
|
|
7378
7511
|
for (const [index, entry] of entries.entries()) {
|
|
7379
7512
|
const id = entryId(entry, `timeline:${index}:${String(entry.cursor ?? "")}`);
|
|
7380
7513
|
if (entry.type === "assistant_message" && typeof entry.text === "string") {
|
|
7381
|
-
const
|
|
7514
|
+
const text3 = entry.text;
|
|
7382
7515
|
const previousText = assistantTextById.get(id) ?? "";
|
|
7383
|
-
if (!previousText &&
|
|
7516
|
+
if (!previousText && text3.trim()) {
|
|
7384
7517
|
writeLine("[Pi assistant]");
|
|
7385
7518
|
}
|
|
7386
|
-
if (
|
|
7387
|
-
const delta =
|
|
7519
|
+
if (text3.startsWith(previousText)) {
|
|
7520
|
+
const delta = text3.slice(previousText.length);
|
|
7388
7521
|
if (delta)
|
|
7389
7522
|
output.write(delta);
|
|
7390
|
-
} else if (
|
|
7523
|
+
} else if (text3.trim() && text3 !== previousText) {
|
|
7391
7524
|
if (previousText)
|
|
7392
7525
|
writeLine(`
|
|
7393
7526
|
[Pi assistant]`);
|
|
7394
|
-
output.write(
|
|
7527
|
+
output.write(text3);
|
|
7395
7528
|
}
|
|
7396
|
-
assistantTextById.set(id,
|
|
7529
|
+
assistantTextById.set(id, text3);
|
|
7397
7530
|
continue;
|
|
7398
7531
|
}
|
|
7399
7532
|
if (seenTimeline.has(id))
|
|
@@ -7408,15 +7541,15 @@ function createPiRunStreamRenderer(output = process.stdout) {
|
|
|
7408
7541
|
continue;
|
|
7409
7542
|
}
|
|
7410
7543
|
if (entry.type === "action") {
|
|
7411
|
-
const
|
|
7412
|
-
if (
|
|
7413
|
-
writeLine(`[Rig action] ${
|
|
7544
|
+
const text3 = String(entry.detail ?? entry.message ?? entry.title ?? "").trim();
|
|
7545
|
+
if (text3)
|
|
7546
|
+
writeLine(`[Rig action] ${text3}`);
|
|
7414
7547
|
continue;
|
|
7415
7548
|
}
|
|
7416
7549
|
if (entry.type === "user_message") {
|
|
7417
|
-
const
|
|
7418
|
-
if (
|
|
7419
|
-
writeLine(`[Operator] ${
|
|
7550
|
+
const text3 = String(entry.text ?? entry.message ?? entry.detail ?? "").trim();
|
|
7551
|
+
if (text3)
|
|
7552
|
+
writeLine(`[Operator] ${text3}`);
|
|
7420
7553
|
continue;
|
|
7421
7554
|
}
|
|
7422
7555
|
const fallback = String(entry.detail ?? entry.message ?? entry.text ?? entry.title ?? "").trim();
|
|
@@ -7496,7 +7629,7 @@ async function promptForTaskSelection(question) {
|
|
|
7496
7629
|
// packages/cli/src/commands/_pi-frontend.ts
|
|
7497
7630
|
import { mkdtempSync, rmSync as rmSync5 } from "fs";
|
|
7498
7631
|
import { tmpdir } from "os";
|
|
7499
|
-
import { join as
|
|
7632
|
+
import { join as join3 } from "path";
|
|
7500
7633
|
import {
|
|
7501
7634
|
createAgentSessionFromServices,
|
|
7502
7635
|
createAgentSessionServices,
|
|
@@ -7628,15 +7761,15 @@ class RigRemoteSessionController {
|
|
|
7628
7761
|
for (const compaction of this.pendingCompactions.splice(0))
|
|
7629
7762
|
compaction.reject(new Error("Remote session closed."));
|
|
7630
7763
|
}
|
|
7631
|
-
async sendPrompt(
|
|
7632
|
-
await this.transport.sendPrompt(this.context, this.runId,
|
|
7764
|
+
async sendPrompt(text3, streamingBehavior) {
|
|
7765
|
+
await this.transport.sendPrompt(this.context, this.runId, text3, streamingBehavior);
|
|
7633
7766
|
}
|
|
7634
|
-
async sendCommand(
|
|
7635
|
-
const result = await this.transport.runCommand(this.context, this.runId,
|
|
7767
|
+
async sendCommand(text3) {
|
|
7768
|
+
const result = await this.transport.runCommand(this.context, this.runId, text3);
|
|
7636
7769
|
return typeof result.message === "string" ? result.message : "worker command accepted";
|
|
7637
7770
|
}
|
|
7638
|
-
async sendShell(
|
|
7639
|
-
await this.transport.sendShell(this.context, this.runId,
|
|
7771
|
+
async sendShell(text3) {
|
|
7772
|
+
await this.transport.sendShell(this.context, this.runId, text3);
|
|
7640
7773
|
}
|
|
7641
7774
|
async abort() {
|
|
7642
7775
|
await this.transport.abort(this.context, this.runId);
|
|
@@ -7788,8 +7921,8 @@ class RigRemoteAgentSession extends PiAgentSession {
|
|
|
7788
7921
|
replaceRemoteMessages(messages) {
|
|
7789
7922
|
this.agent.state.messages = messages;
|
|
7790
7923
|
}
|
|
7791
|
-
async expandLocalInput(
|
|
7792
|
-
let current =
|
|
7924
|
+
async expandLocalInput(text3) {
|
|
7925
|
+
let current = text3;
|
|
7793
7926
|
const runner = this.extensionRunner;
|
|
7794
7927
|
if (runner.hasHandlers("input")) {
|
|
7795
7928
|
const result = await runner.emitInput(current, undefined, "interactive");
|
|
@@ -7802,8 +7935,8 @@ class RigRemoteAgentSession extends PiAgentSession {
|
|
|
7802
7935
|
current = expandPromptTemplate(current, [...this.promptTemplates]);
|
|
7803
7936
|
return current;
|
|
7804
7937
|
}
|
|
7805
|
-
async prompt(
|
|
7806
|
-
const trimmed =
|
|
7938
|
+
async prompt(text3, options) {
|
|
7939
|
+
const trimmed = text3.trim();
|
|
7807
7940
|
if (!trimmed)
|
|
7808
7941
|
return;
|
|
7809
7942
|
if (trimmed.startsWith("/")) {
|
|
@@ -7832,8 +7965,8 @@ class RigRemoteAgentSession extends PiAgentSession {
|
|
|
7832
7965
|
options?.preflightResult?.(true);
|
|
7833
7966
|
await this.remote.sendPrompt(expanded, behavior);
|
|
7834
7967
|
}
|
|
7835
|
-
async steer(
|
|
7836
|
-
const trimmed =
|
|
7968
|
+
async steer(text3) {
|
|
7969
|
+
const trimmed = text3.trim();
|
|
7837
7970
|
if (trimmed.startsWith("/") && await this._tryExecuteExtensionCommand(trimmed))
|
|
7838
7971
|
return;
|
|
7839
7972
|
const expanded = await this.expandLocalInput(trimmed);
|
|
@@ -7841,8 +7974,8 @@ class RigRemoteAgentSession extends PiAgentSession {
|
|
|
7841
7974
|
return;
|
|
7842
7975
|
await this.remote.sendPrompt(expanded, "steer");
|
|
7843
7976
|
}
|
|
7844
|
-
async followUp(
|
|
7845
|
-
const trimmed =
|
|
7977
|
+
async followUp(text3) {
|
|
7978
|
+
const trimmed = text3.trim();
|
|
7846
7979
|
if (trimmed.startsWith("/") && await this._tryExecuteExtensionCommand(trimmed))
|
|
7847
7980
|
return;
|
|
7848
7981
|
const expanded = await this.expandLocalInput(trimmed);
|
|
@@ -7854,8 +7987,8 @@ class RigRemoteAgentSession extends PiAgentSession {
|
|
|
7854
7987
|
await this.remote.abort();
|
|
7855
7988
|
}
|
|
7856
7989
|
async compact(customInstructions) {
|
|
7857
|
-
const pending = new Promise((
|
|
7858
|
-
this.remote.registerPendingCompaction({ resolve:
|
|
7990
|
+
const pending = new Promise((resolve23, reject) => {
|
|
7991
|
+
this.remote.registerPendingCompaction({ resolve: resolve23, reject });
|
|
7859
7992
|
});
|
|
7860
7993
|
await this.remote.sendCommand(`/compact${customInstructions ? ` ${customInstructions}` : ""}`);
|
|
7861
7994
|
return pending;
|
|
@@ -7924,8 +8057,8 @@ class RigRemoteAgentSession extends PiAgentSession {
|
|
|
7924
8057
|
function createRemoteBashOperations(controller, excludeFromContext) {
|
|
7925
8058
|
return {
|
|
7926
8059
|
exec(command, _cwd, execOptions) {
|
|
7927
|
-
return new Promise((
|
|
7928
|
-
const pending = { onData: execOptions.onData, resolve:
|
|
8060
|
+
return new Promise((resolve23, reject) => {
|
|
8061
|
+
const pending = { onData: execOptions.onData, resolve: resolve23, reject, sawChunk: false };
|
|
7929
8062
|
const cleanup = () => {
|
|
7930
8063
|
execOptions.signal?.removeEventListener("abort", onAbort);
|
|
7931
8064
|
if (timer)
|
|
@@ -8089,8 +8222,8 @@ function createRigWorkerPiBridgeExtension(options) {
|
|
|
8089
8222
|
const prefix = busy ? `${SPINNER_FRAMES[frame]} ` : connected ? "\u25CF " : "\u25CB ";
|
|
8090
8223
|
ctx.ui.setStatus("rig-worker-pi", `${prefix}${statusText}`);
|
|
8091
8224
|
};
|
|
8092
|
-
const setStatus = (ctx,
|
|
8093
|
-
statusText =
|
|
8225
|
+
const setStatus = (ctx, text3, isBusy) => {
|
|
8226
|
+
statusText = text3;
|
|
8094
8227
|
busy = isBusy;
|
|
8095
8228
|
renderStatus(ctx);
|
|
8096
8229
|
};
|
|
@@ -8134,7 +8267,7 @@ function createRigWorkerPiBridgeExtension(options) {
|
|
|
8134
8267
|
ctx.ui.notify("Initial message sent to the worker Pi daemon.", "info");
|
|
8135
8268
|
const nativeUi = ctx.ui;
|
|
8136
8269
|
options.controller.setUiHooks({
|
|
8137
|
-
onStatusText: (
|
|
8270
|
+
onStatusText: (text3) => setStatus(ctx, text3, !connected),
|
|
8138
8271
|
onActivity: (label, detail) => {
|
|
8139
8272
|
const active = label !== "idle" && !/complete|ready/i.test(label);
|
|
8140
8273
|
setStatus(ctx, [label, detail].filter(Boolean).join(" \u2014 "), active);
|
|
@@ -8191,7 +8324,7 @@ function setTemporaryEnv(updates) {
|
|
|
8191
8324
|
};
|
|
8192
8325
|
}
|
|
8193
8326
|
async function attachRunBundledPiFrontend(context, input) {
|
|
8194
|
-
const tempSessionDir = mkdtempSync(
|
|
8327
|
+
const tempSessionDir = mkdtempSync(join3(tmpdir(), "rig-pi-frontend-sessions-"));
|
|
8195
8328
|
const restoreEnv = setTemporaryEnv({
|
|
8196
8329
|
PI_CODING_AGENT_SESSION_DIR: tempSessionDir,
|
|
8197
8330
|
PI_SKIP_VERSION_CHECK: "1",
|
|
@@ -8511,7 +8644,7 @@ async function executeRun(context, args) {
|
|
|
8511
8644
|
if (!runId) {
|
|
8512
8645
|
throw new CliError2("run show requires a run id.");
|
|
8513
8646
|
}
|
|
8514
|
-
const record =
|
|
8647
|
+
const record = readAuthorityRun5(context.projectRoot, runId) ?? normalizeRemoteRunDetails2(await getRunDetailsViaServer(context, runId).catch(() => ({})));
|
|
8515
8648
|
if (!record) {
|
|
8516
8649
|
throw new CliError2(`Run not found: ${runId}`, 2);
|
|
8517
8650
|
}
|
|
@@ -8549,6 +8682,46 @@ async function executeRun(context, args) {
|
|
|
8549
8682
|
}
|
|
8550
8683
|
return { ok: true, group: "run", command, details: { runId: run.value, events, cursor } };
|
|
8551
8684
|
}
|
|
8685
|
+
case "replay": {
|
|
8686
|
+
let pending = rest;
|
|
8687
|
+
const run = takeOption(pending, "--run");
|
|
8688
|
+
pending = run.rest;
|
|
8689
|
+
const withSession = takeFlag(pending, "--with-session");
|
|
8690
|
+
pending = withSession.rest;
|
|
8691
|
+
const positionalRunId = pending.length > 0 && pending[0] && !pending[0].startsWith("-") ? pending[0] : undefined;
|
|
8692
|
+
const extra = positionalRunId ? pending.slice(1) : pending;
|
|
8693
|
+
requireNoExtraArgs(extra, "rig run replay <id>|--run <id> [--with-session]");
|
|
8694
|
+
const runId = run.value ?? positionalRunId;
|
|
8695
|
+
if (!runId) {
|
|
8696
|
+
throw new CliError2("run replay requires a run id.", 2);
|
|
8697
|
+
}
|
|
8698
|
+
const replay = buildRunReplay(context.projectRoot, runId, { withSession: withSession.value });
|
|
8699
|
+
if (replay.entryCount === 0 && replay.sessionEntryCount === 0) {
|
|
8700
|
+
throw new CliError2(`No run.jsonl lifecycle log found for ${runId} (looked at ${replay.logPath}).`, 2);
|
|
8701
|
+
}
|
|
8702
|
+
if (context.outputMode === "text") {
|
|
8703
|
+
console.log(`Replay of ${runId} (${replay.entryCount} lifecycle entries${withSession.value ? `, ${replay.sessionEntryCount} session entries` : ""}):`);
|
|
8704
|
+
for (const line of replay.lines) {
|
|
8705
|
+
console.log(line);
|
|
8706
|
+
}
|
|
8707
|
+
if (withSession.value && !replay.sessionFile) {
|
|
8708
|
+
console.log("(no Pi session file resolvable from the run record; showing run.jsonl only)");
|
|
8709
|
+
}
|
|
8710
|
+
}
|
|
8711
|
+
return {
|
|
8712
|
+
ok: true,
|
|
8713
|
+
group: "run",
|
|
8714
|
+
command,
|
|
8715
|
+
details: {
|
|
8716
|
+
runId,
|
|
8717
|
+
logPath: replay.logPath,
|
|
8718
|
+
sessionFile: replay.sessionFile,
|
|
8719
|
+
entryCount: replay.entryCount,
|
|
8720
|
+
sessionEntryCount: replay.sessionEntryCount,
|
|
8721
|
+
lines: replay.lines
|
|
8722
|
+
}
|
|
8723
|
+
};
|
|
8724
|
+
}
|
|
8552
8725
|
case "attach": {
|
|
8553
8726
|
let pending = rest;
|
|
8554
8727
|
const runOption = takeOption(pending, "--run");
|
|
@@ -8871,7 +9044,7 @@ async function executeServer(context, args, options) {
|
|
|
8871
9044
|
init_runner();
|
|
8872
9045
|
import { readFileSync as readFileSync10 } from "fs";
|
|
8873
9046
|
import { spawnSync as spawnSync3 } from "child_process";
|
|
8874
|
-
import { resolve as
|
|
9047
|
+
import { resolve as resolve23 } from "path";
|
|
8875
9048
|
import { cancel as cancel4, confirm as confirm2, isCancel as isCancel4 } from "@clack/prompts";
|
|
8876
9049
|
import {
|
|
8877
9050
|
taskArtifactDir,
|
|
@@ -9049,6 +9222,7 @@ var PRIMARY_GROUPS = [
|
|
|
9049
9222
|
{ command: "stop [<run-id>|--run <id>]", description: "Request stop for one run or local active runs.", primary: true },
|
|
9050
9223
|
{ command: "steer <run-id> --message <text>", description: "Queue a steering message into a live worker without attaching." },
|
|
9051
9224
|
{ command: "timeline --run <id> [--follow]", description: "Stream raw run timeline events." },
|
|
9225
|
+
{ command: "replay <run-id>|--run <id> [--with-session]", description: "Print the run's consolidated run.jsonl as a merged timeline; --with-session interleaves the Pi session log." },
|
|
9052
9226
|
{ command: "resume", description: "Resume the most recent interrupted local run." },
|
|
9053
9227
|
{ command: "restart", description: "Restart the most recent local run from a clean runtime." },
|
|
9054
9228
|
{ command: "delete|cleanup", description: "Remove completed run records/artifacts." }
|
|
@@ -9636,7 +9810,7 @@ async function executeTask(context, args, options) {
|
|
|
9636
9810
|
const fileFlag = takeOption(rest.slice(1), "--file");
|
|
9637
9811
|
let content;
|
|
9638
9812
|
if (fileFlag.value) {
|
|
9639
|
-
content = readFileSync10(
|
|
9813
|
+
content = readFileSync10(resolve23(context.projectRoot, fileFlag.value), "utf-8");
|
|
9640
9814
|
} else {
|
|
9641
9815
|
content = await readStdin();
|
|
9642
9816
|
}
|
|
@@ -9870,8 +10044,8 @@ async function executeTask(context, args, options) {
|
|
|
9870
10044
|
|
|
9871
10045
|
// packages/cli/src/commands/task-run-driver.ts
|
|
9872
10046
|
init_runner();
|
|
9873
|
-
import { copyFileSync as copyFileSync3, existsSync as
|
|
9874
|
-
import { resolve as
|
|
10047
|
+
import { copyFileSync as copyFileSync3, existsSync as existsSync15, mkdirSync as mkdirSync9, readFileSync as readFileSync11, statSync as statSync2, writeFileSync as writeFileSync7 } from "fs";
|
|
10048
|
+
import { resolve as resolve24 } from "path";
|
|
9875
10049
|
import { spawn as spawn2, spawnSync as spawnSync4 } from "child_process";
|
|
9876
10050
|
import { createInterface as createLineInterface } from "readline";
|
|
9877
10051
|
import { loadConfig as loadConfig2 } from "@rig/core/load-config";
|
|
@@ -9895,7 +10069,7 @@ import {
|
|
|
9895
10069
|
isCodexExecRecord
|
|
9896
10070
|
} from "@rig/runtime/control-plane/provider/codex-exec-records";
|
|
9897
10071
|
import { resolvePreferredShellBinary } from "@rig/runtime/control-plane/native/run-ops";
|
|
9898
|
-
import { readAuthorityRun as
|
|
10072
|
+
import { readAuthorityRun as readAuthorityRun6, readJsonFile as readJsonFile3, resolveTaskArtifactDirs as resolveTaskArtifactDirs2 } from "@rig/runtime/control-plane/authority-files";
|
|
9899
10073
|
import {
|
|
9900
10074
|
buildTaskRunLifecycleComment
|
|
9901
10075
|
} from "@rig/runtime/control-plane/tasks/source-lifecycle";
|
|
@@ -9955,12 +10129,12 @@ function copyUntrackedDirtyFiles(sourceRoot, targetRoot) {
|
|
|
9955
10129
|
return 0;
|
|
9956
10130
|
let copied = 0;
|
|
9957
10131
|
for (const relativePath of listed.stdout.split("\x00").filter(Boolean)) {
|
|
9958
|
-
const sourcePath =
|
|
9959
|
-
const targetPath =
|
|
10132
|
+
const sourcePath = resolve24(sourceRoot, relativePath);
|
|
10133
|
+
const targetPath = resolve24(targetRoot, relativePath);
|
|
9960
10134
|
try {
|
|
9961
10135
|
if (!statSync2(sourcePath).isFile())
|
|
9962
10136
|
continue;
|
|
9963
|
-
mkdirSync9(
|
|
10137
|
+
mkdirSync9(resolve24(targetPath, ".."), { recursive: true });
|
|
9964
10138
|
copyFileSync3(sourcePath, targetPath);
|
|
9965
10139
|
copied += 1;
|
|
9966
10140
|
} catch {}
|
|
@@ -9999,7 +10173,7 @@ function buildDirtyBaselineHandshakeEnv(input) {
|
|
|
9999
10173
|
return { RIG_BASELINE_MODE: input.baselineMode ?? "head" };
|
|
10000
10174
|
return {
|
|
10001
10175
|
RIG_BASELINE_MODE: "dirty-snapshot",
|
|
10002
|
-
RIG_DIRTY_BASELINE_READY_FILE:
|
|
10176
|
+
RIG_DIRTY_BASELINE_READY_FILE: resolve24(input.projectRoot, ".rig", "runs", input.runId, "dirty-baseline.ready.json")
|
|
10003
10177
|
};
|
|
10004
10178
|
}
|
|
10005
10179
|
function positiveInt(value, fallback) {
|
|
@@ -10104,9 +10278,9 @@ function createCommandRunner(binary) {
|
|
|
10104
10278
|
const stderrChunks = [];
|
|
10105
10279
|
child.stdout.on("data", (chunk) => stdoutChunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(String(chunk))));
|
|
10106
10280
|
child.stderr.on("data", (chunk) => stderrChunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(String(chunk))));
|
|
10107
|
-
return await new Promise((
|
|
10108
|
-
child.once("error", (error) =>
|
|
10109
|
-
child.once("close", (code) =>
|
|
10281
|
+
return await new Promise((resolve25) => {
|
|
10282
|
+
child.once("error", (error) => resolve25({ exitCode: 1, stderr: error.message }));
|
|
10283
|
+
child.once("close", (code) => resolve25({
|
|
10110
10284
|
exitCode: code ?? 1,
|
|
10111
10285
|
stdout: Buffer.concat(stdoutChunks).toString("utf8"),
|
|
10112
10286
|
stderr: Buffer.concat(stderrChunks).toString("utf8")
|
|
@@ -10180,7 +10354,7 @@ async function runTaskRunPostValidationLifecycle(input) {
|
|
|
10180
10354
|
config,
|
|
10181
10355
|
sourceTask: input.sourceTask,
|
|
10182
10356
|
uploadedSnapshot: input.uploadedSnapshot,
|
|
10183
|
-
artifactRoot:
|
|
10357
|
+
artifactRoot: resolve24(input.projectRoot, "artifacts", taskId3),
|
|
10184
10358
|
command: ghCommand,
|
|
10185
10359
|
gitCommand,
|
|
10186
10360
|
steerPi,
|
|
@@ -10310,7 +10484,7 @@ function summarizeValidationFailure(projectRoot, taskId3) {
|
|
|
10310
10484
|
return null;
|
|
10311
10485
|
}
|
|
10312
10486
|
for (const artifactDir of resolveTaskArtifactDirs2(projectRoot, taskId3)) {
|
|
10313
|
-
const summary = readJsonFile3(
|
|
10487
|
+
const summary = readJsonFile3(resolve24(artifactDir, "validation-summary.json"), null);
|
|
10314
10488
|
if (!summary || summary.status !== "fail") {
|
|
10315
10489
|
continue;
|
|
10316
10490
|
}
|
|
@@ -10391,9 +10565,9 @@ function readTaskRunAcceptedArtifactState(input) {
|
|
|
10391
10565
|
if (!input.taskId || !input.workspaceDir) {
|
|
10392
10566
|
return { accepted: false, reason: null };
|
|
10393
10567
|
}
|
|
10394
|
-
const artifactDir =
|
|
10395
|
-
const reviewStatusPath =
|
|
10396
|
-
const taskResultPath =
|
|
10568
|
+
const artifactDir = resolve24(input.workspaceDir, "artifacts", input.taskId);
|
|
10569
|
+
const reviewStatusPath = resolve24(artifactDir, "review-status.txt");
|
|
10570
|
+
const taskResultPath = resolve24(artifactDir, "task-result.json");
|
|
10397
10571
|
const reviewStatus = readTaskRunReviewStatus(reviewStatusPath);
|
|
10398
10572
|
if (reviewStatus !== "APPROVED") {
|
|
10399
10573
|
return { accepted: false, reason: null };
|
|
@@ -10430,12 +10604,12 @@ function resolveTaskRunRetryContext(input) {
|
|
|
10430
10604
|
if (!input.taskId || !input.workspaceDir) {
|
|
10431
10605
|
return { shouldRetry: false, failureDetail: null, nextPrompt: null };
|
|
10432
10606
|
}
|
|
10433
|
-
const artifactDir =
|
|
10434
|
-
const reviewStatePath =
|
|
10435
|
-
const reviewFeedbackPath =
|
|
10436
|
-
const reviewStatusPath =
|
|
10437
|
-
const failedApproachesPath =
|
|
10438
|
-
const validationSummaryPath =
|
|
10607
|
+
const artifactDir = resolve24(input.workspaceDir, "artifacts", input.taskId);
|
|
10608
|
+
const reviewStatePath = resolve24(artifactDir, "review-state.json");
|
|
10609
|
+
const reviewFeedbackPath = resolve24(artifactDir, "review-feedback.md");
|
|
10610
|
+
const reviewStatusPath = resolve24(artifactDir, "review-status.txt");
|
|
10611
|
+
const failedApproachesPath = resolve24(input.workspaceDir, ".rig", "state", "failed_approaches.md");
|
|
10612
|
+
const validationSummaryPath = resolve24(artifactDir, "validation-summary.json");
|
|
10439
10613
|
const reviewState = readJsonFile3(reviewStatePath, null);
|
|
10440
10614
|
const reviewStatus = readTaskRunReviewStatus(reviewStatusPath);
|
|
10441
10615
|
const reviewRejected = isTaskRunReviewRejected(reviewState);
|
|
@@ -10621,7 +10795,7 @@ function appendToolTimelineFromLog(input) {
|
|
|
10621
10795
|
});
|
|
10622
10796
|
}
|
|
10623
10797
|
function readTaskRunReviewStatus(reviewStatusPath) {
|
|
10624
|
-
if (!
|
|
10798
|
+
if (!existsSync15(reviewStatusPath)) {
|
|
10625
10799
|
return null;
|
|
10626
10800
|
}
|
|
10627
10801
|
try {
|
|
@@ -10701,7 +10875,7 @@ async function updateTaskSourceAfterDriverRun(projectRoot, runId, taskId3, sourc
|
|
|
10701
10875
|
}
|
|
10702
10876
|
}
|
|
10703
10877
|
function readRunSourceTaskContract(projectRoot, runId, taskId3) {
|
|
10704
|
-
const run =
|
|
10878
|
+
const run = readAuthorityRun6(projectRoot, runId);
|
|
10705
10879
|
const raw = run?.sourceTask;
|
|
10706
10880
|
if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
|
|
10707
10881
|
return null;
|
|
@@ -10742,8 +10916,10 @@ async function executeRigOwnedTaskRun(context, input) {
|
|
|
10742
10916
|
process.stderr.on("error", () => {});
|
|
10743
10917
|
configureRunEventSink(context.projectRoot);
|
|
10744
10918
|
const runtimeTaskId = input.taskId?.trim() || `adhoc-${input.runId}`;
|
|
10745
|
-
const existingRunRecord =
|
|
10919
|
+
const existingRunRecord = readAuthorityRun6(context.projectRoot, input.runId);
|
|
10746
10920
|
const resumeMode = process.env.RIG_RUN_RESUME === "1";
|
|
10921
|
+
let latestPiSessionId = typeof existingRunRecord?.piSession?.sessionId === "string" && existingRunRecord.piSession.sessionId.trim() ? existingRunRecord.piSession.sessionId : null;
|
|
10922
|
+
const sessionAnchor = () => latestPiSessionId ? { sessionId: latestPiSessionId } : {};
|
|
10747
10923
|
const resumePreviousStatus = String(existingRunRecord?.status ?? "").toLowerCase();
|
|
10748
10924
|
const sourceTask = readRunSourceTaskContract(context.projectRoot, input.runId, input.taskId);
|
|
10749
10925
|
let prompt = buildRunPrompt({
|
|
@@ -10816,7 +10992,8 @@ async function executeRigOwnedTaskRun(context, input) {
|
|
|
10816
10992
|
type: "status",
|
|
10817
10993
|
runId: input.runId,
|
|
10818
10994
|
status: "preparing",
|
|
10819
|
-
detail: input.taskId ?? input.title ?? runtimeTaskId
|
|
10995
|
+
detail: input.taskId ?? input.title ?? runtimeTaskId,
|
|
10996
|
+
...sessionAnchor()
|
|
10820
10997
|
});
|
|
10821
10998
|
appendRunLog(context.projectRoot, input.runId, {
|
|
10822
10999
|
id: `log:${input.runId}:${resumeMode ? "resume" : "start"}`,
|
|
@@ -10842,15 +11019,15 @@ async function executeRigOwnedTaskRun(context, input) {
|
|
|
10842
11019
|
const loadedAutomationConfig = await loadTaskRunAutomationConfig(context.projectRoot);
|
|
10843
11020
|
const automationConfig = input.prMode ? { ...loadedAutomationConfig ?? {}, pr: { ...loadedAutomationConfig?.pr ?? {}, mode: input.prMode } } : loadedAutomationConfig;
|
|
10844
11021
|
const planningClassification = classifyPlanningNeed({ config: automationConfig, sourceTask });
|
|
10845
|
-
const planningArtifactPath =
|
|
11022
|
+
const planningArtifactPath = resolve24("artifacts", runtimeTaskId, "implementation-plan.md");
|
|
10846
11023
|
const persistedPlanning = {
|
|
10847
11024
|
...planningClassification,
|
|
10848
11025
|
classifier: input.runtimeAdapter === "pi" ? "pi-rig-structured-policy" : "rig-structured-policy",
|
|
10849
11026
|
artifactPath: planningClassification.planningRequired ? planningArtifactPath : null,
|
|
10850
11027
|
classifiedAt: new Date().toISOString()
|
|
10851
11028
|
};
|
|
10852
|
-
mkdirSync9(
|
|
10853
|
-
writeFileSync7(
|
|
11029
|
+
mkdirSync9(resolve24(context.projectRoot, ".rig", "runs", input.runId), { recursive: true });
|
|
11030
|
+
writeFileSync7(resolve24(context.projectRoot, ".rig", "runs", input.runId, "planning-classification.json"), `${JSON.stringify(persistedPlanning, null, 2)}
|
|
10854
11031
|
`, "utf8");
|
|
10855
11032
|
patchAuthorityRun(context.projectRoot, input.runId, { planning: persistedPlanning });
|
|
10856
11033
|
prompt = `${prompt}
|
|
@@ -10900,7 +11077,7 @@ ${planningClassification.planningRequired ? `Before implementing, write a concis
|
|
|
10900
11077
|
let verificationStarted = false;
|
|
10901
11078
|
let reviewStarted = false;
|
|
10902
11079
|
let latestRuntimeWorkspace = resumeMode && typeof existingRunRecord?.worktreePath === "string" ? existingRunRecord.worktreePath : null;
|
|
10903
|
-
let latestSessionDir = resumeMode && typeof existingRunRecord?.sessionPath === "string" ?
|
|
11080
|
+
let latestSessionDir = resumeMode && typeof existingRunRecord?.sessionPath === "string" ? resolve24(existingRunRecord.sessionPath, "..") : null;
|
|
10904
11081
|
let latestLogsDir = resumeMode && typeof existingRunRecord?.logRoot === "string" ? existingRunRecord.logRoot : null;
|
|
10905
11082
|
let latestProviderCommand = null;
|
|
10906
11083
|
let latestRuntimeBranch = resumeMode && typeof existingRunRecord?.branch === "string" ? existingRunRecord.branch : null;
|
|
@@ -10937,7 +11114,7 @@ ${planningClassification.planningRequired ? `Before implementing, write a concis
|
|
|
10937
11114
|
return;
|
|
10938
11115
|
verificationStarted = true;
|
|
10939
11116
|
patchAuthorityRun(context.projectRoot, input.runId, { status: "validating" });
|
|
10940
|
-
emitServerRunEvent({ type: "status", runId: input.runId, status: "validating", detail: detail ?? null });
|
|
11117
|
+
emitServerRunEvent({ type: "status", runId: input.runId, status: "validating", detail: detail ?? null, ...sessionAnchor() });
|
|
10941
11118
|
verificationAction = startRunAction(context.projectRoot, input.runId, {
|
|
10942
11119
|
actionId: `action:${input.runId}:completion-verification`,
|
|
10943
11120
|
actionType: "completion-verification",
|
|
@@ -10950,7 +11127,7 @@ ${planningClassification.planningRequired ? `Before implementing, write a concis
|
|
|
10950
11127
|
return;
|
|
10951
11128
|
reviewStarted = true;
|
|
10952
11129
|
patchAuthorityRun(context.projectRoot, input.runId, { status: "reviewing" });
|
|
10953
|
-
emitServerRunEvent({ type: "status", runId: input.runId, status: "reviewing", detail: detail ?? null });
|
|
11130
|
+
emitServerRunEvent({ type: "status", runId: input.runId, status: "reviewing", detail: detail ?? null, ...sessionAnchor() });
|
|
10954
11131
|
reviewAction = startRunAction(context.projectRoot, input.runId, {
|
|
10955
11132
|
actionId: `action:${input.runId}:review-closeout`,
|
|
10956
11133
|
actionType: "run.review",
|
|
@@ -10986,10 +11163,10 @@ ${planningClassification.planningRequired ? `Before implementing, write a concis
|
|
|
10986
11163
|
patchAuthorityRun(context.projectRoot, input.runId, {
|
|
10987
11164
|
status: "running",
|
|
10988
11165
|
worktreePath: latestRuntimeWorkspace,
|
|
10989
|
-
artifactRoot: latestRuntimeWorkspace && input.taskId ?
|
|
11166
|
+
artifactRoot: latestRuntimeWorkspace && input.taskId ? resolve24(latestRuntimeWorkspace, "artifacts", input.taskId) : null,
|
|
10990
11167
|
logRoot: latestLogsDir,
|
|
10991
|
-
sessionPath: latestSessionDir ?
|
|
10992
|
-
sessionLogPath: latestLogsDir ?
|
|
11168
|
+
sessionPath: latestSessionDir ? resolve24(latestSessionDir, "session.json") : null,
|
|
11169
|
+
sessionLogPath: latestLogsDir ? resolve24(latestLogsDir, "agent-stdout.log") : null,
|
|
10993
11170
|
branch: runtimeId
|
|
10994
11171
|
});
|
|
10995
11172
|
if (!dirtyBaselineApplied && input.baselineMode === "dirty-snapshot" && latestRuntimeWorkspace) {
|
|
@@ -10997,7 +11174,7 @@ ${planningClassification.planningRequired ? `Before implementing, write a concis
|
|
|
10997
11174
|
const dirty = applyDirtyBaselineSnapshot({ sourceRoot: context.projectRoot, targetRoot: latestRuntimeWorkspace });
|
|
10998
11175
|
const readyFile = childEnv.RIG_DIRTY_BASELINE_READY_FILE;
|
|
10999
11176
|
if (readyFile) {
|
|
11000
|
-
mkdirSync9(
|
|
11177
|
+
mkdirSync9(resolve24(readyFile, ".."), { recursive: true });
|
|
11001
11178
|
writeFileSync7(readyFile, `${JSON.stringify({ ...dirty, workspaceDir: latestRuntimeWorkspace, appliedAt: new Date().toISOString() }, null, 2)}
|
|
11002
11179
|
`, "utf8");
|
|
11003
11180
|
}
|
|
@@ -11040,7 +11217,8 @@ ${planningClassification.planningRequired ? `Before implementing, write a concis
|
|
|
11040
11217
|
type: "status",
|
|
11041
11218
|
runId: input.runId,
|
|
11042
11219
|
status: "running",
|
|
11043
|
-
detail: latestRuntimeWorkspace
|
|
11220
|
+
detail: latestRuntimeWorkspace,
|
|
11221
|
+
...sessionAnchor()
|
|
11044
11222
|
});
|
|
11045
11223
|
return true;
|
|
11046
11224
|
}
|
|
@@ -11123,6 +11301,9 @@ ${planningClassification.planningRequired ? `Before implementing, write a concis
|
|
|
11123
11301
|
piSessionPrivate: privateMetadata
|
|
11124
11302
|
});
|
|
11125
11303
|
const sessionId = typeof publicMetadata?.sessionId === "string" ? publicMetadata.sessionId : typeof privateMetadata.public === "object" && privateMetadata.public && !Array.isArray(privateMetadata.public) ? String(privateMetadata.public.sessionId ?? "") : "";
|
|
11304
|
+
if (sessionId) {
|
|
11305
|
+
latestPiSessionId = sessionId;
|
|
11306
|
+
}
|
|
11126
11307
|
appendRunLog(context.projectRoot, input.runId, {
|
|
11127
11308
|
id: `log:${input.runId}:pi-session-ready`,
|
|
11128
11309
|
title: "Worker Pi session ready",
|
|
@@ -11382,7 +11563,7 @@ ${planningClassification.planningRequired ? `Before implementing, write a concis
|
|
|
11382
11563
|
let acceptedArtifactObservedAt = null;
|
|
11383
11564
|
let acceptedArtifactPollTimer = null;
|
|
11384
11565
|
let acceptedArtifactKillTimer = null;
|
|
11385
|
-
const attemptExit = await new Promise((
|
|
11566
|
+
const attemptExit = await new Promise((resolve25) => {
|
|
11386
11567
|
let settled = false;
|
|
11387
11568
|
const settle = (result) => {
|
|
11388
11569
|
if (settled)
|
|
@@ -11390,7 +11571,7 @@ ${planningClassification.planningRequired ? `Before implementing, write a concis
|
|
|
11390
11571
|
settled = true;
|
|
11391
11572
|
if (acceptedArtifactPollTimer)
|
|
11392
11573
|
clearInterval(acceptedArtifactPollTimer);
|
|
11393
|
-
|
|
11574
|
+
resolve25(result);
|
|
11394
11575
|
};
|
|
11395
11576
|
const pollAcceptedArtifacts = () => {
|
|
11396
11577
|
const artifactState = readTaskRunAcceptedArtifactState({
|
|
@@ -11517,7 +11698,8 @@ ${planningClassification.planningRequired ? `Before implementing, write a concis
|
|
|
11517
11698
|
type: "status",
|
|
11518
11699
|
runId: input.runId,
|
|
11519
11700
|
status: "validating",
|
|
11520
|
-
detail: failureDetail
|
|
11701
|
+
detail: failureDetail,
|
|
11702
|
+
...sessionAnchor()
|
|
11521
11703
|
});
|
|
11522
11704
|
emitServerRunEvent({ type: "log", runId: input.runId, title: "Validate failed" });
|
|
11523
11705
|
emitServerRunEvent({ type: "log", runId: input.runId, title: `Steering Pi to retry validation (attempt ${attempt + 1}/${maxAttempts})` });
|
|
@@ -11592,8 +11774,8 @@ Failed to update task source for ${input.taskId ?? runtimeTaskId} to failed: ${e
|
|
|
11592
11774
|
}
|
|
11593
11775
|
if (planningClassification.planningRequired) {
|
|
11594
11776
|
const planWorkspace = latestRuntimeWorkspace ?? context.projectRoot;
|
|
11595
|
-
const expectedPlanPath =
|
|
11596
|
-
if (!
|
|
11777
|
+
const expectedPlanPath = resolve24(planWorkspace, planningArtifactPath);
|
|
11778
|
+
if (!existsSync15(expectedPlanPath)) {
|
|
11597
11779
|
const failedAt = new Date().toISOString();
|
|
11598
11780
|
const failureDetail = `Planning was required (${planningClassification.reason}) but ${planningArtifactPath} was not written before implementation completed.`;
|
|
11599
11781
|
patchAuthorityRun(context.projectRoot, input.runId, {
|
|
@@ -11655,7 +11837,7 @@ Failed to update task source for ${input.taskId ?? runtimeTaskId} to failed: ${e
|
|
|
11655
11837
|
payload: { runtimeWorkspace: latestRuntimeWorkspace, branch: latestRuntimeBranch }
|
|
11656
11838
|
});
|
|
11657
11839
|
emitServerRunEvent({ type: "log", runId: input.runId, title: "Server-owned closeout requested" });
|
|
11658
|
-
emitServerRunEvent({ type: "status", runId: input.runId, status: "reviewing", detail: "Server-owned closeout requested." });
|
|
11840
|
+
emitServerRunEvent({ type: "status", runId: input.runId, status: "reviewing", detail: "Server-owned closeout requested.", ...sessionAnchor() });
|
|
11659
11841
|
await context.emitEvent("command.finished", {
|
|
11660
11842
|
command: [
|
|
11661
11843
|
"rig",
|
|
@@ -11763,9 +11945,9 @@ Failed to update task source for ${input.taskId ?? runtimeTaskId} to failed: ${e
|
|
|
11763
11945
|
});
|
|
11764
11946
|
emitServerRunEvent({ type: "log", runId: input.runId, title: "Pi PR feedback fix stderr" });
|
|
11765
11947
|
});
|
|
11766
|
-
const exitCode = await new Promise((
|
|
11767
|
-
child.once("error", () =>
|
|
11768
|
-
child.once("close", (code) =>
|
|
11948
|
+
const exitCode = await new Promise((resolve25) => {
|
|
11949
|
+
child.once("error", () => resolve25(1));
|
|
11950
|
+
child.once("close", (code) => resolve25(code ?? 1));
|
|
11769
11951
|
});
|
|
11770
11952
|
for (const pendingLog of flushPendingClaudeToolUseLogs({
|
|
11771
11953
|
runId: input.runId,
|
|
@@ -11907,8 +12089,8 @@ async function executeTest(context, args) {
|
|
|
11907
12089
|
|
|
11908
12090
|
// packages/cli/src/commands/setup.ts
|
|
11909
12091
|
init_runner();
|
|
11910
|
-
import { existsSync as
|
|
11911
|
-
import { resolve as
|
|
12092
|
+
import { existsSync as existsSync16, mkdirSync as mkdirSync10, readdirSync as readdirSync3, writeFileSync as writeFileSync8 } from "fs";
|
|
12093
|
+
import { resolve as resolve25 } from "path";
|
|
11912
12094
|
import { createPluginHost } from "@rig/core";
|
|
11913
12095
|
import {
|
|
11914
12096
|
isSupportedBunVersion as isSupportedBunVersion2,
|
|
@@ -11966,8 +12148,8 @@ function runSetupInit(projectRoot) {
|
|
|
11966
12148
|
mkdirSync10(stateDir, { recursive: true });
|
|
11967
12149
|
mkdirSync10(logsDir, { recursive: true });
|
|
11968
12150
|
mkdirSync10(artifactsDir, { recursive: true });
|
|
11969
|
-
const failuresPath =
|
|
11970
|
-
if (!
|
|
12151
|
+
const failuresPath = resolve25(stateDir, "failed_approaches.md");
|
|
12152
|
+
if (!existsSync16(failuresPath)) {
|
|
11971
12153
|
writeFileSync8(failuresPath, `# Failed Approaches
|
|
11972
12154
|
|
|
11973
12155
|
`, "utf-8");
|
|
@@ -11985,19 +12167,19 @@ async function runSetupCheck(projectRoot) {
|
|
|
11985
12167
|
}
|
|
11986
12168
|
async function runSetupPreflight(projectRoot) {
|
|
11987
12169
|
await runSetupCheck(projectRoot);
|
|
11988
|
-
const validationRoot =
|
|
11989
|
-
if (
|
|
11990
|
-
const validators =
|
|
12170
|
+
const validationRoot = resolve25(resolveControlPlaneDefinitionRoot(projectRoot), "validation");
|
|
12171
|
+
if (existsSync16(validationRoot)) {
|
|
12172
|
+
const validators = readdirSync3(validationRoot, { withFileTypes: true }).filter((entry) => entry.isDirectory());
|
|
11991
12173
|
for (const validator of validators) {
|
|
11992
|
-
const script =
|
|
11993
|
-
if (
|
|
12174
|
+
const script = resolve25(validationRoot, validator.name, "validate.sh");
|
|
12175
|
+
if (existsSync16(script)) {
|
|
11994
12176
|
console.log(`OK: validator script ${script}`);
|
|
11995
12177
|
}
|
|
11996
12178
|
}
|
|
11997
12179
|
}
|
|
11998
|
-
const hooksRoot =
|
|
11999
|
-
if (
|
|
12000
|
-
const hooks =
|
|
12180
|
+
const hooksRoot = resolve25(resolveControlPlaneDefinitionRoot(projectRoot), "hooks");
|
|
12181
|
+
if (existsSync16(hooksRoot)) {
|
|
12182
|
+
const hooks = readdirSync3(hooksRoot).filter((name) => name.endsWith(".sh"));
|
|
12001
12183
|
for (const hook of hooks) {
|
|
12002
12184
|
console.log(`OK: hook ${hook}`);
|
|
12003
12185
|
}
|
|
@@ -12141,7 +12323,7 @@ var PROJECT_REQUIRED_GROUPS = new Set([
|
|
|
12141
12323
|
]);
|
|
12142
12324
|
var RIG_CONFIG_FILENAMES = ["rig.config.ts", "rig.config.mts", "rig.config.json"];
|
|
12143
12325
|
function hasInitializedRigProject(projectRoot) {
|
|
12144
|
-
return RIG_CONFIG_FILENAMES.some((name) =>
|
|
12326
|
+
return RIG_CONFIG_FILENAMES.some((name) => existsSync17(resolve26(projectRoot, name))) || existsSync17(resolve26(projectRoot, ".rig"));
|
|
12145
12327
|
}
|
|
12146
12328
|
function requireInitializedRigProject(context, group) {
|
|
12147
12329
|
if (hasInitializedRigProject(context.projectRoot)) {
|
|
@@ -12194,8 +12376,8 @@ function resolveTopLevelLaunchState(context) {
|
|
|
12194
12376
|
let selectedServer = null;
|
|
12195
12377
|
if (projectInitialized) {
|
|
12196
12378
|
try {
|
|
12197
|
-
const statePath =
|
|
12198
|
-
if (
|
|
12379
|
+
const statePath = resolve26(context.projectRoot, ".rig", "state", "connection.json");
|
|
12380
|
+
if (existsSync17(statePath)) {
|
|
12199
12381
|
const parsed = JSON.parse(readFileSync12(statePath, "utf-8"));
|
|
12200
12382
|
selectedServer = parsed.remoteUrl || parsed.url || parsed.selected || null;
|
|
12201
12383
|
}
|
|
@@ -12375,8 +12557,8 @@ var __testOnly = {
|
|
|
12375
12557
|
validateRequiredBugPromptValue
|
|
12376
12558
|
};
|
|
12377
12559
|
// packages/cli/src/launcher.ts
|
|
12378
|
-
import { existsSync as
|
|
12379
|
-
import { basename as basename3, resolve as
|
|
12560
|
+
import { existsSync as existsSync18 } from "fs";
|
|
12561
|
+
import { basename as basename3, resolve as resolve27 } from "path";
|
|
12380
12562
|
import { loadDotEnvSecrets } from "@rig/runtime/baked-secrets";
|
|
12381
12563
|
import { RIG_DEFINITION_DIRNAME, RIG_STATE_DIRNAME, resolveNearestRigProjectRoot } from "@rig/runtime/layout";
|
|
12382
12564
|
function parsePolicyMode(value) {
|
|
@@ -12389,7 +12571,7 @@ function parsePolicyMode(value) {
|
|
|
12389
12571
|
throw new Error(`Invalid --policy-mode value: ${value}. Use off|observe|enforce.`);
|
|
12390
12572
|
}
|
|
12391
12573
|
function hasRigProjectMarker(candidate) {
|
|
12392
|
-
return
|
|
12574
|
+
return existsSync18(resolve27(candidate, RIG_DEFINITION_DIRNAME)) || existsSync18(resolve27(candidate, RIG_STATE_DIRNAME)) || existsSync18(resolve27(candidate, "rig.config.ts")) || existsSync18(resolve27(candidate, "rig.config.json")) || existsSync18(resolve27(candidate, ".git"));
|
|
12393
12575
|
}
|
|
12394
12576
|
function resolveProjectRoot({
|
|
12395
12577
|
envProjectRoot,
|
|
@@ -12398,19 +12580,19 @@ function resolveProjectRoot({
|
|
|
12398
12580
|
cwd = process.cwd()
|
|
12399
12581
|
}) {
|
|
12400
12582
|
if (envProjectRoot) {
|
|
12401
|
-
return
|
|
12583
|
+
return resolve27(cwd, envProjectRoot);
|
|
12402
12584
|
}
|
|
12403
12585
|
const fallbackImportDir = importDir ?? cwd;
|
|
12404
12586
|
const execName = basename3(execPath).toLowerCase();
|
|
12405
|
-
const execCandidates = execName === "rig" || execName === "rig.exe" ? [
|
|
12406
|
-
const candidates = [cwd, ...execCandidates,
|
|
12587
|
+
const execCandidates = execName === "rig" || execName === "rig.exe" ? [resolve27(execPath, "..", "..")] : [];
|
|
12588
|
+
const candidates = [cwd, ...execCandidates, resolve27(fallbackImportDir, "..")];
|
|
12407
12589
|
for (const candidate of candidates) {
|
|
12408
12590
|
const nearest = resolveNearestRigProjectRoot(candidate);
|
|
12409
12591
|
if (hasRigProjectMarker(nearest)) {
|
|
12410
12592
|
return nearest;
|
|
12411
12593
|
}
|
|
12412
12594
|
}
|
|
12413
|
-
return
|
|
12595
|
+
return resolve27(cwd);
|
|
12414
12596
|
}
|
|
12415
12597
|
function normalizeCliErrorCode(message2, isCliError) {
|
|
12416
12598
|
if (message2.startsWith("Invalid --policy-mode value:")) {
|
|
@@ -12477,7 +12659,7 @@ async function runRigCli(module, options = {}) {
|
|
|
12477
12659
|
runId: context.runId,
|
|
12478
12660
|
outcome,
|
|
12479
12661
|
eventsFile: context.eventBus.getEventsFile(),
|
|
12480
|
-
policyFile:
|
|
12662
|
+
policyFile: resolve27(projectRoot, "rig", "policy", "policy.json"),
|
|
12481
12663
|
policyMode: context.policyMode ?? policyMode ?? module.loadPolicy(projectRoot).mode
|
|
12482
12664
|
}, null, 2));
|
|
12483
12665
|
}
|