@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
|
@@ -7,12 +7,19 @@ import { resolve as resolve4 } from "path";
|
|
|
7
7
|
|
|
8
8
|
// packages/cli/src/runner.ts
|
|
9
9
|
import { EventBus } from "@rig/runtime/control-plane/runtime/events";
|
|
10
|
-
import { CliError } from "@rig/runtime/control-plane/errors";
|
|
10
|
+
import { CliError as RuntimeCliError } 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
|
+
|
|
14
|
+
class CliError extends RuntimeCliError {
|
|
15
|
+
hint;
|
|
16
|
+
constructor(message, exitCode = 1, options = {}) {
|
|
17
|
+
super(message, exitCode);
|
|
18
|
+
if (options.hint?.trim()) {
|
|
19
|
+
this.hint = options.hint.trim();
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
16
23
|
|
|
17
24
|
// packages/cli/src/commands/_doctor-checks.ts
|
|
18
25
|
import { isSupportedBunVersion, MIN_SUPPORTED_BUN_VERSION } from "@rig/runtime/control-plane/setup-version";
|
|
@@ -39,9 +46,14 @@ function readJsonFile(path) {
|
|
|
39
46
|
try {
|
|
40
47
|
return JSON.parse(readFileSync(path, "utf8"));
|
|
41
48
|
} catch (error) {
|
|
42
|
-
throw new
|
|
49
|
+
throw new CliError(`Invalid Rig connection state at ${path}: ${error instanceof Error ? error.message : String(error)}`, 1, { hint: "Fix or delete that file, then re-select a server with `rig server use <alias|local>`." });
|
|
43
50
|
}
|
|
44
51
|
}
|
|
52
|
+
function writeJsonFile(path, value) {
|
|
53
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
54
|
+
writeFileSync(path, `${JSON.stringify(value, null, 2)}
|
|
55
|
+
`, "utf8");
|
|
56
|
+
}
|
|
45
57
|
function normalizeConnection(value) {
|
|
46
58
|
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
47
59
|
return null;
|
|
@@ -82,29 +94,42 @@ function readRepoConnection(projectRoot) {
|
|
|
82
94
|
return {
|
|
83
95
|
selected,
|
|
84
96
|
project: typeof record.project === "string" ? record.project : undefined,
|
|
85
|
-
linkedAt: typeof record.linkedAt === "string" ? record.linkedAt : undefined
|
|
97
|
+
linkedAt: typeof record.linkedAt === "string" ? record.linkedAt : undefined,
|
|
98
|
+
serverProjectRoot: typeof record.serverProjectRoot === "string" && record.serverProjectRoot.trim() ? record.serverProjectRoot.trim() : undefined
|
|
86
99
|
};
|
|
87
100
|
}
|
|
101
|
+
function writeRepoConnection(projectRoot, state) {
|
|
102
|
+
writeJsonFile(resolveRepoConnectionPath(projectRoot), state);
|
|
103
|
+
}
|
|
88
104
|
function resolveSelectedConnection(projectRoot, options = {}) {
|
|
89
105
|
const repo = readRepoConnection(projectRoot);
|
|
90
106
|
if (!repo)
|
|
91
107
|
return null;
|
|
92
108
|
if (repo.selected === "local")
|
|
93
|
-
return { alias: "local", connection: { kind: "local", mode: "auto" } };
|
|
109
|
+
return { alias: "local", connection: { kind: "local", mode: "auto" }, serverProjectRoot: repo.serverProjectRoot };
|
|
94
110
|
const global = readGlobalConnections(options);
|
|
95
111
|
const connection = global.connections[repo.selected];
|
|
96
112
|
if (!connection) {
|
|
97
|
-
throw new
|
|
113
|
+
throw new CliError(`Selected Rig server "${repo.selected}" was not found. Run \`rig server list\` or \`rig server use local\`.`, 1);
|
|
98
114
|
}
|
|
99
|
-
return { alias: repo.selected, connection };
|
|
115
|
+
return { alias: repo.selected, connection, serverProjectRoot: repo.serverProjectRoot };
|
|
116
|
+
}
|
|
117
|
+
function writeRepoServerProjectRoot(projectRoot, serverProjectRoot) {
|
|
118
|
+
const repo = readRepoConnection(projectRoot);
|
|
119
|
+
if (!repo)
|
|
120
|
+
return;
|
|
121
|
+
writeRepoConnection(projectRoot, { ...repo, serverProjectRoot });
|
|
100
122
|
}
|
|
101
123
|
|
|
102
124
|
// packages/cli/src/commands/_server-client.ts
|
|
103
|
-
import { spawnSync } from "child_process";
|
|
104
125
|
import { existsSync as existsSync2, readFileSync as readFileSync2 } from "fs";
|
|
105
126
|
import { resolve as resolve2 } from "path";
|
|
106
127
|
import { ensureLocalRigServerConnection } from "@rig/runtime/local-server";
|
|
107
|
-
var
|
|
128
|
+
var scopedGitHubBearerTokens = new Map;
|
|
129
|
+
var serverPhaseListener = null;
|
|
130
|
+
function reportServerPhase(label) {
|
|
131
|
+
serverPhaseListener?.(label);
|
|
132
|
+
}
|
|
108
133
|
function cleanToken(value) {
|
|
109
134
|
const trimmed = value?.trim();
|
|
110
135
|
return trimmed ? trimmed : null;
|
|
@@ -121,49 +146,80 @@ function readPrivateRemoteSessionToken(projectRoot) {
|
|
|
121
146
|
}
|
|
122
147
|
}
|
|
123
148
|
function readGitHubBearerTokenForRemote(projectRoot) {
|
|
124
|
-
|
|
125
|
-
|
|
149
|
+
const scopedKey = resolve2(projectRoot);
|
|
150
|
+
if (scopedGitHubBearerTokens.has(scopedKey))
|
|
151
|
+
return scopedGitHubBearerTokens.get(scopedKey) ?? null;
|
|
126
152
|
const privateSession = readPrivateRemoteSessionToken(projectRoot);
|
|
127
|
-
if (privateSession)
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
return
|
|
153
|
+
if (privateSession)
|
|
154
|
+
return privateSession;
|
|
155
|
+
return cleanToken(process.env.RIG_SERVER_AUTH_TOKEN) ?? cleanToken(process.env.RIG_REMOTE_AUTH_TOKEN);
|
|
156
|
+
}
|
|
157
|
+
function readStoredGitHubAuthToken(projectRoot) {
|
|
158
|
+
const path = resolve2(projectRoot, ".rig", "state", "github-auth.json");
|
|
159
|
+
if (!existsSync2(path))
|
|
160
|
+
return null;
|
|
161
|
+
try {
|
|
162
|
+
const parsed = JSON.parse(readFileSync2(path, "utf8"));
|
|
163
|
+
return cleanToken(typeof parsed.token === "string" ? parsed.token : undefined);
|
|
164
|
+
} catch {
|
|
165
|
+
return null;
|
|
135
166
|
}
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
stdio: ["ignore", "pipe", "ignore"]
|
|
140
|
-
});
|
|
141
|
-
cachedGitHubBearerToken = result.status === 0 ? cleanToken(result.stdout) : null;
|
|
142
|
-
return cachedGitHubBearerToken;
|
|
167
|
+
}
|
|
168
|
+
function readLocalConnectionFallbackToken(projectRoot) {
|
|
169
|
+
return readGitHubBearerTokenForRemote(projectRoot) ?? cleanToken(process.env.RIG_GITHUB_TOKEN) ?? readStoredGitHubAuthToken(projectRoot);
|
|
143
170
|
}
|
|
144
171
|
async function ensureServerForCli(projectRoot) {
|
|
145
172
|
try {
|
|
146
173
|
const selected = resolveSelectedConnection(projectRoot);
|
|
147
174
|
if (selected?.connection.kind === "remote") {
|
|
175
|
+
reportServerPhase(`Connecting to ${selected.alias}\u2026`);
|
|
176
|
+
const authToken = readGitHubBearerTokenForRemote(projectRoot);
|
|
177
|
+
const serverProjectRoot = selected.serverProjectRoot ?? await backfillRemoteServerProjectRoot(projectRoot, selected.connection.baseUrl, authToken);
|
|
148
178
|
return {
|
|
149
179
|
baseUrl: selected.connection.baseUrl,
|
|
150
|
-
authToken
|
|
151
|
-
connectionKind: "remote"
|
|
180
|
+
authToken,
|
|
181
|
+
connectionKind: "remote",
|
|
182
|
+
serverProjectRoot
|
|
152
183
|
};
|
|
153
184
|
}
|
|
185
|
+
reportServerPhase("Starting local Rig server\u2026");
|
|
154
186
|
const connection = await ensureLocalRigServerConnection(projectRoot);
|
|
155
187
|
return {
|
|
156
188
|
baseUrl: connection.baseUrl,
|
|
157
|
-
authToken: connection.authToken,
|
|
158
|
-
connectionKind: "local"
|
|
189
|
+
authToken: connection.authToken ?? readLocalConnectionFallbackToken(projectRoot),
|
|
190
|
+
connectionKind: "local",
|
|
191
|
+
serverProjectRoot: resolve2(projectRoot)
|
|
159
192
|
};
|
|
160
193
|
} catch (error) {
|
|
161
194
|
if (error instanceof Error) {
|
|
162
|
-
throw new
|
|
195
|
+
throw new CliError(error.message, 1);
|
|
163
196
|
}
|
|
164
197
|
throw error;
|
|
165
198
|
}
|
|
166
199
|
}
|
|
200
|
+
async function backfillRemoteServerProjectRoot(projectRoot, baseUrl, authToken) {
|
|
201
|
+
const repo = readRepoConnection(projectRoot);
|
|
202
|
+
const slug = repo?.project?.trim();
|
|
203
|
+
if (!slug)
|
|
204
|
+
return null;
|
|
205
|
+
try {
|
|
206
|
+
const response = await fetch(`${baseUrl}/api/projects/${encodeURIComponent(slug)}`, {
|
|
207
|
+
headers: mergeHeaders(undefined, authToken)
|
|
208
|
+
});
|
|
209
|
+
if (!response.ok)
|
|
210
|
+
return null;
|
|
211
|
+
const payload = await response.json();
|
|
212
|
+
const project = payload.project && typeof payload.project === "object" && !Array.isArray(payload.project) ? payload.project : null;
|
|
213
|
+
const checkouts = Array.isArray(project?.checkouts) ? project.checkouts : [];
|
|
214
|
+
const latestCheckout = [...checkouts].reverse().find((entry) => Boolean(entry && typeof entry === "object" && !Array.isArray(entry) && typeof entry.path === "string"));
|
|
215
|
+
const path = typeof latestCheckout?.path === "string" && latestCheckout.path.trim() ? latestCheckout.path.trim() : null;
|
|
216
|
+
if (path)
|
|
217
|
+
writeRepoServerProjectRoot(projectRoot, path);
|
|
218
|
+
return path;
|
|
219
|
+
} catch {
|
|
220
|
+
return null;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
167
223
|
function mergeHeaders(headers, authToken) {
|
|
168
224
|
const merged = new Headers(headers);
|
|
169
225
|
if (authToken) {
|
|
@@ -186,12 +242,65 @@ function diagnosticMessage(payload) {
|
|
|
186
242
|
});
|
|
187
243
|
return messages.length > 0 ? messages.join("; ") : null;
|
|
188
244
|
}
|
|
245
|
+
var serverReachabilityCache = new Map;
|
|
246
|
+
async function probeServerReachability(baseUrl, authToken) {
|
|
247
|
+
try {
|
|
248
|
+
const response = await fetch(`${baseUrl.replace(/\/+$/, "")}/api/server/status`, {
|
|
249
|
+
headers: mergeHeaders(undefined, authToken),
|
|
250
|
+
signal: AbortSignal.timeout(1500)
|
|
251
|
+
});
|
|
252
|
+
return response.ok;
|
|
253
|
+
} catch {
|
|
254
|
+
return false;
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
function cachedServerReachability(projectRoot, baseUrl, authToken) {
|
|
258
|
+
const key = resolve2(projectRoot);
|
|
259
|
+
const cached = serverReachabilityCache.get(key);
|
|
260
|
+
if (cached)
|
|
261
|
+
return cached;
|
|
262
|
+
const probe = probeServerReachability(baseUrl, authToken);
|
|
263
|
+
serverReachabilityCache.set(key, probe);
|
|
264
|
+
return probe;
|
|
265
|
+
}
|
|
266
|
+
function describeSelectedServer(projectRoot, server) {
|
|
267
|
+
try {
|
|
268
|
+
const selected = resolveSelectedConnection(projectRoot);
|
|
269
|
+
if (selected) {
|
|
270
|
+
return {
|
|
271
|
+
alias: selected.alias,
|
|
272
|
+
target: selected.connection.kind === "remote" ? selected.connection.baseUrl : server.baseUrl
|
|
273
|
+
};
|
|
274
|
+
}
|
|
275
|
+
} catch {}
|
|
276
|
+
return { alias: server.connectionKind === "remote" ? "remote" : "local", target: server.baseUrl };
|
|
277
|
+
}
|
|
278
|
+
async function buildServerFailureContext(projectRoot, server) {
|
|
279
|
+
const { alias, target } = describeSelectedServer(projectRoot, server);
|
|
280
|
+
const reachable = await cachedServerReachability(projectRoot, server.baseUrl, server.authToken);
|
|
281
|
+
const reachability = reachable ? "server is reachable" : "server is unreachable";
|
|
282
|
+
return {
|
|
283
|
+
contextLine: `Currently connected to: ${alias} at ${target} (${reachability}).`,
|
|
284
|
+
hint: "Check the selected server with `rig server status`, or switch with `rig server use <alias|local>`."
|
|
285
|
+
};
|
|
286
|
+
}
|
|
189
287
|
async function requestServerJson(context, pathname, init = {}) {
|
|
190
288
|
const server = await ensureServerForCli(context.projectRoot);
|
|
191
|
-
const
|
|
192
|
-
|
|
193
|
-
headers
|
|
194
|
-
});
|
|
289
|
+
const headers = mergeHeaders(init.headers, server.authToken);
|
|
290
|
+
if (server.serverProjectRoot)
|
|
291
|
+
headers.set("x-rig-project-root", server.serverProjectRoot);
|
|
292
|
+
reportServerPhase(`${(init.method ?? "GET").toUpperCase()} ${pathname.split("?")[0]}\u2026`);
|
|
293
|
+
let response;
|
|
294
|
+
try {
|
|
295
|
+
response = await fetch(`${server.baseUrl}${pathname}`, {
|
|
296
|
+
...init,
|
|
297
|
+
headers
|
|
298
|
+
});
|
|
299
|
+
} catch (error) {
|
|
300
|
+
const failure = await buildServerFailureContext(context.projectRoot, server);
|
|
301
|
+
throw new CliError(`Rig server request failed: ${error instanceof Error ? error.message : String(error)}
|
|
302
|
+
${failure.contextLine}`, 1, { hint: failure.hint });
|
|
303
|
+
}
|
|
195
304
|
const text = await response.text();
|
|
196
305
|
const payload = text.trim().length > 0 ? (() => {
|
|
197
306
|
try {
|
|
@@ -202,11 +311,26 @@ async function requestServerJson(context, pathname, init = {}) {
|
|
|
202
311
|
})() : null;
|
|
203
312
|
if (!response.ok) {
|
|
204
313
|
const diagnostics = diagnosticMessage(payload);
|
|
205
|
-
const
|
|
206
|
-
|
|
314
|
+
const rawDetail = diagnostics ?? (text || response.statusText);
|
|
315
|
+
const detail = diagnostics ? rawDetail : rawDetail.split(`
|
|
316
|
+
`).map((line) => line.trim()).find((line) => line.length > 0)?.slice(0, 200) ?? response.statusText;
|
|
317
|
+
const failure = await buildServerFailureContext(context.projectRoot, server);
|
|
318
|
+
throw new CliError(`Rig server request failed (${response.status}): ${detail}
|
|
319
|
+
${failure.contextLine}`, 1, { hint: failure.hint });
|
|
207
320
|
}
|
|
208
321
|
return payload;
|
|
209
322
|
}
|
|
323
|
+
var RESUMABLE_RUN_STATUSES = new Set([
|
|
324
|
+
"created",
|
|
325
|
+
"preparing",
|
|
326
|
+
"running",
|
|
327
|
+
"validating",
|
|
328
|
+
"reviewing",
|
|
329
|
+
"stopped",
|
|
330
|
+
"failed",
|
|
331
|
+
"needs-attention",
|
|
332
|
+
"needs_attention"
|
|
333
|
+
]);
|
|
210
334
|
|
|
211
335
|
// packages/cli/src/commands/_parsers.ts
|
|
212
336
|
async function loadRigConfigOrNull(projectRoot) {
|
|
@@ -222,7 +346,8 @@ async function loadRigConfigOrNull(projectRoot) {
|
|
|
222
346
|
import { existsSync as existsSync3, readFileSync as readFileSync3, rmSync } from "fs";
|
|
223
347
|
import { homedir as homedir2 } from "os";
|
|
224
348
|
import { resolve as resolve3 } from "path";
|
|
225
|
-
var PI_RIG_PACKAGE_NAME = "@rig/pi-rig";
|
|
349
|
+
var PI_RIG_PACKAGE_NAME = "@h-rig/pi-rig";
|
|
350
|
+
var LEGACY_PI_RIG_PACKAGE_NAME = "@rig/pi-rig";
|
|
226
351
|
async function defaultCommandRunner(command, options = {}) {
|
|
227
352
|
const proc = Bun.spawn(command, { cwd: options.cwd, stdout: "pipe", stderr: "pipe" });
|
|
228
353
|
const [stdout, stderr, exitCode] = await Promise.all([
|
|
@@ -241,7 +366,7 @@ function resolvePiHomeDir(inputHomeDir) {
|
|
|
241
366
|
function piListContainsPiRig(output) {
|
|
242
367
|
return output.split(/\r?\n/).some((line) => {
|
|
243
368
|
const normalized = line.trim();
|
|
244
|
-
return normalized.includes(PI_RIG_PACKAGE_NAME) || /(?:^|[\\/])packages[\\/]pi-rig(?:$|\s)/.test(normalized);
|
|
369
|
+
return normalized.includes(PI_RIG_PACKAGE_NAME) || normalized.includes(LEGACY_PI_RIG_PACKAGE_NAME) || /(?:^|[\\/])packages[\\/]pi-rig(?:$|\s)/.test(normalized);
|
|
245
370
|
});
|
|
246
371
|
}
|
|
247
372
|
async function safeRun(runner, command, options) {
|
|
@@ -409,7 +534,10 @@ async function runRigDoctorChecks(options) {
|
|
|
409
534
|
const bunVersion = options.bunVersion ?? Bun.version;
|
|
410
535
|
const request = options.requestJson ?? ((pathname, init) => requestServerJson({ projectRoot }, pathname, init));
|
|
411
536
|
const loadConfig = options.loadConfig ?? loadRigConfigOrNull;
|
|
537
|
+
const progress = options.onProgress ?? (() => {});
|
|
538
|
+
progress("Checking local toolchain\u2026");
|
|
412
539
|
checks.push(check("bun", `bun >= ${MIN_SUPPORTED_BUN_VERSION}`, isSupportedBunVersion(bunVersion) ? "pass" : "fail", `found ${bunVersion}`, `Install Bun ${MIN_SUPPORTED_BUN_VERSION} or newer.`), check("git", "git", which("git") ? "pass" : "fail", which("git") ?? undefined, "Install git and ensure it is on PATH."), check("jq", "jq", which("jq") ? "pass" : "warn", which("jq") ?? undefined, "Install jq (for example `brew install jq`)."));
|
|
540
|
+
progress("Loading rig.config\u2026");
|
|
413
541
|
const loadedConfig = await loadConfig(projectRoot).catch(() => null);
|
|
414
542
|
const config = loadedConfig ?? loadFallbackConfig(projectRoot);
|
|
415
543
|
const hasConfigFile = ["rig.config.ts", "rig.config.mts", "rig.config.json"].some((name) => existsSync4(resolve4(projectRoot, name)));
|
|
@@ -417,7 +545,7 @@ async function runRigDoctorChecks(options) {
|
|
|
417
545
|
const taskSourceKind = config?.taskSource?.kind;
|
|
418
546
|
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."));
|
|
419
547
|
const repo = readRepoConnection(projectRoot);
|
|
420
|
-
checks.push(repo ? check("project-link", "repo selected Rig
|
|
548
|
+
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>`."));
|
|
421
549
|
const selected = (() => {
|
|
422
550
|
try {
|
|
423
551
|
return resolveSelectedConnection(projectRoot);
|
|
@@ -425,9 +553,10 @@ async function runRigDoctorChecks(options) {
|
|
|
425
553
|
return null;
|
|
426
554
|
}
|
|
427
555
|
})();
|
|
428
|
-
checks.push(selected ? check("connection", "selected server connection", "pass", selected.connection.kind === "remote" ? selected.connection.baseUrl : "local auto") : check("connection", "selected server
|
|
556
|
+
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));
|
|
429
557
|
let server = null;
|
|
430
558
|
try {
|
|
559
|
+
progress("Connecting to the selected Rig server\u2026");
|
|
431
560
|
server = await (options.resolveServer ?? ensureServerForCli)(projectRoot);
|
|
432
561
|
checks.push(check("server", "Rig server reachable", "pass", `${server.connectionKind} ${server.baseUrl}`));
|
|
433
562
|
} catch (error) {
|
|
@@ -435,18 +564,21 @@ async function runRigDoctorChecks(options) {
|
|
|
435
564
|
}
|
|
436
565
|
if (server || options.requestJson) {
|
|
437
566
|
try {
|
|
567
|
+
progress("Checking server status\u2026");
|
|
438
568
|
const status = await request("/api/server/status");
|
|
439
569
|
checks.push(check("server-status", "server project status", "pass", JSON.stringify(status).slice(0, 180)));
|
|
440
570
|
} catch (error) {
|
|
441
571
|
checks.push(check("server-status", "server project status", "fail", errorMessage(error), "Run `rig doctor` after the selected server is reachable."));
|
|
442
572
|
}
|
|
443
573
|
try {
|
|
574
|
+
progress("Checking GitHub auth\u2026");
|
|
444
575
|
const auth = await request("/api/github/auth/status");
|
|
445
576
|
checks.push(isAuthenticated(auth) ? check("github-auth", "GitHub auth", "pass") : check("github-auth", "GitHub auth", "fail", "not authenticated", "Run `rig github auth import-gh` or `rig github auth token --token <token>`."));
|
|
446
577
|
} catch (error) {
|
|
447
578
|
checks.push(check("github-auth", "GitHub auth", "fail", errorMessage(error), "Authenticate GitHub through Rig and ensure the server exposes auth status."));
|
|
448
579
|
}
|
|
449
580
|
try {
|
|
581
|
+
progress("Checking GitHub repo permissions\u2026");
|
|
450
582
|
const permissions = await request("/api/github/repo/permissions");
|
|
451
583
|
const allowed = permissionAllowsPr(permissions);
|
|
452
584
|
checks.push(allowed === true ? check("github-repo-permissions", "GitHub repo PR permissions", "pass", JSON.stringify(permissions).slice(0, 180)) : allowed === false ? check("github-repo-permissions", "GitHub repo PR permissions", "fail", JSON.stringify(permissions).slice(0, 180), "Grant the selected GitHub token permission to push branches, open PRs, and merge according to repo rules.") : check("github-repo-permissions", "GitHub repo PR permissions", "warn", JSON.stringify(permissions).slice(0, 180), "Confirm the selected token can push branches and open PRs."));
|
|
@@ -454,6 +586,7 @@ async function runRigDoctorChecks(options) {
|
|
|
454
586
|
checks.push(check("github-repo-permissions", "GitHub repo PR permissions", "warn", errorMessage(error), "Ensure the server exposes repo permission checks and the token can open PRs."));
|
|
455
587
|
}
|
|
456
588
|
try {
|
|
589
|
+
progress("Checking GitHub issue labels\u2026");
|
|
457
590
|
const labels = await request("/api/workspace/task-labels");
|
|
458
591
|
const ready = labelsReady(labels);
|
|
459
592
|
checks.push(ready === false ? check("task-labels", "GitHub issue labels", "fail", JSON.stringify(labels).slice(0, 180), "Let Rig create required labels or create the configured lifecycle labels manually.") : check("task-labels", "GitHub issue labels", ready === true ? "pass" : "warn", JSON.stringify(labels).slice(0, 180), "Confirm required Rig lifecycle labels exist."));
|
|
@@ -461,6 +594,7 @@ async function runRigDoctorChecks(options) {
|
|
|
461
594
|
checks.push(check("task-labels", "GitHub issue labels", "warn", errorMessage(error), "Run `rig init`/`rig doctor` after label setup is wired on the server."));
|
|
462
595
|
}
|
|
463
596
|
try {
|
|
597
|
+
progress("Checking task projection\u2026");
|
|
464
598
|
const projection = await request("/api/workspace/task-projection");
|
|
465
599
|
checks.push(check("task-projection", "task projection", "pass", JSON.stringify(projection).slice(0, 180)));
|
|
466
600
|
} catch (error) {
|
|
@@ -469,6 +603,7 @@ async function runRigDoctorChecks(options) {
|
|
|
469
603
|
const slug = projectStatusSlug(projectRoot, config);
|
|
470
604
|
if (slug) {
|
|
471
605
|
try {
|
|
606
|
+
progress("Checking server project checkout\u2026");
|
|
472
607
|
const project = await request(`/api/projects/${encodeURIComponent(slug)}`);
|
|
473
608
|
checks.push(check("remote-checkout", "server project checkout", "pass", JSON.stringify(project).slice(0, 180)));
|
|
474
609
|
} catch (error) {
|
|
@@ -483,6 +618,7 @@ async function runRigDoctorChecks(options) {
|
|
|
483
618
|
}
|
|
484
619
|
checks.push(githubProjectsCheck(config));
|
|
485
620
|
checks.push(prMergeCheck(config));
|
|
621
|
+
progress("Checking Pi installation\u2026");
|
|
486
622
|
const piChecks = await (options.piChecks ?? (() => buildPiSetupChecks()))().catch((error) => [{
|
|
487
623
|
ok: false,
|
|
488
624
|
label: "pi/pi-rig checks",
|
|
@@ -508,7 +644,7 @@ function countDoctorFailures(checks) {
|
|
|
508
644
|
function throwIfDoctorFailed(checks) {
|
|
509
645
|
const failures = countDoctorFailures(checks);
|
|
510
646
|
if (failures > 0) {
|
|
511
|
-
throw new
|
|
647
|
+
throw new CliError(`Doctor failed (${failures} failing check${failures === 1 ? "" : "s"}).`, 1);
|
|
512
648
|
}
|
|
513
649
|
}
|
|
514
650
|
export {
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
export type HelpCommand = {
|
|
2
|
+
command: string;
|
|
3
|
+
description: string;
|
|
4
|
+
primary?: boolean;
|
|
5
|
+
};
|
|
6
|
+
export type HelpGroup = {
|
|
7
|
+
name: string;
|
|
8
|
+
summary: string;
|
|
9
|
+
usage: string[];
|
|
10
|
+
commands: HelpCommand[];
|
|
11
|
+
examples?: string[];
|
|
12
|
+
next?: string[];
|
|
13
|
+
advanced?: string[];
|
|
14
|
+
};
|
|
15
|
+
export type TopLevelSection = {
|
|
16
|
+
title: string;
|
|
17
|
+
subtitle: string;
|
|
18
|
+
commands: HelpCommand[];
|
|
19
|
+
};
|
|
20
|
+
/** Catalog DATA for the app's help view — the view builds its own layout
|
|
21
|
+
* from these; the render* functions below remain for plain/script output. */
|
|
22
|
+
export declare function helpCatalog(): {
|
|
23
|
+
sections: readonly TopLevelSection[];
|
|
24
|
+
groups: readonly HelpGroup[];
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* Night City boot screen. Rendered only on interactive TTY launches — plain
|
|
28
|
+
* mode and --json never see it.
|
|
29
|
+
*/
|
|
30
|
+
export declare function renderRigBanner(version?: string): string;
|
|
31
|
+
export declare function renderTopLevelHelp(): string;
|
|
32
|
+
export declare function renderAdvancedHelp(): string;
|
|
33
|
+
export declare function renderGroupHelp(groupName: string): string | null;
|
|
34
|
+
export declare function listHelpGroups(): string[];
|
|
35
|
+
/**
|
|
36
|
+
* Fuzzy-match a bare word against known group subcommand names so the
|
|
37
|
+
* unknown-command error can suggest the canonical `rig <group> <cmd>`
|
|
38
|
+
* spelling. Primary groups win ties (ALL_GROUPS is primary-first).
|
|
39
|
+
*/
|
|
40
|
+
export declare function suggestGroupCommandForWord(word: string): string | null;
|
|
41
|
+
export type TopLevelLaunchState = {
|
|
42
|
+
/** True when the cwd resolves to an initialized Rig project. */
|
|
43
|
+
projectInitialized?: boolean;
|
|
44
|
+
/** Short description of the selected server connection, if known. */
|
|
45
|
+
selectedServer?: string | null;
|
|
46
|
+
/** CLI version for the banner footer. */
|
|
47
|
+
version?: string;
|
|
48
|
+
};
|
|
49
|
+
export declare function printTopLevelHelp(state?: TopLevelLaunchState): void;
|
|
50
|
+
export declare function printAdvancedHelp(): void;
|
|
51
|
+
export declare function printGroupHelpDocument(groupName: string): void;
|