@h-rig/cli 0.0.6-alpha.3 → 0.0.6-alpha.30
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin/rig.js +3606 -1172
- package/dist/src/commands/_authority-runs.js +1 -0
- package/dist/src/commands/_cli-format.js +369 -0
- package/dist/src/commands/_connection-state.js +1 -3
- package/dist/src/commands/_doctor-checks.js +13 -27
- package/dist/src/commands/_help-catalog.js +388 -0
- package/dist/src/commands/_operator-surface.js +204 -0
- package/dist/src/commands/_operator-view.js +861 -56
- package/dist/src/commands/_parsers.js +0 -2
- package/dist/src/commands/_pi-frontend.js +841 -0
- package/dist/src/commands/_pi-install.js +4 -3
- package/dist/src/commands/_pi-worker-bridge-extension.js +759 -0
- package/dist/src/commands/_policy.js +0 -2
- package/dist/src/commands/_preflight.js +32 -109
- package/dist/src/commands/_run-driver-helpers.js +0 -2
- package/dist/src/commands/_server-client.js +161 -31
- package/dist/src/commands/_snapshot-upload.js +8 -23
- package/dist/src/commands/_task-picker.js +44 -16
- package/dist/src/commands/agent.js +9 -9
- package/dist/src/commands/browser.js +4 -6
- package/dist/src/commands/connect.js +132 -25
- package/dist/src/commands/dist.js +4 -6
- package/dist/src/commands/doctor.js +13 -27
- package/dist/src/commands/github.js +10 -25
- package/dist/src/commands/inbox.js +351 -31
- package/dist/src/commands/init.js +298 -71
- package/dist/src/commands/inspect.js +10 -12
- package/dist/src/commands/inspector.js +2 -4
- package/dist/src/commands/plugin.js +76 -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 +1157 -122
- package/dist/src/commands/server.js +217 -33
- package/dist/src/commands/setup.js +17 -37
- package/dist/src/commands/task-report-bug.js +5 -7
- package/dist/src/commands/task-run-driver.js +660 -73
- package/dist/src/commands/task.js +1542 -252
- package/dist/src/commands/test.js +3 -5
- package/dist/src/commands/workspace.js +4 -6
- package/dist/src/commands.js +3599 -1159
- package/dist/src/index.js +3646 -1215
- 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 +6 -4
|
@@ -3,8 +3,6 @@
|
|
|
3
3
|
import { EventBus } from "@rig/runtime/control-plane/runtime/events";
|
|
4
4
|
import { CliError } from "@rig/runtime/control-plane/errors";
|
|
5
5
|
import { evaluate, loadPolicy, resolveAction } from "@rig/runtime/control-plane/runtime/guard";
|
|
6
|
-
import { PluginManager } from "@rig/runtime/control-plane/runtime/plugins";
|
|
7
|
-
import { loadRuntimeContextFromEnv } from "@rig/runtime/control-plane/runtime/context";
|
|
8
6
|
import { buildBinary } from "@rig/runtime/control-plane/runtime/isolation";
|
|
9
7
|
import { CliError as CliError2 } from "@rig/runtime/control-plane/errors";
|
|
10
8
|
function takeOption(args, option) {
|
|
@@ -60,11 +58,8 @@ function normalizeRuntimeAdapter(value) {
|
|
|
60
58
|
return "claude-code";
|
|
61
59
|
}
|
|
62
60
|
|
|
63
|
-
// packages/cli/src/commands/
|
|
64
|
-
import {
|
|
65
|
-
import { existsSync as existsSync2, readFileSync as readFileSync2 } from "fs";
|
|
66
|
-
import { resolve as resolve2 } from "path";
|
|
67
|
-
import { ensureLocalRigServerConnection } from "@rig/runtime/local-server";
|
|
61
|
+
// packages/cli/src/commands/connect.ts
|
|
62
|
+
import { cancel, isCancel, select } from "@clack/prompts";
|
|
68
63
|
|
|
69
64
|
// packages/cli/src/commands/_connection-state.ts
|
|
70
65
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
|
|
@@ -91,6 +86,11 @@ function readJsonFile(path) {
|
|
|
91
86
|
throw new CliError2(`Invalid Rig connection state at ${path}: ${error instanceof Error ? error.message : String(error)}`, 1);
|
|
92
87
|
}
|
|
93
88
|
}
|
|
89
|
+
function writeJsonFile2(path, value) {
|
|
90
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
91
|
+
writeFileSync(path, `${JSON.stringify(value, null, 2)}
|
|
92
|
+
`, "utf8");
|
|
93
|
+
}
|
|
94
94
|
function normalizeConnection(value) {
|
|
95
95
|
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
96
96
|
return null;
|
|
@@ -120,6 +120,18 @@ function readGlobalConnections(options = {}) {
|
|
|
120
120
|
}
|
|
121
121
|
return { connections };
|
|
122
122
|
}
|
|
123
|
+
function writeGlobalConnections(state, options = {}) {
|
|
124
|
+
writeJsonFile2(resolveGlobalConnectionsPath(options.env ?? process.env), state);
|
|
125
|
+
}
|
|
126
|
+
function upsertGlobalConnection(alias, connection, options = {}) {
|
|
127
|
+
const cleanAlias = alias.trim();
|
|
128
|
+
if (!cleanAlias)
|
|
129
|
+
throw new CliError2("Connection alias is required.", 1);
|
|
130
|
+
const state = readGlobalConnections(options);
|
|
131
|
+
state.connections[cleanAlias] = connection;
|
|
132
|
+
writeGlobalConnections(state, options);
|
|
133
|
+
return state;
|
|
134
|
+
}
|
|
123
135
|
function readRepoConnection(projectRoot) {
|
|
124
136
|
const payload = readJsonFile(resolveRepoConnectionPath(projectRoot));
|
|
125
137
|
if (!payload || typeof payload !== "object" || Array.isArray(payload))
|
|
@@ -134,6 +146,9 @@ function readRepoConnection(projectRoot) {
|
|
|
134
146
|
linkedAt: typeof record.linkedAt === "string" ? record.linkedAt : undefined
|
|
135
147
|
};
|
|
136
148
|
}
|
|
149
|
+
function writeRepoConnection(projectRoot, state) {
|
|
150
|
+
writeJsonFile2(resolveRepoConnectionPath(projectRoot), state);
|
|
151
|
+
}
|
|
137
152
|
function resolveSelectedConnection(projectRoot, options = {}) {
|
|
138
153
|
const repo = readRepoConnection(projectRoot);
|
|
139
154
|
if (!repo)
|
|
@@ -143,13 +158,191 @@ function resolveSelectedConnection(projectRoot, options = {}) {
|
|
|
143
158
|
const global = readGlobalConnections(options);
|
|
144
159
|
const connection = global.connections[repo.selected];
|
|
145
160
|
if (!connection) {
|
|
146
|
-
throw new CliError2(`Selected Rig
|
|
161
|
+
throw new CliError2(`Selected Rig server "${repo.selected}" was not found. Run \`rig server list\` or \`rig server use local\`.`, 1);
|
|
147
162
|
}
|
|
148
163
|
return { alias: repo.selected, connection };
|
|
149
164
|
}
|
|
150
165
|
|
|
166
|
+
// packages/cli/src/commands/_cli-format.ts
|
|
167
|
+
import { log, note } from "@clack/prompts";
|
|
168
|
+
import pc from "picocolors";
|
|
169
|
+
function truncate(value, width) {
|
|
170
|
+
if (value.length <= width)
|
|
171
|
+
return value;
|
|
172
|
+
if (width <= 1)
|
|
173
|
+
return "\u2026";
|
|
174
|
+
return `${value.slice(0, width - 1)}\u2026`;
|
|
175
|
+
}
|
|
176
|
+
function pad(value, width) {
|
|
177
|
+
return value.length >= width ? value : `${value}${" ".repeat(width - value.length)}`;
|
|
178
|
+
}
|
|
179
|
+
function statusColor(status) {
|
|
180
|
+
const normalized = status.toLowerCase();
|
|
181
|
+
if (["completed", "merged", "closed", "done", "accepted", "pass", "selected", "approved"].includes(normalized))
|
|
182
|
+
return pc.green;
|
|
183
|
+
if (["failed", "needs_attention", "needs-attention", "blocked", "error", "rejected"].includes(normalized))
|
|
184
|
+
return pc.red;
|
|
185
|
+
if (["running", "reviewing", "validating", "in_progress", "in-progress", "remote"].includes(normalized))
|
|
186
|
+
return pc.cyan;
|
|
187
|
+
if (["ready", "open", "queued", "created", "preparing", "local", "pending"].includes(normalized))
|
|
188
|
+
return pc.yellow;
|
|
189
|
+
return pc.dim;
|
|
190
|
+
}
|
|
191
|
+
function formatStatusPill(status) {
|
|
192
|
+
const label = status || "unknown";
|
|
193
|
+
return statusColor(label)(`\u25CF ${label}`);
|
|
194
|
+
}
|
|
195
|
+
function formatSection(title, subtitle) {
|
|
196
|
+
return `${pc.bold(pc.cyan("\u25C6"))} ${pc.bold(title)}${subtitle ? pc.dim(` \u2014 ${subtitle}`) : ""}`;
|
|
197
|
+
}
|
|
198
|
+
function formatSuccessCard(title, rows = []) {
|
|
199
|
+
const body = rows.filter(([, value]) => value !== undefined && value !== null && String(value).length > 0).map(([key, value]) => `${pc.dim("\u2502")} ${pc.dim(key.padEnd(12))} ${value}`);
|
|
200
|
+
return [formatSection(title), ...body].join(`
|
|
201
|
+
`);
|
|
202
|
+
}
|
|
203
|
+
function formatNextSteps(steps) {
|
|
204
|
+
if (steps.length === 0)
|
|
205
|
+
return [];
|
|
206
|
+
return [pc.bold("Next"), ...steps.map((step) => `${pc.dim("\u203A")} ${step}`)];
|
|
207
|
+
}
|
|
208
|
+
function formatConnectionList(connections) {
|
|
209
|
+
const rows = [["local", { kind: "local", mode: "auto" }], ...Object.entries(connections)];
|
|
210
|
+
const aliasWidth = Math.min(24, Math.max(5, ...rows.map(([alias]) => alias.length)));
|
|
211
|
+
const lines = rows.map(([alias, connection]) => [
|
|
212
|
+
pc.bold(pad(truncate(alias, aliasWidth), aliasWidth)),
|
|
213
|
+
formatStatusPill(connection.kind),
|
|
214
|
+
connection.kind === "remote" ? connection.baseUrl ?? "" : connection.mode ?? "local"
|
|
215
|
+
].join(" "));
|
|
216
|
+
return [formatSection("Rig servers", `${rows.length} available`), `${pc.bold(pad("ALIAS", aliasWidth))} ${pc.bold("KIND")} ${pc.bold("TARGET")}`, ...lines, "", ...formatNextSteps(["Select one: `rig server use <alias|local>`"])].join(`
|
|
217
|
+
`);
|
|
218
|
+
}
|
|
219
|
+
function formatConnectionStatus(selected, connections) {
|
|
220
|
+
const connection = selected === "local" ? { kind: "local", mode: "auto" } : connections[selected];
|
|
221
|
+
const target = !connection ? "not configured" : connection.kind === "remote" ? connection.baseUrl : "local";
|
|
222
|
+
return [
|
|
223
|
+
formatSection("Rig server", "selected for this repo"),
|
|
224
|
+
`${pc.dim("\u2502")} ${pc.dim("selected ")} ${pc.bold(selected)}`,
|
|
225
|
+
`${pc.dim("\u2502")} ${pc.dim("kind ")} ${formatStatusPill(connection?.kind ?? "unknown")}`,
|
|
226
|
+
`${pc.dim("\u2502")} ${pc.dim("target ")} ${target ?? "not configured"}`,
|
|
227
|
+
"",
|
|
228
|
+
...formatNextSteps(["Change: `rig server use <alias|local>`", "List saved servers: `rig server list`"])
|
|
229
|
+
].join(`
|
|
230
|
+
`);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
// packages/cli/src/commands/connect.ts
|
|
234
|
+
function usageName(options) {
|
|
235
|
+
return `rig ${options.group}`;
|
|
236
|
+
}
|
|
237
|
+
function parseConnection(alias, value, options) {
|
|
238
|
+
if (alias === "local" && !value)
|
|
239
|
+
return { kind: "local", mode: "auto" };
|
|
240
|
+
if (!value)
|
|
241
|
+
throw new CliError2(`Missing remote server URL. Usage: ${usageName(options)} add <alias> <url>`, 1);
|
|
242
|
+
let parsed;
|
|
243
|
+
try {
|
|
244
|
+
parsed = new URL(value);
|
|
245
|
+
} catch {
|
|
246
|
+
throw new CliError2(`Invalid Rig server URL: ${value}`, 1);
|
|
247
|
+
}
|
|
248
|
+
if (parsed.protocol !== "https:" && parsed.protocol !== "http:") {
|
|
249
|
+
throw new CliError2("Rig remote server URL must be http(s).", 1);
|
|
250
|
+
}
|
|
251
|
+
return { kind: "remote", baseUrl: parsed.toString().replace(/\/+$/, "") };
|
|
252
|
+
}
|
|
253
|
+
function printJsonOrText(context, payload, text) {
|
|
254
|
+
if (context.outputMode === "json") {
|
|
255
|
+
console.log(JSON.stringify(payload, null, 2));
|
|
256
|
+
} else {
|
|
257
|
+
console.log(text);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
async function promptForConnectionAlias(context) {
|
|
261
|
+
const state = readGlobalConnections();
|
|
262
|
+
const repo = readRepoConnection(context.projectRoot);
|
|
263
|
+
const options = [
|
|
264
|
+
{ value: "local", label: "local", hint: "Use/start a local Rig server" },
|
|
265
|
+
...Object.entries(state.connections).map(([alias, connection]) => ({
|
|
266
|
+
value: alias,
|
|
267
|
+
label: alias,
|
|
268
|
+
hint: connection.kind === "remote" ? connection.baseUrl : "local"
|
|
269
|
+
}))
|
|
270
|
+
].filter((option, index, all) => all.findIndex((candidate) => candidate.value === option.value) === index);
|
|
271
|
+
const answer = await select({
|
|
272
|
+
message: "Select Rig server for this repo",
|
|
273
|
+
initialValue: repo?.selected ?? "local",
|
|
274
|
+
options
|
|
275
|
+
});
|
|
276
|
+
if (isCancel(answer)) {
|
|
277
|
+
cancel("No server selected.");
|
|
278
|
+
throw new CliError2("No server selected.", 3);
|
|
279
|
+
}
|
|
280
|
+
return String(answer);
|
|
281
|
+
}
|
|
282
|
+
async function executeConnectionCommand(context, args, options) {
|
|
283
|
+
const [command, ...rest] = args;
|
|
284
|
+
switch (command ?? "status") {
|
|
285
|
+
case "list": {
|
|
286
|
+
requireNoExtraArgs(rest, `${usageName(options)} list`);
|
|
287
|
+
const state = readGlobalConnections();
|
|
288
|
+
printJsonOrText(context, state, formatConnectionList(state.connections));
|
|
289
|
+
return { ok: true, group: options.group, command: "list", details: state };
|
|
290
|
+
}
|
|
291
|
+
case "add": {
|
|
292
|
+
const [alias, url, ...extra] = rest;
|
|
293
|
+
if (!alias)
|
|
294
|
+
throw new CliError2(`Missing alias. Usage: ${usageName(options)} add <alias> <url>`, 1);
|
|
295
|
+
requireNoExtraArgs(extra, `${usageName(options)} add <alias> <url>`);
|
|
296
|
+
const connection = parseConnection(alias, url, options);
|
|
297
|
+
const state = upsertGlobalConnection(alias, connection);
|
|
298
|
+
printJsonOrText(context, { alias, connection }, formatSuccessCard("Rig server saved", [
|
|
299
|
+
["alias", alias],
|
|
300
|
+
["target", connection.kind === "remote" ? connection.baseUrl : "local"],
|
|
301
|
+
["next", `${usageName(options)} use ${alias}`]
|
|
302
|
+
]));
|
|
303
|
+
return { ok: true, group: options.group, command: "add", details: { alias, connection, count: Object.keys(state.connections).length } };
|
|
304
|
+
}
|
|
305
|
+
case "use": {
|
|
306
|
+
let [alias, ...extra] = rest;
|
|
307
|
+
requireNoExtraArgs(extra, `${usageName(options)} use <alias|local>`);
|
|
308
|
+
if (!alias && options.interactiveUse && context.outputMode === "text" && process.stdin.isTTY) {
|
|
309
|
+
alias = await promptForConnectionAlias(context);
|
|
310
|
+
}
|
|
311
|
+
if (!alias)
|
|
312
|
+
throw new CliError2(`Missing alias. Usage: ${usageName(options)} use <alias|local>`, 1);
|
|
313
|
+
if (alias !== "local") {
|
|
314
|
+
const state = readGlobalConnections();
|
|
315
|
+
if (!state.connections[alias])
|
|
316
|
+
throw new CliError2(`Unknown Rig server: ${alias}`, 1);
|
|
317
|
+
}
|
|
318
|
+
const repoState = { selected: alias, linkedAt: new Date().toISOString() };
|
|
319
|
+
writeRepoConnection(context.projectRoot, repoState);
|
|
320
|
+
printJsonOrText(context, repoState, formatSuccessCard("Rig server selected", [
|
|
321
|
+
["selected", alias],
|
|
322
|
+
["scope", "this repo"],
|
|
323
|
+
["next", "rig task list"]
|
|
324
|
+
]));
|
|
325
|
+
return { ok: true, group: options.group, command: "use", details: repoState };
|
|
326
|
+
}
|
|
327
|
+
case "status": {
|
|
328
|
+
requireNoExtraArgs(rest, `${usageName(options)} status`);
|
|
329
|
+
const repo = readRepoConnection(context.projectRoot);
|
|
330
|
+
const global = readGlobalConnections();
|
|
331
|
+
const details = { selected: repo?.selected ?? "local", repo, connections: global.connections };
|
|
332
|
+
printJsonOrText(context, details, formatConnectionStatus(details.selected, global.connections));
|
|
333
|
+
return { ok: true, group: options.group, command: "status", details };
|
|
334
|
+
}
|
|
335
|
+
default:
|
|
336
|
+
throw new CliError2(`Unknown ${options.group} command: ${String(command)}
|
|
337
|
+
Usage: ${usageName(options)} <list|add|use|status>`, 1);
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
|
|
151
341
|
// packages/cli/src/commands/_server-client.ts
|
|
152
|
-
|
|
342
|
+
import { existsSync as existsSync2, readFileSync as readFileSync2 } from "fs";
|
|
343
|
+
import { resolve as resolve2 } from "path";
|
|
344
|
+
import { ensureLocalRigServerConnection } from "@rig/runtime/local-server";
|
|
345
|
+
var scopedGitHubBearerTokens = new Map;
|
|
153
346
|
function cleanToken(value) {
|
|
154
347
|
const trimmed = value?.trim();
|
|
155
348
|
return trimmed ? trimmed : null;
|
|
@@ -166,25 +359,13 @@ function readPrivateRemoteSessionToken(projectRoot) {
|
|
|
166
359
|
}
|
|
167
360
|
}
|
|
168
361
|
function readGitHubBearerTokenForRemote(projectRoot) {
|
|
169
|
-
|
|
170
|
-
|
|
362
|
+
const scopedKey = resolve2(projectRoot);
|
|
363
|
+
if (scopedGitHubBearerTokens.has(scopedKey))
|
|
364
|
+
return scopedGitHubBearerTokens.get(scopedKey) ?? null;
|
|
171
365
|
const privateSession = readPrivateRemoteSessionToken(projectRoot);
|
|
172
|
-
if (privateSession)
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
}
|
|
176
|
-
const envToken = cleanToken(process.env.RIG_GITHUB_TOKEN) ?? cleanToken(process.env.GITHUB_TOKEN) ?? cleanToken(process.env.GH_TOKEN);
|
|
177
|
-
if (envToken) {
|
|
178
|
-
cachedGitHubBearerToken = envToken;
|
|
179
|
-
return cachedGitHubBearerToken;
|
|
180
|
-
}
|
|
181
|
-
const result = spawnSync("gh", ["auth", "token"], {
|
|
182
|
-
encoding: "utf8",
|
|
183
|
-
timeout: 5000,
|
|
184
|
-
stdio: ["ignore", "pipe", "ignore"]
|
|
185
|
-
});
|
|
186
|
-
cachedGitHubBearerToken = result.status === 0 ? cleanToken(result.stdout) : null;
|
|
187
|
-
return cachedGitHubBearerToken;
|
|
366
|
+
if (privateSession)
|
|
367
|
+
return privateSession;
|
|
368
|
+
return cleanToken(process.env.RIG_SERVER_AUTH_TOKEN) ?? cleanToken(process.env.RIG_REMOTE_AUTH_TOKEN);
|
|
188
369
|
}
|
|
189
370
|
async function ensureServerForCli(projectRoot) {
|
|
190
371
|
try {
|
|
@@ -286,7 +467,10 @@ async function submitTaskRunViaServer(context, input) {
|
|
|
286
467
|
|
|
287
468
|
// packages/cli/src/commands/server.ts
|
|
288
469
|
async function executeServer(context, args, options) {
|
|
289
|
-
const [command = "
|
|
470
|
+
const [command = "status", ...rest] = args;
|
|
471
|
+
if (["status", "list", "add", "use"].includes(command)) {
|
|
472
|
+
return executeConnectionCommand(context, [command, ...rest], { group: "server", interactiveUse: true });
|
|
473
|
+
}
|
|
290
474
|
switch (command) {
|
|
291
475
|
case "start": {
|
|
292
476
|
let pending = rest;
|
|
@@ -298,8 +482,8 @@ async function executeServer(context, args, options) {
|
|
|
298
482
|
pending = pollResult.rest;
|
|
299
483
|
const authTokenResult = takeOption(pending, "--auth-token");
|
|
300
484
|
pending = authTokenResult.rest;
|
|
301
|
-
requireNoExtraArgs(pending, "
|
|
302
|
-
const commandParts = ["
|
|
485
|
+
requireNoExtraArgs(pending, "rig server start [--host <host>] [--port <n>] [--poll-ms <n>] [--auth-token <token>]");
|
|
486
|
+
const commandParts = ["rig-server", "start"];
|
|
303
487
|
if (hostResult.value) {
|
|
304
488
|
commandParts.push("--host", hostResult.value);
|
|
305
489
|
}
|
|
@@ -321,8 +505,8 @@ async function executeServer(context, args, options) {
|
|
|
321
505
|
let pending = rest;
|
|
322
506
|
const eventResult = takeOption(pending, "--event");
|
|
323
507
|
pending = eventResult.rest;
|
|
324
|
-
requireNoExtraArgs(pending, "
|
|
325
|
-
const commandParts = ["
|
|
508
|
+
requireNoExtraArgs(pending, "rig server notify-test [--event <type>]");
|
|
509
|
+
const commandParts = ["rig-server", "notify-test"];
|
|
326
510
|
if (eventResult.value) {
|
|
327
511
|
commandParts.push("--event", eventResult.value);
|
|
328
512
|
}
|
|
@@ -349,7 +533,7 @@ async function executeServer(context, args, options) {
|
|
|
349
533
|
pending = dirtyBaselineResult.rest;
|
|
350
534
|
const prResult = takeOption(pending, "--pr");
|
|
351
535
|
pending = prResult.rest;
|
|
352
|
-
requireNoExtraArgs(pending, "
|
|
536
|
+
requireNoExtraArgs(pending, "rig --run-id <run-id> server task-run [--task <id>] [--title <text>] [--runtime-adapter claude-code|codex|pi] [--model <model>] [--runtime-mode <mode>] [--interaction-mode <mode>] [--initial-prompt <text>] [--dirty-baseline head|dirty-snapshot] [--pr auto|ask|off]");
|
|
353
537
|
if (!taskResult.value && !initialPromptResult.value && !titleResult.value) {
|
|
354
538
|
throw new CliError2("server task-run requires either --task <id> or --initial-prompt/--title for an ad hoc run.", 2);
|
|
355
539
|
}
|
|
@@ -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) {
|
|
@@ -252,17 +251,16 @@ function resolveSelectedConnection(projectRoot, options = {}) {
|
|
|
252
251
|
const global = readGlobalConnections(options);
|
|
253
252
|
const connection = global.connections[repo.selected];
|
|
254
253
|
if (!connection) {
|
|
255
|
-
throw new CliError2(`Selected Rig
|
|
254
|
+
throw new CliError2(`Selected Rig server "${repo.selected}" was not found. Run \`rig server list\` or \`rig server use local\`.`, 1);
|
|
256
255
|
}
|
|
257
256
|
return { alias: repo.selected, connection };
|
|
258
257
|
}
|
|
259
258
|
|
|
260
259
|
// packages/cli/src/commands/_server-client.ts
|
|
261
|
-
import { spawnSync } from "child_process";
|
|
262
260
|
import { existsSync as existsSync3, readFileSync as readFileSync3 } from "fs";
|
|
263
261
|
import { resolve as resolve4 } from "path";
|
|
264
262
|
import { ensureLocalRigServerConnection } from "@rig/runtime/local-server";
|
|
265
|
-
var
|
|
263
|
+
var scopedGitHubBearerTokens = new Map;
|
|
266
264
|
function cleanToken(value) {
|
|
267
265
|
const trimmed = value?.trim();
|
|
268
266
|
return trimmed ? trimmed : null;
|
|
@@ -279,25 +277,13 @@ function readPrivateRemoteSessionToken(projectRoot) {
|
|
|
279
277
|
}
|
|
280
278
|
}
|
|
281
279
|
function readGitHubBearerTokenForRemote(projectRoot) {
|
|
282
|
-
|
|
283
|
-
|
|
280
|
+
const scopedKey = resolve4(projectRoot);
|
|
281
|
+
if (scopedGitHubBearerTokens.has(scopedKey))
|
|
282
|
+
return scopedGitHubBearerTokens.get(scopedKey) ?? null;
|
|
284
283
|
const privateSession = readPrivateRemoteSessionToken(projectRoot);
|
|
285
|
-
if (privateSession)
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
}
|
|
289
|
-
const envToken = cleanToken(process.env.RIG_GITHUB_TOKEN) ?? cleanToken(process.env.GITHUB_TOKEN) ?? cleanToken(process.env.GH_TOKEN);
|
|
290
|
-
if (envToken) {
|
|
291
|
-
cachedGitHubBearerToken = envToken;
|
|
292
|
-
return cachedGitHubBearerToken;
|
|
293
|
-
}
|
|
294
|
-
const result = spawnSync("gh", ["auth", "token"], {
|
|
295
|
-
encoding: "utf8",
|
|
296
|
-
timeout: 5000,
|
|
297
|
-
stdio: ["ignore", "pipe", "ignore"]
|
|
298
|
-
});
|
|
299
|
-
cachedGitHubBearerToken = result.status === 0 ? cleanToken(result.stdout) : null;
|
|
300
|
-
return cachedGitHubBearerToken;
|
|
284
|
+
if (privateSession)
|
|
285
|
+
return privateSession;
|
|
286
|
+
return cleanToken(process.env.RIG_SERVER_AUTH_TOKEN) ?? cleanToken(process.env.RIG_REMOTE_AUTH_TOKEN);
|
|
301
287
|
}
|
|
302
288
|
async function ensureServerForCli(projectRoot) {
|
|
303
289
|
try {
|
|
@@ -493,7 +479,7 @@ async function runRigDoctorChecks(options) {
|
|
|
493
479
|
const taskSourceKind = config?.taskSource?.kind;
|
|
494
480
|
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
481
|
const repo = readRepoConnection(projectRoot);
|
|
496
|
-
checks.push(repo ? check("project-link", "repo selected Rig
|
|
482
|
+
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
483
|
const selected = (() => {
|
|
498
484
|
try {
|
|
499
485
|
return resolveSelectedConnection(projectRoot);
|
|
@@ -501,7 +487,7 @@ async function runRigDoctorChecks(options) {
|
|
|
501
487
|
return null;
|
|
502
488
|
}
|
|
503
489
|
})();
|
|
504
|
-
checks.push(selected ? check("connection", "selected server connection", "pass", selected.connection.kind === "remote" ? selected.connection.baseUrl : "local auto") : check("connection", "selected server
|
|
490
|
+
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
491
|
let server = null;
|
|
506
492
|
try {
|
|
507
493
|
server = await (options.resolveServer ?? ensureServerForCli)(projectRoot);
|
|
@@ -587,7 +573,7 @@ async function executeSetup(context, args) {
|
|
|
587
573
|
const [command = "check", ...rest] = args;
|
|
588
574
|
switch (command) {
|
|
589
575
|
case "bootstrap":
|
|
590
|
-
requireNoExtraArgs(rest, "
|
|
576
|
+
requireNoExtraArgs(rest, "rig setup bootstrap");
|
|
591
577
|
{
|
|
592
578
|
const hostBash = Bun.which("bash") || "/bin/bash";
|
|
593
579
|
const env = { ...process.env };
|
|
@@ -610,25 +596,19 @@ async function executeSetup(context, args) {
|
|
|
610
596
|
}
|
|
611
597
|
return { ok: true, group: "setup", command };
|
|
612
598
|
case "check":
|
|
613
|
-
requireNoExtraArgs(rest, `
|
|
599
|
+
requireNoExtraArgs(rest, `rig setup ${command}`);
|
|
614
600
|
{
|
|
615
601
|
const checks = await withMutedConsole(context.outputMode === "json", () => runSetupCheck(context.projectRoot));
|
|
616
602
|
return { ok: true, group: "setup", command, details: { checks, failures: countDoctorFailures(checks) } };
|
|
617
603
|
}
|
|
618
604
|
case "setup":
|
|
619
|
-
requireNoExtraArgs(rest, "
|
|
605
|
+
requireNoExtraArgs(rest, "rig setup setup");
|
|
620
606
|
withMutedConsole(context.outputMode === "json", () => runSetupInit(context.projectRoot));
|
|
621
607
|
return { ok: true, group: "setup", command };
|
|
622
608
|
case "preflight":
|
|
623
|
-
requireNoExtraArgs(rest, "
|
|
609
|
+
requireNoExtraArgs(rest, "rig setup preflight");
|
|
624
610
|
await withMutedConsole(context.outputMode === "json", () => runSetupPreflight(context.projectRoot));
|
|
625
611
|
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
612
|
default:
|
|
633
613
|
throw new CliError2(`Unknown setup command: ${command}`);
|
|
634
614
|
}
|
|
@@ -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 {
|