@h-rig/cli-surface-plugin 0.0.6-alpha.146

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.
Files changed (94) hide show
  1. package/README.md +1 -0
  2. package/dist/src/app/drone-ui.d.ts +34 -0
  3. package/dist/src/app/drone-ui.js +278 -0
  4. package/dist/src/commands/_async-ui.d.ts +10 -0
  5. package/dist/src/commands/_async-ui.js +121 -0
  6. package/dist/src/commands/_cli-format.d.ts +56 -0
  7. package/dist/src/commands/_cli-format.js +332 -0
  8. package/dist/src/commands/_connection-state.d.ts +54 -0
  9. package/dist/src/commands/_connection-state.js +187 -0
  10. package/dist/src/commands/_doctor-checks.d.ts +9 -0
  11. package/dist/src/commands/_doctor-checks.js +24 -0
  12. package/dist/src/commands/_help-catalog.d.ts +29 -0
  13. package/dist/src/commands/_help-catalog.js +157 -0
  14. package/dist/src/commands/_inprocess-services.d.ts +33 -0
  15. package/dist/src/commands/_inprocess-services.js +102 -0
  16. package/dist/src/commands/_json-output.d.ts +11 -0
  17. package/dist/src/commands/_json-output.js +54 -0
  18. package/dist/src/commands/_parsers.d.ts +15 -0
  19. package/dist/src/commands/_parsers.js +114 -0
  20. package/dist/src/commands/_paths.d.ts +11 -0
  21. package/dist/src/commands/_paths.js +50 -0
  22. package/dist/src/commands/_pi-frontend.d.ts +35 -0
  23. package/dist/src/commands/_pi-frontend.js +64 -0
  24. package/dist/src/commands/_pi-install.d.ts +42 -0
  25. package/dist/src/commands/_pi-install.js +167 -0
  26. package/dist/src/commands/_policy.d.ts +8 -0
  27. package/dist/src/commands/_policy.js +138 -0
  28. package/dist/src/commands/_probes.d.ts +1 -0
  29. package/dist/src/commands/_probes.js +13 -0
  30. package/dist/src/commands/_run-driver-helpers.d.ts +26 -0
  31. package/dist/src/commands/_run-driver-helpers.js +132 -0
  32. package/dist/src/commands/_run-subcommands.d.ts +3 -0
  33. package/dist/src/commands/_run-subcommands.js +31 -0
  34. package/dist/src/commands/_spinner.d.ts +25 -0
  35. package/dist/src/commands/_spinner.js +65 -0
  36. package/dist/src/commands/agent.d.ts +3 -0
  37. package/dist/src/commands/agent.js +322 -0
  38. package/dist/src/commands/config.d.ts +3 -0
  39. package/dist/src/commands/config.js +193 -0
  40. package/dist/src/commands/dist.d.ts +28 -0
  41. package/dist/src/commands/dist.js +435 -0
  42. package/dist/src/commands/doctor.d.ts +3 -0
  43. package/dist/src/commands/doctor.js +171 -0
  44. package/dist/src/commands/github.d.ts +3 -0
  45. package/dist/src/commands/github.js +342 -0
  46. package/dist/src/commands/inbox.d.ts +19 -0
  47. package/dist/src/commands/inbox.js +241 -0
  48. package/dist/src/commands/init.d.ts +64 -0
  49. package/dist/src/commands/init.js +1449 -0
  50. package/dist/src/commands/inspect.d.ts +20 -0
  51. package/dist/src/commands/inspect.js +337 -0
  52. package/dist/src/commands/pi.d.ts +3 -0
  53. package/dist/src/commands/pi.js +177 -0
  54. package/dist/src/commands/plugin.d.ts +20 -0
  55. package/dist/src/commands/plugin.js +238 -0
  56. package/dist/src/commands/profile-and-review.d.ts +4 -0
  57. package/dist/src/commands/profile-and-review.js +223 -0
  58. package/dist/src/commands/queue.d.ts +3 -0
  59. package/dist/src/commands/queue.js +197 -0
  60. package/dist/src/commands/remote.d.ts +3 -0
  61. package/dist/src/commands/remote.js +516 -0
  62. package/dist/src/commands/repo-git-harness.d.ts +5 -0
  63. package/dist/src/commands/repo-git-harness.js +282 -0
  64. package/dist/src/commands/run.d.ts +22 -0
  65. package/dist/src/commands/run.js +645 -0
  66. package/dist/src/commands/server.d.ts +3 -0
  67. package/dist/src/commands/server.js +155 -0
  68. package/dist/src/commands/setup.d.ts +16 -0
  69. package/dist/src/commands/setup.js +356 -0
  70. package/dist/src/commands/stats.d.ts +11 -0
  71. package/dist/src/commands/stats.js +219 -0
  72. package/dist/src/commands/task-run-driver.d.ts +93 -0
  73. package/dist/src/commands/task-run-driver.js +136 -0
  74. package/dist/src/commands/task.d.ts +46 -0
  75. package/dist/src/commands/task.js +555 -0
  76. package/dist/src/commands/test.d.ts +3 -0
  77. package/dist/src/commands/test.js +46 -0
  78. package/dist/src/commands/triage.d.ts +11 -0
  79. package/dist/src/commands/triage.js +224 -0
  80. package/dist/src/commands/workspace.d.ts +3 -0
  81. package/dist/src/commands/workspace.js +130 -0
  82. package/dist/src/kernel-dispatch.d.ts +15 -0
  83. package/dist/src/kernel-dispatch.js +16 -0
  84. package/dist/src/plugin.d.ts +3 -0
  85. package/dist/src/plugin.js +5440 -0
  86. package/dist/src/rig-config-package-deps.d.ts +10 -0
  87. package/dist/src/rig-config-package-deps.js +272 -0
  88. package/dist/src/runner.d.ts +47 -0
  89. package/dist/src/runner.js +267 -0
  90. package/dist/src/version.d.ts +8 -0
  91. package/dist/src/version.js +47 -0
  92. package/dist/src/withMutedConsole.d.ts +2 -0
  93. package/dist/src/withMutedConsole.js +42 -0
  94. package/package.json +34 -0
