@h-rig/cli 0.0.6-alpha.9 → 0.0.6-alpha.90
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/build-rig-binaries.d.ts +2 -0
- package/dist/bin/rig.d.ts +2 -0
- package/dist/bin/rig.js +11052 -6668
- package/dist/src/app/board.d.ts +23 -0
- package/dist/src/app/board.js +1786 -0
- package/dist/src/app/drone-ui.d.ts +37 -0
- package/dist/src/app/drone-ui.js +294 -0
- package/dist/src/app/theme.d.ts +47 -0
- package/dist/src/app/theme.js +150 -0
- package/dist/src/commands/_async-ui.d.ts +13 -0
- package/dist/src/commands/_async-ui.js +223 -0
- package/dist/src/commands/_authority-runs.d.ts +22 -0
- package/dist/src/commands/_authority-runs.js +2 -3
- package/dist/src/commands/_cli-format.d.ts +49 -0
- package/dist/src/commands/_cli-format.js +447 -0
- package/dist/src/commands/_connection-state.d.ts +44 -0
- package/dist/src/commands/_connection-state.js +30 -11
- package/dist/src/commands/_doctor-checks.d.ts +52 -0
- package/dist/src/commands/_doctor-checks.js +180 -44
- package/dist/src/commands/_help-catalog.d.ts +51 -0
- package/dist/src/commands/_help-catalog.js +442 -0
- package/dist/src/commands/_json-output.d.ts +11 -0
- package/dist/src/commands/_json-output.js +56 -0
- package/dist/src/commands/_operator-surface.d.ts +34 -0
- package/dist/src/commands/_operator-surface.js +220 -0
- package/dist/src/commands/_operator-view.d.ts +30 -0
- package/dist/src/commands/_operator-view.js +803 -73
- package/dist/src/commands/_parsers.d.ts +15 -0
- package/dist/src/commands/_parsers.js +18 -11
- package/dist/src/commands/_paths.d.ts +11 -0
- package/dist/src/commands/_pi-frontend.d.ts +27 -0
- package/dist/src/commands/_pi-frontend.js +742 -0
- package/dist/src/commands/_pi-install.d.ts +42 -0
- package/dist/src/commands/_pi-install.js +5 -4
- package/dist/src/commands/_policy.d.ts +8 -0
- package/dist/src/commands/_policy.js +12 -5
- package/dist/src/commands/_preflight.d.ts +22 -0
- package/dist/src/commands/_preflight.js +190 -128
- package/dist/src/commands/_probes.d.ts +1 -0
- package/dist/src/commands/_run-driver-helpers.d.ts +99 -0
- package/dist/src/commands/_run-driver-helpers.js +75 -22
- package/dist/src/commands/_run-replay.d.ts +24 -0
- package/dist/src/commands/_run-replay.js +142 -0
- package/dist/src/commands/_server-client.d.ts +186 -0
- package/dist/src/commands/_server-client.js +360 -61
- package/dist/src/commands/_snapshot-upload.d.ts +39 -0
- package/dist/src/commands/_snapshot-upload.js +163 -39
- package/dist/src/commands/_spinner.d.ts +25 -0
- package/dist/src/commands/_spinner.js +65 -0
- package/dist/src/commands/_task-picker.d.ts +9 -0
- package/dist/src/commands/_task-picker.js +172 -19
- package/dist/src/commands/agent.d.ts +3 -0
- package/dist/src/commands/agent.js +39 -20
- package/dist/src/commands/browser.d.ts +65 -0
- package/dist/src/commands/browser.js +334 -51
- package/dist/src/commands/connect.d.ts +7 -0
- package/dist/src/commands/connect.js +272 -33
- package/dist/src/commands/dist.d.ts +28 -0
- package/dist/src/commands/dist.js +19 -12
- package/dist/src/commands/doctor.d.ts +3 -0
- package/dist/src/commands/doctor.js +378 -45
- package/dist/src/commands/github.d.ts +3 -0
- package/dist/src/commands/github.js +375 -53
- package/dist/src/commands/inbox.d.ts +30 -0
- package/dist/src/commands/inbox.js +760 -70
- package/dist/src/commands/init.d.ts +74 -0
- package/dist/src/commands/init.js +963 -119
- package/dist/src/commands/inspect.d.ts +3 -0
- package/dist/src/commands/inspect.js +588 -32
- package/dist/src/commands/inspector.d.ts +3 -0
- package/dist/src/commands/inspector.js +20 -13
- package/dist/src/commands/pi.d.ts +3 -0
- package/dist/src/commands/pi.js +177 -0
- package/dist/src/commands/plugin.d.ts +16 -0
- package/dist/src/commands/plugin.js +95 -27
- package/dist/src/commands/profile-and-review.d.ts +4 -0
- package/dist/src/commands/profile-and-review.js +26 -19
- package/dist/src/commands/queue.d.ts +3 -0
- package/dist/src/commands/queue.js +32 -12
- package/dist/src/commands/remote.d.ts +3 -0
- package/dist/src/commands/remote.js +43 -36
- package/dist/src/commands/repo-git-harness.d.ts +5 -0
- package/dist/src/commands/repo-git-harness.js +22 -15
- package/dist/src/commands/run.d.ts +3 -0
- package/dist/src/commands/run.js +1379 -159
- package/dist/src/commands/server.d.ts +7 -0
- package/dist/src/commands/server.js +502 -57
- package/dist/src/commands/setup.d.ts +16 -0
- package/dist/src/commands/setup.js +390 -63
- package/dist/src/commands/stats.d.ts +12 -0
- package/dist/src/commands/stats.js +1051 -0
- package/dist/src/commands/task-report-bug.d.ts +19 -0
- package/dist/src/commands/task-report-bug.js +260 -62
- package/dist/src/commands/task-run-driver.d.ts +132 -0
- package/dist/src/commands/task-run-driver.js +886 -130
- package/dist/src/commands/task.d.ts +14 -0
- package/dist/src/commands/task.js +1644 -314
- package/dist/src/commands/test.d.ts +3 -0
- package/dist/src/commands/test.js +15 -8
- package/dist/src/commands/workspace.d.ts +3 -0
- package/dist/src/commands/workspace.js +18 -11
- package/dist/src/commands.d.ts +29 -0
- package/dist/src/commands.js +10967 -6637
- package/dist/src/index.d.ts +4 -0
- package/dist/src/index.js +10168 -5787
- package/dist/src/launcher.d.ts +61 -0
- package/dist/src/launcher.js +77 -13
- package/dist/src/report-bug.d.ts +44 -0
- package/dist/src/report-bug.js +3 -3
- package/dist/src/runner.d.ts +47 -0
- package/dist/src/runner.js +16 -22
- package/dist/src/withMutedConsole.d.ts +2 -0
- package/package.json +13 -6
|
@@ -1,12 +1,19 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
// packages/cli/src/runner.ts
|
|
3
3
|
import { EventBus } from "@rig/runtime/control-plane/runtime/events";
|
|
4
|
-
import { CliError } from "@rig/runtime/control-plane/errors";
|
|
4
|
+
import { CliError as RuntimeCliError } 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
|
+
|
|
8
|
+
class CliError extends RuntimeCliError {
|
|
9
|
+
hint;
|
|
10
|
+
constructor(message, exitCode = 1, options = {}) {
|
|
11
|
+
super(message, exitCode);
|
|
12
|
+
if (options.hint?.trim()) {
|
|
13
|
+
this.hint = options.hint.trim();
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
}
|
|
10
17
|
function takeFlag(args, flag) {
|
|
11
18
|
const rest = [];
|
|
12
19
|
let value = false;
|
|
@@ -27,7 +34,7 @@ function takeOption(args, option) {
|
|
|
27
34
|
if (current === option) {
|
|
28
35
|
const next = args[index + 1];
|
|
29
36
|
if (!next || next.startsWith("-")) {
|
|
30
|
-
throw new CliError(`Missing value for ${option}`);
|
|
37
|
+
throw new CliError(`Missing value for ${option}`, 1, { hint: `Provide a value after ${option}, e.g. \`${option} <value>\`.` });
|
|
31
38
|
}
|
|
32
39
|
value = next;
|
|
33
40
|
index += 1;
|
|
@@ -56,7 +63,7 @@ function parsePositiveInt(value, option, fallback) {
|
|
|
56
63
|
}
|
|
57
64
|
const parsed = Number.parseInt(value, 10);
|
|
58
65
|
if (!Number.isFinite(parsed) || parsed <= 0) {
|
|
59
|
-
throw new
|
|
66
|
+
throw new CliError(`Invalid ${option} value: ${value}`, 1, { hint: `Pass a positive integer, e.g. \`${option} 10\`.` });
|
|
60
67
|
}
|
|
61
68
|
return parsed;
|
|
62
69
|
}
|
|
@@ -70,7 +77,7 @@ function parseAction(value) {
|
|
|
70
77
|
if (value === "pipeline") {
|
|
71
78
|
return "pipeline";
|
|
72
79
|
}
|
|
73
|
-
throw new
|
|
80
|
+
throw new CliError(`Invalid --action value: ${value}. Use validate, verify, or pipeline.`);
|
|
74
81
|
}
|
|
75
82
|
function parseIsolationMode(value, allowOff) {
|
|
76
83
|
if (!value) {
|
|
@@ -82,7 +89,7 @@ function parseIsolationMode(value, allowOff) {
|
|
|
82
89
|
if (allowOff && value === "off") {
|
|
83
90
|
return value;
|
|
84
91
|
}
|
|
85
|
-
throw new
|
|
92
|
+
throw new CliError(`Invalid isolation mode: ${value}. Use ${allowOff ? "off|" : ""}worktree.`);
|
|
86
93
|
}
|
|
87
94
|
|
|
88
95
|
// packages/cli/src/commands/_preflight.ts
|
|
@@ -90,6 +97,19 @@ import { ensureProjectMainFreshBeforeRun } from "@rig/runtime/control-plane/proj
|
|
|
90
97
|
|
|
91
98
|
// packages/cli/src/commands/_server-client.ts
|
|
92
99
|
import { ensureLocalRigServerConnection } from "@rig/runtime/local-server";
|
|
100
|
+
var scopedGitHubBearerTokens = new Map;
|
|
101
|
+
var serverReachabilityCache = new Map;
|
|
102
|
+
var RESUMABLE_RUN_STATUSES = new Set([
|
|
103
|
+
"created",
|
|
104
|
+
"preparing",
|
|
105
|
+
"running",
|
|
106
|
+
"validating",
|
|
107
|
+
"reviewing",
|
|
108
|
+
"stopped",
|
|
109
|
+
"failed",
|
|
110
|
+
"needs-attention",
|
|
111
|
+
"needs_attention"
|
|
112
|
+
]);
|
|
93
113
|
|
|
94
114
|
// packages/cli/src/commands/_preflight.ts
|
|
95
115
|
async function runProjectMainSyncPreflight(context, options) {
|
|
@@ -105,7 +125,7 @@ async function runProjectMainSyncPreflight(context, options) {
|
|
|
105
125
|
runBootstrap: async () => {
|
|
106
126
|
const bootstrap = await context.runCommand(["bun", "run", "bootstrap"]);
|
|
107
127
|
if (bootstrap.exitCode !== 0) {
|
|
108
|
-
throw new
|
|
128
|
+
throw new CliError(bootstrap.stderr || bootstrap.stdout || "bun run bootstrap failed during project pre-run sync", bootstrap.exitCode || 1);
|
|
109
129
|
}
|
|
110
130
|
}
|
|
111
131
|
});
|
|
@@ -150,7 +170,7 @@ async function executeQueue(context, args) {
|
|
|
150
170
|
pending = failFastResult.rest;
|
|
151
171
|
const skipProjectSyncResult = takeFlag(pending, "--skip-project-sync");
|
|
152
172
|
pending = skipProjectSyncResult.rest;
|
|
153
|
-
requireNoExtraArgs(pending, "
|
|
173
|
+
requireNoExtraArgs(pending, "rig queue run [--workers <n>] [--max-tasks <n>] [--action validate|verify|pipeline] [--isolation off|worktree] [--no-runtime-reuse] [--fail-fast] [--skip-project-sync]");
|
|
154
174
|
const workers = parsePositiveInt(workersResult.value, "--workers", 2);
|
|
155
175
|
const maxTasks = parsePositiveInt(maxTasksResult.value, "--max-tasks", 10);
|
|
156
176
|
const action = parseAction(actionResult.value);
|
|
@@ -171,7 +191,7 @@ async function executeQueue(context, args) {
|
|
|
171
191
|
console.log(`Failed: ${summary.failed}`);
|
|
172
192
|
}
|
|
173
193
|
if (summary.failed > 0) {
|
|
174
|
-
throw new
|
|
194
|
+
throw new CliError(`Queue finished with ${summary.failed} failed task(s).`, 3, { hint: "Inspect the failures with `rig inspect failures`, then re-run `rig queue run`." });
|
|
175
195
|
}
|
|
176
196
|
return {
|
|
177
197
|
ok: true,
|
|
@@ -189,7 +209,7 @@ async function executeQueue(context, args) {
|
|
|
189
209
|
};
|
|
190
210
|
}
|
|
191
211
|
default:
|
|
192
|
-
throw new
|
|
212
|
+
throw new CliError(`Unknown queue command: ${command}`, 1, { hint: "Run `rig queue --help` \u2014 the primary command is `rig queue run`." });
|
|
193
213
|
}
|
|
194
214
|
}
|
|
195
215
|
export {
|
|
@@ -1,12 +1,19 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
// packages/cli/src/runner.ts
|
|
3
3
|
import { EventBus } from "@rig/runtime/control-plane/runtime/events";
|
|
4
|
-
import { CliError } from "@rig/runtime/control-plane/errors";
|
|
4
|
+
import { CliError as RuntimeCliError } 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
|
+
|
|
8
|
+
class CliError extends RuntimeCliError {
|
|
9
|
+
hint;
|
|
10
|
+
constructor(message, exitCode = 1, options = {}) {
|
|
11
|
+
super(message, exitCode);
|
|
12
|
+
if (options.hint?.trim()) {
|
|
13
|
+
this.hint = options.hint.trim();
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
}
|
|
10
17
|
function takeFlag(args, flag) {
|
|
11
18
|
const rest = [];
|
|
12
19
|
let value = false;
|
|
@@ -27,7 +34,7 @@ function takeOption(args, option) {
|
|
|
27
34
|
if (current === option) {
|
|
28
35
|
const next = args[index + 1];
|
|
29
36
|
if (!next || next.startsWith("-")) {
|
|
30
|
-
throw new CliError(`Missing value for ${option}`);
|
|
37
|
+
throw new CliError(`Missing value for ${option}`, 1, { hint: `Provide a value after ${option}, e.g. \`${option} <value>\`.` });
|
|
31
38
|
}
|
|
32
39
|
value = next;
|
|
33
40
|
index += 1;
|
|
@@ -75,17 +82,17 @@ function parseOptionalPositiveInt(value, option) {
|
|
|
75
82
|
}
|
|
76
83
|
const parsed = Number.parseInt(value, 10);
|
|
77
84
|
if (!Number.isFinite(parsed) || parsed <= 0) {
|
|
78
|
-
throw new
|
|
85
|
+
throw new CliError(`Invalid ${option} value: ${value}`, 1, { hint: `Pass a positive integer, e.g. \`${option} 10\`.` });
|
|
79
86
|
}
|
|
80
87
|
return parsed;
|
|
81
88
|
}
|
|
82
89
|
function parseRequiredPositiveInt(value, option) {
|
|
83
90
|
if (!value) {
|
|
84
|
-
throw new
|
|
91
|
+
throw new CliError(`Missing value for ${option}.`, 1, { hint: `Provide a value after ${option}, e.g. \`${option} 10\`.` });
|
|
85
92
|
}
|
|
86
93
|
const parsed = Number.parseInt(value, 10);
|
|
87
94
|
if (!Number.isFinite(parsed) || parsed <= 0) {
|
|
88
|
-
throw new
|
|
95
|
+
throw new CliError(`Invalid ${option} value: ${value}`, 1, { hint: `Pass a positive integer, e.g. \`${option} 10\`.` });
|
|
89
96
|
}
|
|
90
97
|
return parsed;
|
|
91
98
|
}
|
|
@@ -134,7 +141,7 @@ async function executeRemote(context, args) {
|
|
|
134
141
|
const [subcommand = "list", ...subRest] = rest;
|
|
135
142
|
switch (subcommand) {
|
|
136
143
|
case "list": {
|
|
137
|
-
requireNoExtraArgs(subRest, "
|
|
144
|
+
requireNoExtraArgs(subRest, "rig remote endpoint list");
|
|
138
145
|
const endpoints = listManagedRemoteEndpoints(undefined, context.projectRoot);
|
|
139
146
|
const redactedEndpoints = endpoints.map((endpoint2) => redactRemoteEndpoint(endpoint2));
|
|
140
147
|
if (context.outputMode === "text") {
|
|
@@ -158,9 +165,9 @@ async function executeRemote(context, args) {
|
|
|
158
165
|
pending2 = port.rest;
|
|
159
166
|
const token = takeOption(pending2, "--token");
|
|
160
167
|
pending2 = token.rest;
|
|
161
|
-
requireNoExtraArgs(pending2, "
|
|
168
|
+
requireNoExtraArgs(pending2, "rig remote endpoint add --alias <a> --host <h> --port <n> --token <t>");
|
|
162
169
|
if (!alias.value || !host.value || !token.value || !port.value) {
|
|
163
|
-
throw new
|
|
170
|
+
throw new CliError("remote endpoint add requires --alias, --host, --port, and --token.", 1, { hint: "Re-run as `rig remote endpoint add --alias <a> --host <h> --port <n> --token <t>`." });
|
|
164
171
|
}
|
|
165
172
|
const created = upsertManagedRemoteEndpoint({
|
|
166
173
|
alias: alias.value,
|
|
@@ -185,9 +192,9 @@ async function executeRemote(context, args) {
|
|
|
185
192
|
pending2 = port.rest;
|
|
186
193
|
const token = takeOption(pending2, "--token");
|
|
187
194
|
pending2 = token.rest;
|
|
188
|
-
requireNoExtraArgs(pending2, "
|
|
195
|
+
requireNoExtraArgs(pending2, "rig remote endpoint update --id <id> [--alias <a>] [--host <h>] [--port <n>] [--token <t>]");
|
|
189
196
|
if (!endpointId.value && !alias.value) {
|
|
190
|
-
throw new
|
|
197
|
+
throw new CliError("remote endpoint update requires --id <id> or --alias <a>.", 1, { hint: "List endpoints with `rig remote endpoint list`, then pass --id or --alias." });
|
|
191
198
|
}
|
|
192
199
|
const updated = updateManagedRemoteEndpointInAuthority(context.projectRoot, {
|
|
193
200
|
endpointId: endpointId.value || undefined,
|
|
@@ -197,7 +204,7 @@ async function executeRemote(context, args) {
|
|
|
197
204
|
token: token.value || undefined
|
|
198
205
|
});
|
|
199
206
|
if (!updated) {
|
|
200
|
-
throw new
|
|
207
|
+
throw new CliError("Remote endpoint not found.", 2, { hint: "Run `rig remote endpoint list` to see configured endpoints." });
|
|
201
208
|
}
|
|
202
209
|
if (context.outputMode === "text") {
|
|
203
210
|
console.log(`Updated remote endpoint ${updated.alias} -> ${updated.host}:${updated.port}`);
|
|
@@ -208,13 +215,13 @@ async function executeRemote(context, args) {
|
|
|
208
215
|
let pending2 = subRest;
|
|
209
216
|
const alias = takeOption(pending2, "--alias");
|
|
210
217
|
pending2 = alias.rest;
|
|
211
|
-
requireNoExtraArgs(pending2, "
|
|
218
|
+
requireNoExtraArgs(pending2, "rig remote endpoint remove --alias <a>");
|
|
212
219
|
if (!alias.value) {
|
|
213
|
-
throw new
|
|
220
|
+
throw new CliError("remote endpoint remove requires --alias.", 1, { hint: "Run `rig remote endpoint list` to find the alias, then `rig remote endpoint remove --alias <a>`." });
|
|
214
221
|
}
|
|
215
222
|
const removed = removeManagedRemoteEndpoint(alias.value, undefined, context.projectRoot);
|
|
216
223
|
if (!removed) {
|
|
217
|
-
throw new
|
|
224
|
+
throw new CliError(`Remote endpoint alias not found: ${alias.value}`, 2, { hint: "Run `rig remote endpoint list` to see configured endpoint aliases." });
|
|
218
225
|
}
|
|
219
226
|
if (context.outputMode === "text") {
|
|
220
227
|
console.log(`Removed remote endpoint ${alias.value}`);
|
|
@@ -225,9 +232,9 @@ async function executeRemote(context, args) {
|
|
|
225
232
|
let pending2 = subRest;
|
|
226
233
|
const alias = takeOption(pending2, "--alias");
|
|
227
234
|
pending2 = alias.rest;
|
|
228
|
-
requireNoExtraArgs(pending2, "
|
|
235
|
+
requireNoExtraArgs(pending2, "rig remote endpoint test --alias <a>");
|
|
229
236
|
if (!alias.value) {
|
|
230
|
-
throw new
|
|
237
|
+
throw new CliError("remote endpoint test requires --alias.", 1, { hint: "Run `rig remote endpoint list` to find the alias, then `rig remote endpoint test --alias <a>`." });
|
|
231
238
|
}
|
|
232
239
|
const endpoint2 = resolveRemoteEndpoint({ remoteAlias: alias.value, projectRoot: context.projectRoot });
|
|
233
240
|
const client = new RemoteWsClient(endpoint2);
|
|
@@ -256,7 +263,7 @@ async function executeRemote(context, args) {
|
|
|
256
263
|
}
|
|
257
264
|
}
|
|
258
265
|
case "migrate": {
|
|
259
|
-
requireNoExtraArgs(subRest, "
|
|
266
|
+
requireNoExtraArgs(subRest, "rig remote endpoint migrate");
|
|
260
267
|
const result = migrateManagedRemoteEndpoints(context.projectRoot);
|
|
261
268
|
if (context.outputMode === "text") {
|
|
262
269
|
console.log(`Imported ${result.imported} endpoint(s) from ${result.sourcePath}${result.skipped > 0 ? `, skipped ${result.skipped}` : ""}.`);
|
|
@@ -264,7 +271,7 @@ async function executeRemote(context, args) {
|
|
|
264
271
|
return { ok: true, group: "remote", command: "endpoint migrate", details: result };
|
|
265
272
|
}
|
|
266
273
|
case "doctor": {
|
|
267
|
-
requireNoExtraArgs(subRest, "
|
|
274
|
+
requireNoExtraArgs(subRest, "rig remote endpoint doctor");
|
|
268
275
|
const result = doctorManagedRemoteEndpoints(context.projectRoot);
|
|
269
276
|
if (context.outputMode === "text") {
|
|
270
277
|
console.log(JSON.stringify(result, null, 2));
|
|
@@ -272,7 +279,7 @@ async function executeRemote(context, args) {
|
|
|
272
279
|
return { ok: true, group: "remote", command: "endpoint doctor", details: result };
|
|
273
280
|
}
|
|
274
281
|
default:
|
|
275
|
-
throw new
|
|
282
|
+
throw new CliError(`Unknown remote endpoint command: ${subcommand}`, 1, { hint: "Run `rig remote --help` for endpoint commands (list|add|update|remove|test)." });
|
|
276
283
|
}
|
|
277
284
|
}
|
|
278
285
|
let pending = rest;
|
|
@@ -317,17 +324,17 @@ async function executeRemote(context, args) {
|
|
|
317
324
|
try {
|
|
318
325
|
switch (command) {
|
|
319
326
|
case "test": {
|
|
320
|
-
requireNoExtraArgs(pending, "
|
|
327
|
+
requireNoExtraArgs(pending, "rig remote test [--remote <alias>] [--host <host>] [--port <n>] [--token <token>]");
|
|
321
328
|
const response = await withClient((client) => client.ping());
|
|
322
329
|
return { ok: true, group: "remote", command, details: toDetails(response) };
|
|
323
330
|
}
|
|
324
331
|
case "status": {
|
|
325
|
-
requireNoExtraArgs(pending, "
|
|
332
|
+
requireNoExtraArgs(pending, "rig remote status [--remote <alias>] [--host <host>] [--port <n>] [--token <token>]");
|
|
326
333
|
const response = await withClient((client) => client.getState());
|
|
327
334
|
return { ok: true, group: "remote", command, details: toDetails(response) };
|
|
328
335
|
}
|
|
329
336
|
case "tasks": {
|
|
330
|
-
requireNoExtraArgs(pending, "
|
|
337
|
+
requireNoExtraArgs(pending, "rig remote tasks [--remote <alias>] [--host <host>] [--port <n>] [--token <token>]");
|
|
331
338
|
const response = await withClient((client) => client.getTasks());
|
|
332
339
|
return { ok: true, group: "remote", command, details: toDetails(response) };
|
|
333
340
|
}
|
|
@@ -337,11 +344,11 @@ async function executeRemote(context, args) {
|
|
|
337
344
|
watchPending = secondsResult.rest;
|
|
338
345
|
const eventResult = takeOption(watchPending, "--event");
|
|
339
346
|
watchPending = eventResult.rest;
|
|
340
|
-
requireNoExtraArgs(watchPending, "
|
|
347
|
+
requireNoExtraArgs(watchPending, "rig remote watch [--seconds <n>] [--event <type>] [--remote <alias>] [--host <host>] [--port <n>] [--token <token>]");
|
|
341
348
|
const seconds = parseOptionalPositiveInt(secondsResult.value, "--seconds");
|
|
342
349
|
const eventFilter = eventResult.value || undefined;
|
|
343
350
|
if (context.outputMode === "json" && !seconds) {
|
|
344
|
-
throw new
|
|
351
|
+
throw new CliError("--json remote watch requires --seconds <n> to produce bounded output.", 2, { hint: "Re-run as `rig remote watch --seconds 10 --json`." });
|
|
345
352
|
}
|
|
346
353
|
const captured = [];
|
|
347
354
|
let dropped = 0;
|
|
@@ -406,7 +413,7 @@ async function executeRemote(context, args) {
|
|
|
406
413
|
case "stop":
|
|
407
414
|
case "continue":
|
|
408
415
|
case "refresh": {
|
|
409
|
-
requireNoExtraArgs(pending, `
|
|
416
|
+
requireNoExtraArgs(pending, `rig remote ${command} [--remote <alias>] [--host <host>] [--port <n>] [--token <token>]`);
|
|
410
417
|
const response = await withClient(async (client) => {
|
|
411
418
|
switch (command) {
|
|
412
419
|
case "pause":
|
|
@@ -429,7 +436,7 @@ async function executeRemote(context, args) {
|
|
|
429
436
|
let countPending = pending;
|
|
430
437
|
const countResult = takeOption(countPending, "--count");
|
|
431
438
|
countPending = countResult.rest;
|
|
432
|
-
requireNoExtraArgs(countPending, `
|
|
439
|
+
requireNoExtraArgs(countPending, `rig remote ${command} --count <n> [--remote <alias>] [--host <host>] [--port <n>] [--token <token>]`);
|
|
433
440
|
const count = parseRequiredPositiveInt(countResult.value, "--count");
|
|
434
441
|
const response = await withClient(async (client) => command === "add-iterations" ? await client.addIterations(count) : await client.removeIterations(count));
|
|
435
442
|
assertRemoteOperationSuccess(command, response);
|
|
@@ -440,8 +447,8 @@ async function executeRemote(context, args) {
|
|
|
440
447
|
let taskPending = pending;
|
|
441
448
|
const taskResult = takeOption(taskPending, "--task");
|
|
442
449
|
taskPending = taskResult.rest;
|
|
443
|
-
requireNoExtraArgs(taskPending, `
|
|
444
|
-
const taskId = requireTask(taskResult.value, `
|
|
450
|
+
requireNoExtraArgs(taskPending, `rig remote ${command} --task <id> [--remote <alias>] [--host <host>] [--port <n>] [--token <token>]`);
|
|
451
|
+
const taskId = requireTask(taskResult.value, `rig remote ${command} --task <id>`);
|
|
445
452
|
const response = await withClient(async (client) => command === "prompt-preview" ? await client.getPromptPreview(taskId) : await client.getIterationOutput(taskId));
|
|
446
453
|
assertRemoteOperationSuccess(command, response);
|
|
447
454
|
return { ok: true, group: "remote", command, details: toDetails(response) };
|
|
@@ -454,7 +461,7 @@ async function executeRemote(context, args) {
|
|
|
454
461
|
orchestrationPending = maxIterationsResult.rest;
|
|
455
462
|
const directMergeResult = takeFlag(orchestrationPending, "--direct-merge");
|
|
456
463
|
orchestrationPending = directMergeResult.rest;
|
|
457
|
-
requireNoExtraArgs(orchestrationPending, "
|
|
464
|
+
requireNoExtraArgs(orchestrationPending, "rig remote orchestrate-start [--max-workers <n>] [--max-iterations <n>] [--direct-merge]");
|
|
458
465
|
const response = await withClient((client) => client.startOrchestration({
|
|
459
466
|
maxWorkers: parseOptionalPositiveInt(maxWorkersResult.value, "--max-workers"),
|
|
460
467
|
maxIterations: parseOptionalPositiveInt(maxIterationsResult.value, "--max-iterations"),
|
|
@@ -475,8 +482,8 @@ async function executeRemote(context, args) {
|
|
|
475
482
|
let orchestrationPending = pending;
|
|
476
483
|
const idResult = takeOption(orchestrationPending, "--id");
|
|
477
484
|
orchestrationPending = idResult.rest;
|
|
478
|
-
requireNoExtraArgs(orchestrationPending, `
|
|
479
|
-
const orchestrationId = requireTask(idResult.value, `
|
|
485
|
+
requireNoExtraArgs(orchestrationPending, `rig remote ${command} --id <orch-id> [--remote <alias>] [--host <host>] [--port <n>] [--token <token>]`);
|
|
486
|
+
const orchestrationId = requireTask(idResult.value, `rig remote ${command} --id <orch-id> [--remote <alias>] [--host <host>] [--port <n>] [--token <token>]`);
|
|
480
487
|
const response = await withClient(async (client) => {
|
|
481
488
|
switch (command) {
|
|
482
489
|
case "orchestrate-pause":
|
|
@@ -493,11 +500,11 @@ async function executeRemote(context, args) {
|
|
|
493
500
|
return { ok: true, group: "remote", command, details: toDetails(response) };
|
|
494
501
|
}
|
|
495
502
|
default:
|
|
496
|
-
throw new
|
|
503
|
+
throw new CliError(`Unknown remote command: ${command}`, 1, { hint: "Run `rig remote --help` to list remote commands." });
|
|
497
504
|
}
|
|
498
505
|
} catch (error) {
|
|
499
506
|
if (error instanceof RemoteCliError) {
|
|
500
|
-
throw new
|
|
507
|
+
throw new CliError(`[${error.code}] ${error.message}`, error.exitCode);
|
|
501
508
|
}
|
|
502
509
|
throw error;
|
|
503
510
|
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { type RunnerContext } from "../runner";
|
|
2
|
+
import type { CommandOutcome } from "@rig/runtime/control-plane/runtime/types";
|
|
3
|
+
export declare function executeRepo(context: RunnerContext, args: string[]): Promise<CommandOutcome>;
|
|
4
|
+
export declare function executeGit(context: RunnerContext, args: string[]): Promise<CommandOutcome>;
|
|
5
|
+
export declare function executeHarness(context: RunnerContext, args: string[]): Promise<CommandOutcome>;
|
|
@@ -1,12 +1,19 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
// packages/cli/src/runner.ts
|
|
3
3
|
import { EventBus } from "@rig/runtime/control-plane/runtime/events";
|
|
4
|
-
import { CliError } from "@rig/runtime/control-plane/errors";
|
|
4
|
+
import { CliError as RuntimeCliError } 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
|
+
|
|
8
|
+
class CliError extends RuntimeCliError {
|
|
9
|
+
hint;
|
|
10
|
+
constructor(message, exitCode = 1, options = {}) {
|
|
11
|
+
super(message, exitCode);
|
|
12
|
+
if (options.hint?.trim()) {
|
|
13
|
+
this.hint = options.hint.trim();
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
}
|
|
10
17
|
function formatCommand(parts) {
|
|
11
18
|
return parts.map((part) => /[^a-zA-Z0-9_./:-]/.test(part) ? JSON.stringify(part) : part).join(" ");
|
|
12
19
|
}
|
|
@@ -30,7 +37,7 @@ function takeOption(args, option) {
|
|
|
30
37
|
if (current === option) {
|
|
31
38
|
const next = args[index + 1];
|
|
32
39
|
if (!next || next.startsWith("-")) {
|
|
33
|
-
throw new CliError(`Missing value for ${option}`);
|
|
40
|
+
throw new CliError(`Missing value for ${option}`, 1, { hint: `Provide a value after ${option}, e.g. \`${option} <value>\`.` });
|
|
34
41
|
}
|
|
35
42
|
value = next;
|
|
36
43
|
index += 1;
|
|
@@ -148,7 +155,7 @@ async function enforceNativeCommandPolicy(context, args, options) {
|
|
|
148
155
|
appendControlledBashAudit(context, mode, command, args, matchedRuleIds, action === "block" ? "blocked" : action === "warn" ? "warn" : undefined);
|
|
149
156
|
}
|
|
150
157
|
if (action === "block") {
|
|
151
|
-
throw new
|
|
158
|
+
throw new CliError(`Policy blocked command: ${command}`, 126, { hint: "Review rig/policy/policy.json, or re-run with `--policy-mode observe` to log instead of block." });
|
|
152
159
|
}
|
|
153
160
|
}
|
|
154
161
|
|
|
@@ -158,23 +165,23 @@ async function executeRepo(context, args) {
|
|
|
158
165
|
switch (command) {
|
|
159
166
|
case "sync": {
|
|
160
167
|
const { value: task, rest: remaining } = takeOption(rest, "--task");
|
|
161
|
-
requireNoExtraArgs(remaining, "
|
|
168
|
+
requireNoExtraArgs(remaining, "rig repo sync [--task <task-id>]");
|
|
162
169
|
withMutedConsole(context.outputMode === "json", () => repoEnsure(context.projectRoot, task || undefined));
|
|
163
170
|
return { ok: true, group: "repo", command, details: { task: task || null } };
|
|
164
171
|
}
|
|
165
172
|
case "reset-baseline": {
|
|
166
173
|
const { value: keepTaskStatusFlag, rest: remaining } = takeFlag(rest, "--keep-task-status");
|
|
167
|
-
requireNoExtraArgs(remaining, "
|
|
174
|
+
requireNoExtraArgs(remaining, "rig repo reset-baseline [--keep-task-status]");
|
|
168
175
|
withMutedConsole(context.outputMode === "json", () => resetBaseline(context.projectRoot, keepTaskStatusFlag));
|
|
169
176
|
return { ok: true, group: "repo", command, details: { keepTaskStatus: keepTaskStatusFlag } };
|
|
170
177
|
}
|
|
171
178
|
default:
|
|
172
|
-
throw new
|
|
179
|
+
throw new CliError(`Unknown repo command: ${command}`, 1, { hint: "Run `rig repo --help` \u2014 commands are sync|reset-baseline." });
|
|
173
180
|
}
|
|
174
181
|
}
|
|
175
182
|
async function executeGit(context, args) {
|
|
176
183
|
if (args.length === 0) {
|
|
177
|
-
throw new
|
|
184
|
+
throw new CliError("Usage: rig git <git-flow args...>");
|
|
178
185
|
}
|
|
179
186
|
await enforceNativeCommandPolicy(context, args, {
|
|
180
187
|
commandPrefix: "rig-agent git",
|
|
@@ -187,15 +194,15 @@ async function executeGit(context, args) {
|
|
|
187
194
|
return { ok: true, group: "git", command: args[0] ?? "git" };
|
|
188
195
|
}
|
|
189
196
|
try {
|
|
190
|
-
await executeHarnessCommand(context.projectRoot,
|
|
197
|
+
await executeHarnessCommand(context.projectRoot, ["git", ...args]);
|
|
191
198
|
} catch (error) {
|
|
192
|
-
throw new
|
|
199
|
+
throw new CliError(error instanceof Error ? error.message : String(error), 2);
|
|
193
200
|
}
|
|
194
201
|
return { ok: true, group: "git", command: args[0] ?? "git" };
|
|
195
202
|
}
|
|
196
203
|
async function executeHarness(context, args) {
|
|
197
204
|
if (args.length === 0) {
|
|
198
|
-
throw new
|
|
205
|
+
throw new CliError("Usage: rig harness <harness args...>");
|
|
199
206
|
}
|
|
200
207
|
await enforceNativeCommandPolicy(context, args, {
|
|
201
208
|
commandPrefix: "rig-agent",
|
|
@@ -208,9 +215,9 @@ async function executeHarness(context, args) {
|
|
|
208
215
|
return { ok: true, group: "harness", command: args[0] ?? "harness" };
|
|
209
216
|
}
|
|
210
217
|
try {
|
|
211
|
-
await executeHarnessCommand(context.projectRoot,
|
|
218
|
+
await executeHarnessCommand(context.projectRoot, args);
|
|
212
219
|
} catch (error) {
|
|
213
|
-
throw new
|
|
220
|
+
throw new CliError(error instanceof Error ? error.message : String(error), 2);
|
|
214
221
|
}
|
|
215
222
|
return { ok: true, group: "harness", command: args[0] ?? "harness" };
|
|
216
223
|
}
|