@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.
Files changed (206) hide show
  1. package/dist/bin/build-rig-binaries.js +40 -8
  2. package/dist/bin/rig.js +23402 -14577
  3. package/dist/src/app/board.js +217 -41
  4. package/dist/src/app-opentui/adapters/command.d.ts +2 -0
  5. package/dist/src/app-opentui/adapters/command.js +329 -0
  6. package/dist/src/app-opentui/adapters/common.js +2 -2
  7. package/dist/src/app-opentui/adapters/doctor.d.ts +0 -2
  8. package/dist/src/app-opentui/adapters/doctor.js +64 -39
  9. package/dist/src/app-opentui/adapters/family.d.ts +62 -0
  10. package/dist/src/app-opentui/adapters/family.js +14305 -0
  11. package/dist/src/app-opentui/adapters/fleet.d.ts +0 -2
  12. package/dist/src/app-opentui/adapters/fleet.js +90 -60
  13. package/dist/src/app-opentui/adapters/inbox.d.ts +12 -2
  14. package/dist/src/app-opentui/adapters/inbox.js +137 -78
  15. package/dist/src/app-opentui/adapters/init.d.ts +0 -2
  16. package/dist/src/app-opentui/adapters/init.js +85 -47
  17. package/dist/src/app-opentui/adapters/inspect.d.ts +52 -0
  18. package/dist/src/app-opentui/adapters/inspect.js +1024 -0
  19. package/dist/src/app-opentui/adapters/pi-attach.d.ts +15 -6
  20. package/dist/src/app-opentui/adapters/pi-attach.js +442 -125
  21. package/dist/src/app-opentui/adapters/pi.d.ts +23 -0
  22. package/dist/src/app-opentui/adapters/pi.js +363 -0
  23. package/dist/src/app-opentui/adapters/plugin.d.ts +84 -0
  24. package/dist/src/app-opentui/adapters/plugin.js +544 -0
  25. package/dist/src/app-opentui/adapters/repo.d.ts +37 -0
  26. package/dist/src/app-opentui/adapters/repo.js +186 -0
  27. package/dist/src/app-opentui/adapters/run-detail.d.ts +9 -2
  28. package/dist/src/app-opentui/adapters/run-detail.js +180 -63
  29. package/dist/src/app-opentui/adapters/server.d.ts +10 -2
  30. package/dist/src/app-opentui/adapters/server.js +191 -45
  31. package/dist/src/app-opentui/adapters/tasks.d.ts +11 -2
  32. package/dist/src/app-opentui/adapters/tasks.js +1123 -143
  33. package/dist/src/app-opentui/adapters/workspace.d.ts +49 -0
  34. package/dist/src/app-opentui/adapters/workspace.js +333 -0
  35. package/dist/src/app-opentui/autocomplete.d.ts +20 -0
  36. package/dist/src/app-opentui/autocomplete.js +576 -0
  37. package/dist/src/app-opentui/bootstrap.d.ts +1 -6
  38. package/dist/src/app-opentui/bootstrap.js +25252 -16474
  39. package/dist/src/app-opentui/command-palette.d.ts +3 -0
  40. package/dist/src/app-opentui/command-palette.js +1010 -0
  41. package/dist/src/app-opentui/command-pty-host.d.ts +62 -0
  42. package/dist/src/app-opentui/command-pty-host.js +248 -0
  43. package/dist/src/app-opentui/drone.js +8 -6
  44. package/dist/src/app-opentui/events.js +1 -1
  45. package/dist/src/app-opentui/fleet-stats.d.ts +32 -0
  46. package/dist/src/app-opentui/fleet-stats.js +114 -0
  47. package/dist/src/app-opentui/focus-manager.d.ts +14 -0
  48. package/dist/src/app-opentui/focus-manager.js +24 -0
  49. package/dist/src/app-opentui/index.js +5431 -2797
  50. package/dist/src/app-opentui/intent.js +179 -50
  51. package/dist/src/app-opentui/keymap.d.ts +21 -0
  52. package/dist/src/app-opentui/keymap.js +1748 -0
  53. package/dist/src/app-opentui/launch-routing.d.ts +16 -0
  54. package/dist/src/app-opentui/launch-routing.js +55 -0
  55. package/dist/src/app-opentui/layout.d.ts +7 -0
  56. package/dist/src/app-opentui/layout.js +13 -6
  57. package/dist/src/app-opentui/list-search.d.ts +24 -0
  58. package/dist/src/app-opentui/list-search.js +88 -1
  59. package/dist/src/app-opentui/pi-host-child.js +99 -17
  60. package/dist/src/app-opentui/pi-pty-host.d.ts +14 -0
  61. package/dist/src/app-opentui/pi-pty-host.js +30 -14
  62. package/dist/src/app-opentui/react/App.d.ts +9 -0
  63. package/dist/src/app-opentui/react/App.js +5144 -0
  64. package/dist/src/app-opentui/react/Backdrop.d.ts +5 -0
  65. package/dist/src/app-opentui/react/Backdrop.js +1834 -0
  66. package/dist/src/app-opentui/react/ChromeHost.d.ts +5 -0
  67. package/dist/src/app-opentui/react/ChromeHost.js +2942 -0
  68. package/dist/src/app-opentui/react/SceneFrameView.d.ts +7 -0
  69. package/dist/src/app-opentui/react/SceneFrameView.js +529 -0
  70. package/dist/src/app-opentui/react/context.d.ts +17 -0
  71. package/dist/src/app-opentui/react/context.js +37 -0
  72. package/dist/src/app-opentui/react/launch.d.ts +2 -0
  73. package/dist/src/app-opentui/react/launch.js +5743 -0
  74. package/dist/src/app-opentui/react/nav.d.ts +18 -0
  75. package/dist/src/app-opentui/react/nav.js +54 -0
  76. package/dist/src/app-opentui/react/scroll.d.ts +12 -0
  77. package/dist/src/app-opentui/react/scroll.js +21 -0
  78. package/dist/src/app-opentui/react/syntax.d.ts +2 -0
  79. package/dist/src/app-opentui/react/syntax.js +64 -0
  80. package/dist/src/app-opentui/registry.js +20428 -4828
  81. package/dist/src/app-opentui/render/ascii-fleet.d.ts +15 -0
  82. package/dist/src/app-opentui/render/ascii-fleet.js +82 -0
  83. package/dist/src/app-opentui/render/constants.d.ts +31 -0
  84. package/dist/src/app-opentui/render/constants.js +66 -0
  85. package/dist/src/app-opentui/render/graphics.d.ts +2 -1
  86. package/dist/src/app-opentui/render/graphics.js +228 -46
  87. package/dist/src/app-opentui/render/image-visual-layer-worker.js +469 -930
  88. package/dist/src/app-opentui/render/image-visual-layer.d.ts +25 -10
  89. package/dist/src/app-opentui/render/image-visual-layer.js +448 -329
  90. package/dist/src/app-opentui/render/native-host.d.ts +37 -0
  91. package/dist/src/app-opentui/render/native-host.js +179 -0
  92. package/dist/src/app-opentui/render/panel-layout.d.ts +38 -0
  93. package/dist/src/app-opentui/render/panel-layout.js +48 -0
  94. package/dist/src/app-opentui/render/panels.d.ts +2 -0
  95. package/dist/src/app-opentui/render/panels.js +78 -38
  96. package/dist/src/app-opentui/render/preloader.d.ts +10 -0
  97. package/dist/src/app-opentui/render/preloader.js +165 -0
  98. package/dist/src/app-opentui/render/scene.d.ts +53 -1
  99. package/dist/src/app-opentui/render/scene.js +195 -6
  100. package/dist/src/app-opentui/render/text.d.ts +7 -1
  101. package/dist/src/app-opentui/render/text.js +15 -8
  102. package/dist/src/app-opentui/render/type-bar.d.ts +2 -1
  103. package/dist/src/app-opentui/render/type-bar.js +113 -39
  104. package/dist/src/app-opentui/runtime-resources.d.ts +16 -0
  105. package/dist/src/app-opentui/runtime-resources.js +62 -0
  106. package/dist/src/app-opentui/runtime.d.ts +44 -1
  107. package/dist/src/app-opentui/runtime.js +5415 -2738
  108. package/dist/src/app-opentui/scenes/command.d.ts +3 -0
  109. package/dist/src/app-opentui/scenes/command.js +117 -0
  110. package/dist/src/app-opentui/scenes/doctor.d.ts +2 -1
  111. package/dist/src/app-opentui/scenes/doctor.js +221 -17
  112. package/dist/src/app-opentui/scenes/error.js +60 -20
  113. package/dist/src/app-opentui/scenes/family-domains/agent.d.ts +2 -0
  114. package/dist/src/app-opentui/scenes/family-domains/agent.js +348 -0
  115. package/dist/src/app-opentui/scenes/family-domains/browser.d.ts +2 -0
  116. package/dist/src/app-opentui/scenes/family-domains/browser.js +195 -0
  117. package/dist/src/app-opentui/scenes/family-domains/dist.d.ts +2 -0
  118. package/dist/src/app-opentui/scenes/family-domains/dist.js +243 -0
  119. package/dist/src/app-opentui/scenes/family-domains/git.d.ts +2 -0
  120. package/dist/src/app-opentui/scenes/family-domains/git.js +195 -0
  121. package/dist/src/app-opentui/scenes/family-domains/github.d.ts +2 -0
  122. package/dist/src/app-opentui/scenes/family-domains/github.js +274 -0
  123. package/dist/src/app-opentui/scenes/family-domains/harness.d.ts +2 -0
  124. package/dist/src/app-opentui/scenes/family-domains/harness.js +152 -0
  125. package/dist/src/app-opentui/scenes/family-domains/index.d.ts +4 -0
  126. package/dist/src/app-opentui/scenes/family-domains/index.js +1679 -0
  127. package/dist/src/app-opentui/scenes/family-domains/kit.d.ts +76 -0
  128. package/dist/src/app-opentui/scenes/family-domains/kit.js +305 -0
  129. package/dist/src/app-opentui/scenes/family-domains/profile.d.ts +2 -0
  130. package/dist/src/app-opentui/scenes/family-domains/profile.js +212 -0
  131. package/dist/src/app-opentui/scenes/family-domains/queue.d.ts +2 -0
  132. package/dist/src/app-opentui/scenes/family-domains/queue.js +146 -0
  133. package/dist/src/app-opentui/scenes/family-domains/remote.d.ts +2 -0
  134. package/dist/src/app-opentui/scenes/family-domains/remote.js +518 -0
  135. package/dist/src/app-opentui/scenes/family-domains/review.d.ts +2 -0
  136. package/dist/src/app-opentui/scenes/family-domains/review.js +280 -0
  137. package/dist/src/app-opentui/scenes/family-domains/setup.d.ts +2 -0
  138. package/dist/src/app-opentui/scenes/family-domains/setup.js +267 -0
  139. package/dist/src/app-opentui/scenes/family-domains/stats.d.ts +2 -0
  140. package/dist/src/app-opentui/scenes/family-domains/stats.js +370 -0
  141. package/dist/src/app-opentui/scenes/family.d.ts +3 -0
  142. package/dist/src/app-opentui/scenes/family.js +2144 -0
  143. package/dist/src/app-opentui/scenes/fleet.js +552 -43
  144. package/dist/src/app-opentui/scenes/handoff.js +342 -35
  145. package/dist/src/app-opentui/scenes/help.js +640 -56
  146. package/dist/src/app-opentui/scenes/inbox.d.ts +2 -1
  147. package/dist/src/app-opentui/scenes/inbox.js +329 -21
  148. package/dist/src/app-opentui/scenes/init.d.ts +2 -1
  149. package/dist/src/app-opentui/scenes/init.js +120 -34
  150. package/dist/src/app-opentui/scenes/inspect.d.ts +3 -0
  151. package/dist/src/app-opentui/scenes/inspect.js +793 -0
  152. package/dist/src/app-opentui/scenes/main.d.ts +2 -1
  153. package/dist/src/app-opentui/scenes/main.js +264 -29
  154. package/dist/src/app-opentui/scenes/pi.d.ts +3 -0
  155. package/dist/src/app-opentui/scenes/pi.js +508 -0
  156. package/dist/src/app-opentui/scenes/plugin.d.ts +3 -0
  157. package/dist/src/app-opentui/scenes/plugin.js +486 -0
  158. package/dist/src/app-opentui/scenes/repo.d.ts +3 -0
  159. package/dist/src/app-opentui/scenes/repo.js +424 -0
  160. package/dist/src/app-opentui/scenes/run-detail.d.ts +2 -1
  161. package/dist/src/app-opentui/scenes/run-detail.js +362 -35
  162. package/dist/src/app-opentui/scenes/server.d.ts +2 -1
  163. package/dist/src/app-opentui/scenes/server.js +243 -26
  164. package/dist/src/app-opentui/scenes/tasks.js +518 -41
  165. package/dist/src/app-opentui/scenes/workspace.d.ts +3 -0
  166. package/dist/src/app-opentui/scenes/workspace.js +426 -0
  167. package/dist/src/app-opentui/selectable.d.ts +19 -0
  168. package/dist/src/app-opentui/selectable.js +79 -0
  169. package/dist/src/app-opentui/state.js +129 -36
  170. package/dist/src/app-opentui/surface-catalog.d.ts +20 -0
  171. package/dist/src/app-opentui/surface-catalog.js +540 -0
  172. package/dist/src/app-opentui/terminal-capabilities.d.ts +7 -0
  173. package/dist/src/app-opentui/terminal-capabilities.js +15 -0
  174. package/dist/src/app-opentui/theme.d.ts +28 -6
  175. package/dist/src/app-opentui/theme.js +61 -8
  176. package/dist/src/app-opentui/types.d.ts +130 -5
  177. package/dist/src/commands/_authority-runs.d.ts +1 -1
  178. package/dist/src/commands/_authority-runs.js +2 -12
  179. package/dist/src/commands/_doctor-checks.js +62 -13
  180. package/dist/src/commands/_help-catalog.js +95 -15
  181. package/dist/src/commands/_operator-view.js +97 -15
  182. package/dist/src/commands/_pi-frontend.d.ts +2 -0
  183. package/dist/src/commands/_pi-frontend.js +97 -13
  184. package/dist/src/commands/_preflight.js +64 -14
  185. package/dist/src/commands/_server-client.js +82 -18
  186. package/dist/src/commands/_server-events.d.ts +26 -0
  187. package/dist/src/commands/_server-events.js +310 -0
  188. package/dist/src/commands/_snapshot-upload.js +62 -13
  189. package/dist/src/commands/agent.js +2 -12
  190. package/dist/src/commands/connect.js +7 -1
  191. package/dist/src/commands/doctor.js +62 -13
  192. package/dist/src/commands/github.js +144 -23
  193. package/dist/src/commands/inbox.js +62 -13
  194. package/dist/src/commands/init.js +82 -18
  195. package/dist/src/commands/inspect.js +62 -13
  196. package/dist/src/commands/run.js +100 -15
  197. package/dist/src/commands/server.js +71 -26
  198. package/dist/src/commands/setup.js +62 -13
  199. package/dist/src/commands/stats.js +157 -28
  200. package/dist/src/commands/task-run-driver.js +64 -25
  201. package/dist/src/commands/task.js +196 -43
  202. package/dist/src/commands.js +419 -123
  203. package/dist/src/index.js +426 -130
  204. package/package.json +11 -10
  205. package/dist/src/app-opentui/render/image-visual-layer-native-canvas.d.ts +0 -2
  206. 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 readPrivateRemoteSessionToken(projectRoot) {
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 cleanToken(typeof parsed.apiSessionToken === "string" ? parsed.apiSessionToken : typeof parsed.sessionToken === "string" ? parsed.sessionToken : undefined);
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 path = resolve2(projectRoot, ".rig", "state", "github-auth.json");
217
- if (!existsSync2(path))
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
- try {
220
- const parsed = JSON.parse(readFileSync2(path, "utf8"));
221
- return cleanToken(typeof parsed.token === "string" ? parsed.token : undefined);
222
- } catch {
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 response = await fetch(`${baseUrl}/api/projects/${encodeURIComponent(slug)}`, {
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
- merged.set("authorization", `Bearer ${authToken}`);
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(`${server.baseUrl}${pathname}`, {
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 payload = await requestServerJson(context, "/api/github/auth/token", {
425
- method: "POST",
426
- headers: { "content-type": "application/json" },
427
- body: JSON.stringify({ token, selectedRepo: options.selectedRepo, projectRoot: options.projectRoot })
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("Rig app adapter requires a projectRoot.");
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 Rig server");
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 readPrivateRemoteSessionToken(projectRoot) {
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 cleanToken(typeof parsed.apiSessionToken === "string" ? parsed.apiSessionToken : typeof parsed.sessionToken === "string" ? parsed.sessionToken : undefined);
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 path = resolve2(projectRoot, ".rig", "state", "github-auth.json");
480
- if (!existsSync2(path))
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
- try {
483
- const parsed = JSON.parse(readFileSync2(path, "utf8"));
484
- return cleanToken(typeof parsed.token === "string" ? parsed.token : undefined);
485
- } catch {
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 response = await fetch(`${baseUrl}/api/projects/${encodeURIComponent(slug)}`, {
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
- merged.set("authorization", `Bearer ${authToken}`);
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(`${server.baseUrl}${pathname}`, {
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 payload = await requestServerJson(context, "/api/github/auth/token", {
688
- method: "POST",
689
- headers: { "content-type": "application/json" },
690
- body: JSON.stringify({ token, selectedRepo: options.selectedRepo, projectRoot: options.projectRoot })
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("Rig app adapter requires a projectRoot.");
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 createInboxAdapter() {
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 findInRecords(records, requestId) {
1348
- return records.find((record) => record.requestId === requestId || record.requestId.startsWith(requestId)) ?? null;
1368
+ function payloadOf(nested) {
1369
+ return asObject(nested.payload) ?? nested;
1349
1370
  }
1350
- function findInboxRecord(ctx, kind, requestId) {
1351
- const inbox = ctx.getState().data?.inbox;
1352
- if (!inbox || typeof inbox !== "object" || Array.isArray(inbox))
1371
+ function formatArgs(value) {
1372
+ if (value === undefined || value === null)
1353
1373
  return null;
1354
- const records = inbox[kind];
1355
- if (!Array.isArray(records))
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
- return findInRecords(records, requestId);
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 = record.record && typeof record.record === "object" && !Array.isArray(record.record) ? record.record : {};
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: stringField(nested, ["title", "prompt", "message", "toolName"], kind === "approvals" ? "approval request" : "input request"),
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(() => ({ approvals: [], inputs: [] }));
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(() => ({ approvals: [], inputs: [] }));
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
  };
@@ -1,6 +1,4 @@
1
- import type { AppAdapter } from "../types";
2
1
  import { type AppAdapterContext } from "./common";
3
- export declare function createInitAdapter(): AppAdapter;
4
2
  export type InitFactState = {
5
3
  readonly hasConfig: boolean;
6
4
  readonly configPath?: string;