@@ -0,0 +1,155 @@
1
+ // @bun
2
+ // packages/cli-surface-plugin/src/commands/server.ts
3
+ import { addPlacement, listPlacements, readPlacement, removePlacement, selectPlacement } from "@rig/client";
4
+
5
+ // packages/cli-surface-plugin/src/runner.ts
6
+ import { EventBus } from "@rig/runtime/control-plane/runtime/events";
7
+ import { CliError as RuntimeCliError } from "@rig/runtime/control-plane/errors";
8
+ import { evaluate, loadPolicy, resolveAction } from "@rig/runtime/control-plane/runtime/guard";
9
+ import { buildBinary } from "@rig/runtime/control-plane/runtime/isolation";
10
+
11
+ class CliError extends RuntimeCliError {
12
+ hint;
13
+ constructor(message, exitCode = 1, options = {}) {
14
+ super(message, exitCode);
15
+ if (options.hint?.trim()) {
16
+ this.hint = options.hint.trim();
17
+ }
18
+ }
19
+ }
20
+ function takeOption(args, option) {
21
+ const rest = [];
22
+ let value;
23
+ for (let index = 0;index < args.length; index += 1) {
24
+ const current = args[index];
25
+ if (current === option) {
26
+ const next = args[index + 1];
27
+ if (!next || next.startsWith("-")) {
28
+ throw new CliError(`Missing value for ${option}`, 1, { hint: `Provide a value after ${option}, e.g. \`${option} <value>\`.` });
29
+ }
30
+ value = next;
31
+ index += 1;
32
+ continue;
33
+ }
34
+ if (current !== undefined) {
35
+ rest.push(current);
36
+ }
37
+ }
38
+ return { value, rest };
39
+ }
40
+ function requireNoExtraArgs(args, usage) {
41
+ if (args.length > 0) {
42
+ throw new CliError(`Unexpected arguments: ${args.join(" ")}
43
+ Usage: ${usage}`);
44
+ }
45
+ }
46
+
47
+ // packages/cli-surface-plugin/src/commands/_cli-format.ts
48
+ import pc from "picocolors";
49
+ import { runStatusColorRole, runStatusText, statusColorRole } from "@rig/client";
50
+ var dim = pc.dim;
51
+ var faintBar = pc.dim("\u2502");
52
+ var accent = pc.cyan;
53
+ function printFormattedOutput(message) {
54
+ console.log(message);
55
+ }
56
+
57
+ // packages/cli-surface-plugin/src/commands/server.ts
58
+ var DEFAULT_REMOTE_PORT = 22;
59
+ async function executeServer(context, args) {
60
+ const [command = "status", ...rest] = args;
61
+ const text = context.outputMode === "text";
62
+ const projectRoot = context.projectRoot;
63
+ switch (command) {
64
+ case "status": {
65
+ requireNoExtraArgs(rest, "rig server status");
66
+ const target = await readPlacement(projectRoot);
67
+ if (text) {
68
+ printFormattedOutput(target.kind === "local" ? "Placement: local (runs execute on this machine)." : `Placement: remote \u2192 ${target.alias}${target.host ? ` (${target.host}:${target.port ?? DEFAULT_REMOTE_PORT})` : ""}`);
69
+ printFormattedOutput(`Task source: ${target.taskSource}`);
70
+ }
71
+ return { ok: true, group: "server", command, details: { placement: target.kind, alias: target.alias, taskSource: target.taskSource, ...target.host ? { host: target.host, port: target.port } : {} } };
72
+ }
73
+ case "list": {
74
+ requireNoExtraArgs(rest, "rig server list");
75
+ const placements = listPlacements(projectRoot);
76
+ const selected = placements.find((placement) => placement.status === "selected")?.alias ?? "local";
77
+ if (text) {
78
+ for (const placement of placements) {
79
+ const marker = selected === placement.alias ? "* " : " ";
80
+ if (placement.alias === "local")
81
+ printFormattedOutput(`${marker}local \u2014 runs execute on this machine`);
82
+ else if (placement.alias === "remote")
83
+ printFormattedOutput(`${marker}remote \u2014 runs execute on the shared host (${placement.host})`);
84
+ else
85
+ printFormattedOutput(`${marker}${placement.alias} \u2014 ${placement.host}:${placement.port}`);
86
+ }
87
+ }
88
+ return { ok: true, group: "server", command, details: { selected, builtins: ["local", "remote"], endpoints: placements.filter((placement) => placement.alias !== "local" && placement.alias !== "remote").map((placement) => ({ alias: placement.alias, host: placement.host, port: placement.port })) } };
89
+ }
90
+ case "use": {
91
+ const [aliasArg, ...extra] = rest;
92
+ requireNoExtraArgs(extra, "rig server use <local|alias>");
93
+ const alias = (aliasArg ?? "").trim();
94
+ if (!alias)
95
+ throw new CliError("rig server use requires a target.", 2, { hint: "rig server use local | rig server use <alias>" });
96
+ let selected;
97
+ try {
98
+ selected = selectPlacement(projectRoot, alias, { dryRun: context.dryRun });
99
+ } catch (error) {
100
+ throw new CliError(error instanceof Error ? error.message : String(error), 2, { hint: "Run `rig server list`, or add it with `rig server add --alias <a> --host <h>`." });
101
+ }
102
+ if (context.dryRun)
103
+ return { ok: true, group: "server", command, details: { selected: alias, dryRun: true } };
104
+ if (text)
105
+ printFormattedOutput(selected.alias === "local" ? "Placement set to local." : `Placement set to remote \u2192 ${selected.alias}.`);
106
+ return { ok: true, group: "server", command, details: { selected: selected.alias } };
107
+ }
108
+ case "add": {
109
+ const aliasOpt = takeOption(rest, "--alias");
110
+ const hostOpt = takeOption(aliasOpt.rest, "--host");
111
+ const portOpt = takeOption(hostOpt.rest, "--port");
112
+ const tokenOpt = takeOption(portOpt.rest, "--token");
113
+ const positional = tokenOpt.rest.filter((arg) => !arg.startsWith("-"));
114
+ const alias = (aliasOpt.value ?? positional[0] ?? "").trim();
115
+ const host = (hostOpt.value ?? positional[1] ?? "").trim();
116
+ const portRaw = portOpt.value ?? positional[2];
117
+ if (!alias || !host)
118
+ throw new CliError("rig server add requires --alias <a> and --host <h>.", 2, { hint: "rig server add --alias prod --host prod.example.com --port 22" });
119
+ const port = portRaw ? Number(portRaw) : DEFAULT_REMOTE_PORT;
120
+ if (!Number.isFinite(port))
121
+ throw new CliError(`Invalid --port: ${portRaw}`, 2);
122
+ const saved = addPlacement(projectRoot, { alias, host, port, ...tokenOpt.value ? { token: tokenOpt.value } : {} }, { dryRun: context.dryRun });
123
+ if (context.dryRun)
124
+ return { ok: true, group: "server", command, details: { alias, host, port, dryRun: true } };
125
+ if (text)
126
+ printFormattedOutput(`Saved remote endpoint ${saved.alias} \u2192 ${saved.host}:${saved.port}. Select it with \`rig server use ${saved.alias}\`.`);
127
+ return { ok: true, group: "server", command, details: { alias: saved.alias, host: saved.host, port: saved.port } };
128
+ }
129
+ case "remove": {
130
+ const [aliasArg, ...extra] = rest;
131
+ requireNoExtraArgs(extra, "rig server remove <alias>");
132
+ const alias = (aliasArg ?? "").trim();
133
+ if (!alias)
134
+ throw new CliError("rig server remove requires an alias.", 2);
135
+ const removed = removePlacement(projectRoot, alias, { dryRun: context.dryRun });
136
+ if (context.dryRun)
137
+ return { ok: true, group: "server", command, details: { alias, dryRun: true } };
138
+ if (!removed.removed) {
139
+ throw new CliError(`No remote endpoint named ${alias}.`, 1, { hint: "Run `rig server list` to see configured endpoints." });
140
+ }
141
+ if (text)
142
+ printFormattedOutput(`Removed remote endpoint ${alias}.`);
143
+ return { ok: true, group: "server", command, details: { alias, removed: true } };
144
+ }
145
+ case "start":
146
+ throw new CliError("rig server start is retired: there is no standalone Rig server process after the OMP migration.", 2, { hint: "Runs execute locally (tmux) or on a selected remote \u2014 pick one with `rig server use local|<alias>`." });
147
+ case "repair-link":
148
+ throw new CliError("rig server repair-link is retired with the standalone server.", 2, { hint: "Select placement with `rig server use local|<alias>`." });
149
+ default:
150
+ throw new CliError(`Unknown server command: ${command}`, 1, { hint: "Run `rig server --help` \u2014 commands are status|list|use|add|remove." });
151
+ }
152
+ }
153
+ export {
154
+ executeServer
155
+ };
@@ -0,0 +1,16 @@
1
+ import type { TaskSourceConfig } from "@rig/contracts";
2
+ import type { CommandOutcome } from "@rig/runtime";
3
+ import { type RigPluginWithRuntime } from "@rig/core";
4
+ import { type RunnerContext } from "../runner";
5
+ type SetupCheck = {
6
+ ok: boolean;
7
+ label: string;
8
+ hint?: string;
9
+ };
10
+ type SetupRigConfig = {
11
+ plugins?: readonly RigPluginWithRuntime[];
12
+ taskSource?: TaskSourceConfig;
13
+ };
14
+ export declare function buildTaskSourceKindSetupCheck(config: SetupRigConfig): SetupCheck | null;
15
+ export declare function executeSetup(context: RunnerContext, args: string[]): Promise<CommandOutcome>;
16
+ export {};
@@ -0,0 +1,356 @@
1
+ // @bun
2
+ // packages/cli-surface-plugin/src/commands/setup.ts
3
+ import { createPluginHost } from "@rig/core";
4
+ import { detectStartupStatus, ensureGitHubAuth, parseRepoSlug, runSetup, validateGitHubAuth } from "@rig/client";
5
+
6
+ // packages/cli-surface-plugin/src/runner.ts
7
+ import { EventBus } from "@rig/runtime/control-plane/runtime/events";
8
+ import { CliError as RuntimeCliError } from "@rig/runtime/control-plane/errors";
9
+ import { evaluate, loadPolicy, resolveAction } from "@rig/runtime/control-plane/runtime/guard";
10
+ import { buildBinary } from "@rig/runtime/control-plane/runtime/isolation";
11
+
12
+ class CliError extends RuntimeCliError {
13
+ hint;
14
+ constructor(message, exitCode = 1, options = {}) {
15
+ super(message, exitCode);
16
+ if (options.hint?.trim()) {
17
+ this.hint = options.hint.trim();
18
+ }
19
+ }
20
+ }
21
+ function takeFlag(args, flag) {
22
+ const rest = [];
23
+ let value = false;
24
+ for (const arg of args) {
25
+ if (arg === flag) {
26
+ value = true;
27
+ continue;
28
+ }
29
+ rest.push(arg);
30
+ }
31
+ return { value, rest };
32
+ }
33
+ function takeOption(args, option) {
34
+ const rest = [];
35
+ let value;
36
+ for (let index = 0;index < args.length; index += 1) {
37
+ const current = args[index];
38
+ if (current === option) {
39
+ const next = args[index + 1];
40
+ if (!next || next.startsWith("-")) {
41
+ throw new CliError(`Missing value for ${option}`, 1, { hint: `Provide a value after ${option}, e.g. \`${option} <value>\`.` });
42
+ }
43
+ value = next;
44
+ index += 1;
45
+ continue;
46
+ }
47
+ if (current !== undefined) {
48
+ rest.push(current);
49
+ }
50
+ }
51
+ return { value, rest };
52
+ }
53
+ function requireNoExtraArgs(args, usage) {
54
+ if (args.length > 0) {
55
+ throw new CliError(`Unexpected arguments: ${args.join(" ")}
56
+ Usage: ${usage}`);
57
+ }
58
+ }
59
+
60
+ // packages/cli-surface-plugin/src/withMutedConsole.ts
61
+ function isPromise(value) {
62
+ if (typeof value !== "object" && typeof value !== "function") {
63
+ return false;
64
+ }
65
+ return value !== null && typeof value.then === "function";
66
+ }
67
+ function withMutedConsole(mute, fn) {
68
+ if (!mute) {
69
+ return fn();
70
+ }
71
+ const originalLog = console.log;
72
+ const originalWarn = console.warn;
73
+ const originalInfo = console.info;
74
+ const restore = () => {
75
+ console.log = originalLog;
76
+ console.warn = originalWarn;
77
+ console.info = originalInfo;
78
+ };
79
+ console.log = () => {};
80
+ console.warn = () => {};
81
+ console.info = () => {};
82
+ try {
83
+ const result = fn();
84
+ if (isPromise(result)) {
85
+ return result.finally(restore);
86
+ }
87
+ restore();
88
+ return result;
89
+ } catch (error) {
90
+ restore();
91
+ throw error;
92
+ } finally {
93
+ if (console.log === originalLog) {
94
+ restore();
95
+ }
96
+ }
97
+ }
98
+
99
+ // packages/cli-surface-plugin/src/commands/_doctor-checks.ts
100
+ import { countDoctorFailures, runDoctorChecks } from "@rig/client";
101
+ var runRigDoctorChecks = runDoctorChecks;
102
+ function formatDoctorChecks(checks) {
103
+ return checks.map((entry) => {
104
+ const status = String(entry.status ?? entry.level ?? "warn");
105
+ const marker = status === "pass" || status === "ok" ? "OK" : status === "warn" ? "WARN" : "FAIL";
106
+ return `${marker}: ${entry.label}${entry.detail ? ` \u2014 ${entry.detail}` : ""}${entry.remediation ? `
107
+ fix: ${entry.remediation}` : ""}`;
108
+ }).join(`
109
+ `);
110
+ }
111
+
112
+ // packages/cli-surface-plugin/src/commands/_async-ui.ts
113
+ import pc from "picocolors";
114
+
115
+ // packages/cli-surface-plugin/src/commands/_spinner.ts
116
+ var SPINNER_FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
117
+ function createTtySpinner(input) {
118
+ const output = input.output ?? process.stdout;
119
+ const isTty = output.isTTY === true;
120
+ const frames = input.frames && input.frames.length > 0 ? input.frames : SPINNER_FRAMES;
121
+ let label = input.label;
122
+ let frame = 0;
123
+ let paused = false;
124
+ let stopped = false;
125
+ let lastPrintedLabel = "";
126
+ const render = () => {
127
+ if (stopped || paused)
128
+ return;
129
+ if (!isTty) {
130
+ if (label !== lastPrintedLabel) {
131
+ output.write(`${label}
132
+ `);
133
+ lastPrintedLabel = label;
134
+ }
135
+ return;
136
+ }
137
+ frame = (frame + 1) % frames.length;
138
+ const glyph = frames[frame] ?? frames[0] ?? "";
139
+ output.write(`\r\x1B[2K${input.styleFrame ? input.styleFrame(glyph) : glyph} ${label}`);
140
+ };
141
+ const clearLine = () => {
142
+ if (isTty)
143
+ output.write("\r\x1B[2K");
144
+ };
145
+ render();
146
+ const timer = isTty ? setInterval(render, input.intervalMs ?? 16) : null;
147
+ return {
148
+ setLabel(next) {
149
+ label = next;
150
+ render();
151
+ },
152
+ pause() {
153
+ paused = true;
154
+ clearLine();
155
+ },
156
+ resume() {
157
+ if (stopped)
158
+ return;
159
+ paused = false;
160
+ render();
161
+ },
162
+ stop(finalLine) {
163
+ if (stopped)
164
+ return;
165
+ stopped = true;
166
+ if (timer)
167
+ clearInterval(timer);
168
+ clearLine();
169
+ if (finalLine)
170
+ output.write(`${finalLine}
171
+ `);
172
+ }
173
+ };
174
+ }
175
+
176
+ // packages/cli-surface-plugin/src/commands/_async-ui.ts
177
+ var FRAMES = ["\u25D0", "\u25D3", "\u25D1", "\u25D2"];
178
+ var DONE_SYMBOL = pc.green("\u25C7");
179
+ var FAIL_SYMBOL = pc.red("\u25A0");
180
+ var activeUpdate = null;
181
+ async function withSpinner(label, work, options = {}) {
182
+ if (options.outputMode === "json") {
183
+ return work(() => {
184
+ return;
185
+ });
186
+ }
187
+ if (activeUpdate) {
188
+ activeUpdate(label);
189
+ return work(activeUpdate);
190
+ }
191
+ const output = options.output ?? process.stderr;
192
+ const isTty = output.isTTY === true;
193
+ let lastLabel = label;
194
+ if (!isTty) {
195
+ output.write(`${label}
196
+ `);
197
+ const update2 = (next) => {
198
+ lastLabel = next;
199
+ };
200
+ activeUpdate = update2;
201
+ try {
202
+ return await work(update2);
203
+ } finally {
204
+ activeUpdate = null;
205
+ }
206
+ }
207
+ const spinner = createTtySpinner({
208
+ label,
209
+ output,
210
+ frames: FRAMES,
211
+ styleFrame: (frame) => pc.cyan(frame)
212
+ });
213
+ const update = (next) => {
214
+ lastLabel = next;
215
+ spinner.setLabel(next);
216
+ };
217
+ activeUpdate = update;
218
+ try {
219
+ const result = await work(update);
220
+ spinner.stop(options.doneLabel ? `${DONE_SYMBOL} ${options.doneLabel}` : undefined);
221
+ return result;
222
+ } catch (error) {
223
+ spinner.stop(`${FAIL_SYMBOL} ${lastLabel}`);
224
+ throw error;
225
+ } finally {
226
+ activeUpdate = null;
227
+ }
228
+ }
229
+
230
+ // packages/cli-surface-plugin/src/commands/setup.ts
231
+ function formatTaskSourceKinds(kinds) {
232
+ return kinds.length > 0 ? kinds.join(", ") : "none";
233
+ }
234
+ function buildTaskSourceKindSetupCheck(config) {
235
+ if (!config.taskSource)
236
+ return null;
237
+ const kind = config.taskSource.kind;
238
+ const pluginHost = createPluginHost(config.plugins ?? []);
239
+ const registeredKinds = pluginHost.listExecutableTaskSources().map((source) => source.kind);
240
+ const isRegistered = Boolean(pluginHost.resolveTaskSourceFactoryByKind(kind));
241
+ return {
242
+ ok: isRegistered,
243
+ label: `task source kind "${kind}" registered`,
244
+ hint: isRegistered ? undefined : `registered kinds: ${formatTaskSourceKinds(registeredKinds)}; load a plugin that contributes an executable task source factory for "${kind}"`
245
+ };
246
+ }
247
+ async function executeSetup(context, args) {
248
+ const [command = "check", ...rest] = args;
249
+ switch (command) {
250
+ case "bootstrap":
251
+ requireNoExtraArgs(rest, "rig setup bootstrap");
252
+ await runBootstrap(context.projectRoot);
253
+ return { ok: true, group: "setup", command };
254
+ case "check":
255
+ requireNoExtraArgs(rest, `rig setup ${command}`);
256
+ return withMutedConsole(context.outputMode === "json", async () => {
257
+ const checks = await runSetupCheck(context.projectRoot, context.outputMode);
258
+ return { ok: true, group: "setup", command, details: { checks, failures: countDoctorFailures(checks) } };
259
+ });
260
+ case "setup":
261
+ return withMutedConsole(context.outputMode === "json", () => runSetupCommand(context, rest));
262
+ case "preflight":
263
+ requireNoExtraArgs(rest, "rig setup preflight");
264
+ await withMutedConsole(context.outputMode === "json", () => runSetupPreflight(context.projectRoot, context.outputMode));
265
+ return { ok: true, group: "setup", command };
266
+ default:
267
+ throw new CliError(`Unknown setup command: ${command}`, 1, { hint: "Run `rig setup --help` \u2014 commands are bootstrap|check|setup|preflight." });
268
+ }
269
+ }
270
+ async function runBootstrap(projectRoot) {
271
+ const hostBash = Bun.which("bash") || "/bin/bash";
272
+ const env = { ...process.env };
273
+ delete env.BASH;
274
+ delete env.RIG_BASH_MODE;
275
+ delete env.RIG_TASK_ID;
276
+ delete env.RIG_TASK_RUNTIME_ID;
277
+ delete env.RIG_TASK_WORKSPACE;
278
+ const proc = Bun.spawn([hostBash, "./bootstrap.sh"], { cwd: projectRoot, env, stdin: "inherit", stdout: "inherit", stderr: "inherit" });
279
+ const exitCode = await proc.exited;
280
+ if (exitCode !== 0)
281
+ throw new CliError(`Command failed (${exitCode}): ${hostBash} ./bootstrap.sh`, exitCode);
282
+ }
283
+ async function runSetupCheck(projectRoot, outputMode = "text") {
284
+ const status = await detectStartupStatus({ projectRoot });
285
+ await validateGitHubAuth(projectRoot, status.slug);
286
+ const doctorChecks = await withSpinner("Running setup checks\u2026", (update) => runRigDoctorChecks({ projectRoot, onProgress: update }), { outputMode });
287
+ console.log(formatDoctorChecks(doctorChecks));
288
+ const failures = countDoctorFailures(doctorChecks);
289
+ if (failures > 0)
290
+ throw new CliError(`Setup check failed (${failures} failing doctor check${failures === 1 ? "" : "s"}).`, 1, { hint: "Run bare `rig` and open Cockpit \u2192 Doctor for remediation details." });
291
+ return doctorChecks;
292
+ }
293
+ async function runSetupCommand(context, args) {
294
+ let pending = args;
295
+ const repoResult = takeOption(pending, "--repo");
296
+ pending = repoResult.rest;
297
+ const slugResult = takeOption(pending, "--slug");
298
+ pending = slugResult.rest;
299
+ const placementResult = takeOption(pending, "--placement");
300
+ pending = placementResult.rest;
301
+ const hostResult = takeOption(pending, "--host");
302
+ pending = hostResult.rest;
303
+ const portResult = takeOption(pending, "--port");
304
+ pending = portResult.rest;
305
+ const tokenResult = takeOption(pending, "--token");
306
+ pending = tokenResult.rest;
307
+ const githubTokenResult = takeOption(pending, "--github-token");
308
+ pending = githubTokenResult.rest;
309
+ const importGhToken = takeFlag(pending, "--import-gh-token");
310
+ pending = importGhToken.rest;
311
+ const noPi = takeFlag(pending, "--no-pi");
312
+ pending = noPi.rest;
313
+ const noLabels = takeFlag(pending, "--no-labels");
314
+ pending = noLabels.rest;
315
+ const noConfig = takeFlag(pending, "--no-config");
316
+ pending = noConfig.rest;
317
+ requireNoExtraArgs(pending, "rig setup setup --repo <owner/repo> [--placement local|<alias>] [--host <ssh-host>] [--port <n>] [--token <t>] [--github-token <t>|--import-gh-token] [--no-pi] [--no-labels] [--no-config]");
318
+ const startup = await detectStartupStatus({ projectRoot: context.projectRoot });
319
+ const slug = repoResult.value ?? slugResult.value ?? startup.slug;
320
+ if (!slug)
321
+ throw new CliError("rig setup setup requires --repo <owner/repo> when no GitHub origin/config is detectable.", 2);
322
+ const repo = parseRepoSlug(slug);
323
+ await ensureGitHubAuth({ projectRoot: context.projectRoot, slug: repo.slug, token: githubTokenResult.value, importGhToken: importGhToken.value });
324
+ const placement = setupPlacement(placementResult.value, hostResult.value, portResult.value, tokenResult.value);
325
+ const result = await runSetup({
326
+ projectRoot: context.projectRoot,
327
+ slug: repo.slug,
328
+ placement,
329
+ rewriteConfig: !noConfig.value,
330
+ ensurePi: !noPi.value,
331
+ ensureLabels: !noLabels.value,
332
+ githubToken: githubTokenResult.value,
333
+ importGhToken: importGhToken.value
334
+ });
335
+ if (context.outputMode === "text")
336
+ console.log(`Rig setup complete for ${result.repoSlug} (${result.placement}).`);
337
+ return { ok: true, group: "setup", command: "setup", details: result };
338
+ }
339
+ function setupPlacement(aliasValue, host, portValue, token) {
340
+ const alias = aliasValue?.trim() || (host?.trim() ? "remote" : "local");
341
+ const port = portValue ? Number(portValue) : undefined;
342
+ if (portValue && !Number.isFinite(port))
343
+ throw new CliError(`Invalid --port: ${portValue}`, 2);
344
+ return { alias, kind: host?.trim() ? "remote" : "local", ...host?.trim() ? { host: host.trim() } : {}, ...port ? { port } : {}, ...token ? { token } : {} };
345
+ }
346
+ async function runSetupPreflight(projectRoot, outputMode = "text") {
347
+ await runSetupCheck(projectRoot, outputMode);
348
+ const startup = await detectStartupStatus({ projectRoot });
349
+ if (!startup.configured)
350
+ throw new CliError(`Rig startup is not configured: ${startup.reasons.join("; ")}`, 1);
351
+ console.log("OK: rig startup status configured");
352
+ }
353
+ export {
354
+ executeSetup,
355
+ buildTaskSourceKindSetupCheck
356
+ };
@@ -0,0 +1,11 @@
1
+ import type { RigStatsData } from "@rig/contracts";
2
+ import type { CommandOutcome } from "@rig/runtime";
3
+ import type { RunRecord } from "@rig/client";
4
+ import { type RunnerContext } from "../runner";
5
+ type StatsCommandDeps = {
6
+ listRuns?: (projectRoot: string) => Promise<RunRecord[]>;
7
+ };
8
+ export declare function parseSinceOption(value: string | undefined, now?: Date): Date | null;
9
+ export declare function formatStatsRows(stats: RigStatsData): Array<[string, unknown]>;
10
+ export declare function executeStats(context: RunnerContext, args: string[], deps?: StatsCommandDeps): Promise<CommandOutcome>;
11
+ export {};