@h-rig/cli 0.0.6-alpha.6 → 0.0.6-alpha.60
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/README.md +1 -1
- package/dist/bin/rig.js +4184 -1228
- package/dist/src/commands/_cli-format.js +369 -0
- package/dist/src/commands/_connection-state.js +12 -6
- package/dist/src/commands/_doctor-checks.js +79 -34
- package/dist/src/commands/_help-catalog.js +445 -0
- package/dist/src/commands/_operator-surface.js +220 -0
- package/dist/src/commands/_operator-view.js +1124 -64
- package/dist/src/commands/_parsers.js +0 -2
- package/dist/src/commands/_pi-frontend.js +1080 -0
- package/dist/src/commands/_pi-install.js +4 -3
- package/dist/src/commands/_pi-remote-session.js +771 -0
- package/dist/src/commands/_pi-worker-bridge-extension.js +834 -0
- package/dist/src/commands/_policy.js +0 -2
- package/dist/src/commands/_preflight.js +98 -116
- package/dist/src/commands/_run-driver-helpers.js +34 -2
- package/dist/src/commands/_server-client.js +225 -48
- package/dist/src/commands/_snapshot-upload.js +74 -30
- package/dist/src/commands/_spinner.js +63 -0
- package/dist/src/commands/_task-picker.js +44 -16
- package/dist/src/commands/agent.js +8 -9
- package/dist/src/commands/browser.js +4 -6
- package/dist/src/commands/connect.js +134 -26
- package/dist/src/commands/dist.js +4 -6
- package/dist/src/commands/doctor.js +79 -34
- package/dist/src/commands/github.js +76 -32
- package/dist/src/commands/inbox.js +410 -31
- package/dist/src/commands/init.js +398 -90
- package/dist/src/commands/inspect.js +296 -23
- package/dist/src/commands/inspector.js +2 -4
- package/dist/src/commands/pi.js +168 -0
- package/dist/src/commands/plugin.js +81 -22
- package/dist/src/commands/profile-and-review.js +8 -10
- package/dist/src/commands/queue.js +2 -3
- package/dist/src/commands/remote.js +18 -20
- package/dist/src/commands/repo-git-harness.js +6 -8
- package/dist/src/commands/run.js +1422 -131
- package/dist/src/commands/server.js +280 -40
- package/dist/src/commands/setup.js +84 -45
- package/dist/src/commands/task-report-bug.js +5 -7
- package/dist/src/commands/task-run-driver.js +710 -70
- package/dist/src/commands/task.js +1861 -260
- package/dist/src/commands/test.js +3 -5
- package/dist/src/commands/workspace.js +4 -6
- package/dist/src/commands.js +4143 -1181
- package/dist/src/index.js +4156 -1203
- package/dist/src/launcher.js +5 -3
- package/dist/src/report-bug.js +3 -3
- package/dist/src/runner.js +5 -19
- package/package.json +7 -5
|
@@ -9,8 +9,6 @@ import { resolve as resolve6 } from "path";
|
|
|
9
9
|
import { EventBus } from "@rig/runtime/control-plane/runtime/events";
|
|
10
10
|
import { CliError } from "@rig/runtime/control-plane/errors";
|
|
11
11
|
import { evaluate, loadPolicy, resolveAction } from "@rig/runtime/control-plane/runtime/guard";
|
|
12
|
-
import { PluginManager } from "@rig/runtime/control-plane/runtime/plugins";
|
|
13
|
-
import { loadRuntimeContextFromEnv } from "@rig/runtime/control-plane/runtime/context";
|
|
14
12
|
import { buildBinary } from "@rig/runtime/control-plane/runtime/isolation";
|
|
15
13
|
import { CliError as CliError2 } from "@rig/runtime/control-plane/errors";
|
|
16
14
|
function requireNoExtraArgs(args, usage) {
|
|
@@ -102,7 +100,8 @@ function resolveControlPlaneDefinitionRoot(projectRoot) {
|
|
|
102
100
|
import { existsSync, readFileSync, rmSync } from "fs";
|
|
103
101
|
import { homedir } from "os";
|
|
104
102
|
import { resolve as resolve2 } from "path";
|
|
105
|
-
var PI_RIG_PACKAGE_NAME = "@rig/pi-rig";
|
|
103
|
+
var PI_RIG_PACKAGE_NAME = "@h-rig/pi-rig";
|
|
104
|
+
var LEGACY_PI_RIG_PACKAGE_NAME = "@rig/pi-rig";
|
|
106
105
|
async function defaultCommandRunner(command, options = {}) {
|
|
107
106
|
const proc = Bun.spawn(command, { cwd: options.cwd, stdout: "pipe", stderr: "pipe" });
|
|
108
107
|
const [stdout, stderr, exitCode] = await Promise.all([
|
|
@@ -121,7 +120,7 @@ function resolvePiHomeDir(inputHomeDir) {
|
|
|
121
120
|
function piListContainsPiRig(output) {
|
|
122
121
|
return output.split(/\r?\n/).some((line) => {
|
|
123
122
|
const normalized = line.trim();
|
|
124
|
-
return normalized.includes(PI_RIG_PACKAGE_NAME) || /(?:^|[\\/])packages[\\/]pi-rig(?:$|\s)/.test(normalized);
|
|
123
|
+
return normalized.includes(PI_RIG_PACKAGE_NAME) || normalized.includes(LEGACY_PI_RIG_PACKAGE_NAME) || /(?:^|[\\/])packages[\\/]pi-rig(?:$|\s)/.test(normalized);
|
|
125
124
|
});
|
|
126
125
|
}
|
|
127
126
|
async function safeRun(runner, command, options) {
|
|
@@ -200,6 +199,11 @@ function readJsonFile(path) {
|
|
|
200
199
|
throw new CliError2(`Invalid Rig connection state at ${path}: ${error instanceof Error ? error.message : String(error)}`, 1);
|
|
201
200
|
}
|
|
202
201
|
}
|
|
202
|
+
function writeJsonFile(path, value) {
|
|
203
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
204
|
+
writeFileSync(path, `${JSON.stringify(value, null, 2)}
|
|
205
|
+
`, "utf8");
|
|
206
|
+
}
|
|
203
207
|
function normalizeConnection(value) {
|
|
204
208
|
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
205
209
|
return null;
|
|
@@ -240,29 +244,38 @@ function readRepoConnection(projectRoot) {
|
|
|
240
244
|
return {
|
|
241
245
|
selected,
|
|
242
246
|
project: typeof record.project === "string" ? record.project : undefined,
|
|
243
|
-
linkedAt: typeof record.linkedAt === "string" ? record.linkedAt : undefined
|
|
247
|
+
linkedAt: typeof record.linkedAt === "string" ? record.linkedAt : undefined,
|
|
248
|
+
serverProjectRoot: typeof record.serverProjectRoot === "string" && record.serverProjectRoot.trim() ? record.serverProjectRoot.trim() : undefined
|
|
244
249
|
};
|
|
245
250
|
}
|
|
251
|
+
function writeRepoConnection(projectRoot, state) {
|
|
252
|
+
writeJsonFile(resolveRepoConnectionPath(projectRoot), state);
|
|
253
|
+
}
|
|
246
254
|
function resolveSelectedConnection(projectRoot, options = {}) {
|
|
247
255
|
const repo = readRepoConnection(projectRoot);
|
|
248
256
|
if (!repo)
|
|
249
257
|
return null;
|
|
250
258
|
if (repo.selected === "local")
|
|
251
|
-
return { alias: "local", connection: { kind: "local", mode: "auto" } };
|
|
259
|
+
return { alias: "local", connection: { kind: "local", mode: "auto" }, serverProjectRoot: repo.serverProjectRoot };
|
|
252
260
|
const global = readGlobalConnections(options);
|
|
253
261
|
const connection = global.connections[repo.selected];
|
|
254
262
|
if (!connection) {
|
|
255
|
-
throw new CliError2(`Selected Rig
|
|
263
|
+
throw new CliError2(`Selected Rig server "${repo.selected}" was not found. Run \`rig server list\` or \`rig server use local\`.`, 1);
|
|
256
264
|
}
|
|
257
|
-
return { alias: repo.selected, connection };
|
|
265
|
+
return { alias: repo.selected, connection, serverProjectRoot: repo.serverProjectRoot };
|
|
266
|
+
}
|
|
267
|
+
function writeRepoServerProjectRoot(projectRoot, serverProjectRoot) {
|
|
268
|
+
const repo = readRepoConnection(projectRoot);
|
|
269
|
+
if (!repo)
|
|
270
|
+
return;
|
|
271
|
+
writeRepoConnection(projectRoot, { ...repo, serverProjectRoot });
|
|
258
272
|
}
|
|
259
273
|
|
|
260
274
|
// packages/cli/src/commands/_server-client.ts
|
|
261
|
-
import { spawnSync } from "child_process";
|
|
262
275
|
import { existsSync as existsSync3, readFileSync as readFileSync3 } from "fs";
|
|
263
276
|
import { resolve as resolve4 } from "path";
|
|
264
277
|
import { ensureLocalRigServerConnection } from "@rig/runtime/local-server";
|
|
265
|
-
var
|
|
278
|
+
var scopedGitHubBearerTokens = new Map;
|
|
266
279
|
function cleanToken(value) {
|
|
267
280
|
const trimmed = value?.trim();
|
|
268
281
|
return trimmed ? trimmed : null;
|
|
@@ -279,41 +292,47 @@ function readPrivateRemoteSessionToken(projectRoot) {
|
|
|
279
292
|
}
|
|
280
293
|
}
|
|
281
294
|
function readGitHubBearerTokenForRemote(projectRoot) {
|
|
282
|
-
|
|
283
|
-
|
|
295
|
+
const scopedKey = resolve4(projectRoot);
|
|
296
|
+
if (scopedGitHubBearerTokens.has(scopedKey))
|
|
297
|
+
return scopedGitHubBearerTokens.get(scopedKey) ?? null;
|
|
284
298
|
const privateSession = readPrivateRemoteSessionToken(projectRoot);
|
|
285
|
-
if (privateSession)
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
return
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
|
|
299
|
+
if (privateSession)
|
|
300
|
+
return privateSession;
|
|
301
|
+
return cleanToken(process.env.RIG_SERVER_AUTH_TOKEN) ?? cleanToken(process.env.RIG_REMOTE_AUTH_TOKEN);
|
|
302
|
+
}
|
|
303
|
+
function readStoredGitHubAuthToken(projectRoot) {
|
|
304
|
+
const path = resolve4(projectRoot, ".rig", "state", "github-auth.json");
|
|
305
|
+
if (!existsSync3(path))
|
|
306
|
+
return null;
|
|
307
|
+
try {
|
|
308
|
+
const parsed = JSON.parse(readFileSync3(path, "utf8"));
|
|
309
|
+
return cleanToken(typeof parsed.token === "string" ? parsed.token : undefined);
|
|
310
|
+
} catch {
|
|
311
|
+
return null;
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
function readLocalConnectionFallbackToken(projectRoot) {
|
|
315
|
+
return readGitHubBearerTokenForRemote(projectRoot) ?? cleanToken(process.env.RIG_GITHUB_TOKEN) ?? readStoredGitHubAuthToken(projectRoot);
|
|
301
316
|
}
|
|
302
317
|
async function ensureServerForCli(projectRoot) {
|
|
303
318
|
try {
|
|
304
319
|
const selected = resolveSelectedConnection(projectRoot);
|
|
305
320
|
if (selected?.connection.kind === "remote") {
|
|
321
|
+
const authToken = readGitHubBearerTokenForRemote(projectRoot);
|
|
322
|
+
const serverProjectRoot = selected.serverProjectRoot ?? await backfillRemoteServerProjectRoot(projectRoot, selected.connection.baseUrl, authToken);
|
|
306
323
|
return {
|
|
307
324
|
baseUrl: selected.connection.baseUrl,
|
|
308
|
-
authToken
|
|
309
|
-
connectionKind: "remote"
|
|
325
|
+
authToken,
|
|
326
|
+
connectionKind: "remote",
|
|
327
|
+
serverProjectRoot
|
|
310
328
|
};
|
|
311
329
|
}
|
|
312
330
|
const connection = await ensureLocalRigServerConnection(projectRoot);
|
|
313
331
|
return {
|
|
314
332
|
baseUrl: connection.baseUrl,
|
|
315
|
-
authToken: connection.authToken,
|
|
316
|
-
connectionKind: "local"
|
|
333
|
+
authToken: connection.authToken ?? readLocalConnectionFallbackToken(projectRoot),
|
|
334
|
+
connectionKind: "local",
|
|
335
|
+
serverProjectRoot: resolve4(projectRoot)
|
|
317
336
|
};
|
|
318
337
|
} catch (error) {
|
|
319
338
|
if (error instanceof Error) {
|
|
@@ -322,6 +341,29 @@ async function ensureServerForCli(projectRoot) {
|
|
|
322
341
|
throw error;
|
|
323
342
|
}
|
|
324
343
|
}
|
|
344
|
+
async function backfillRemoteServerProjectRoot(projectRoot, baseUrl, authToken) {
|
|
345
|
+
const repo = readRepoConnection(projectRoot);
|
|
346
|
+
const slug = repo?.project?.trim();
|
|
347
|
+
if (!slug)
|
|
348
|
+
return null;
|
|
349
|
+
try {
|
|
350
|
+
const response = await fetch(`${baseUrl}/api/projects/${encodeURIComponent(slug)}`, {
|
|
351
|
+
headers: mergeHeaders(undefined, authToken)
|
|
352
|
+
});
|
|
353
|
+
if (!response.ok)
|
|
354
|
+
return null;
|
|
355
|
+
const payload = await response.json();
|
|
356
|
+
const project = payload.project && typeof payload.project === "object" && !Array.isArray(payload.project) ? payload.project : null;
|
|
357
|
+
const checkouts = Array.isArray(project?.checkouts) ? project.checkouts : [];
|
|
358
|
+
const latestCheckout = [...checkouts].reverse().find((entry) => Boolean(entry && typeof entry === "object" && !Array.isArray(entry) && typeof entry.path === "string"));
|
|
359
|
+
const path = typeof latestCheckout?.path === "string" && latestCheckout.path.trim() ? latestCheckout.path.trim() : null;
|
|
360
|
+
if (path)
|
|
361
|
+
writeRepoServerProjectRoot(projectRoot, path);
|
|
362
|
+
return path;
|
|
363
|
+
} catch {
|
|
364
|
+
return null;
|
|
365
|
+
}
|
|
366
|
+
}
|
|
325
367
|
function mergeHeaders(headers, authToken) {
|
|
326
368
|
const merged = new Headers(headers);
|
|
327
369
|
if (authToken) {
|
|
@@ -346,9 +388,12 @@ function diagnosticMessage(payload) {
|
|
|
346
388
|
}
|
|
347
389
|
async function requestServerJson(context, pathname, init = {}) {
|
|
348
390
|
const server = await ensureServerForCli(context.projectRoot);
|
|
391
|
+
const headers = mergeHeaders(init.headers, server.authToken);
|
|
392
|
+
if (server.serverProjectRoot)
|
|
393
|
+
headers.set("x-rig-project-root", server.serverProjectRoot);
|
|
349
394
|
const response = await fetch(`${server.baseUrl}${pathname}`, {
|
|
350
395
|
...init,
|
|
351
|
-
headers
|
|
396
|
+
headers
|
|
352
397
|
});
|
|
353
398
|
const text = await response.text();
|
|
354
399
|
const payload = text.trim().length > 0 ? (() => {
|
|
@@ -493,7 +538,7 @@ async function runRigDoctorChecks(options) {
|
|
|
493
538
|
const taskSourceKind = config?.taskSource?.kind;
|
|
494
539
|
checks.push(taskSourceKind ? check("task-source", "task source configured", "pass", taskSourceKind) : check("task-source", "task source configured", "fail", "missing taskSource", "Configure taskSource in rig.config.ts."));
|
|
495
540
|
const repo = readRepoConnection(projectRoot);
|
|
496
|
-
checks.push(repo ? check("project-link", "repo selected Rig
|
|
541
|
+
checks.push(repo ? check("project-link", "repo selected Rig server", repo.project ? "pass" : "warn", `${repo.selected}${repo.project ? ` -> ${repo.project}` : ""}`, "Run `rig init --yes --repo owner/repo` to link this checkout to a GitHub repo slug.") : check("project-link", "repo selected Rig server", "fail", "missing .rig/state/connection.json", "Run `rig init` or `rig server use <alias|local>`."));
|
|
497
542
|
const selected = (() => {
|
|
498
543
|
try {
|
|
499
544
|
return resolveSelectedConnection(projectRoot);
|
|
@@ -501,7 +546,7 @@ async function runRigDoctorChecks(options) {
|
|
|
501
546
|
return null;
|
|
502
547
|
}
|
|
503
548
|
})();
|
|
504
|
-
checks.push(selected ? check("connection", "selected server connection", "pass", selected.connection.kind === "remote" ? selected.connection.baseUrl : "local auto") : check("connection", "selected server
|
|
549
|
+
checks.push(selected ? check("connection", "selected server connection", "pass", selected.connection.kind === "remote" ? selected.connection.baseUrl : "local auto") : check("connection", "selected server", repo ? "fail" : "warn", repo ? "selected alias is missing" : "will auto-start local server", repo ? "Run `rig server list` and `rig server use <alias|local>`." : undefined));
|
|
505
550
|
let server = null;
|
|
506
551
|
try {
|
|
507
552
|
server = await (options.resolveServer ?? ensureServerForCli)(projectRoot);
|
|
@@ -587,7 +632,7 @@ async function executeSetup(context, args) {
|
|
|
587
632
|
const [command = "check", ...rest] = args;
|
|
588
633
|
switch (command) {
|
|
589
634
|
case "bootstrap":
|
|
590
|
-
requireNoExtraArgs(rest, "
|
|
635
|
+
requireNoExtraArgs(rest, "rig setup bootstrap");
|
|
591
636
|
{
|
|
592
637
|
const hostBash = Bun.which("bash") || "/bin/bash";
|
|
593
638
|
const env = { ...process.env };
|
|
@@ -610,25 +655,19 @@ async function executeSetup(context, args) {
|
|
|
610
655
|
}
|
|
611
656
|
return { ok: true, group: "setup", command };
|
|
612
657
|
case "check":
|
|
613
|
-
requireNoExtraArgs(rest, `
|
|
658
|
+
requireNoExtraArgs(rest, `rig setup ${command}`);
|
|
614
659
|
{
|
|
615
660
|
const checks = await withMutedConsole(context.outputMode === "json", () => runSetupCheck(context.projectRoot));
|
|
616
661
|
return { ok: true, group: "setup", command, details: { checks, failures: countDoctorFailures(checks) } };
|
|
617
662
|
}
|
|
618
663
|
case "setup":
|
|
619
|
-
requireNoExtraArgs(rest, "
|
|
664
|
+
requireNoExtraArgs(rest, "rig setup setup");
|
|
620
665
|
withMutedConsole(context.outputMode === "json", () => runSetupInit(context.projectRoot));
|
|
621
666
|
return { ok: true, group: "setup", command };
|
|
622
667
|
case "preflight":
|
|
623
|
-
requireNoExtraArgs(rest, "
|
|
668
|
+
requireNoExtraArgs(rest, "rig setup preflight");
|
|
624
669
|
await withMutedConsole(context.outputMode === "json", () => runSetupPreflight(context.projectRoot));
|
|
625
670
|
return { ok: true, group: "setup", command };
|
|
626
|
-
case "install-agent-shell":
|
|
627
|
-
requireNoExtraArgs(rest, "bun run rig setup install-agent-shell");
|
|
628
|
-
if (context.outputMode === "text") {
|
|
629
|
-
console.log("install-agent-shell is deprecated. Runtime shells now use compiled rig-agent directly.");
|
|
630
|
-
}
|
|
631
|
-
return { ok: true, group: "setup", command };
|
|
632
671
|
default:
|
|
633
672
|
throw new CliError2(`Unknown setup command: ${command}`);
|
|
634
673
|
}
|
|
@@ -9,8 +9,6 @@ import pc from "picocolors";
|
|
|
9
9
|
import { EventBus } from "@rig/runtime/control-plane/runtime/events";
|
|
10
10
|
import { CliError } from "@rig/runtime/control-plane/errors";
|
|
11
11
|
import { evaluate, loadPolicy, resolveAction } from "@rig/runtime/control-plane/runtime/guard";
|
|
12
|
-
import { PluginManager } from "@rig/runtime/control-plane/runtime/plugins";
|
|
13
|
-
import { loadRuntimeContextFromEnv } from "@rig/runtime/control-plane/runtime/context";
|
|
14
12
|
import { buildBinary } from "@rig/runtime/control-plane/runtime/isolation";
|
|
15
13
|
import { CliError as CliError2 } from "@rig/runtime/control-plane/errors";
|
|
16
14
|
function formatCommand(parts) {
|
|
@@ -241,15 +239,15 @@ function buildBugReportMarkdown(input, browser, screenshots, assets) {
|
|
|
241
239
|
...input.issueId ? [
|
|
242
240
|
`- Canonical task assets live under \`artifacts/${input.issueId}/bug-report/\`.`,
|
|
243
241
|
`- Start with \`artifacts/${input.issueId}/bug-report/task.md\` and the files in \`artifacts/${input.issueId}/bug-report/assets/\`.`,
|
|
244
|
-
browserRequired ? `- Run \`
|
|
242
|
+
browserRequired ? `- Run \`rig task info --task ${input.issueId}\` to confirm browser wiring before debugging.` : `- Run \`rig task info --task ${input.issueId}\` to confirm scope and artifact links before debugging.`
|
|
245
243
|
] : [
|
|
246
|
-
"- Draft-only report: convert this into a
|
|
244
|
+
"- Draft-only report: convert this into a Rig task before assigning it to an agent run."
|
|
247
245
|
],
|
|
248
246
|
"",
|
|
249
247
|
"## Validation",
|
|
250
248
|
"",
|
|
251
249
|
"```bash",
|
|
252
|
-
...input.issueId ? [`
|
|
250
|
+
...input.issueId ? [`rig task validate --task ${input.issueId}`] : [],
|
|
253
251
|
...browserRequired ? [
|
|
254
252
|
"bun run app:check:browser:hp-next",
|
|
255
253
|
"bun run app:e2e:browser:hp-next"
|
|
@@ -396,7 +394,7 @@ async function executeTaskReportBug(context, args) {
|
|
|
396
394
|
pending = outputRootResult.rest;
|
|
397
395
|
const slugResult = takeOption(pending, "--slug");
|
|
398
396
|
pending = slugResult.rest;
|
|
399
|
-
requireNoExtraArgs(pending, "
|
|
397
|
+
requireNoExtraArgs(pending, "rig report-bug [--no-prompt] [--no-beads] [--browser|--no-browser] --title <text> --url <url> [--asset <dragged-file>]");
|
|
400
398
|
let draft = {
|
|
401
399
|
outputRoot: outputRootResult.value || "",
|
|
402
400
|
title: titleResult.value,
|
|
@@ -501,7 +499,7 @@ async function executeTaskReportBug(context, args) {
|
|
|
501
499
|
console.log(`Evidence assets: ${result.assetDir}`);
|
|
502
500
|
if (taskConfigPath) {
|
|
503
501
|
console.log(`Task config: ${taskConfigPath}`);
|
|
504
|
-
console.log(`Run:
|
|
502
|
+
console.log(`Run: rig task info --task ${issueId}`);
|
|
505
503
|
}
|
|
506
504
|
}
|
|
507
505
|
return {
|