@h-rig/cli 0.0.6-alpha.4 → 0.0.6-alpha.41
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 +3905 -1193
- 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 +445 -0
- package/dist/src/commands/_operator-surface.js +220 -0
- package/dist/src/commands/_operator-view.js +916 -56
- package/dist/src/commands/_parsers.js +0 -2
- package/dist/src/commands/_pi-frontend.js +880 -0
- package/dist/src/commands/_pi-install.js +4 -3
- package/dist/src/commands/_pi-remote-session.js +665 -0
- package/dist/src/commands/_pi-worker-bridge-extension.js +676 -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 +2 -2
- package/dist/src/commands/_server-client.js +152 -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 +8 -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 +237 -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 +1214 -123
- package/dist/src/commands/server.js +222 -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 +630 -71
- package/dist/src/commands/task.js +1653 -252
- package/dist/src/commands/test.js +3 -5
- package/dist/src/commands/workspace.js +4 -6
- package/dist/src/commands.js +3884 -1166
- package/dist/src/index.js +3898 -1189
- 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) {
|
|
@@ -34,6 +32,9 @@ Usage: ${usage}`);
|
|
|
34
32
|
}
|
|
35
33
|
}
|
|
36
34
|
|
|
35
|
+
// packages/cli/src/commands/server.ts
|
|
36
|
+
import { resolveRigServerCommand } from "@rig/runtime/local-server";
|
|
37
|
+
|
|
37
38
|
// packages/cli/src/commands/_authority-runs.ts
|
|
38
39
|
import {
|
|
39
40
|
readAuthorityRun,
|
|
@@ -60,11 +61,8 @@ function normalizeRuntimeAdapter(value) {
|
|
|
60
61
|
return "claude-code";
|
|
61
62
|
}
|
|
62
63
|
|
|
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";
|
|
64
|
+
// packages/cli/src/commands/connect.ts
|
|
65
|
+
import { cancel, isCancel, select } from "@clack/prompts";
|
|
68
66
|
|
|
69
67
|
// packages/cli/src/commands/_connection-state.ts
|
|
70
68
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
|
|
@@ -91,6 +89,11 @@ function readJsonFile(path) {
|
|
|
91
89
|
throw new CliError2(`Invalid Rig connection state at ${path}: ${error instanceof Error ? error.message : String(error)}`, 1);
|
|
92
90
|
}
|
|
93
91
|
}
|
|
92
|
+
function writeJsonFile2(path, value) {
|
|
93
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
94
|
+
writeFileSync(path, `${JSON.stringify(value, null, 2)}
|
|
95
|
+
`, "utf8");
|
|
96
|
+
}
|
|
94
97
|
function normalizeConnection(value) {
|
|
95
98
|
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
96
99
|
return null;
|
|
@@ -120,6 +123,18 @@ function readGlobalConnections(options = {}) {
|
|
|
120
123
|
}
|
|
121
124
|
return { connections };
|
|
122
125
|
}
|
|
126
|
+
function writeGlobalConnections(state, options = {}) {
|
|
127
|
+
writeJsonFile2(resolveGlobalConnectionsPath(options.env ?? process.env), state);
|
|
128
|
+
}
|
|
129
|
+
function upsertGlobalConnection(alias, connection, options = {}) {
|
|
130
|
+
const cleanAlias = alias.trim();
|
|
131
|
+
if (!cleanAlias)
|
|
132
|
+
throw new CliError2("Connection alias is required.", 1);
|
|
133
|
+
const state = readGlobalConnections(options);
|
|
134
|
+
state.connections[cleanAlias] = connection;
|
|
135
|
+
writeGlobalConnections(state, options);
|
|
136
|
+
return state;
|
|
137
|
+
}
|
|
123
138
|
function readRepoConnection(projectRoot) {
|
|
124
139
|
const payload = readJsonFile(resolveRepoConnectionPath(projectRoot));
|
|
125
140
|
if (!payload || typeof payload !== "object" || Array.isArray(payload))
|
|
@@ -134,6 +149,9 @@ function readRepoConnection(projectRoot) {
|
|
|
134
149
|
linkedAt: typeof record.linkedAt === "string" ? record.linkedAt : undefined
|
|
135
150
|
};
|
|
136
151
|
}
|
|
152
|
+
function writeRepoConnection(projectRoot, state) {
|
|
153
|
+
writeJsonFile2(resolveRepoConnectionPath(projectRoot), state);
|
|
154
|
+
}
|
|
137
155
|
function resolveSelectedConnection(projectRoot, options = {}) {
|
|
138
156
|
const repo = readRepoConnection(projectRoot);
|
|
139
157
|
if (!repo)
|
|
@@ -143,13 +161,191 @@ function resolveSelectedConnection(projectRoot, options = {}) {
|
|
|
143
161
|
const global = readGlobalConnections(options);
|
|
144
162
|
const connection = global.connections[repo.selected];
|
|
145
163
|
if (!connection) {
|
|
146
|
-
throw new CliError2(`Selected Rig
|
|
164
|
+
throw new CliError2(`Selected Rig server "${repo.selected}" was not found. Run \`rig server list\` or \`rig server use local\`.`, 1);
|
|
147
165
|
}
|
|
148
166
|
return { alias: repo.selected, connection };
|
|
149
167
|
}
|
|
150
168
|
|
|
169
|
+
// packages/cli/src/commands/_cli-format.ts
|
|
170
|
+
import { log, note } from "@clack/prompts";
|
|
171
|
+
import pc from "picocolors";
|
|
172
|
+
function truncate(value, width) {
|
|
173
|
+
if (value.length <= width)
|
|
174
|
+
return value;
|
|
175
|
+
if (width <= 1)
|
|
176
|
+
return "\u2026";
|
|
177
|
+
return `${value.slice(0, width - 1)}\u2026`;
|
|
178
|
+
}
|
|
179
|
+
function pad(value, width) {
|
|
180
|
+
return value.length >= width ? value : `${value}${" ".repeat(width - value.length)}`;
|
|
181
|
+
}
|
|
182
|
+
function statusColor(status) {
|
|
183
|
+
const normalized = status.toLowerCase();
|
|
184
|
+
if (["completed", "merged", "closed", "done", "accepted", "pass", "selected", "approved"].includes(normalized))
|
|
185
|
+
return pc.green;
|
|
186
|
+
if (["failed", "needs_attention", "needs-attention", "blocked", "error", "rejected"].includes(normalized))
|
|
187
|
+
return pc.red;
|
|
188
|
+
if (["running", "reviewing", "validating", "in_progress", "in-progress", "remote"].includes(normalized))
|
|
189
|
+
return pc.cyan;
|
|
190
|
+
if (["ready", "open", "queued", "created", "preparing", "local", "pending"].includes(normalized))
|
|
191
|
+
return pc.yellow;
|
|
192
|
+
return pc.dim;
|
|
193
|
+
}
|
|
194
|
+
function formatStatusPill(status) {
|
|
195
|
+
const label = status || "unknown";
|
|
196
|
+
return statusColor(label)(`\u25CF ${label}`);
|
|
197
|
+
}
|
|
198
|
+
function formatSection(title, subtitle) {
|
|
199
|
+
return `${pc.bold(pc.cyan("\u25C6"))} ${pc.bold(title)}${subtitle ? pc.dim(` \u2014 ${subtitle}`) : ""}`;
|
|
200
|
+
}
|
|
201
|
+
function formatSuccessCard(title, rows = []) {
|
|
202
|
+
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}`);
|
|
203
|
+
return [formatSection(title), ...body].join(`
|
|
204
|
+
`);
|
|
205
|
+
}
|
|
206
|
+
function formatNextSteps(steps) {
|
|
207
|
+
if (steps.length === 0)
|
|
208
|
+
return [];
|
|
209
|
+
return [pc.bold("Next"), ...steps.map((step) => `${pc.dim("\u203A")} ${step}`)];
|
|
210
|
+
}
|
|
211
|
+
function formatConnectionList(connections) {
|
|
212
|
+
const rows = [["local", { kind: "local", mode: "auto" }], ...Object.entries(connections)];
|
|
213
|
+
const aliasWidth = Math.min(24, Math.max(5, ...rows.map(([alias]) => alias.length)));
|
|
214
|
+
const lines = rows.map(([alias, connection]) => [
|
|
215
|
+
pc.bold(pad(truncate(alias, aliasWidth), aliasWidth)),
|
|
216
|
+
formatStatusPill(connection.kind),
|
|
217
|
+
connection.kind === "remote" ? connection.baseUrl ?? "" : connection.mode ?? "local"
|
|
218
|
+
].join(" "));
|
|
219
|
+
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(`
|
|
220
|
+
`);
|
|
221
|
+
}
|
|
222
|
+
function formatConnectionStatus(selected, connections) {
|
|
223
|
+
const connection = selected === "local" ? { kind: "local", mode: "auto" } : connections[selected];
|
|
224
|
+
const target = !connection ? "not configured" : connection.kind === "remote" ? connection.baseUrl : "local";
|
|
225
|
+
return [
|
|
226
|
+
formatSection("Rig server", "selected for this repo"),
|
|
227
|
+
`${pc.dim("\u2502")} ${pc.dim("selected ")} ${pc.bold(selected)}`,
|
|
228
|
+
`${pc.dim("\u2502")} ${pc.dim("kind ")} ${formatStatusPill(connection?.kind ?? "unknown")}`,
|
|
229
|
+
`${pc.dim("\u2502")} ${pc.dim("target ")} ${target ?? "not configured"}`,
|
|
230
|
+
"",
|
|
231
|
+
...formatNextSteps(["Change: `rig server use <alias|local>`", "List saved servers: `rig server list`"])
|
|
232
|
+
].join(`
|
|
233
|
+
`);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// packages/cli/src/commands/connect.ts
|
|
237
|
+
function usageName(options) {
|
|
238
|
+
return `rig ${options.group}`;
|
|
239
|
+
}
|
|
240
|
+
function parseConnection(alias, value, options) {
|
|
241
|
+
if (alias === "local" && !value)
|
|
242
|
+
return { kind: "local", mode: "auto" };
|
|
243
|
+
if (!value)
|
|
244
|
+
throw new CliError2(`Missing remote server URL. Usage: ${usageName(options)} add <alias> <url>`, 1);
|
|
245
|
+
let parsed;
|
|
246
|
+
try {
|
|
247
|
+
parsed = new URL(value);
|
|
248
|
+
} catch {
|
|
249
|
+
throw new CliError2(`Invalid Rig server URL: ${value}`, 1);
|
|
250
|
+
}
|
|
251
|
+
if (parsed.protocol !== "https:" && parsed.protocol !== "http:") {
|
|
252
|
+
throw new CliError2("Rig remote server URL must be http(s).", 1);
|
|
253
|
+
}
|
|
254
|
+
return { kind: "remote", baseUrl: parsed.toString().replace(/\/+$/, "") };
|
|
255
|
+
}
|
|
256
|
+
function printJsonOrText(context, payload, text) {
|
|
257
|
+
if (context.outputMode === "json") {
|
|
258
|
+
console.log(JSON.stringify(payload, null, 2));
|
|
259
|
+
} else {
|
|
260
|
+
console.log(text);
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
async function promptForConnectionAlias(context) {
|
|
264
|
+
const state = readGlobalConnections();
|
|
265
|
+
const repo = readRepoConnection(context.projectRoot);
|
|
266
|
+
const options = [
|
|
267
|
+
{ value: "local", label: "local", hint: "Use/start a local Rig server" },
|
|
268
|
+
...Object.entries(state.connections).map(([alias, connection]) => ({
|
|
269
|
+
value: alias,
|
|
270
|
+
label: alias,
|
|
271
|
+
hint: connection.kind === "remote" ? connection.baseUrl : "local"
|
|
272
|
+
}))
|
|
273
|
+
].filter((option, index, all) => all.findIndex((candidate) => candidate.value === option.value) === index);
|
|
274
|
+
const answer = await select({
|
|
275
|
+
message: "Select Rig server for this repo",
|
|
276
|
+
initialValue: repo?.selected ?? "local",
|
|
277
|
+
options
|
|
278
|
+
});
|
|
279
|
+
if (isCancel(answer)) {
|
|
280
|
+
cancel("No server selected.");
|
|
281
|
+
throw new CliError2("No server selected.", 3);
|
|
282
|
+
}
|
|
283
|
+
return String(answer);
|
|
284
|
+
}
|
|
285
|
+
async function executeConnectionCommand(context, args, options) {
|
|
286
|
+
const [command, ...rest] = args;
|
|
287
|
+
switch (command ?? "status") {
|
|
288
|
+
case "list": {
|
|
289
|
+
requireNoExtraArgs(rest, `${usageName(options)} list`);
|
|
290
|
+
const state = readGlobalConnections();
|
|
291
|
+
printJsonOrText(context, state, formatConnectionList(state.connections));
|
|
292
|
+
return { ok: true, group: options.group, command: "list", details: state };
|
|
293
|
+
}
|
|
294
|
+
case "add": {
|
|
295
|
+
const [alias, url, ...extra] = rest;
|
|
296
|
+
if (!alias)
|
|
297
|
+
throw new CliError2(`Missing alias. Usage: ${usageName(options)} add <alias> <url>`, 1);
|
|
298
|
+
requireNoExtraArgs(extra, `${usageName(options)} add <alias> <url>`);
|
|
299
|
+
const connection = parseConnection(alias, url, options);
|
|
300
|
+
const state = upsertGlobalConnection(alias, connection);
|
|
301
|
+
printJsonOrText(context, { alias, connection }, formatSuccessCard("Rig server saved", [
|
|
302
|
+
["alias", alias],
|
|
303
|
+
["target", connection.kind === "remote" ? connection.baseUrl : "local"],
|
|
304
|
+
["next", `${usageName(options)} use ${alias}`]
|
|
305
|
+
]));
|
|
306
|
+
return { ok: true, group: options.group, command: "add", details: { alias, connection, count: Object.keys(state.connections).length } };
|
|
307
|
+
}
|
|
308
|
+
case "use": {
|
|
309
|
+
let [alias, ...extra] = rest;
|
|
310
|
+
requireNoExtraArgs(extra, `${usageName(options)} use <alias|local>`);
|
|
311
|
+
if (!alias && options.interactiveUse && context.outputMode === "text" && process.stdin.isTTY) {
|
|
312
|
+
alias = await promptForConnectionAlias(context);
|
|
313
|
+
}
|
|
314
|
+
if (!alias)
|
|
315
|
+
throw new CliError2(`Missing alias. Usage: ${usageName(options)} use <alias|local>`, 1);
|
|
316
|
+
if (alias !== "local") {
|
|
317
|
+
const state = readGlobalConnections();
|
|
318
|
+
if (!state.connections[alias])
|
|
319
|
+
throw new CliError2(`Unknown Rig server: ${alias}`, 1);
|
|
320
|
+
}
|
|
321
|
+
const repoState = { selected: alias, linkedAt: new Date().toISOString() };
|
|
322
|
+
writeRepoConnection(context.projectRoot, repoState);
|
|
323
|
+
printJsonOrText(context, repoState, formatSuccessCard("Rig server selected", [
|
|
324
|
+
["selected", alias],
|
|
325
|
+
["scope", "this repo"],
|
|
326
|
+
["next", "rig task list"]
|
|
327
|
+
]));
|
|
328
|
+
return { ok: true, group: options.group, command: "use", details: repoState };
|
|
329
|
+
}
|
|
330
|
+
case "status": {
|
|
331
|
+
requireNoExtraArgs(rest, `${usageName(options)} status`);
|
|
332
|
+
const repo = readRepoConnection(context.projectRoot);
|
|
333
|
+
const global = readGlobalConnections();
|
|
334
|
+
const details = { selected: repo?.selected ?? "local", repo, connections: global.connections };
|
|
335
|
+
printJsonOrText(context, details, formatConnectionStatus(details.selected, global.connections));
|
|
336
|
+
return { ok: true, group: options.group, command: "status", details };
|
|
337
|
+
}
|
|
338
|
+
default:
|
|
339
|
+
throw new CliError2(`Unknown ${options.group} command: ${String(command)}
|
|
340
|
+
Usage: ${usageName(options)} <list|add|use|status>`, 1);
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
|
|
151
344
|
// packages/cli/src/commands/_server-client.ts
|
|
152
|
-
|
|
345
|
+
import { existsSync as existsSync2, readFileSync as readFileSync2 } from "fs";
|
|
346
|
+
import { resolve as resolve2 } from "path";
|
|
347
|
+
import { ensureLocalRigServerConnection } from "@rig/runtime/local-server";
|
|
348
|
+
var scopedGitHubBearerTokens = new Map;
|
|
153
349
|
function cleanToken(value) {
|
|
154
350
|
const trimmed = value?.trim();
|
|
155
351
|
return trimmed ? trimmed : null;
|
|
@@ -166,25 +362,13 @@ function readPrivateRemoteSessionToken(projectRoot) {
|
|
|
166
362
|
}
|
|
167
363
|
}
|
|
168
364
|
function readGitHubBearerTokenForRemote(projectRoot) {
|
|
169
|
-
|
|
170
|
-
|
|
365
|
+
const scopedKey = resolve2(projectRoot);
|
|
366
|
+
if (scopedGitHubBearerTokens.has(scopedKey))
|
|
367
|
+
return scopedGitHubBearerTokens.get(scopedKey) ?? null;
|
|
171
368
|
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;
|
|
369
|
+
if (privateSession)
|
|
370
|
+
return privateSession;
|
|
371
|
+
return cleanToken(process.env.RIG_SERVER_AUTH_TOKEN) ?? cleanToken(process.env.RIG_REMOTE_AUTH_TOKEN);
|
|
188
372
|
}
|
|
189
373
|
async function ensureServerForCli(projectRoot) {
|
|
190
374
|
try {
|
|
@@ -286,7 +470,10 @@ async function submitTaskRunViaServer(context, input) {
|
|
|
286
470
|
|
|
287
471
|
// packages/cli/src/commands/server.ts
|
|
288
472
|
async function executeServer(context, args, options) {
|
|
289
|
-
const [command = "
|
|
473
|
+
const [command = "status", ...rest] = args;
|
|
474
|
+
if (["status", "list", "add", "use"].includes(command)) {
|
|
475
|
+
return executeConnectionCommand(context, [command, ...rest], { group: "server", interactiveUse: true });
|
|
476
|
+
}
|
|
290
477
|
switch (command) {
|
|
291
478
|
case "start": {
|
|
292
479
|
let pending = rest;
|
|
@@ -298,8 +485,9 @@ async function executeServer(context, args, options) {
|
|
|
298
485
|
pending = pollResult.rest;
|
|
299
486
|
const authTokenResult = takeOption(pending, "--auth-token");
|
|
300
487
|
pending = authTokenResult.rest;
|
|
301
|
-
requireNoExtraArgs(pending, "
|
|
302
|
-
const
|
|
488
|
+
requireNoExtraArgs(pending, "rig server start [--host <host>] [--port <n>] [--poll-ms <n>] [--auth-token <token>]");
|
|
489
|
+
const serverCommand = resolveRigServerCommand(context.projectRoot);
|
|
490
|
+
const commandParts = [serverCommand.command, ...serverCommand.commandArgs, "start"];
|
|
303
491
|
if (hostResult.value) {
|
|
304
492
|
commandParts.push("--host", hostResult.value);
|
|
305
493
|
}
|
|
@@ -321,8 +509,9 @@ async function executeServer(context, args, options) {
|
|
|
321
509
|
let pending = rest;
|
|
322
510
|
const eventResult = takeOption(pending, "--event");
|
|
323
511
|
pending = eventResult.rest;
|
|
324
|
-
requireNoExtraArgs(pending, "
|
|
325
|
-
const
|
|
512
|
+
requireNoExtraArgs(pending, "rig server notify-test [--event <type>]");
|
|
513
|
+
const serverCommand = resolveRigServerCommand(context.projectRoot);
|
|
514
|
+
const commandParts = [serverCommand.command, ...serverCommand.commandArgs, "notify-test"];
|
|
326
515
|
if (eventResult.value) {
|
|
327
516
|
commandParts.push("--event", eventResult.value);
|
|
328
517
|
}
|
|
@@ -349,7 +538,7 @@ async function executeServer(context, args, options) {
|
|
|
349
538
|
pending = dirtyBaselineResult.rest;
|
|
350
539
|
const prResult = takeOption(pending, "--pr");
|
|
351
540
|
pending = prResult.rest;
|
|
352
|
-
requireNoExtraArgs(pending, "
|
|
541
|
+
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
542
|
if (!taskResult.value && !initialPromptResult.value && !titleResult.value) {
|
|
354
543
|
throw new CliError2("server task-run requires either --task <id> or --initial-prompt/--title for an ad hoc run.", 2);
|
|
355
544
|
}
|
|
@@ -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 {
|