@h-rig/cli 0.0.6-alpha.90 → 0.0.6-alpha.91
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 +18 -19
- package/dist/bin/build-rig-binaries.js +22 -10
- package/dist/bin/rig.d.ts +71 -1
- package/dist/bin/rig.js +15078 -11169
- package/dist/config/rig-default-config.yml +5 -0
- package/dist/src/app/drone-ui.d.ts +11 -14
- package/dist/src/app/drone-ui.js +70 -86
- package/dist/src/commands/_async-ui.d.ts +1 -4
- package/dist/src/commands/_async-ui.js +9 -111
- package/dist/src/commands/_cli-format.d.ts +16 -9
- package/dist/src/commands/_cli-format.js +167 -295
- package/dist/src/commands/_connection-state.d.ts +11 -1
- package/dist/src/commands/_connection-state.js +50 -5
- package/dist/src/commands/_doctor-checks.d.ts +0 -6
- package/dist/src/commands/_doctor-checks.js +79 -382
- package/dist/src/commands/_help-catalog.d.ts +1 -1
- package/dist/src/commands/_help-catalog.js +217 -157
- package/dist/src/commands/_inprocess-services.d.ts +33 -0
- package/dist/src/commands/_inprocess-services.js +102 -0
- package/dist/src/commands/_json-output.js +4 -0
- package/dist/src/commands/_lazy-reconcile.d.ts +34 -0
- package/dist/src/commands/_lazy-reconcile.js +102 -0
- package/dist/src/commands/_paths.js +1 -1
- package/dist/src/commands/_pi-frontend.d.ts +18 -10
- package/dist/src/commands/_pi-frontend.js +37 -715
- package/dist/src/commands/_pi-install.js +18 -36
- package/dist/src/commands/_policy.d.ts +1 -1
- package/dist/src/commands/_policy.js +56 -15
- package/dist/src/commands/_run-bridge.d.ts +114 -0
- package/dist/src/commands/_run-bridge.js +387 -0
- package/dist/src/commands/_run-diagnostics.d.ts +9 -0
- package/dist/src/commands/_run-diagnostics.js +51 -0
- package/dist/src/commands/_run-driver-helpers.d.ts +8 -81
- package/dist/src/commands/_run-driver-helpers.js +79 -283
- package/dist/src/commands/_run-projection.d.ts +50 -0
- package/dist/src/commands/_run-projection.js +349 -0
- package/dist/src/commands/_run-subcommands.d.ts +3 -0
- package/dist/src/commands/_run-subcommands.js +31 -0
- package/dist/src/commands/_spinner.js +1 -1
- package/dist/src/commands/agent.d.ts +1 -1
- package/dist/src/commands/agent.js +8559 -239
- package/dist/src/commands/dist.d.ts +1 -1
- package/dist/src/commands/dist.js +27 -19
- package/dist/src/commands/doctor.d.ts +1 -1
- package/dist/src/commands/doctor.js +93 -475
- package/dist/src/commands/github.d.ts +1 -1
- package/dist/src/commands/github.js +113 -387
- package/dist/src/commands/inbox.d.ts +22 -24
- package/dist/src/commands/inbox.js +420 -691
- package/dist/src/commands/init.d.ts +6 -16
- package/dist/src/commands/init.js +334 -971
- package/dist/src/commands/inspect.d.ts +19 -2
- package/dist/src/commands/inspect.js +644 -610
- package/dist/src/commands/pi.d.ts +1 -1
- package/dist/src/commands/plugin.d.ts +1 -1
- package/dist/src/commands/plugin.js +486 -7
- package/dist/src/commands/profile-and-review.d.ts +1 -1
- package/dist/src/commands/profile-and-review.js +94 -56
- package/dist/src/commands/queue.js +1 -21
- package/dist/src/commands/remote.d.ts +1 -1
- package/dist/src/commands/remote.js +837 -14
- package/dist/src/commands/repo-git-harness.d.ts +1 -1
- package/dist/src/commands/repo-git-harness.js +57 -14
- package/dist/src/commands/run.d.ts +20 -2
- package/dist/src/commands/run.js +17579 -1759
- package/dist/src/commands/server.d.ts +2 -6
- package/dist/src/commands/server.js +141 -723
- package/dist/src/commands/setup.d.ts +1 -1
- package/dist/src/commands/setup.js +102 -484
- package/dist/src/commands/stats.d.ts +13 -10
- package/dist/src/commands/stats.js +689 -761
- package/dist/src/commands/task-run-driver.d.ts +50 -88
- package/dist/src/commands/task-run-driver.js +116 -2717
- package/dist/src/commands/task.d.ts +34 -13
- package/dist/src/commands/task.js +668 -2523
- package/dist/src/commands/test.d.ts +1 -1
- package/dist/src/commands/triage.d.ts +11 -0
- package/dist/src/commands/triage.js +227 -0
- package/dist/src/commands/workspace.d.ts +1 -1
- package/dist/src/commands.d.ts +0 -16
- package/dist/src/commands.js +16657 -12250
- package/dist/src/index.js +16528 -12497
- package/dist/src/launcher.js +4 -0
- package/dist/src/operator-cli.d.ts +2 -0
- package/dist/src/operator-cli.js +17837 -0
- package/dist/src/operator-entry.d.ts +1 -0
- package/dist/src/operator-entry.js +3 -0
- package/package.json +18 -12
- package/dist/src/app/board.d.ts +0 -23
- package/dist/src/app/board.js +0 -1786
- package/dist/src/app/theme.d.ts +0 -47
- package/dist/src/app/theme.js +0 -150
- package/dist/src/commands/_authority-runs.d.ts +0 -22
- package/dist/src/commands/_authority-runs.js +0 -110
- package/dist/src/commands/_operator-surface.d.ts +0 -34
- package/dist/src/commands/_operator-surface.js +0 -220
- package/dist/src/commands/_operator-view.d.ts +0 -30
- package/dist/src/commands/_operator-view.js +0 -1070
- package/dist/src/commands/_preflight.d.ts +0 -22
- package/dist/src/commands/_preflight.js +0 -540
- package/dist/src/commands/_run-replay.d.ts +0 -24
- package/dist/src/commands/_run-replay.js +0 -142
- package/dist/src/commands/_server-client.d.ts +0 -186
- package/dist/src/commands/_server-client.js +0 -681
- package/dist/src/commands/_snapshot-upload.d.ts +0 -39
- package/dist/src/commands/_snapshot-upload.js +0 -455
- package/dist/src/commands/_task-picker.d.ts +0 -9
- package/dist/src/commands/_task-picker.js +0 -201
- package/dist/src/commands/browser.d.ts +0 -65
- package/dist/src/commands/browser.js +0 -1173
- package/dist/src/commands/connect.d.ts +0 -7
- package/dist/src/commands/connect.js +0 -419
- package/dist/src/commands/inspector.d.ts +0 -3
- package/dist/src/commands/inspector.js +0 -263
- package/dist/src/commands/task-report-bug.d.ts +0 -19
- package/dist/src/commands/task-report-bug.js +0 -1281
- package/dist/src/report-bug.d.ts +0 -44
- package/dist/src/report-bug.js +0 -260
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
var __require = import.meta.require;
|
|
3
3
|
|
|
4
4
|
// packages/cli/src/commands/_doctor-checks.ts
|
|
5
|
-
import { existsSync as
|
|
6
|
-
import { resolve as
|
|
5
|
+
import { existsSync as existsSync3, readFileSync as readFileSync2 } from "fs";
|
|
6
|
+
import { resolve as resolve3 } from "path";
|
|
7
7
|
|
|
8
8
|
// packages/cli/src/runner.ts
|
|
9
9
|
import { EventBus } from "@rig/runtime/control-plane/runtime/events";
|
|
@@ -26,17 +26,7 @@ import { isSupportedBunVersion, MIN_SUPPORTED_BUN_VERSION } from "@rig/runtime/c
|
|
|
26
26
|
|
|
27
27
|
// packages/cli/src/commands/_connection-state.ts
|
|
28
28
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
|
|
29
|
-
import { homedir } from "os";
|
|
30
29
|
import { dirname, resolve } from "path";
|
|
31
|
-
function resolveGlobalConnectionsPath(env = process.env) {
|
|
32
|
-
const explicit = env.RIG_CONNECTIONS_FILE?.trim();
|
|
33
|
-
if (explicit)
|
|
34
|
-
return resolve(explicit);
|
|
35
|
-
const stateDir = env.RIG_GLOBAL_STATE_DIR?.trim();
|
|
36
|
-
if (stateDir)
|
|
37
|
-
return resolve(stateDir, "connections.json");
|
|
38
|
-
return resolve(homedir(), ".rig", "connections.json");
|
|
39
|
-
}
|
|
40
30
|
function resolveRepoConnectionPath(projectRoot) {
|
|
41
31
|
return resolve(projectRoot, ".rig", "state", "connection.json");
|
|
42
32
|
}
|
|
@@ -49,40 +39,6 @@ function readJsonFile(path) {
|
|
|
49
39
|
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>`." });
|
|
50
40
|
}
|
|
51
41
|
}
|
|
52
|
-
function writeJsonFile(path, value) {
|
|
53
|
-
mkdirSync(dirname(path), { recursive: true });
|
|
54
|
-
writeFileSync(path, `${JSON.stringify(value, null, 2)}
|
|
55
|
-
`, "utf8");
|
|
56
|
-
}
|
|
57
|
-
function normalizeConnection(value) {
|
|
58
|
-
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
59
|
-
return null;
|
|
60
|
-
const record = value;
|
|
61
|
-
if (record.kind === "local")
|
|
62
|
-
return { kind: "local", mode: "auto" };
|
|
63
|
-
if (record.kind === "remote" && typeof record.baseUrl === "string" && record.baseUrl.trim()) {
|
|
64
|
-
const baseUrl = record.baseUrl.trim().replace(/\/+$/, "");
|
|
65
|
-
return { kind: "remote", baseUrl };
|
|
66
|
-
}
|
|
67
|
-
return null;
|
|
68
|
-
}
|
|
69
|
-
function readGlobalConnections(options = {}) {
|
|
70
|
-
const path = resolveGlobalConnectionsPath(options.env ?? process.env);
|
|
71
|
-
const payload = readJsonFile(path);
|
|
72
|
-
if (!payload || typeof payload !== "object" || Array.isArray(payload)) {
|
|
73
|
-
return { connections: {} };
|
|
74
|
-
}
|
|
75
|
-
const rawConnections = payload.connections;
|
|
76
|
-
const connections = {};
|
|
77
|
-
if (rawConnections && typeof rawConnections === "object" && !Array.isArray(rawConnections)) {
|
|
78
|
-
for (const [alias, raw] of Object.entries(rawConnections)) {
|
|
79
|
-
const connection = normalizeConnection(raw);
|
|
80
|
-
if (connection)
|
|
81
|
-
connections[alias] = connection;
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
return { connections };
|
|
85
|
-
}
|
|
86
42
|
function readRepoConnection(projectRoot) {
|
|
87
43
|
const payload = readJsonFile(resolveRepoConnectionPath(projectRoot));
|
|
88
44
|
if (!payload || typeof payload !== "object" || Array.isArray(payload))
|
|
@@ -95,242 +51,68 @@ function readRepoConnection(projectRoot) {
|
|
|
95
51
|
selected,
|
|
96
52
|
project: typeof record.project === "string" ? record.project : undefined,
|
|
97
53
|
linkedAt: typeof record.linkedAt === "string" ? record.linkedAt : undefined,
|
|
98
|
-
serverProjectRoot: typeof record.serverProjectRoot === "string" && record.serverProjectRoot.trim() ? record.serverProjectRoot.trim() : undefined
|
|
54
|
+
serverProjectRoot: typeof record.serverProjectRoot === "string" && record.serverProjectRoot.trim() ? record.serverProjectRoot.trim() : undefined,
|
|
55
|
+
serverProjectRootAlias: typeof record.serverProjectRootAlias === "string" && record.serverProjectRootAlias.trim() ? record.serverProjectRootAlias.trim() : undefined,
|
|
56
|
+
serverProjectRootBaseUrl: typeof record.serverProjectRootBaseUrl === "string" && record.serverProjectRootBaseUrl.trim() ? record.serverProjectRootBaseUrl.trim().replace(/\/+$/, "") : undefined
|
|
99
57
|
};
|
|
100
58
|
}
|
|
101
|
-
function writeRepoConnection(projectRoot, state) {
|
|
102
|
-
writeJsonFile(resolveRepoConnectionPath(projectRoot), state);
|
|
103
|
-
}
|
|
104
|
-
function resolveSelectedConnection(projectRoot, options = {}) {
|
|
105
|
-
const repo = readRepoConnection(projectRoot);
|
|
106
|
-
if (!repo)
|
|
107
|
-
return null;
|
|
108
|
-
if (repo.selected === "local")
|
|
109
|
-
return { alias: "local", connection: { kind: "local", mode: "auto" }, serverProjectRoot: repo.serverProjectRoot };
|
|
110
|
-
const global = readGlobalConnections(options);
|
|
111
|
-
const connection = global.connections[repo.selected];
|
|
112
|
-
if (!connection) {
|
|
113
|
-
throw new CliError(`Selected Rig server "${repo.selected}" was not found. Run \`rig server list\` or \`rig server use local\`.`, 1);
|
|
114
|
-
}
|
|
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 });
|
|
122
|
-
}
|
|
123
59
|
|
|
124
|
-
// packages/cli/src/commands/
|
|
125
|
-
import {
|
|
126
|
-
|
|
127
|
-
|
|
60
|
+
// packages/cli/src/commands/_inprocess-services.ts
|
|
61
|
+
import {
|
|
62
|
+
beginGitHubDeviceFlow,
|
|
63
|
+
checkGitHubRepoPermissions,
|
|
64
|
+
createGitHubAuthStore,
|
|
65
|
+
listGitHubProjects,
|
|
66
|
+
pollGitHubDeviceFlow,
|
|
67
|
+
resolveGitHubAuthStatus,
|
|
68
|
+
resolveProjectStatusField,
|
|
69
|
+
saveGitHubTokenForProject
|
|
70
|
+
} from "@rig/runtime/control-plane/github/index";
|
|
128
71
|
var scopedGitHubBearerTokens = new Map;
|
|
129
|
-
var serverPhaseListener = null;
|
|
130
|
-
function reportServerPhase(label) {
|
|
131
|
-
serverPhaseListener?.(label);
|
|
132
|
-
}
|
|
133
72
|
function cleanToken(value) {
|
|
134
73
|
const trimmed = value?.trim();
|
|
135
74
|
return trimmed ? trimmed : null;
|
|
136
75
|
}
|
|
137
|
-
function
|
|
138
|
-
|
|
139
|
-
if (!existsSync2(path))
|
|
140
|
-
return null;
|
|
141
|
-
try {
|
|
142
|
-
const parsed = JSON.parse(readFileSync2(path, "utf8"));
|
|
143
|
-
return cleanToken(typeof parsed.apiSessionToken === "string" ? parsed.apiSessionToken : typeof parsed.sessionToken === "string" ? parsed.sessionToken : undefined);
|
|
144
|
-
} catch {
|
|
145
|
-
return null;
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
function readGitHubBearerTokenForRemote(projectRoot) {
|
|
149
|
-
const scopedKey = resolve2(projectRoot);
|
|
150
|
-
if (scopedGitHubBearerTokens.has(scopedKey))
|
|
151
|
-
return scopedGitHubBearerTokens.get(scopedKey) ?? null;
|
|
152
|
-
const privateSession = readPrivateRemoteSessionToken(projectRoot);
|
|
153
|
-
if (privateSession)
|
|
154
|
-
return privateSession;
|
|
155
|
-
return cleanToken(process.env.RIG_SERVER_AUTH_TOKEN) ?? cleanToken(process.env.RIG_REMOTE_AUTH_TOKEN);
|
|
76
|
+
function cleanString(value) {
|
|
77
|
+
return typeof value === "string" && value.trim() ? value.trim() : null;
|
|
156
78
|
}
|
|
157
|
-
function
|
|
158
|
-
|
|
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;
|
|
166
|
-
}
|
|
79
|
+
function oauthClientId() {
|
|
80
|
+
return cleanToken(process.env.RIG_GITHUB_OAUTH_CLIENT_ID);
|
|
167
81
|
}
|
|
168
|
-
function
|
|
169
|
-
return
|
|
82
|
+
async function getGitHubAuthStatusInProcess(context) {
|
|
83
|
+
return { ok: true, ...resolveGitHubAuthStatus({ projectRoot: context.projectRoot, oauthConfigured: Boolean(oauthClientId()) }) };
|
|
170
84
|
}
|
|
171
|
-
async function
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
const serverProjectRoot = selected.serverProjectRoot ?? await backfillRemoteServerProjectRoot(projectRoot, selected.connection.baseUrl, authToken);
|
|
178
|
-
return {
|
|
179
|
-
baseUrl: selected.connection.baseUrl,
|
|
180
|
-
authToken,
|
|
181
|
-
connectionKind: "remote",
|
|
182
|
-
serverProjectRoot
|
|
183
|
-
};
|
|
184
|
-
}
|
|
185
|
-
reportServerPhase("Starting local Rig server\u2026");
|
|
186
|
-
const connection = await ensureLocalRigServerConnection(projectRoot);
|
|
187
|
-
return {
|
|
188
|
-
baseUrl: connection.baseUrl,
|
|
189
|
-
authToken: connection.authToken ?? readLocalConnectionFallbackToken(projectRoot),
|
|
190
|
-
connectionKind: "local",
|
|
191
|
-
serverProjectRoot: resolve2(projectRoot)
|
|
192
|
-
};
|
|
193
|
-
} catch (error) {
|
|
194
|
-
if (error instanceof Error) {
|
|
195
|
-
throw new CliError(error.message, 1);
|
|
196
|
-
}
|
|
197
|
-
throw error;
|
|
85
|
+
async function requestGitHubAuthJsonInProcess(context, pathname, init = {}) {
|
|
86
|
+
const method = (init.method ?? "GET").toUpperCase();
|
|
87
|
+
if (pathname === "/api/github/auth/status")
|
|
88
|
+
return getGitHubAuthStatusInProcess(context);
|
|
89
|
+
if (pathname === "/api/github/repo/permissions") {
|
|
90
|
+
return checkGitHubRepoPermissions({ projectRoot: context.projectRoot, oauthConfigured: Boolean(oauthClientId()) });
|
|
198
91
|
}
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
return
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
92
|
+
if (pathname === "/api/github/auth/device/start" && method === "POST") {
|
|
93
|
+
const clientId = oauthClientId();
|
|
94
|
+
if (!clientId)
|
|
95
|
+
return { ok: false, oauthConfigured: false, error: "RIG_GITHUB_OAUTH_CLIENT_ID is not configured." };
|
|
96
|
+
const body = init.body ? JSON.parse(String(init.body)) : {};
|
|
97
|
+
return beginGitHubDeviceFlow({
|
|
98
|
+
projectRoot: context.projectRoot,
|
|
99
|
+
clientId,
|
|
100
|
+
scope: cleanString(body.scope) ?? undefined,
|
|
101
|
+
selectedRepo: cleanString(body.repoSlug)
|
|
208
102
|
});
|
|
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
103
|
}
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
104
|
+
if (pathname === "/api/github/auth/device/poll" && method === "POST") {
|
|
105
|
+
const clientId = oauthClientId();
|
|
106
|
+
if (!clientId)
|
|
107
|
+
return { ok: false, oauthConfigured: false, error: "RIG_GITHUB_OAUTH_CLIENT_ID is not configured." };
|
|
108
|
+
const body = init.body ? JSON.parse(String(init.body)) : {};
|
|
109
|
+
const pollId = cleanString(body.pollId);
|
|
110
|
+
if (!pollId)
|
|
111
|
+
return { ok: false, status: "error", error: "pollId is required" };
|
|
112
|
+
return pollGitHubDeviceFlow({ projectRoot: context.projectRoot, clientId, pollId, selectedRepo: cleanString(body.repoSlug) });
|
|
227
113
|
}
|
|
228
|
-
|
|
114
|
+
throw new Error(`No in-process GitHub auth API for ${method} ${pathname}`);
|
|
229
115
|
}
|
|
230
|
-
function diagnosticMessage(payload) {
|
|
231
|
-
if (!payload || typeof payload !== "object" || Array.isArray(payload))
|
|
232
|
-
return null;
|
|
233
|
-
const record = payload;
|
|
234
|
-
const diagnostics = Array.isArray(record.diagnostics) ? record.diagnostics : [];
|
|
235
|
-
const messages = diagnostics.flatMap((entry) => {
|
|
236
|
-
if (!entry || typeof entry !== "object" || Array.isArray(entry))
|
|
237
|
-
return [];
|
|
238
|
-
const diagnostic = entry;
|
|
239
|
-
const kind = typeof diagnostic.kind === "string" ? diagnostic.kind : "task-source";
|
|
240
|
-
const message = typeof diagnostic.message === "string" ? diagnostic.message : null;
|
|
241
|
-
return message ? [`${kind}: ${message}`] : [];
|
|
242
|
-
});
|
|
243
|
-
return messages.length > 0 ? messages.join("; ") : null;
|
|
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
|
-
}
|
|
287
|
-
async function requestServerJson(context, pathname, init = {}) {
|
|
288
|
-
const server = await ensureServerForCli(context.projectRoot);
|
|
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
|
-
}
|
|
304
|
-
const text = await response.text();
|
|
305
|
-
const payload = text.trim().length > 0 ? (() => {
|
|
306
|
-
try {
|
|
307
|
-
return JSON.parse(text);
|
|
308
|
-
} catch {
|
|
309
|
-
return null;
|
|
310
|
-
}
|
|
311
|
-
})() : null;
|
|
312
|
-
if (!response.ok) {
|
|
313
|
-
const diagnostics = diagnosticMessage(payload);
|
|
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 });
|
|
320
|
-
}
|
|
321
|
-
return payload;
|
|
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
|
-
]);
|
|
334
116
|
|
|
335
117
|
// packages/cli/src/commands/_parsers.ts
|
|
336
118
|
async function loadRigConfigOrNull(projectRoot) {
|
|
@@ -343,11 +125,10 @@ async function loadRigConfigOrNull(projectRoot) {
|
|
|
343
125
|
}
|
|
344
126
|
|
|
345
127
|
// packages/cli/src/commands/_pi-install.ts
|
|
346
|
-
import { existsSync as
|
|
347
|
-
import { homedir
|
|
348
|
-
import { resolve as
|
|
128
|
+
import { existsSync as existsSync2 } from "fs";
|
|
129
|
+
import { homedir } from "os";
|
|
130
|
+
import { resolve as resolve2 } from "path";
|
|
349
131
|
var PI_RIG_PACKAGE_NAME = "@h-rig/pi-rig";
|
|
350
|
-
var LEGACY_PI_RIG_PACKAGE_NAME = "@rig/pi-rig";
|
|
351
132
|
async function defaultCommandRunner(command, options = {}) {
|
|
352
133
|
const proc = Bun.spawn(command, { cwd: options.cwd, stdout: "pipe", stderr: "pipe" });
|
|
353
134
|
const [stdout, stderr, exitCode] = await Promise.all([
|
|
@@ -358,15 +139,15 @@ async function defaultCommandRunner(command, options = {}) {
|
|
|
358
139
|
return { exitCode, stdout, stderr };
|
|
359
140
|
}
|
|
360
141
|
function resolvePiRigExtensionPath(homeDir) {
|
|
361
|
-
return
|
|
142
|
+
return resolve2(homeDir, ".pi", "agent", "extensions", "pi-rig");
|
|
362
143
|
}
|
|
363
144
|
function resolvePiHomeDir(inputHomeDir) {
|
|
364
|
-
return inputHomeDir ?? process.env.RIG_PI_HOME_DIR?.trim() ??
|
|
145
|
+
return inputHomeDir ?? process.env.RIG_PI_HOME_DIR?.trim() ?? homedir();
|
|
365
146
|
}
|
|
366
147
|
function piListContainsPiRig(output) {
|
|
367
148
|
return output.split(/\r?\n/).some((line) => {
|
|
368
149
|
const normalized = line.trim();
|
|
369
|
-
return normalized.includes(PI_RIG_PACKAGE_NAME) ||
|
|
150
|
+
return normalized.includes(PI_RIG_PACKAGE_NAME) || /(?:^|[\\/])packages[\\/]pi-rig(?:$|\s)/.test(normalized);
|
|
370
151
|
});
|
|
371
152
|
}
|
|
372
153
|
async function safeRun(runner, command, options) {
|
|
@@ -386,27 +167,25 @@ async function checkPiRigInstall(input = {}) {
|
|
|
386
167
|
piRig: { ok: true, label: "pi-rig global extension", detail: extensionPath }
|
|
387
168
|
};
|
|
388
169
|
}
|
|
389
|
-
const exists = input.exists ?? existsSync3;
|
|
390
170
|
const runner = input.commandRunner ?? defaultCommandRunner;
|
|
391
171
|
const piResult = await safeRun(runner, ["pi", "--version"]);
|
|
392
172
|
const piListResult = piResult.exitCode === 0 ? await safeRun(runner, ["pi", "list"]) : { exitCode: 1, stdout: "", stderr: "" };
|
|
393
|
-
const
|
|
173
|
+
const hasPiRig = piListResult.exitCode === 0 && piListContainsPiRig(`${piListResult.stdout}
|
|
394
174
|
${piListResult.stderr}`);
|
|
395
|
-
const
|
|
396
|
-
const hasPiRig = listedPiRig;
|
|
175
|
+
const hasLegacyBridgeScaffold = !hasPiRig && (input.exists ?? existsSync2)(extensionPath);
|
|
397
176
|
return {
|
|
398
177
|
extensionPath,
|
|
399
178
|
pi: {
|
|
400
179
|
ok: piResult.exitCode === 0,
|
|
401
180
|
label: "pi",
|
|
402
181
|
detail: (piResult.stdout || piResult.stderr).trim() || undefined,
|
|
403
|
-
hint: piResult.exitCode === 0 ? undefined : "Install Pi or
|
|
182
|
+
hint: piResult.exitCode === 0 ? undefined : "Install Pi/OMP manually or set RIG_PI_INSTALL_COMMAND before verifying with bare `rig` / Cockpit \u2192 Doctor."
|
|
404
183
|
},
|
|
405
184
|
piRig: {
|
|
406
185
|
ok: hasPiRig,
|
|
407
186
|
label: "pi-rig global extension",
|
|
408
|
-
detail: hasPiRig ? piListResult.stdout.trim() || PI_RIG_PACKAGE_NAME :
|
|
409
|
-
hint: hasPiRig ? undefined :
|
|
187
|
+
detail: hasPiRig ? piListResult.stdout.trim() || PI_RIG_PACKAGE_NAME : hasLegacyBridgeScaffold ? `legacy bridge scaffold at ${extensionPath}` : undefined,
|
|
188
|
+
hint: hasPiRig ? undefined : `Install the Rig OMP extension with \`pi install ${PI_RIG_PACKAGE_NAME}\`, then verify with bare \`rig\` / Cockpit \u2192 Doctor.`
|
|
410
189
|
}
|
|
411
190
|
};
|
|
412
191
|
}
|
|
@@ -434,31 +213,14 @@ function isAuthenticated(payload) {
|
|
|
434
213
|
const record = payload;
|
|
435
214
|
return record.signedIn === true || record.authenticated === true || record.status === "authenticated" || record.ok === true && typeof record.login === "string" && record.login.trim().length > 0;
|
|
436
215
|
}
|
|
437
|
-
function repoSlugFromConfig(config) {
|
|
438
|
-
const project = config?.project;
|
|
439
|
-
if (project && typeof project === "object" && !Array.isArray(project)) {
|
|
440
|
-
const record = project;
|
|
441
|
-
if (typeof record.repo === "string" && /^([^/\s]+)\/([^/\s]+)$/.test(record.repo))
|
|
442
|
-
return record.repo;
|
|
443
|
-
if (typeof record.name === "string" && /^([^/\s]+)\/([^/\s]+)$/.test(record.name))
|
|
444
|
-
return record.name;
|
|
445
|
-
}
|
|
446
|
-
const taskSource = config?.taskSource;
|
|
447
|
-
if (taskSource && typeof taskSource === "object" && !Array.isArray(taskSource)) {
|
|
448
|
-
const source = taskSource;
|
|
449
|
-
if (typeof source.owner === "string" && typeof source.repo === "string")
|
|
450
|
-
return `${source.owner}/${source.repo}`;
|
|
451
|
-
}
|
|
452
|
-
return null;
|
|
453
|
-
}
|
|
454
216
|
function loadFallbackConfig(projectRoot) {
|
|
455
217
|
const candidates = ["rig.config.ts", "rig.config.mts", "rig.config.json"];
|
|
456
218
|
for (const name of candidates) {
|
|
457
|
-
const path =
|
|
458
|
-
if (!
|
|
219
|
+
const path = resolve3(projectRoot, name);
|
|
220
|
+
if (!existsSync3(path))
|
|
459
221
|
continue;
|
|
460
222
|
try {
|
|
461
|
-
const source =
|
|
223
|
+
const source = readFileSync2(path, "utf8");
|
|
462
224
|
if (name.endsWith(".json"))
|
|
463
225
|
return JSON.parse(source);
|
|
464
226
|
const owner = source.match(/owner\s*:\s*["']([^"']+)["']/)?.[1];
|
|
@@ -477,14 +239,11 @@ function loadFallbackConfig(projectRoot) {
|
|
|
477
239
|
}
|
|
478
240
|
return null;
|
|
479
241
|
}
|
|
480
|
-
function projectStatusSlug(projectRoot, config) {
|
|
481
|
-
return readRepoConnection(projectRoot)?.project ?? repoSlugFromConfig(config);
|
|
482
|
-
}
|
|
483
242
|
function githubProjectsCheck(config) {
|
|
484
243
|
const github = config?.github;
|
|
485
244
|
const projects = github?.projects;
|
|
486
245
|
if (!projects?.enabled) {
|
|
487
|
-
return check("github-projects", "GitHub Projects status sync", "warn", "disabled or not configured", "
|
|
246
|
+
return check("github-projects", "GitHub Projects status sync", "warn", "disabled or not configured", "Current OMP flow does not require GitHub Projects status sync; configure github.projects manually when Project status sync should be authoritative.");
|
|
488
247
|
}
|
|
489
248
|
if (projects.projectId && projects.statusFieldId) {
|
|
490
249
|
return check("github-projects", "GitHub Projects status sync", "pass", `project ${projects.projectId}`);
|
|
@@ -509,16 +268,6 @@ function permissionAllowsPr(payload) {
|
|
|
509
268
|
}
|
|
510
269
|
return null;
|
|
511
270
|
}
|
|
512
|
-
function labelsReady(payload) {
|
|
513
|
-
if (!payload || typeof payload !== "object" || Array.isArray(payload))
|
|
514
|
-
return null;
|
|
515
|
-
const record = payload;
|
|
516
|
-
if (record.ok === true || record.ready === true || record.labelsReady === true)
|
|
517
|
-
return true;
|
|
518
|
-
if (record.ok === false || record.ready === false || record.labelsReady === false)
|
|
519
|
-
return false;
|
|
520
|
-
return null;
|
|
521
|
-
}
|
|
522
271
|
function prMergeCheck(config) {
|
|
523
272
|
const pr = config?.pr;
|
|
524
273
|
const merge = config?.merge;
|
|
@@ -532,7 +281,7 @@ async function runRigDoctorChecks(options) {
|
|
|
532
281
|
const checks = [];
|
|
533
282
|
const which = options.which ?? ((binary) => Bun.which(binary));
|
|
534
283
|
const bunVersion = options.bunVersion ?? Bun.version;
|
|
535
|
-
const request = options.requestJson ?? ((pathname, init) =>
|
|
284
|
+
const request = options.requestJson ?? ((pathname, init) => requestGitHubAuthJsonInProcess({ projectRoot }, pathname, init));
|
|
536
285
|
const loadConfig = options.loadConfig ?? loadRigConfigOrNull;
|
|
537
286
|
const progress = options.onProgress ?? (() => {});
|
|
538
287
|
progress("Checking local toolchain\u2026");
|
|
@@ -540,78 +289,26 @@ async function runRigDoctorChecks(options) {
|
|
|
540
289
|
progress("Loading rig.config\u2026");
|
|
541
290
|
const loadedConfig = await loadConfig(projectRoot).catch(() => null);
|
|
542
291
|
const config = loadedConfig ?? loadFallbackConfig(projectRoot);
|
|
543
|
-
const hasConfigFile = ["rig.config.ts", "rig.config.mts", "rig.config.json"].some((name) =>
|
|
544
|
-
checks.push(config ? check("config", "rig.config loadable", "pass") : check("config", "rig.config loadable", hasConfigFile ? "fail" : "fail", hasConfigFile ? "config file exists but failed to load" : "missing rig.config.ts/json", "
|
|
292
|
+
const hasConfigFile = ["rig.config.ts", "rig.config.mts", "rig.config.json"].some((name) => existsSync3(resolve3(projectRoot, name)));
|
|
293
|
+
checks.push(config ? check("config", "rig.config loadable", "pass") : check("config", "rig.config loadable", hasConfigFile ? "fail" : "fail", hasConfigFile ? "config file exists but failed to load" : "missing rig.config.ts/json", "Create/fix rig.config.ts or use the OMP cockpit Start tab to scaffold one."));
|
|
545
294
|
const taskSourceKind = config?.taskSource?.kind;
|
|
546
295
|
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."));
|
|
547
296
|
const repo = readRepoConnection(projectRoot);
|
|
548
|
-
checks.push(repo ? check("project-link", "repo selected
|
|
549
|
-
const selected = (() => {
|
|
550
|
-
try {
|
|
551
|
-
return resolveSelectedConnection(projectRoot);
|
|
552
|
-
} catch {
|
|
553
|
-
return null;
|
|
554
|
-
}
|
|
555
|
-
})();
|
|
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));
|
|
557
|
-
let server = null;
|
|
297
|
+
checks.push(repo ? check("project-link", "repo selected for local setup", repo.project ? "pass" : "warn", `${repo.selected}${repo.project ? ` -> ${repo.project}` : ""}`, "Run `rig init --repo owner/repo` if this project should use GitHub Issues.") : check("project-link", "repo selected for local setup", "warn", "missing .rig/state/connection.json", "Current UX can run without this compatibility file; `rig init` recreates it for GitHub-backed projects."));
|
|
558
298
|
try {
|
|
559
|
-
progress("
|
|
560
|
-
|
|
561
|
-
checks.push(check("
|
|
299
|
+
progress("Checking GitHub auth\u2026");
|
|
300
|
+
const auth = await request("/api/github/auth/status");
|
|
301
|
+
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>`."));
|
|
562
302
|
} catch (error) {
|
|
563
|
-
checks.push(check("
|
|
303
|
+
checks.push(check("github-auth", "GitHub auth", "fail", errorMessage(error), "Authenticate GitHub through Rig."));
|
|
564
304
|
}
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
}
|
|
573
|
-
try {
|
|
574
|
-
progress("Checking GitHub auth\u2026");
|
|
575
|
-
const auth = await request("/api/github/auth/status");
|
|
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>`."));
|
|
577
|
-
} catch (error) {
|
|
578
|
-
checks.push(check("github-auth", "GitHub auth", "fail", errorMessage(error), "Authenticate GitHub through Rig and ensure the server exposes auth status."));
|
|
579
|
-
}
|
|
580
|
-
try {
|
|
581
|
-
progress("Checking GitHub repo permissions\u2026");
|
|
582
|
-
const permissions = await request("/api/github/repo/permissions");
|
|
583
|
-
const allowed = permissionAllowsPr(permissions);
|
|
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."));
|
|
585
|
-
} catch (error) {
|
|
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."));
|
|
587
|
-
}
|
|
588
|
-
try {
|
|
589
|
-
progress("Checking GitHub issue labels\u2026");
|
|
590
|
-
const labels = await request("/api/workspace/task-labels");
|
|
591
|
-
const ready = labelsReady(labels);
|
|
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."));
|
|
593
|
-
} catch (error) {
|
|
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."));
|
|
595
|
-
}
|
|
596
|
-
try {
|
|
597
|
-
progress("Checking task projection\u2026");
|
|
598
|
-
const projection = await request("/api/workspace/task-projection");
|
|
599
|
-
checks.push(check("task-projection", "task projection", "pass", JSON.stringify(projection).slice(0, 180)));
|
|
600
|
-
} catch (error) {
|
|
601
|
-
checks.push(check("task-projection", "task projection", "warn", errorMessage(error), "Refresh task projection with `rig task list` or fix the task source."));
|
|
602
|
-
}
|
|
603
|
-
const slug = projectStatusSlug(projectRoot, config);
|
|
604
|
-
if (slug) {
|
|
605
|
-
try {
|
|
606
|
-
progress("Checking server project checkout\u2026");
|
|
607
|
-
const project = await request(`/api/projects/${encodeURIComponent(slug)}`);
|
|
608
|
-
checks.push(check("remote-checkout", "server project checkout", "pass", JSON.stringify(project).slice(0, 180)));
|
|
609
|
-
} catch (error) {
|
|
610
|
-
checks.push(check("remote-checkout", "server project checkout", "warn", errorMessage(error), "Run `rig init --yes --repo owner/repo` to register/link the server project checkout."));
|
|
611
|
-
}
|
|
612
|
-
} else {
|
|
613
|
-
checks.push(check("remote-checkout", "server project checkout", "warn", "repo slug unknown", "Set project.repo or run `rig init --repo owner/repo`."));
|
|
614
|
-
}
|
|
305
|
+
try {
|
|
306
|
+
progress("Checking GitHub repo permissions\u2026");
|
|
307
|
+
const permissions = await request("/api/github/repo/permissions");
|
|
308
|
+
const allowed = permissionAllowsPr(permissions);
|
|
309
|
+
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."));
|
|
310
|
+
} catch (error) {
|
|
311
|
+
checks.push(check("github-repo-permissions", "GitHub repo PR permissions", "warn", errorMessage(error), "Ensure the token can open PRs."));
|
|
615
312
|
}
|
|
616
313
|
if (taskSourceKind === "github-issues") {
|
|
617
314
|
checks.push(check("gh", "gh CLI fallback", which("gh") ? "pass" : "warn", which("gh") ?? undefined, "Install gh for local/dev GitHub fallback operations."));
|
|
@@ -625,7 +322,7 @@ async function runRigDoctorChecks(options) {
|
|
|
625
322
|
hint: errorMessage(error)
|
|
626
323
|
}]);
|
|
627
324
|
for (const pi of piChecks) {
|
|
628
|
-
checks.push(check(pi.label === "pi" ? "pi" : "pi-rig", pi.label, pi.ok ? "pass" : "warn", pi.detail, pi.hint ?? (pi.ok ? undefined : "
|
|
325
|
+
checks.push(check(pi.label === "pi" ? "pi" : "pi-rig", pi.label, pi.ok ? "pass" : "warn", pi.detail, pi.hint ?? (pi.ok ? undefined : "Install Pi/OMP and the Rig extension, then use bare `rig` or Cockpit \u2192 Doctor to verify.")));
|
|
629
326
|
}
|
|
630
327
|
return checks;
|
|
631
328
|
}
|
|
@@ -37,7 +37,7 @@ export declare function listHelpGroups(): string[];
|
|
|
37
37
|
* unknown-command error can suggest the canonical `rig <group> <cmd>`
|
|
38
38
|
* spelling. Primary groups win ties (ALL_GROUPS is primary-first).
|
|
39
39
|
*/
|
|
40
|
-
export declare function suggestGroupCommandForWord(word: string): string | null;
|
|
40
|
+
export declare function suggestGroupCommandForWord(word: string, liveGroups?: ReadonlySet<string>): string | null;
|
|
41
41
|
export type TopLevelLaunchState = {
|
|
42
42
|
/** True when the cwd resolves to an initialized Rig project. */
|
|
43
43
|
projectInitialized?: boolean;
|