@h-rig/cli 0.0.6-alpha.82 → 0.0.6-alpha.84
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin/build-rig-binaries.js +40 -8
- package/dist/bin/rig.js +23402 -14577
- package/dist/src/app/board.js +217 -41
- package/dist/src/app-opentui/adapters/command.d.ts +2 -0
- package/dist/src/app-opentui/adapters/command.js +329 -0
- package/dist/src/app-opentui/adapters/common.js +2 -2
- package/dist/src/app-opentui/adapters/doctor.d.ts +0 -2
- package/dist/src/app-opentui/adapters/doctor.js +64 -39
- package/dist/src/app-opentui/adapters/family.d.ts +62 -0
- package/dist/src/app-opentui/adapters/family.js +14305 -0
- package/dist/src/app-opentui/adapters/fleet.d.ts +0 -2
- package/dist/src/app-opentui/adapters/fleet.js +90 -60
- package/dist/src/app-opentui/adapters/inbox.d.ts +12 -2
- package/dist/src/app-opentui/adapters/inbox.js +137 -78
- package/dist/src/app-opentui/adapters/init.d.ts +0 -2
- package/dist/src/app-opentui/adapters/init.js +85 -47
- package/dist/src/app-opentui/adapters/inspect.d.ts +52 -0
- package/dist/src/app-opentui/adapters/inspect.js +1024 -0
- package/dist/src/app-opentui/adapters/pi-attach.d.ts +15 -6
- package/dist/src/app-opentui/adapters/pi-attach.js +442 -125
- package/dist/src/app-opentui/adapters/pi.d.ts +23 -0
- package/dist/src/app-opentui/adapters/pi.js +363 -0
- package/dist/src/app-opentui/adapters/plugin.d.ts +84 -0
- package/dist/src/app-opentui/adapters/plugin.js +544 -0
- package/dist/src/app-opentui/adapters/repo.d.ts +37 -0
- package/dist/src/app-opentui/adapters/repo.js +186 -0
- package/dist/src/app-opentui/adapters/run-detail.d.ts +9 -2
- package/dist/src/app-opentui/adapters/run-detail.js +180 -63
- package/dist/src/app-opentui/adapters/server.d.ts +10 -2
- package/dist/src/app-opentui/adapters/server.js +191 -45
- package/dist/src/app-opentui/adapters/tasks.d.ts +11 -2
- package/dist/src/app-opentui/adapters/tasks.js +1123 -143
- package/dist/src/app-opentui/adapters/workspace.d.ts +49 -0
- package/dist/src/app-opentui/adapters/workspace.js +333 -0
- package/dist/src/app-opentui/autocomplete.d.ts +20 -0
- package/dist/src/app-opentui/autocomplete.js +576 -0
- package/dist/src/app-opentui/bootstrap.d.ts +1 -6
- package/dist/src/app-opentui/bootstrap.js +25252 -16474
- package/dist/src/app-opentui/command-palette.d.ts +3 -0
- package/dist/src/app-opentui/command-palette.js +1010 -0
- package/dist/src/app-opentui/command-pty-host.d.ts +62 -0
- package/dist/src/app-opentui/command-pty-host.js +248 -0
- package/dist/src/app-opentui/drone.js +8 -6
- package/dist/src/app-opentui/events.js +1 -1
- package/dist/src/app-opentui/fleet-stats.d.ts +32 -0
- package/dist/src/app-opentui/fleet-stats.js +114 -0
- package/dist/src/app-opentui/focus-manager.d.ts +14 -0
- package/dist/src/app-opentui/focus-manager.js +24 -0
- package/dist/src/app-opentui/index.js +5431 -2797
- package/dist/src/app-opentui/intent.js +179 -50
- package/dist/src/app-opentui/keymap.d.ts +21 -0
- package/dist/src/app-opentui/keymap.js +1748 -0
- package/dist/src/app-opentui/launch-routing.d.ts +16 -0
- package/dist/src/app-opentui/launch-routing.js +55 -0
- package/dist/src/app-opentui/layout.d.ts +7 -0
- package/dist/src/app-opentui/layout.js +13 -6
- package/dist/src/app-opentui/list-search.d.ts +24 -0
- package/dist/src/app-opentui/list-search.js +88 -1
- package/dist/src/app-opentui/pi-host-child.js +99 -17
- package/dist/src/app-opentui/pi-pty-host.d.ts +14 -0
- package/dist/src/app-opentui/pi-pty-host.js +30 -14
- package/dist/src/app-opentui/react/App.d.ts +9 -0
- package/dist/src/app-opentui/react/App.js +5144 -0
- package/dist/src/app-opentui/react/Backdrop.d.ts +5 -0
- package/dist/src/app-opentui/react/Backdrop.js +1834 -0
- package/dist/src/app-opentui/react/ChromeHost.d.ts +5 -0
- package/dist/src/app-opentui/react/ChromeHost.js +2942 -0
- package/dist/src/app-opentui/react/SceneFrameView.d.ts +7 -0
- package/dist/src/app-opentui/react/SceneFrameView.js +529 -0
- package/dist/src/app-opentui/react/context.d.ts +17 -0
- package/dist/src/app-opentui/react/context.js +37 -0
- package/dist/src/app-opentui/react/launch.d.ts +2 -0
- package/dist/src/app-opentui/react/launch.js +5743 -0
- package/dist/src/app-opentui/react/nav.d.ts +18 -0
- package/dist/src/app-opentui/react/nav.js +54 -0
- package/dist/src/app-opentui/react/scroll.d.ts +12 -0
- package/dist/src/app-opentui/react/scroll.js +21 -0
- package/dist/src/app-opentui/react/syntax.d.ts +2 -0
- package/dist/src/app-opentui/react/syntax.js +64 -0
- package/dist/src/app-opentui/registry.js +20428 -4828
- package/dist/src/app-opentui/render/ascii-fleet.d.ts +15 -0
- package/dist/src/app-opentui/render/ascii-fleet.js +82 -0
- package/dist/src/app-opentui/render/constants.d.ts +31 -0
- package/dist/src/app-opentui/render/constants.js +66 -0
- package/dist/src/app-opentui/render/graphics.d.ts +2 -1
- package/dist/src/app-opentui/render/graphics.js +228 -46
- package/dist/src/app-opentui/render/image-visual-layer-worker.js +469 -930
- package/dist/src/app-opentui/render/image-visual-layer.d.ts +25 -10
- package/dist/src/app-opentui/render/image-visual-layer.js +448 -329
- package/dist/src/app-opentui/render/native-host.d.ts +37 -0
- package/dist/src/app-opentui/render/native-host.js +179 -0
- package/dist/src/app-opentui/render/panel-layout.d.ts +38 -0
- package/dist/src/app-opentui/render/panel-layout.js +48 -0
- package/dist/src/app-opentui/render/panels.d.ts +2 -0
- package/dist/src/app-opentui/render/panels.js +78 -38
- package/dist/src/app-opentui/render/preloader.d.ts +10 -0
- package/dist/src/app-opentui/render/preloader.js +165 -0
- package/dist/src/app-opentui/render/scene.d.ts +53 -1
- package/dist/src/app-opentui/render/scene.js +195 -6
- package/dist/src/app-opentui/render/text.d.ts +7 -1
- package/dist/src/app-opentui/render/text.js +15 -8
- package/dist/src/app-opentui/render/type-bar.d.ts +2 -1
- package/dist/src/app-opentui/render/type-bar.js +113 -39
- package/dist/src/app-opentui/runtime-resources.d.ts +16 -0
- package/dist/src/app-opentui/runtime-resources.js +62 -0
- package/dist/src/app-opentui/runtime.d.ts +44 -1
- package/dist/src/app-opentui/runtime.js +5415 -2738
- package/dist/src/app-opentui/scenes/command.d.ts +3 -0
- package/dist/src/app-opentui/scenes/command.js +117 -0
- package/dist/src/app-opentui/scenes/doctor.d.ts +2 -1
- package/dist/src/app-opentui/scenes/doctor.js +221 -17
- package/dist/src/app-opentui/scenes/error.js +60 -20
- package/dist/src/app-opentui/scenes/family-domains/agent.d.ts +2 -0
- package/dist/src/app-opentui/scenes/family-domains/agent.js +348 -0
- package/dist/src/app-opentui/scenes/family-domains/browser.d.ts +2 -0
- package/dist/src/app-opentui/scenes/family-domains/browser.js +195 -0
- package/dist/src/app-opentui/scenes/family-domains/dist.d.ts +2 -0
- package/dist/src/app-opentui/scenes/family-domains/dist.js +243 -0
- package/dist/src/app-opentui/scenes/family-domains/git.d.ts +2 -0
- package/dist/src/app-opentui/scenes/family-domains/git.js +195 -0
- package/dist/src/app-opentui/scenes/family-domains/github.d.ts +2 -0
- package/dist/src/app-opentui/scenes/family-domains/github.js +274 -0
- package/dist/src/app-opentui/scenes/family-domains/harness.d.ts +2 -0
- package/dist/src/app-opentui/scenes/family-domains/harness.js +152 -0
- package/dist/src/app-opentui/scenes/family-domains/index.d.ts +4 -0
- package/dist/src/app-opentui/scenes/family-domains/index.js +1679 -0
- package/dist/src/app-opentui/scenes/family-domains/kit.d.ts +76 -0
- package/dist/src/app-opentui/scenes/family-domains/kit.js +305 -0
- package/dist/src/app-opentui/scenes/family-domains/profile.d.ts +2 -0
- package/dist/src/app-opentui/scenes/family-domains/profile.js +212 -0
- package/dist/src/app-opentui/scenes/family-domains/queue.d.ts +2 -0
- package/dist/src/app-opentui/scenes/family-domains/queue.js +146 -0
- package/dist/src/app-opentui/scenes/family-domains/remote.d.ts +2 -0
- package/dist/src/app-opentui/scenes/family-domains/remote.js +518 -0
- package/dist/src/app-opentui/scenes/family-domains/review.d.ts +2 -0
- package/dist/src/app-opentui/scenes/family-domains/review.js +280 -0
- package/dist/src/app-opentui/scenes/family-domains/setup.d.ts +2 -0
- package/dist/src/app-opentui/scenes/family-domains/setup.js +267 -0
- package/dist/src/app-opentui/scenes/family-domains/stats.d.ts +2 -0
- package/dist/src/app-opentui/scenes/family-domains/stats.js +370 -0
- package/dist/src/app-opentui/scenes/family.d.ts +3 -0
- package/dist/src/app-opentui/scenes/family.js +2144 -0
- package/dist/src/app-opentui/scenes/fleet.js +552 -43
- package/dist/src/app-opentui/scenes/handoff.js +342 -35
- package/dist/src/app-opentui/scenes/help.js +640 -56
- package/dist/src/app-opentui/scenes/inbox.d.ts +2 -1
- package/dist/src/app-opentui/scenes/inbox.js +329 -21
- package/dist/src/app-opentui/scenes/init.d.ts +2 -1
- package/dist/src/app-opentui/scenes/init.js +120 -34
- package/dist/src/app-opentui/scenes/inspect.d.ts +3 -0
- package/dist/src/app-opentui/scenes/inspect.js +793 -0
- package/dist/src/app-opentui/scenes/main.d.ts +2 -1
- package/dist/src/app-opentui/scenes/main.js +264 -29
- package/dist/src/app-opentui/scenes/pi.d.ts +3 -0
- package/dist/src/app-opentui/scenes/pi.js +508 -0
- package/dist/src/app-opentui/scenes/plugin.d.ts +3 -0
- package/dist/src/app-opentui/scenes/plugin.js +486 -0
- package/dist/src/app-opentui/scenes/repo.d.ts +3 -0
- package/dist/src/app-opentui/scenes/repo.js +424 -0
- package/dist/src/app-opentui/scenes/run-detail.d.ts +2 -1
- package/dist/src/app-opentui/scenes/run-detail.js +362 -35
- package/dist/src/app-opentui/scenes/server.d.ts +2 -1
- package/dist/src/app-opentui/scenes/server.js +243 -26
- package/dist/src/app-opentui/scenes/tasks.js +518 -41
- package/dist/src/app-opentui/scenes/workspace.d.ts +3 -0
- package/dist/src/app-opentui/scenes/workspace.js +426 -0
- package/dist/src/app-opentui/selectable.d.ts +19 -0
- package/dist/src/app-opentui/selectable.js +79 -0
- package/dist/src/app-opentui/state.js +129 -36
- package/dist/src/app-opentui/surface-catalog.d.ts +20 -0
- package/dist/src/app-opentui/surface-catalog.js +540 -0
- package/dist/src/app-opentui/terminal-capabilities.d.ts +7 -0
- package/dist/src/app-opentui/terminal-capabilities.js +15 -0
- package/dist/src/app-opentui/theme.d.ts +28 -6
- package/dist/src/app-opentui/theme.js +61 -8
- package/dist/src/app-opentui/types.d.ts +130 -5
- package/dist/src/commands/_authority-runs.d.ts +1 -1
- package/dist/src/commands/_authority-runs.js +2 -12
- package/dist/src/commands/_doctor-checks.js +62 -13
- package/dist/src/commands/_help-catalog.js +95 -15
- package/dist/src/commands/_operator-view.js +97 -15
- package/dist/src/commands/_pi-frontend.d.ts +2 -0
- package/dist/src/commands/_pi-frontend.js +97 -13
- package/dist/src/commands/_preflight.js +64 -14
- package/dist/src/commands/_server-client.js +82 -18
- package/dist/src/commands/_server-events.d.ts +26 -0
- package/dist/src/commands/_server-events.js +310 -0
- package/dist/src/commands/_snapshot-upload.js +62 -13
- package/dist/src/commands/agent.js +2 -12
- package/dist/src/commands/connect.js +7 -1
- package/dist/src/commands/doctor.js +62 -13
- package/dist/src/commands/github.js +144 -23
- package/dist/src/commands/inbox.js +62 -13
- package/dist/src/commands/init.js +82 -18
- package/dist/src/commands/inspect.js +62 -13
- package/dist/src/commands/run.js +100 -15
- package/dist/src/commands/server.js +71 -26
- package/dist/src/commands/setup.js +62 -13
- package/dist/src/commands/stats.js +157 -28
- package/dist/src/commands/task-run-driver.js +64 -25
- package/dist/src/commands/task.js +196 -43
- package/dist/src/commands.js +419 -123
- package/dist/src/index.js +426 -130
- package/package.json +11 -10
- package/dist/src/app-opentui/render/image-visual-layer-native-canvas.d.ts +0 -2
- package/dist/src/app-opentui/render/image-visual-layer-native-canvas.js +0 -1484
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import type { AppAdapter } from "../types";
|
|
2
1
|
import { type AppAdapterContext } from "./common";
|
|
3
2
|
export type AppRunRecord = {
|
|
4
3
|
readonly runId: string;
|
|
@@ -12,5 +11,4 @@ export declare function normalizeRunRecord(record: Record<string, unknown>): App
|
|
|
12
11
|
export declare function refreshFleet(ctx: AppAdapterContext, options?: {
|
|
13
12
|
readonly limit?: number;
|
|
14
13
|
}): Promise<AppRunRecord[]>;
|
|
15
|
-
export declare function createFleetAdapter(): AppAdapter;
|
|
16
14
|
export declare function stopFleetRun(ctx: AppAdapterContext, runId: string): Promise<Record<string, unknown>>;
|
|
@@ -192,17 +192,21 @@ function setGitHubBearerTokenForCurrentProcess(token, projectRoot) {
|
|
|
192
192
|
const scopedKey = resolve2(projectRoot ?? process.cwd());
|
|
193
193
|
scopedGitHubBearerTokens.set(scopedKey, cleanToken(token ?? undefined));
|
|
194
194
|
}
|
|
195
|
-
function
|
|
195
|
+
function readRemoteAuthState(projectRoot) {
|
|
196
196
|
const path = resolve2(projectRoot, ".rig", "state", "github-auth.json");
|
|
197
197
|
if (!existsSync2(path))
|
|
198
198
|
return null;
|
|
199
199
|
try {
|
|
200
200
|
const parsed = JSON.parse(readFileSync2(path, "utf8"));
|
|
201
|
-
return
|
|
201
|
+
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
|
|
202
202
|
} catch {
|
|
203
203
|
return null;
|
|
204
204
|
}
|
|
205
205
|
}
|
|
206
|
+
function readPrivateRemoteSessionToken(projectRoot) {
|
|
207
|
+
const parsed = readRemoteAuthState(projectRoot);
|
|
208
|
+
return parsed ? cleanToken(typeof parsed.apiSessionToken === "string" ? parsed.apiSessionToken : typeof parsed.sessionToken === "string" ? parsed.sessionToken : undefined) : null;
|
|
209
|
+
}
|
|
206
210
|
function readGitHubBearerTokenForRemote(projectRoot) {
|
|
207
211
|
const scopedKey = resolve2(projectRoot);
|
|
208
212
|
if (scopedGitHubBearerTokens.has(scopedKey))
|
|
@@ -213,15 +217,25 @@ function readGitHubBearerTokenForRemote(projectRoot) {
|
|
|
213
217
|
return cleanToken(process.env.RIG_SERVER_AUTH_TOKEN) ?? cleanToken(process.env.RIG_REMOTE_AUTH_TOKEN);
|
|
214
218
|
}
|
|
215
219
|
function readStoredGitHubAuthToken(projectRoot) {
|
|
216
|
-
const
|
|
217
|
-
|
|
220
|
+
const parsed = readRemoteAuthState(projectRoot);
|
|
221
|
+
return parsed ? cleanToken(typeof parsed.token === "string" ? parsed.token : undefined) : null;
|
|
222
|
+
}
|
|
223
|
+
function inferRemoteServerProjectRootFromAuthState(projectRoot) {
|
|
224
|
+
const repo = readRepoConnection(projectRoot);
|
|
225
|
+
const slug = repo?.project?.trim();
|
|
226
|
+
if (!slug || !/^[^/]+\/[^/]+$/.test(slug))
|
|
218
227
|
return null;
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
228
|
+
const auth = readRemoteAuthState(projectRoot);
|
|
229
|
+
const authUpdatedAt = typeof auth?.updatedAt === "string" ? Date.parse(auth.updatedAt) : Number.NaN;
|
|
230
|
+
const repoLinkedAt = typeof repo?.linkedAt === "string" ? Date.parse(repo.linkedAt) : Number.NaN;
|
|
231
|
+
if (Number.isFinite(authUpdatedAt) && Number.isFinite(repoLinkedAt) && authUpdatedAt + 1000 < repoLinkedAt)
|
|
223
232
|
return null;
|
|
224
|
-
|
|
233
|
+
const checkoutBaseDir = typeof auth?.checkoutBaseDir === "string" && auth.checkoutBaseDir.trim() ? auth.checkoutBaseDir.trim() : null;
|
|
234
|
+
if (!checkoutBaseDir)
|
|
235
|
+
return null;
|
|
236
|
+
const inferred = `${checkoutBaseDir.replace(/\/+$/, "")}/${slug}`;
|
|
237
|
+
writeRepoServerProjectRoot(projectRoot, inferred);
|
|
238
|
+
return inferred;
|
|
225
239
|
}
|
|
226
240
|
function readLocalConnectionFallbackToken(projectRoot) {
|
|
227
241
|
return readGitHubBearerTokenForRemote(projectRoot) ?? cleanToken(process.env.RIG_GITHUB_TOKEN) ?? readStoredGitHubAuthToken(projectRoot);
|
|
@@ -232,7 +246,7 @@ async function ensureServerForCli(projectRoot) {
|
|
|
232
246
|
if (selected?.connection.kind === "remote") {
|
|
233
247
|
reportServerPhase(`Connecting to ${selected.alias}\u2026`);
|
|
234
248
|
const authToken = readGitHubBearerTokenForRemote(projectRoot);
|
|
235
|
-
const serverProjectRoot = selected.serverProjectRoot ?? await backfillRemoteServerProjectRoot(projectRoot, selected.connection.baseUrl, authToken);
|
|
249
|
+
const serverProjectRoot = selected.serverProjectRoot ?? inferRemoteServerProjectRootFromAuthState(projectRoot) ?? await backfillRemoteServerProjectRoot(projectRoot, selected.connection.baseUrl, authToken);
|
|
236
250
|
return {
|
|
237
251
|
baseUrl: selected.connection.baseUrl,
|
|
238
252
|
authToken,
|
|
@@ -261,7 +275,10 @@ async function backfillRemoteServerProjectRoot(projectRoot, baseUrl, authToken)
|
|
|
261
275
|
if (!slug)
|
|
262
276
|
return null;
|
|
263
277
|
try {
|
|
264
|
-
const
|
|
278
|
+
const url = new URL(`${baseUrl}/api/projects/${encodeURIComponent(slug)}`);
|
|
279
|
+
if (authToken && queryAuthFallbackEnabled())
|
|
280
|
+
url.searchParams.set("rt", authToken);
|
|
281
|
+
const response = await fetch(url, {
|
|
265
282
|
headers: mergeHeaders(undefined, authToken)
|
|
266
283
|
});
|
|
267
284
|
if (!response.ok)
|
|
@@ -288,10 +305,23 @@ function appendTaskFilterParams(url, filters) {
|
|
|
288
305
|
if (filters.limit !== undefined)
|
|
289
306
|
url.searchParams.set("limit", String(filters.limit));
|
|
290
307
|
}
|
|
308
|
+
function mergeCookie(existing, name, value) {
|
|
309
|
+
const encoded = `${name}=${encodeURIComponent(value)}`;
|
|
310
|
+
if (!existing?.trim())
|
|
311
|
+
return encoded;
|
|
312
|
+
const parts = existing.split(";").map((part) => part.trim()).filter((part) => part && !part.startsWith(`${name}=`));
|
|
313
|
+
return [...parts, encoded].join("; ");
|
|
314
|
+
}
|
|
315
|
+
function queryAuthFallbackEnabled(env = process.env) {
|
|
316
|
+
return env.RIG_ENABLE_QUERY_AUTH_FALLBACK === "1" || env.RIG_QUERY_AUTH_FALLBACK === "1";
|
|
317
|
+
}
|
|
291
318
|
function mergeHeaders(headers, authToken) {
|
|
292
319
|
const merged = new Headers(headers);
|
|
293
320
|
if (authToken) {
|
|
294
|
-
|
|
321
|
+
const bearer = `Bearer ${authToken}`;
|
|
322
|
+
merged.set("authorization", bearer);
|
|
323
|
+
merged.set("x-auth", bearer);
|
|
324
|
+
merged.set("cookie", mergeCookie(merged.get("cookie"), "rig_auth", authToken));
|
|
295
325
|
}
|
|
296
326
|
return merged;
|
|
297
327
|
}
|
|
@@ -351,15 +381,34 @@ async function buildServerFailureContext(projectRoot, server) {
|
|
|
351
381
|
hint: "Check the selected server with `rig server status`, or switch with `rig server use <alias|local>`."
|
|
352
382
|
};
|
|
353
383
|
}
|
|
384
|
+
function isLoopbackRemoteBaseUrl(baseUrl) {
|
|
385
|
+
try {
|
|
386
|
+
const host = new URL(baseUrl).hostname.toLowerCase();
|
|
387
|
+
return host === "localhost" || host === "127.0.0.1" || host === "::1" || host === "[::1]";
|
|
388
|
+
} catch {
|
|
389
|
+
return false;
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
function canUseRemoteWithoutProjectRoot(pathname) {
|
|
393
|
+
return pathname === "/health" || pathname === "/api/health" || pathname === "/api/server/status" || pathname === "/api/server/project-root" || pathname.startsWith("/api/github/auth/") || pathname === "/api/projects" || pathname.startsWith("/api/projects/");
|
|
394
|
+
}
|
|
354
395
|
async function requestServerJson(context, pathname, init = {}) {
|
|
355
396
|
const server = await ensureServerForCli(context.projectRoot);
|
|
397
|
+
const requestUrl = new URL(`${server.baseUrl}${pathname}`);
|
|
398
|
+
if (server.connectionKind === "remote" && !server.serverProjectRoot && !canUseRemoteWithoutProjectRoot(requestUrl.pathname) && (server.authToken || !isLoopbackRemoteBaseUrl(server.baseUrl))) {
|
|
399
|
+
const repo = readRepoConnection(context.projectRoot);
|
|
400
|
+
throw new CliError(`Remote server is selected for ${repo?.project ?? "this repo"}, but this checkout has no server-host project root link.`, 1, { hint: "Run `rig init --repair` or `rig init --yes --repo owner/repo --server remote` to repair the remote project link before task/run commands." });
|
|
401
|
+
}
|
|
356
402
|
const headers = mergeHeaders(init.headers, server.authToken);
|
|
357
403
|
if (server.serverProjectRoot)
|
|
358
404
|
headers.set("x-rig-project-root", server.serverProjectRoot);
|
|
405
|
+
if (server.connectionKind === "remote" && server.authToken && queryAuthFallbackEnabled()) {
|
|
406
|
+
requestUrl.searchParams.set("rt", server.authToken);
|
|
407
|
+
}
|
|
359
408
|
reportServerPhase(`${(init.method ?? "GET").toUpperCase()} ${pathname.split("?")[0]}\u2026`);
|
|
360
409
|
let response;
|
|
361
410
|
try {
|
|
362
|
-
response = await fetch(
|
|
411
|
+
response = await fetch(requestUrl, {
|
|
363
412
|
...init,
|
|
364
413
|
headers
|
|
365
414
|
});
|
|
@@ -421,11 +470,26 @@ async function getGitHubAuthStatusViaServer(context) {
|
|
|
421
470
|
return payload && typeof payload === "object" && !Array.isArray(payload) ? payload : {};
|
|
422
471
|
}
|
|
423
472
|
async function postGitHubTokenViaServer(context, token, options = {}) {
|
|
424
|
-
const
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
473
|
+
const server = await ensureServerForCli(context.projectRoot);
|
|
474
|
+
const requestUrl = new URL(`${server.baseUrl}/api/github/auth/token`);
|
|
475
|
+
reportServerPhase("POST /api/github/auth/token\u2026");
|
|
476
|
+
let response;
|
|
477
|
+
try {
|
|
478
|
+
response = await fetch(requestUrl, {
|
|
479
|
+
method: "POST",
|
|
480
|
+
headers: { "content-type": "application/json" },
|
|
481
|
+
body: JSON.stringify({ token, selectedRepo: options.selectedRepo, projectRoot: options.projectRoot ?? server.serverProjectRoot ?? undefined })
|
|
482
|
+
});
|
|
483
|
+
} catch (error) {
|
|
484
|
+
const failure = await buildServerFailureContext(context.projectRoot, server);
|
|
485
|
+
throw new CliError(`Rig server auth bootstrap failed: ${error instanceof Error ? error.message : String(error)}
|
|
486
|
+
${failure.contextLine}`, 1, { hint: failure.hint });
|
|
487
|
+
}
|
|
488
|
+
const payload = await response.json().catch(() => null);
|
|
489
|
+
if (!response.ok) {
|
|
490
|
+
const detail = payload && typeof payload === "object" && !Array.isArray(payload) ? String(payload.error ?? JSON.stringify(payload)) : `HTTP ${response.status}`;
|
|
491
|
+
throw new CliError(`Rig server auth bootstrap failed (${response.status}): ${detail}`, 1, { hint: "Re-run `rig github auth import-gh`, or check the selected server with `rig server status`." });
|
|
492
|
+
}
|
|
429
493
|
return payload && typeof payload === "object" && !Array.isArray(payload) ? payload : {};
|
|
430
494
|
}
|
|
431
495
|
async function prepareRemoteCheckoutViaServer(context, input) {
|
|
@@ -703,20 +767,11 @@ var init__server_client = __esm(() => {
|
|
|
703
767
|
});
|
|
704
768
|
|
|
705
769
|
// packages/cli/src/app-opentui/adapters/common.ts
|
|
706
|
-
function adapterContextFromRuntime(runtime, renderer) {
|
|
707
|
-
return {
|
|
708
|
-
projectRoot: runtime.getState().projectRoot,
|
|
709
|
-
renderer,
|
|
710
|
-
ensureRuntime: () => runtime.getRunnerContext(),
|
|
711
|
-
emit: (event) => runtime.emit(event),
|
|
712
|
-
getState: () => runtime.getState()
|
|
713
|
-
};
|
|
714
|
-
}
|
|
715
770
|
function projectRootOf(ctx) {
|
|
716
771
|
const root = ctx.rig?.projectRoot ?? ctx.projectRoot ?? ctx.getState().projectRoot;
|
|
717
772
|
if (typeof root === "string" && root.trim())
|
|
718
773
|
return root;
|
|
719
|
-
throw new Error("
|
|
774
|
+
throw new Error("App adapter requires a projectRoot.");
|
|
720
775
|
}
|
|
721
776
|
function normalizeAppError(error) {
|
|
722
777
|
const message = error instanceof Error ? error.message : String(error);
|
|
@@ -772,10 +827,6 @@ function compactRecord(record, keys) {
|
|
|
772
827
|
}
|
|
773
828
|
return out;
|
|
774
829
|
}
|
|
775
|
-
function payloadString(intent, key) {
|
|
776
|
-
const value = intent.action.payload?.[key];
|
|
777
|
-
return typeof value === "string" && value.trim() ? value.trim() : undefined;
|
|
778
|
-
}
|
|
779
830
|
|
|
780
831
|
// packages/cli/src/app-opentui/adapters/fleet.ts
|
|
781
832
|
function normalizeRunRecord(record) {
|
|
@@ -800,7 +851,7 @@ async function refreshFleet(ctx, options = {}) {
|
|
|
800
851
|
try {
|
|
801
852
|
const { listRunsViaServer: listRunsViaServer2, resolveServerConnectionLabel: resolveServerConnectionLabel2 } = await Promise.resolve().then(() => (init__server_client(), exports__server_client));
|
|
802
853
|
const projectRoot = projectRootOf(ctx);
|
|
803
|
-
emitProgress(ctx, label, "contacting selected
|
|
854
|
+
emitProgress(ctx, label, "contacting selected server");
|
|
804
855
|
const [runs, serverLabel] = await Promise.all([
|
|
805
856
|
listRunsViaServer2({ projectRoot }, { limit: options.limit ?? 50 }),
|
|
806
857
|
resolveServerConnectionLabel2(projectRoot)
|
|
@@ -809,7 +860,7 @@ async function refreshFleet(ctx, options = {}) {
|
|
|
809
860
|
const entry = normalizeRunRecord(run);
|
|
810
861
|
return entry ? [entry] : [];
|
|
811
862
|
});
|
|
812
|
-
patchData(ctx, { fleet: { runs: normalized, refreshedAt: new Date().toISOString() } });
|
|
863
|
+
patchData(ctx, { fleet: { runs: normalized, refreshedAt: new Date().toISOString() }, lastRefreshError: undefined });
|
|
813
864
|
patchFooter(ctx, { server: serverLabel, runs: String(normalized.length) });
|
|
814
865
|
emitCompleted(ctx, label, { count: normalized.length });
|
|
815
866
|
return normalized;
|
|
@@ -818,29 +869,6 @@ async function refreshFleet(ctx, options = {}) {
|
|
|
818
869
|
throw error;
|
|
819
870
|
}
|
|
820
871
|
}
|
|
821
|
-
function createFleetAdapter() {
|
|
822
|
-
return {
|
|
823
|
-
id: "fleet",
|
|
824
|
-
async handleIntent(runtime, intent) {
|
|
825
|
-
if (intent.scene !== "fleet" && intent.action.kind !== "run-stop")
|
|
826
|
-
return false;
|
|
827
|
-
const ctx = adapterContextFromRuntime(runtime);
|
|
828
|
-
if (intent.action.kind === "run-stop") {
|
|
829
|
-
const runId = payloadString(intent, "runId");
|
|
830
|
-
if (runId)
|
|
831
|
-
await stopFleetRun(ctx, runId);
|
|
832
|
-
else
|
|
833
|
-
await refreshFleet(ctx, { limit: 50 });
|
|
834
|
-
return true;
|
|
835
|
-
}
|
|
836
|
-
if (intent.action.kind === "refresh" || intent.action.kind === "navigate") {
|
|
837
|
-
await refreshFleet(ctx, { limit: 50 });
|
|
838
|
-
return true;
|
|
839
|
-
}
|
|
840
|
-
return false;
|
|
841
|
-
}
|
|
842
|
-
};
|
|
843
|
-
}
|
|
844
872
|
async function stopFleetRun(ctx, runId) {
|
|
845
873
|
const cleanRunId = runId.trim();
|
|
846
874
|
const label = `Stopping ${cleanRunId.slice(0, 8)}`;
|
|
@@ -859,7 +887,10 @@ async function stopFleetRun(ctx, runId) {
|
|
|
859
887
|
const { stopRunViaServer: stopRunViaServer2 } = await Promise.resolve().then(() => (init__server_client(), exports__server_client));
|
|
860
888
|
const result = await stopRunViaServer2({ projectRoot: projectRootOf(ctx) }, cleanRunId);
|
|
861
889
|
emitCompleted(ctx, label, { runId: cleanRunId, result: compactRecord(result, ["ok", "runId", "status", "stopped"]) });
|
|
862
|
-
await refreshFleet(ctx, { limit: 50 }).catch(() =>
|
|
890
|
+
await refreshFleet(ctx, { limit: 50 }).catch((error) => {
|
|
891
|
+
patchData(ctx, { lastRefreshError: normalizeAppError(error).message });
|
|
892
|
+
return [];
|
|
893
|
+
});
|
|
863
894
|
return result;
|
|
864
895
|
} catch (error) {
|
|
865
896
|
emitFailed(ctx, label, error, { runId: cleanRunId, revert: { status: "unknown" } });
|
|
@@ -869,6 +900,5 @@ async function stopFleetRun(ctx, runId) {
|
|
|
869
900
|
export {
|
|
870
901
|
stopFleetRun,
|
|
871
902
|
refreshFleet,
|
|
872
|
-
normalizeRunRecord
|
|
873
|
-
createFleetAdapter
|
|
903
|
+
normalizeRunRecord
|
|
874
904
|
};
|
|
@@ -1,7 +1,11 @@
|
|
|
1
|
-
import type { AppAdapter } from "../types";
|
|
2
1
|
import { type AppAdapterContext } from "./common";
|
|
3
|
-
export declare function createInboxAdapter(): AppAdapter;
|
|
4
2
|
export type AppInboxKind = "approvals" | "inputs";
|
|
3
|
+
/** One key/value fact extracted from the request payload (tool, command, an
|
|
4
|
+
* argument) so the operator sees WHAT they are approving, not just a glyph. */
|
|
5
|
+
export type AppInboxDetail = {
|
|
6
|
+
readonly label: string;
|
|
7
|
+
readonly value: string;
|
|
8
|
+
};
|
|
5
9
|
export type AppInboxRecord = {
|
|
6
10
|
readonly kind: AppInboxKind;
|
|
7
11
|
readonly runId: string;
|
|
@@ -9,6 +13,12 @@ export type AppInboxRecord = {
|
|
|
9
13
|
readonly taskId?: string;
|
|
10
14
|
readonly status: string;
|
|
11
15
|
readonly title: string;
|
|
16
|
+
/** Structured facts (tool name, command, args, prompt) pulled from the
|
|
17
|
+
* request payload — rendered under the title before the action rows. */
|
|
18
|
+
readonly details: readonly AppInboxDetail[];
|
|
19
|
+
/** A unified diff / multi-line preview from the payload, if present, so a
|
|
20
|
+
* blocking edit/patch is reviewed in full rather than approved blind. */
|
|
21
|
+
readonly diff?: string;
|
|
12
22
|
readonly raw: Record<string, unknown>;
|
|
13
23
|
};
|
|
14
24
|
export declare function normalizeInboxRecord(kind: AppInboxKind, record: Record<string, unknown>): AppInboxRecord | null;
|
|
@@ -455,17 +455,21 @@ function setGitHubBearerTokenForCurrentProcess(token, projectRoot) {
|
|
|
455
455
|
const scopedKey = resolve2(projectRoot ?? process.cwd());
|
|
456
456
|
scopedGitHubBearerTokens.set(scopedKey, cleanToken(token ?? undefined));
|
|
457
457
|
}
|
|
458
|
-
function
|
|
458
|
+
function readRemoteAuthState(projectRoot) {
|
|
459
459
|
const path = resolve2(projectRoot, ".rig", "state", "github-auth.json");
|
|
460
460
|
if (!existsSync2(path))
|
|
461
461
|
return null;
|
|
462
462
|
try {
|
|
463
463
|
const parsed = JSON.parse(readFileSync2(path, "utf8"));
|
|
464
|
-
return
|
|
464
|
+
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
|
|
465
465
|
} catch {
|
|
466
466
|
return null;
|
|
467
467
|
}
|
|
468
468
|
}
|
|
469
|
+
function readPrivateRemoteSessionToken(projectRoot) {
|
|
470
|
+
const parsed = readRemoteAuthState(projectRoot);
|
|
471
|
+
return parsed ? cleanToken(typeof parsed.apiSessionToken === "string" ? parsed.apiSessionToken : typeof parsed.sessionToken === "string" ? parsed.sessionToken : undefined) : null;
|
|
472
|
+
}
|
|
469
473
|
function readGitHubBearerTokenForRemote(projectRoot) {
|
|
470
474
|
const scopedKey = resolve2(projectRoot);
|
|
471
475
|
if (scopedGitHubBearerTokens.has(scopedKey))
|
|
@@ -476,15 +480,25 @@ function readGitHubBearerTokenForRemote(projectRoot) {
|
|
|
476
480
|
return cleanToken(process.env.RIG_SERVER_AUTH_TOKEN) ?? cleanToken(process.env.RIG_REMOTE_AUTH_TOKEN);
|
|
477
481
|
}
|
|
478
482
|
function readStoredGitHubAuthToken(projectRoot) {
|
|
479
|
-
const
|
|
480
|
-
|
|
483
|
+
const parsed = readRemoteAuthState(projectRoot);
|
|
484
|
+
return parsed ? cleanToken(typeof parsed.token === "string" ? parsed.token : undefined) : null;
|
|
485
|
+
}
|
|
486
|
+
function inferRemoteServerProjectRootFromAuthState(projectRoot) {
|
|
487
|
+
const repo = readRepoConnection(projectRoot);
|
|
488
|
+
const slug = repo?.project?.trim();
|
|
489
|
+
if (!slug || !/^[^/]+\/[^/]+$/.test(slug))
|
|
481
490
|
return null;
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
491
|
+
const auth = readRemoteAuthState(projectRoot);
|
|
492
|
+
const authUpdatedAt = typeof auth?.updatedAt === "string" ? Date.parse(auth.updatedAt) : Number.NaN;
|
|
493
|
+
const repoLinkedAt = typeof repo?.linkedAt === "string" ? Date.parse(repo.linkedAt) : Number.NaN;
|
|
494
|
+
if (Number.isFinite(authUpdatedAt) && Number.isFinite(repoLinkedAt) && authUpdatedAt + 1000 < repoLinkedAt)
|
|
486
495
|
return null;
|
|
487
|
-
|
|
496
|
+
const checkoutBaseDir = typeof auth?.checkoutBaseDir === "string" && auth.checkoutBaseDir.trim() ? auth.checkoutBaseDir.trim() : null;
|
|
497
|
+
if (!checkoutBaseDir)
|
|
498
|
+
return null;
|
|
499
|
+
const inferred = `${checkoutBaseDir.replace(/\/+$/, "")}/${slug}`;
|
|
500
|
+
writeRepoServerProjectRoot(projectRoot, inferred);
|
|
501
|
+
return inferred;
|
|
488
502
|
}
|
|
489
503
|
function readLocalConnectionFallbackToken(projectRoot) {
|
|
490
504
|
return readGitHubBearerTokenForRemote(projectRoot) ?? cleanToken(process.env.RIG_GITHUB_TOKEN) ?? readStoredGitHubAuthToken(projectRoot);
|
|
@@ -495,7 +509,7 @@ async function ensureServerForCli(projectRoot) {
|
|
|
495
509
|
if (selected?.connection.kind === "remote") {
|
|
496
510
|
reportServerPhase(`Connecting to ${selected.alias}\u2026`);
|
|
497
511
|
const authToken = readGitHubBearerTokenForRemote(projectRoot);
|
|
498
|
-
const serverProjectRoot = selected.serverProjectRoot ?? await backfillRemoteServerProjectRoot(projectRoot, selected.connection.baseUrl, authToken);
|
|
512
|
+
const serverProjectRoot = selected.serverProjectRoot ?? inferRemoteServerProjectRootFromAuthState(projectRoot) ?? await backfillRemoteServerProjectRoot(projectRoot, selected.connection.baseUrl, authToken);
|
|
499
513
|
return {
|
|
500
514
|
baseUrl: selected.connection.baseUrl,
|
|
501
515
|
authToken,
|
|
@@ -524,7 +538,10 @@ async function backfillRemoteServerProjectRoot(projectRoot, baseUrl, authToken)
|
|
|
524
538
|
if (!slug)
|
|
525
539
|
return null;
|
|
526
540
|
try {
|
|
527
|
-
const
|
|
541
|
+
const url = new URL(`${baseUrl}/api/projects/${encodeURIComponent(slug)}`);
|
|
542
|
+
if (authToken && queryAuthFallbackEnabled())
|
|
543
|
+
url.searchParams.set("rt", authToken);
|
|
544
|
+
const response = await fetch(url, {
|
|
528
545
|
headers: mergeHeaders(undefined, authToken)
|
|
529
546
|
});
|
|
530
547
|
if (!response.ok)
|
|
@@ -551,10 +568,23 @@ function appendTaskFilterParams(url, filters) {
|
|
|
551
568
|
if (filters.limit !== undefined)
|
|
552
569
|
url.searchParams.set("limit", String(filters.limit));
|
|
553
570
|
}
|
|
571
|
+
function mergeCookie(existing, name, value) {
|
|
572
|
+
const encoded = `${name}=${encodeURIComponent(value)}`;
|
|
573
|
+
if (!existing?.trim())
|
|
574
|
+
return encoded;
|
|
575
|
+
const parts = existing.split(";").map((part) => part.trim()).filter((part) => part && !part.startsWith(`${name}=`));
|
|
576
|
+
return [...parts, encoded].join("; ");
|
|
577
|
+
}
|
|
578
|
+
function queryAuthFallbackEnabled(env = process.env) {
|
|
579
|
+
return env.RIG_ENABLE_QUERY_AUTH_FALLBACK === "1" || env.RIG_QUERY_AUTH_FALLBACK === "1";
|
|
580
|
+
}
|
|
554
581
|
function mergeHeaders(headers, authToken) {
|
|
555
582
|
const merged = new Headers(headers);
|
|
556
583
|
if (authToken) {
|
|
557
|
-
|
|
584
|
+
const bearer = `Bearer ${authToken}`;
|
|
585
|
+
merged.set("authorization", bearer);
|
|
586
|
+
merged.set("x-auth", bearer);
|
|
587
|
+
merged.set("cookie", mergeCookie(merged.get("cookie"), "rig_auth", authToken));
|
|
558
588
|
}
|
|
559
589
|
return merged;
|
|
560
590
|
}
|
|
@@ -614,15 +644,34 @@ async function buildServerFailureContext(projectRoot, server) {
|
|
|
614
644
|
hint: "Check the selected server with `rig server status`, or switch with `rig server use <alias|local>`."
|
|
615
645
|
};
|
|
616
646
|
}
|
|
647
|
+
function isLoopbackRemoteBaseUrl(baseUrl) {
|
|
648
|
+
try {
|
|
649
|
+
const host = new URL(baseUrl).hostname.toLowerCase();
|
|
650
|
+
return host === "localhost" || host === "127.0.0.1" || host === "::1" || host === "[::1]";
|
|
651
|
+
} catch {
|
|
652
|
+
return false;
|
|
653
|
+
}
|
|
654
|
+
}
|
|
655
|
+
function canUseRemoteWithoutProjectRoot(pathname) {
|
|
656
|
+
return pathname === "/health" || pathname === "/api/health" || pathname === "/api/server/status" || pathname === "/api/server/project-root" || pathname.startsWith("/api/github/auth/") || pathname === "/api/projects" || pathname.startsWith("/api/projects/");
|
|
657
|
+
}
|
|
617
658
|
async function requestServerJson(context, pathname, init = {}) {
|
|
618
659
|
const server = await ensureServerForCli(context.projectRoot);
|
|
660
|
+
const requestUrl = new URL(`${server.baseUrl}${pathname}`);
|
|
661
|
+
if (server.connectionKind === "remote" && !server.serverProjectRoot && !canUseRemoteWithoutProjectRoot(requestUrl.pathname) && (server.authToken || !isLoopbackRemoteBaseUrl(server.baseUrl))) {
|
|
662
|
+
const repo = readRepoConnection(context.projectRoot);
|
|
663
|
+
throw new CliError(`Remote server is selected for ${repo?.project ?? "this repo"}, but this checkout has no server-host project root link.`, 1, { hint: "Run `rig init --repair` or `rig init --yes --repo owner/repo --server remote` to repair the remote project link before task/run commands." });
|
|
664
|
+
}
|
|
619
665
|
const headers = mergeHeaders(init.headers, server.authToken);
|
|
620
666
|
if (server.serverProjectRoot)
|
|
621
667
|
headers.set("x-rig-project-root", server.serverProjectRoot);
|
|
668
|
+
if (server.connectionKind === "remote" && server.authToken && queryAuthFallbackEnabled()) {
|
|
669
|
+
requestUrl.searchParams.set("rt", server.authToken);
|
|
670
|
+
}
|
|
622
671
|
reportServerPhase(`${(init.method ?? "GET").toUpperCase()} ${pathname.split("?")[0]}\u2026`);
|
|
623
672
|
let response;
|
|
624
673
|
try {
|
|
625
|
-
response = await fetch(
|
|
674
|
+
response = await fetch(requestUrl, {
|
|
626
675
|
...init,
|
|
627
676
|
headers
|
|
628
677
|
});
|
|
@@ -684,11 +733,26 @@ async function getGitHubAuthStatusViaServer(context) {
|
|
|
684
733
|
return payload && typeof payload === "object" && !Array.isArray(payload) ? payload : {};
|
|
685
734
|
}
|
|
686
735
|
async function postGitHubTokenViaServer(context, token, options = {}) {
|
|
687
|
-
const
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
736
|
+
const server = await ensureServerForCli(context.projectRoot);
|
|
737
|
+
const requestUrl = new URL(`${server.baseUrl}/api/github/auth/token`);
|
|
738
|
+
reportServerPhase("POST /api/github/auth/token\u2026");
|
|
739
|
+
let response;
|
|
740
|
+
try {
|
|
741
|
+
response = await fetch(requestUrl, {
|
|
742
|
+
method: "POST",
|
|
743
|
+
headers: { "content-type": "application/json" },
|
|
744
|
+
body: JSON.stringify({ token, selectedRepo: options.selectedRepo, projectRoot: options.projectRoot ?? server.serverProjectRoot ?? undefined })
|
|
745
|
+
});
|
|
746
|
+
} catch (error) {
|
|
747
|
+
const failure = await buildServerFailureContext(context.projectRoot, server);
|
|
748
|
+
throw new CliError(`Rig server auth bootstrap failed: ${error instanceof Error ? error.message : String(error)}
|
|
749
|
+
${failure.contextLine}`, 1, { hint: failure.hint });
|
|
750
|
+
}
|
|
751
|
+
const payload = await response.json().catch(() => null);
|
|
752
|
+
if (!response.ok) {
|
|
753
|
+
const detail = payload && typeof payload === "object" && !Array.isArray(payload) ? String(payload.error ?? JSON.stringify(payload)) : `HTTP ${response.status}`;
|
|
754
|
+
throw new CliError(`Rig server auth bootstrap failed (${response.status}): ${detail}`, 1, { hint: "Re-run `rig github auth import-gh`, or check the selected server with `rig server status`." });
|
|
755
|
+
}
|
|
692
756
|
return payload && typeof payload === "object" && !Array.isArray(payload) ? payload : {};
|
|
693
757
|
}
|
|
694
758
|
async function prepareRemoteCheckoutViaServer(context, input) {
|
|
@@ -1245,20 +1309,11 @@ var init_inbox = __esm(() => {
|
|
|
1245
1309
|
});
|
|
1246
1310
|
|
|
1247
1311
|
// packages/cli/src/app-opentui/adapters/common.ts
|
|
1248
|
-
function adapterContextFromRuntime(runtime, renderer) {
|
|
1249
|
-
return {
|
|
1250
|
-
projectRoot: runtime.getState().projectRoot,
|
|
1251
|
-
renderer,
|
|
1252
|
-
ensureRuntime: () => runtime.getRunnerContext(),
|
|
1253
|
-
emit: (event) => runtime.emit(event),
|
|
1254
|
-
getState: () => runtime.getState()
|
|
1255
|
-
};
|
|
1256
|
-
}
|
|
1257
1312
|
function projectRootOf(ctx) {
|
|
1258
1313
|
const root = ctx.rig?.projectRoot ?? ctx.projectRoot ?? ctx.getState().projectRoot;
|
|
1259
1314
|
if (typeof root === "string" && root.trim())
|
|
1260
1315
|
return root;
|
|
1261
|
-
throw new Error("
|
|
1316
|
+
throw new Error("App adapter requires a projectRoot.");
|
|
1262
1317
|
}
|
|
1263
1318
|
function normalizeAppError(error) {
|
|
1264
1319
|
const message = error instanceof Error ? error.message : String(error);
|
|
@@ -1305,56 +1360,52 @@ function stringField(record, keys, fallback = "") {
|
|
|
1305
1360
|
}
|
|
1306
1361
|
return fallback;
|
|
1307
1362
|
}
|
|
1308
|
-
function payloadString(intent, key) {
|
|
1309
|
-
const value = intent.action.payload?.[key];
|
|
1310
|
-
return typeof value === "string" && value.trim() ? value.trim() : undefined;
|
|
1311
|
-
}
|
|
1312
1363
|
|
|
1313
1364
|
// packages/cli/src/app-opentui/adapters/inbox.ts
|
|
1314
|
-
function
|
|
1315
|
-
return
|
|
1316
|
-
id: "inbox",
|
|
1317
|
-
async handleIntent(runtime, intent) {
|
|
1318
|
-
if (intent.scene !== "inbox" && !intent.action.kind.startsWith("inbox-"))
|
|
1319
|
-
return false;
|
|
1320
|
-
const ctx = adapterContextFromRuntime(runtime);
|
|
1321
|
-
if (intent.action.kind === "inbox-approve" || intent.action.kind === "inbox-reject") {
|
|
1322
|
-
const requestId = payloadString(intent, "requestId");
|
|
1323
|
-
let match = requestId ? findInboxRecord(ctx, "approvals", requestId) : null;
|
|
1324
|
-
if (requestId && !match)
|
|
1325
|
-
match = findInRecords((await refreshInbox(ctx)).approvals, requestId);
|
|
1326
|
-
if (requestId && match) {
|
|
1327
|
-
await resolveApproval(ctx, { runId: match.runId, requestId: match.requestId, decision: intent.action.kind === "inbox-approve" ? "approve" : "reject" });
|
|
1328
|
-
return true;
|
|
1329
|
-
}
|
|
1330
|
-
}
|
|
1331
|
-
if (intent.action.kind === "inbox-answer") {
|
|
1332
|
-
const requestId = payloadString(intent, "requestId");
|
|
1333
|
-
let match = requestId ? findInboxRecord(ctx, "inputs", requestId) : null;
|
|
1334
|
-
if (requestId && !match)
|
|
1335
|
-
match = findInRecords((await refreshInbox(ctx)).inputs, requestId);
|
|
1336
|
-
const answer = payloadString(intent, "answer");
|
|
1337
|
-
if (requestId && match && answer) {
|
|
1338
|
-
await answerInputRequest(ctx, { runId: match.runId, requestId: match.requestId, answers: { answer } });
|
|
1339
|
-
return true;
|
|
1340
|
-
}
|
|
1341
|
-
}
|
|
1342
|
-
await refreshInbox(ctx);
|
|
1343
|
-
return true;
|
|
1344
|
-
}
|
|
1345
|
-
};
|
|
1365
|
+
function asObject(value) {
|
|
1366
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
1346
1367
|
}
|
|
1347
|
-
function
|
|
1348
|
-
return
|
|
1368
|
+
function payloadOf(nested) {
|
|
1369
|
+
return asObject(nested.payload) ?? nested;
|
|
1349
1370
|
}
|
|
1350
|
-
function
|
|
1351
|
-
|
|
1352
|
-
if (!inbox || typeof inbox !== "object" || Array.isArray(inbox))
|
|
1371
|
+
function formatArgs(value) {
|
|
1372
|
+
if (value === undefined || value === null)
|
|
1353
1373
|
return null;
|
|
1354
|
-
|
|
1355
|
-
|
|
1374
|
+
if (typeof value === "string")
|
|
1375
|
+
return value.trim() ? value.trim().replace(/\s+/g, " ").slice(0, 200) : null;
|
|
1376
|
+
if (typeof value === "number" || typeof value === "boolean")
|
|
1377
|
+
return String(value);
|
|
1378
|
+
try {
|
|
1379
|
+
const json = JSON.stringify(value);
|
|
1380
|
+
return json && json !== "{}" && json !== "[]" ? json.slice(0, 200) : null;
|
|
1381
|
+
} catch {
|
|
1356
1382
|
return null;
|
|
1357
|
-
|
|
1383
|
+
}
|
|
1384
|
+
}
|
|
1385
|
+
function extractInboxFacts(kind, nested) {
|
|
1386
|
+
const payload = payloadOf(nested);
|
|
1387
|
+
const details = [];
|
|
1388
|
+
const tool = stringField(payload, ["toolName", "tool", "name", "action", "actionId"]) || stringField(nested, ["toolName", "tool", "requestKind", "actionId"]);
|
|
1389
|
+
if (tool)
|
|
1390
|
+
details.push({ label: "tool", value: tool });
|
|
1391
|
+
const command = stringField(payload, ["command", "cmd", "commandLine", "commandString", "shell", "script"]);
|
|
1392
|
+
if (command)
|
|
1393
|
+
details.push({ label: "command", value: command.replace(/\s+/g, " ").slice(0, 200) });
|
|
1394
|
+
const argsValue = payload.args ?? payload.arguments ?? payload.input ?? payload.params ?? payload.parameters;
|
|
1395
|
+
const args = formatArgs(argsValue);
|
|
1396
|
+
if (args)
|
|
1397
|
+
details.push({ label: "args", value: args });
|
|
1398
|
+
const path = stringField(payload, ["path", "file", "filePath", "target"]);
|
|
1399
|
+
if (path)
|
|
1400
|
+
details.push({ label: "path", value: path });
|
|
1401
|
+
const prompt = stringField(payload, ["prompt", "message", "reason", "question", "description"]) || stringField(nested, ["prompt", "message", "reason"]);
|
|
1402
|
+
if (prompt)
|
|
1403
|
+
details.push({ label: kind === "inputs" ? "prompt" : "reason", value: prompt.replace(/\s+/g, " ").slice(0, 240) });
|
|
1404
|
+
const diffRaw = stringField(payload, ["diff", "patch", "preview", "content"]);
|
|
1405
|
+
const diff = diffRaw && diffRaw.includes(`
|
|
1406
|
+
`) ? diffRaw : diffRaw || undefined;
|
|
1407
|
+
const title = tool && command ? `${tool} \xB7 ${command.replace(/\s+/g, " ").slice(0, 80)}` : command || tool || stringField(nested, ["title"]) || prompt || (kind === "approvals" ? "approval request" : "input request");
|
|
1408
|
+
return { title, details, ...diff ? { diff } : {} };
|
|
1358
1409
|
}
|
|
1359
1410
|
function normalizeInboxRecord(kind, record) {
|
|
1360
1411
|
const runId = stringField(record, ["runId"]);
|
|
@@ -1362,14 +1413,17 @@ function normalizeInboxRecord(kind, record) {
|
|
|
1362
1413
|
if (!runId || !requestId)
|
|
1363
1414
|
return null;
|
|
1364
1415
|
const taskId = stringField(record, ["taskId"]);
|
|
1365
|
-
const nested =
|
|
1416
|
+
const nested = asObject(record.record) ?? {};
|
|
1417
|
+
const facts = extractInboxFacts(kind, nested);
|
|
1366
1418
|
return {
|
|
1367
1419
|
kind,
|
|
1368
1420
|
runId,
|
|
1369
1421
|
requestId,
|
|
1370
1422
|
status: stringField(record, ["status"], "pending"),
|
|
1371
|
-
title:
|
|
1423
|
+
title: facts.title,
|
|
1424
|
+
details: facts.details,
|
|
1372
1425
|
raw: record,
|
|
1426
|
+
...facts.diff ? { diff: facts.diff } : {},
|
|
1373
1427
|
...taskId ? { taskId } : {}
|
|
1374
1428
|
};
|
|
1375
1429
|
}
|
|
@@ -1392,7 +1446,7 @@ async function refreshInbox(ctx, filters = {}) {
|
|
|
1392
1446
|
const normalized = normalizeInboxRecord("inputs", entry);
|
|
1393
1447
|
return normalized ? [normalized] : [];
|
|
1394
1448
|
});
|
|
1395
|
-
patchData(ctx, { inbox: { approvals, inputs, refreshedAt: new Date().toISOString() } });
|
|
1449
|
+
patchData(ctx, { inbox: { approvals, inputs, refreshedAt: new Date().toISOString() }, lastRefreshError: undefined });
|
|
1396
1450
|
patchFooter(ctx, { inbox: `${approvals.length + inputs.length} pending` });
|
|
1397
1451
|
emitCompleted(ctx, label, { approvals: approvals.length, inputs: inputs.length });
|
|
1398
1452
|
return { approvals, inputs };
|
|
@@ -1416,7 +1470,10 @@ async function resolveApproval(ctx, input) {
|
|
|
1416
1470
|
});
|
|
1417
1471
|
const record = result && typeof result === "object" && !Array.isArray(result) ? result : { ok: true };
|
|
1418
1472
|
emitCompleted(ctx, label, { runId: input.runId, requestId: input.requestId, decision: input.decision, result: record });
|
|
1419
|
-
await refreshInbox(ctx).catch(() =>
|
|
1473
|
+
await refreshInbox(ctx).catch((error) => {
|
|
1474
|
+
patchData(ctx, { lastRefreshError: normalizeAppError(error).message });
|
|
1475
|
+
return { approvals: [], inputs: [] };
|
|
1476
|
+
});
|
|
1420
1477
|
return record;
|
|
1421
1478
|
} catch (error) {
|
|
1422
1479
|
emitFailed(ctx, label, error, { runId: input.runId, requestId: input.requestId, revert: { status: "pending" } });
|
|
@@ -1438,7 +1495,10 @@ async function answerInputRequest(ctx, input) {
|
|
|
1438
1495
|
});
|
|
1439
1496
|
const record = result && typeof result === "object" && !Array.isArray(result) ? result : { ok: true };
|
|
1440
1497
|
emitCompleted(ctx, label, { runId: input.runId, requestId: input.requestId, result: record });
|
|
1441
|
-
await refreshInbox(ctx).catch(() =>
|
|
1498
|
+
await refreshInbox(ctx).catch((error) => {
|
|
1499
|
+
patchData(ctx, { lastRefreshError: normalizeAppError(error).message });
|
|
1500
|
+
return { approvals: [], inputs: [] };
|
|
1501
|
+
});
|
|
1442
1502
|
return record;
|
|
1443
1503
|
} catch (error) {
|
|
1444
1504
|
emitFailed(ctx, label, error, { runId: input.runId, requestId: input.requestId, revert: { status: "pending" } });
|
|
@@ -1449,6 +1509,5 @@ export {
|
|
|
1449
1509
|
resolveApproval,
|
|
1450
1510
|
refreshInbox,
|
|
1451
1511
|
normalizeInboxRecord,
|
|
1452
|
-
createInboxAdapter,
|
|
1453
1512
|
answerInputRequest
|
|
1454
1513
|
};
|