@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
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Interactive CLI is app-shell first.
3
+ *
4
+ * Native scenes handle the common surfaces (project menu, runs, tasks, inbox,
5
+ * server, init, doctor, Pi attach). Every other interactive command still
6
+ * enters OpenTUI and is executed inside an embedded plain-CLI PTY, preserving
7
+ * the exact existing options/actions/wizards without pretending unsupported
8
+ * commands were handled by a read-only scene. Machine/internal paths stay plain.
9
+ */
10
+ export declare function isOpenTuiAppCommand(argv: readonly string[], env?: NodeJS.ProcessEnv): boolean;
11
+ export declare function shouldLaunchTtyApp(input: {
12
+ readonly argv: readonly string[];
13
+ readonly stdoutIsTty?: boolean;
14
+ readonly stdinIsTty?: boolean;
15
+ readonly env?: NodeJS.ProcessEnv;
16
+ }): boolean;
@@ -0,0 +1,55 @@
1
+ // @bun
2
+ // packages/cli/src/app-opentui/launch-routing.ts
3
+ var GLOBAL_OPTIONS_WITH_VALUE = new Set(["--project", "--policy-mode", "--run-id"]);
4
+ var GLOBAL_FLAGS = new Set(["--dry-run"]);
5
+ function envTruthy(value) {
6
+ if (!value)
7
+ return false;
8
+ const normalized = value.trim().toLowerCase();
9
+ return normalized !== "0" && normalized !== "false" && normalized !== "no";
10
+ }
11
+ function stripGlobalAppOptions(argv) {
12
+ const rest = [];
13
+ for (let index = 0;index < argv.length; index += 1) {
14
+ const arg = argv[index];
15
+ if (GLOBAL_FLAGS.has(arg))
16
+ continue;
17
+ if (GLOBAL_OPTIONS_WITH_VALUE.has(arg)) {
18
+ index += 1;
19
+ continue;
20
+ }
21
+ rest.push(arg);
22
+ }
23
+ return rest;
24
+ }
25
+ function isOpenTuiAppCommand(argv, env = process.env) {
26
+ const commandArgv = stripGlobalAppOptions(argv);
27
+ const [group = "", command = ""] = commandArgv;
28
+ const normalizedGroup = group.toLowerCase();
29
+ const normalizedCommand = command.toLowerCase();
30
+ if (!normalizedGroup)
31
+ return true;
32
+ if (normalizedGroup === "__opentui-pi-host" || normalizedGroup === "__rig-server")
33
+ return false;
34
+ if (normalizedGroup === "server" && normalizedCommand === "task-run")
35
+ return false;
36
+ if (normalizedGroup === "server" && normalizedCommand === "start" && env.RIG_SERVER_INTERNAL_EXEC === "1")
37
+ return false;
38
+ return true;
39
+ }
40
+ function shouldLaunchTtyApp(input) {
41
+ const env = input.env ?? process.env;
42
+ if (input.argv.includes("--json"))
43
+ return false;
44
+ if (env.RIG_CLI_PLAIN_HELP === "1" || env.RIG_PLAIN === "1")
45
+ return false;
46
+ if (envTruthy(env.CI))
47
+ return false;
48
+ if (!isOpenTuiAppCommand(input.argv, env))
49
+ return false;
50
+ return Boolean(input.stdoutIsTty && input.stdinIsTty);
51
+ }
52
+ export {
53
+ shouldLaunchTtyApp,
54
+ isOpenTuiAppCommand
55
+ };
@@ -8,7 +8,14 @@ export type StageLayout = {
8
8
  readonly typeBarTop: number;
9
9
  readonly footerTop: number;
10
10
  readonly compact: boolean;
11
+ /** Raw terminal is below the usable threshold; render a guidance message
12
+ * instead of a scene that would clip into nothing (#18). */
13
+ readonly tooSmall: boolean;
11
14
  };
15
+ /** Below these raw dimensions, ad-terminal panels collapse below their 4×4
16
+ * floor and the UI would blank silently. We show a "resize me" card instead. */
17
+ export declare const MIN_TERMINAL_WIDTH = 48;
18
+ export declare const MIN_TERMINAL_HEIGHT = 16;
12
19
  export declare function computeStageLayout(width: number, height: number): StageLayout;
13
20
  export declare function visibleWidth(text: string): number;
14
21
  export declare function alignText(text: string, width: number, align?: "left" | "center" | "right"): string;
@@ -1,17 +1,22 @@
1
1
  // @bun
2
2
  // packages/cli/src/app-opentui/layout.ts
3
+ var MIN_TERMINAL_WIDTH = 48;
4
+ var MIN_TERMINAL_HEIGHT = 16;
3
5
  function computeStageLayout(width, height) {
4
- const safeWidth = Math.max(40, Math.trunc(width || 80));
5
- const safeHeight = Math.max(18, Math.trunc(height || 24));
6
+ const rawWidth = Math.trunc(width || 80);
7
+ const rawHeight = Math.trunc(height || 24);
8
+ const tooSmall = rawWidth < MIN_TERMINAL_WIDTH || rawHeight < MIN_TERMINAL_HEIGHT;
9
+ const safeWidth = Math.max(40, rawWidth);
10
+ const safeHeight = Math.max(18, rawHeight);
6
11
  const compact = safeWidth < 92 || safeHeight < 30;
7
12
  const horizontalGutter = compact ? 1 : 2;
8
13
  const centerWidth = Math.max(36, safeWidth - horizontalGutter * 2);
9
14
  const centerLeft = horizontalGutter;
10
- const typeBarTop = Math.max(0, safeHeight - 3);
11
15
  const footerTop = Math.max(0, safeHeight - 1);
16
+ const typeBarTop = Math.max(0, footerTop - 1);
12
17
  const centerTop = compact ? 1 : Math.max(1, Math.floor(safeHeight * 0.055));
13
- const centerHeight = Math.max(8, typeBarTop - centerTop - 1);
14
- return { width: safeWidth, height: safeHeight, centerWidth, centerLeft, centerTop, centerHeight, typeBarTop, footerTop, compact };
18
+ const centerHeight = Math.max(6, typeBarTop - centerTop);
19
+ return { width: safeWidth, height: safeHeight, centerWidth, centerLeft, centerTop, centerHeight, typeBarTop, footerTop, compact, tooSmall };
15
20
  }
16
21
  function visibleWidth(text) {
17
22
  return [...text].length;
@@ -40,5 +45,7 @@ export {
40
45
  visibleWidth,
41
46
  truncateText,
42
47
  computeStageLayout,
43
- alignText
48
+ alignText,
49
+ MIN_TERMINAL_WIDTH,
50
+ MIN_TERMINAL_HEIGHT
44
51
  };
@@ -6,3 +6,27 @@ export declare function listSearchQuery(state: AppState): string;
6
6
  export declare function filterRunsForSearch(runs: readonly AppRunRecord[], query: string): AppRunRecord[];
7
7
  export declare function filterTasksForSearch(tasks: readonly AppTaskRecord[], query: string): AppTaskRecord[];
8
8
  export declare function searchSummary(kind: "runs" | "tasks", query: string, visible: number, total: number): string;
9
+ export type SortDir = "asc" | "desc";
10
+ export type RunSortKey = "status" | "runId" | "title" | "age";
11
+ export type RunSortSpec = {
12
+ readonly key: RunSortKey;
13
+ readonly dir: SortDir;
14
+ };
15
+ export type TaskSortKey = "status" | "id" | "priority" | "assignee" | "title";
16
+ export type TaskSortSpec = {
17
+ readonly key: TaskSortKey;
18
+ readonly dir: SortDir;
19
+ };
20
+ /** Read a typed run sort spec off the data bag, narrowing the `unknown` slice. */
21
+ export declare function runSortSpec(value: unknown): RunSortSpec | null;
22
+ /** Read a typed task sort spec off the data bag, narrowing the `unknown` slice. */
23
+ export declare function taskSortSpec(value: unknown): TaskSortSpec | null;
24
+ /** Cycle a column's sort: clicking the active column flips asc→desc→default;
25
+ * clicking a new column starts it ascending. `null` means "back to default". */
26
+ export declare function cycleRunSort(current: RunSortSpec | null, key: RunSortKey): RunSortSpec | null;
27
+ export declare function cycleTaskSort(current: TaskSortSpec | null, key: TaskSortKey): TaskSortSpec | null;
28
+ /** Sort runs by a column. `spec === null` returns the input order unchanged. */
29
+ export declare function sortRuns(runs: readonly AppRunRecord[], spec: RunSortSpec | null): AppRunRecord[];
30
+ /** Sort tasks by a column, client-side over already-fetched records. `spec ===
31
+ * null` returns the input order unchanged (server/adapter order is preserved). */
32
+ export declare function sortTasks(tasks: readonly AppTaskRecord[], spec: TaskSortSpec | null): AppTaskRecord[];
@@ -34,10 +34,97 @@ function filterTasksForSearch(tasks, query) {
34
34
  function searchSummary(kind, query, visible, total) {
35
35
  return query.trim() ? `search ${JSON.stringify(query)} \xB7 ${visible}/${total} ${kind}` : `${total} ${kind}`;
36
36
  }
37
+ function runSortSpec(value) {
38
+ if (!value || typeof value !== "object" || Array.isArray(value))
39
+ return null;
40
+ const record = value;
41
+ const key = record.key;
42
+ const dir = record.dir;
43
+ if ((key === "status" || key === "runId" || key === "title" || key === "age") && (dir === "asc" || dir === "desc")) {
44
+ return { key, dir };
45
+ }
46
+ return null;
47
+ }
48
+ function taskSortSpec(value) {
49
+ if (!value || typeof value !== "object" || Array.isArray(value))
50
+ return null;
51
+ const record = value;
52
+ const key = record.key;
53
+ const dir = record.dir;
54
+ if ((key === "status" || key === "id" || key === "priority" || key === "assignee" || key === "title") && (dir === "asc" || dir === "desc")) {
55
+ return { key, dir };
56
+ }
57
+ return null;
58
+ }
59
+ function cycleRunSort(current, key) {
60
+ if (!current || current.key !== key)
61
+ return { key, dir: "asc" };
62
+ if (current.dir === "asc")
63
+ return { key, dir: "desc" };
64
+ return null;
65
+ }
66
+ function cycleTaskSort(current, key) {
67
+ if (!current || current.key !== key)
68
+ return { key, dir: "asc" };
69
+ if (current.dir === "asc")
70
+ return { key, dir: "desc" };
71
+ return null;
72
+ }
73
+ function ageValue(updatedAt) {
74
+ const parsed = Date.parse(updatedAt ?? "");
75
+ return Number.isFinite(parsed) ? parsed : 0;
76
+ }
77
+ function applyDir(rows, compare, dir) {
78
+ const sorted = [...rows].sort(compare);
79
+ return dir === "desc" ? sorted.reverse() : sorted;
80
+ }
81
+ function sortRuns(runs, spec) {
82
+ if (!spec)
83
+ return [...runs];
84
+ const { key, dir } = spec;
85
+ if (key === "age") {
86
+ const byNewest = applyDir(runs, (a, b) => ageValue(b.updatedAt) - ageValue(a.updatedAt) || a.runId.localeCompare(b.runId), "asc");
87
+ return dir === "asc" ? byNewest : [...byNewest].reverse();
88
+ }
89
+ const compare = (a, b) => {
90
+ if (key === "status")
91
+ return a.status.localeCompare(b.status) || a.runId.localeCompare(b.runId);
92
+ if (key === "title")
93
+ return a.title.localeCompare(b.title, undefined, { sensitivity: "base" }) || a.runId.localeCompare(b.runId);
94
+ return a.runId.localeCompare(b.runId, undefined, { numeric: true });
95
+ };
96
+ return applyDir(runs, compare, dir);
97
+ }
98
+ function sortTasks(tasks, spec) {
99
+ if (!spec)
100
+ return [...tasks];
101
+ const { key, dir } = spec;
102
+ const compare = (a, b) => {
103
+ if (key === "status")
104
+ return a.status.localeCompare(b.status) || a.id.localeCompare(b.id, undefined, { numeric: true });
105
+ if (key === "priority") {
106
+ const left = a.priority ?? Number.NEGATIVE_INFINITY;
107
+ const right = b.priority ?? Number.NEGATIVE_INFINITY;
108
+ return right - left || a.id.localeCompare(b.id, undefined, { numeric: true });
109
+ }
110
+ if (key === "assignee")
111
+ return (a.assignees[0] ?? "").localeCompare(b.assignees[0] ?? "") || a.id.localeCompare(b.id, undefined, { numeric: true });
112
+ if (key === "title")
113
+ return a.title.localeCompare(b.title, undefined, { sensitivity: "base" }) || a.id.localeCompare(b.id, undefined, { numeric: true });
114
+ return a.id.localeCompare(b.id, undefined, { numeric: true });
115
+ };
116
+ return applyDir(tasks, compare, dir);
117
+ }
37
118
  export {
119
+ taskSortSpec,
120
+ sortTasks,
121
+ sortRuns,
38
122
  searchSummary,
123
+ runSortSpec,
39
124
  listSearchQuery,
40
125
  isListSearchScene,
41
126
  filterTasksForSearch,
42
- filterRunsForSearch
127
+ filterRunsForSearch,
128
+ cycleTaskSort,
129
+ cycleRunSort
43
130
  };
@@ -143,17 +143,21 @@ function cleanToken(value) {
143
143
  const trimmed = value?.trim();
144
144
  return trimmed ? trimmed : null;
145
145
  }
146
- function readPrivateRemoteSessionToken(projectRoot) {
146
+ function readRemoteAuthState(projectRoot) {
147
147
  const path = resolve2(projectRoot, ".rig", "state", "github-auth.json");
148
148
  if (!existsSync2(path))
149
149
  return null;
150
150
  try {
151
151
  const parsed = JSON.parse(readFileSync2(path, "utf8"));
152
- return cleanToken(typeof parsed.apiSessionToken === "string" ? parsed.apiSessionToken : typeof parsed.sessionToken === "string" ? parsed.sessionToken : undefined);
152
+ return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
153
153
  } catch {
154
154
  return null;
155
155
  }
156
156
  }
157
+ function readPrivateRemoteSessionToken(projectRoot) {
158
+ const parsed = readRemoteAuthState(projectRoot);
159
+ return parsed ? cleanToken(typeof parsed.apiSessionToken === "string" ? parsed.apiSessionToken : typeof parsed.sessionToken === "string" ? parsed.sessionToken : undefined) : null;
160
+ }
157
161
  function readGitHubBearerTokenForRemote(projectRoot) {
158
162
  const scopedKey = resolve2(projectRoot);
159
163
  if (scopedGitHubBearerTokens.has(scopedKey))
@@ -164,15 +168,25 @@ function readGitHubBearerTokenForRemote(projectRoot) {
164
168
  return cleanToken(process.env.RIG_SERVER_AUTH_TOKEN) ?? cleanToken(process.env.RIG_REMOTE_AUTH_TOKEN);
165
169
  }
166
170
  function readStoredGitHubAuthToken(projectRoot) {
167
- const path = resolve2(projectRoot, ".rig", "state", "github-auth.json");
168
- if (!existsSync2(path))
171
+ const parsed = readRemoteAuthState(projectRoot);
172
+ return parsed ? cleanToken(typeof parsed.token === "string" ? parsed.token : undefined) : null;
173
+ }
174
+ function inferRemoteServerProjectRootFromAuthState(projectRoot) {
175
+ const repo = readRepoConnection(projectRoot);
176
+ const slug = repo?.project?.trim();
177
+ if (!slug || !/^[^/]+\/[^/]+$/.test(slug))
169
178
  return null;
170
- try {
171
- const parsed = JSON.parse(readFileSync2(path, "utf8"));
172
- return cleanToken(typeof parsed.token === "string" ? parsed.token : undefined);
173
- } catch {
179
+ const auth = readRemoteAuthState(projectRoot);
180
+ const authUpdatedAt = typeof auth?.updatedAt === "string" ? Date.parse(auth.updatedAt) : Number.NaN;
181
+ const repoLinkedAt = typeof repo?.linkedAt === "string" ? Date.parse(repo.linkedAt) : Number.NaN;
182
+ if (Number.isFinite(authUpdatedAt) && Number.isFinite(repoLinkedAt) && authUpdatedAt + 1000 < repoLinkedAt)
174
183
  return null;
175
- }
184
+ const checkoutBaseDir = typeof auth?.checkoutBaseDir === "string" && auth.checkoutBaseDir.trim() ? auth.checkoutBaseDir.trim() : null;
185
+ if (!checkoutBaseDir)
186
+ return null;
187
+ const inferred = `${checkoutBaseDir.replace(/\/+$/, "")}/${slug}`;
188
+ writeRepoServerProjectRoot(projectRoot, inferred);
189
+ return inferred;
176
190
  }
177
191
  function readLocalConnectionFallbackToken(projectRoot) {
178
192
  return readGitHubBearerTokenForRemote(projectRoot) ?? cleanToken(process.env.RIG_GITHUB_TOKEN) ?? readStoredGitHubAuthToken(projectRoot);
@@ -183,7 +197,7 @@ async function ensureServerForCli(projectRoot) {
183
197
  if (selected?.connection.kind === "remote") {
184
198
  reportServerPhase(`Connecting to ${selected.alias}\u2026`);
185
199
  const authToken = readGitHubBearerTokenForRemote(projectRoot);
186
- const serverProjectRoot = selected.serverProjectRoot ?? await backfillRemoteServerProjectRoot(projectRoot, selected.connection.baseUrl, authToken);
200
+ const serverProjectRoot = selected.serverProjectRoot ?? inferRemoteServerProjectRootFromAuthState(projectRoot) ?? await backfillRemoteServerProjectRoot(projectRoot, selected.connection.baseUrl, authToken);
187
201
  return {
188
202
  baseUrl: selected.connection.baseUrl,
189
203
  authToken,
@@ -212,7 +226,10 @@ async function backfillRemoteServerProjectRoot(projectRoot, baseUrl, authToken)
212
226
  if (!slug)
213
227
  return null;
214
228
  try {
215
- const response = await fetch(`${baseUrl}/api/projects/${encodeURIComponent(slug)}`, {
229
+ const url = new URL(`${baseUrl}/api/projects/${encodeURIComponent(slug)}`);
230
+ if (authToken && queryAuthFallbackEnabled())
231
+ url.searchParams.set("rt", authToken);
232
+ const response = await fetch(url, {
216
233
  headers: mergeHeaders(undefined, authToken)
217
234
  });
218
235
  if (!response.ok)
@@ -229,10 +246,23 @@ async function backfillRemoteServerProjectRoot(projectRoot, baseUrl, authToken)
229
246
  return null;
230
247
  }
231
248
  }
249
+ function mergeCookie(existing, name, value) {
250
+ const encoded = `${name}=${encodeURIComponent(value)}`;
251
+ if (!existing?.trim())
252
+ return encoded;
253
+ const parts = existing.split(";").map((part) => part.trim()).filter((part) => part && !part.startsWith(`${name}=`));
254
+ return [...parts, encoded].join("; ");
255
+ }
256
+ function queryAuthFallbackEnabled(env = process.env) {
257
+ return env.RIG_ENABLE_QUERY_AUTH_FALLBACK === "1" || env.RIG_QUERY_AUTH_FALLBACK === "1";
258
+ }
232
259
  function mergeHeaders(headers, authToken) {
233
260
  const merged = new Headers(headers);
234
261
  if (authToken) {
235
- merged.set("authorization", `Bearer ${authToken}`);
262
+ const bearer = `Bearer ${authToken}`;
263
+ merged.set("authorization", bearer);
264
+ merged.set("x-auth", bearer);
265
+ merged.set("cookie", mergeCookie(merged.get("cookie"), "rig_auth", authToken));
236
266
  }
237
267
  return merged;
238
268
  }
@@ -293,15 +323,34 @@ async function buildServerFailureContext(projectRoot, server) {
293
323
  hint: "Check the selected server with `rig server status`, or switch with `rig server use <alias|local>`."
294
324
  };
295
325
  }
326
+ function isLoopbackRemoteBaseUrl(baseUrl) {
327
+ try {
328
+ const host = new URL(baseUrl).hostname.toLowerCase();
329
+ return host === "localhost" || host === "127.0.0.1" || host === "::1" || host === "[::1]";
330
+ } catch {
331
+ return false;
332
+ }
333
+ }
334
+ function canUseRemoteWithoutProjectRoot(pathname) {
335
+ 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/");
336
+ }
296
337
  async function requestServerJson(context, pathname, init = {}) {
297
338
  const server = await ensureServerForCli(context.projectRoot);
339
+ const requestUrl = new URL(`${server.baseUrl}${pathname}`);
340
+ if (server.connectionKind === "remote" && !server.serverProjectRoot && !canUseRemoteWithoutProjectRoot(requestUrl.pathname) && (server.authToken || !isLoopbackRemoteBaseUrl(server.baseUrl))) {
341
+ const repo = readRepoConnection(context.projectRoot);
342
+ 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." });
343
+ }
298
344
  const headers = mergeHeaders(init.headers, server.authToken);
299
345
  if (server.serverProjectRoot)
300
346
  headers.set("x-rig-project-root", server.serverProjectRoot);
347
+ if (server.connectionKind === "remote" && server.authToken && queryAuthFallbackEnabled()) {
348
+ requestUrl.searchParams.set("rt", server.authToken);
349
+ }
301
350
  reportServerPhase(`${(init.method ?? "GET").toUpperCase()} ${pathname.split("?")[0]}\u2026`);
302
351
  let response;
303
352
  try {
304
- response = await fetch(`${server.baseUrl}${pathname}`, {
353
+ response = await fetch(requestUrl, {
305
354
  ...init,
306
355
  headers
307
356
  });
@@ -538,6 +587,14 @@ async function withSpinner(label, work, options = {}) {
538
587
  }
539
588
 
540
589
  // packages/cli/src/commands/_pi-frontend.ts
590
+ var TERMINAL_RUN_STATUSES = new Set(["completed", "failed", "stopped", "cancelled", "canceled", "closed", "merged", "needs_attention", "needs-attention"]);
591
+
592
+ class OperatorTranscriptUnavailableError extends Error {
593
+ constructor(message) {
594
+ super(message);
595
+ this.name = "OperatorTranscriptUnavailableError";
596
+ }
597
+ }
541
598
  function setTemporaryEnv(updates) {
542
599
  const previous = new Map;
543
600
  for (const [key, value] of Object.entries(updates)) {
@@ -565,6 +622,23 @@ function buildOperatorPiEnv(input) {
565
622
  ...input.serverProjectRoot ? { RIG_PROJECT_ROOT: input.serverProjectRoot } : {}
566
623
  };
567
624
  }
625
+ function shouldRequireOperatorTranscript(status) {
626
+ return typeof status === "string" && TERMINAL_RUN_STATUSES.has(status.trim().toLowerCase());
627
+ }
628
+ function missingOperatorTranscriptMessage(runId, status) {
629
+ const shortRun = runId.trim().slice(0, 8) || "unknown";
630
+ const statusText = typeof status === "string" && status.trim() ? status.trim() : "terminal";
631
+ return `Run ${shortRun} is ${statusText}, but no worker Pi session transcript is recorded for this run. It likely failed before Pi started or predates full-session capture. Use \`rig run show ${runId}\` and \`rig run logs ${runId}\` for the lifecycle details.`;
632
+ }
633
+ function statusFromRunDetails(run) {
634
+ if (!run || typeof run !== "object" || Array.isArray(run))
635
+ return;
636
+ const record = run;
637
+ if (typeof record.status === "string")
638
+ return record.status;
639
+ const nested = record.run;
640
+ return nested && typeof nested === "object" && !Array.isArray(nested) ? nested.status : undefined;
641
+ }
568
642
  async function prepareOperatorConsole(context, runId, tempSessionDir) {
569
643
  const server = await ensureServerForCli(context.projectRoot);
570
644
  const localCwd = join(homedir2(), ".rig", "drones", runId.slice(0, 8));
@@ -594,6 +668,13 @@ async function prepareOperatorConsole(context, runId, tempSessionDir) {
594
668
  sessionFileArg = ["--session", localSessionPath];
595
669
  }
596
670
  } catch {}
671
+ if (sessionFileArg.length === 0) {
672
+ const run = await getRunDetailsViaServer(context, runId).catch(() => null);
673
+ const status = statusFromRunDetails(run);
674
+ if (shouldRequireOperatorTranscript(status)) {
675
+ throw new OperatorTranscriptUnavailableError(missingOperatorTranscriptMessage(runId, status));
676
+ }
677
+ }
597
678
  return { server, sessionFileArg };
598
679
  }
599
680
  var RIG_PI_THEME = {
@@ -711,6 +792,7 @@ async function attachRunBundledPiFrontend(context, input) {
711
792
  let detached = false;
712
793
  try {
713
794
  await runPiMain([
795
+ "--offline",
714
796
  "--no-extensions",
715
797
  "--no-skills",
716
798
  "--no-prompt-templates",
@@ -751,9 +833,9 @@ function parseArgs(argv) {
751
833
  const runId = takeOption(argv, "--run-id")?.trim();
752
834
  const projectRoot = takeOption(argv, "--project-root")?.trim();
753
835
  if (!runId)
754
- throw new Error("Missing --run-id for Rig Pi host child.");
836
+ throw new Error("Missing --run-id for Pi host child.");
755
837
  if (!projectRoot)
756
- throw new Error("Missing --project-root for Rig Pi host child.");
838
+ throw new Error("Missing --project-root for Pi host child.");
757
839
  return { runId, projectRoot };
758
840
  }
759
841
  async function runOpenTuiPiHostChild(argv = process.argv.slice(2)) {
@@ -765,9 +847,9 @@ if (import.meta.main) {
765
847
  try {
766
848
  await runOpenTuiPiHostChild();
767
849
  } catch (error) {
768
- const message = error instanceof Error ? error.stack || error.message : String(error);
850
+ const message = error instanceof Error ? error.name === "OperatorTranscriptUnavailableError" ? error.message : error.stack || error.message : String(error);
769
851
  process.stderr.write(`
770
- Rig Pi host failed:
852
+ Pi host failed:
771
853
  ${message}
772
854
  `);
773
855
  process.exit(1);
@@ -1,5 +1,14 @@
1
1
  import { StyledText } from "@opentui/core";
2
2
  export type PiPtyHostStatus = "starting" | "running" | "exited" | "failed";
3
+ /**
4
+ * Temporary embedded-Pi presentation contract.
5
+ *
6
+ * The worker/remote Pi daemon still owns tools, skills, cwd, model, session and
7
+ * context. This local host only mirrors a PTY/xterm viewport into selectable
8
+ * OpenTUI text. Keep this snapshot path explicit until Rig grows a dedicated
9
+ * PTY/xterm viewport renderable or deliberately suspends OpenTUI for direct Pi
10
+ * terminal ownership.
11
+ */
3
12
  export type PiPtyHostSnapshot = {
4
13
  readonly runId: string;
5
14
  readonly status: PiPtyHostStatus;
@@ -8,6 +17,7 @@ export type PiPtyHostSnapshot = {
8
17
  readonly lines: readonly string[];
9
18
  readonly styledLines?: readonly StyledText[];
10
19
  readonly message?: string;
20
+ readonly resizeError?: string;
11
21
  readonly exitCode?: number;
12
22
  readonly signal?: string | null;
13
23
  };
@@ -40,9 +50,13 @@ export declare class PiPtyHost {
40
50
  private cols;
41
51
  private rows;
42
52
  private message;
53
+ private lastResizeError;
43
54
  private exitCode;
44
55
  private signal;
45
56
  private notifyTimer;
57
+ /** Last streamed buffer content, so the onWriteParsed handler only emits a
58
+ * snapshot when the rendered content actually changed. */
59
+ private lastStreamKey;
46
60
  private _disposed;
47
61
  constructor(options: PiPtyHostOptions);
48
62
  get disposed(): boolean;
@@ -8,8 +8,8 @@ var MIN_COLS = 40;
8
8
  var MIN_ROWS = 12;
9
9
  var MAX_ROWS = 300;
10
10
  var MAX_SNAPSHOT_LINES = 360;
11
- var STYLED_SNAPSHOT_MARGIN = 24;
12
- var SNAPSHOT_DELAY_MS = 33;
11
+ var STYLED_SNAPSHOT_MARGIN = 6;
12
+ var SNAPSHOT_DELAY_MS = 120;
13
13
  var fallbackChildScriptPath = fileURLToPath(new URL("./pi-host-child.ts", import.meta.url));
14
14
  var activeHost = null;
15
15
  function clampCols(cols) {
@@ -107,17 +107,15 @@ function lineToStyledText(line, cols) {
107
107
  function childCommandPrefix() {
108
108
  const execName = basename(process.execPath).toLowerCase();
109
109
  const currentEntry = process.argv[1];
110
- if ((execName === "bun" || execName === "bun.exe") && currentEntry) {
111
- return [process.execPath, currentEntry, "__opentui-pi-host"];
110
+ if (execName === "bun" || execName === "bun.exe") {
111
+ return currentEntry ? [process.execPath, currentEntry, "__opentui-pi-host"] : [process.execPath, fallbackChildScriptPath];
112
112
  }
113
- if (currentEntry)
114
- return [process.execPath, "__opentui-pi-host"];
115
- return [process.execPath, fallbackChildScriptPath];
113
+ return [process.execPath, "__opentui-pi-host"];
116
114
  }
117
115
  function withEnv(base) {
118
116
  const env = {};
119
117
  for (const [key, value] of Object.entries(base ?? process.env)) {
120
- if (key === "RIG_PLAIN" || key === "RIG_CLI_PLAIN_HELP")
118
+ if (key === "RIG_PLAIN" || key === "RIG_CLI_PLAIN_HELP" || key === "NO_COLOR")
121
119
  continue;
122
120
  if (typeof value === "string")
123
121
  env[key] = value;
@@ -160,9 +158,11 @@ class PiPtyHost {
160
158
  cols;
161
159
  rows;
162
160
  message = "starting bundled Pi";
161
+ lastResizeError = null;
163
162
  exitCode;
164
163
  signal;
165
164
  notifyTimer = null;
165
+ lastStreamKey = "";
166
166
  _disposed = false;
167
167
  constructor(options) {
168
168
  this.runId = options.runId;
@@ -176,9 +176,20 @@ class PiPtyHost {
176
176
  allowProposedApi: true,
177
177
  cols: this.cols,
178
178
  rows: this.rows,
179
- scrollback: 5000
179
+ scrollback: 1000
180
180
  });
181
181
  this.registerTerminalResponders();
182
+ this.disposables.push(this.terminal.onWriteParsed(() => {
183
+ if (this._disposed)
184
+ return;
185
+ const snapshot = this.createSnapshot();
186
+ const key = snapshot.lines.join(`
187
+ `);
188
+ if (key === this.lastStreamKey)
189
+ return;
190
+ this.lastStreamKey = key;
191
+ this.onSnapshot?.(snapshot);
192
+ }));
182
193
  }
183
194
  get disposed() {
184
195
  return this._disposed;
@@ -190,7 +201,7 @@ class PiPtyHost {
190
201
  if (this._disposed)
191
202
  throw new Error("Pi PTY host is disposed.");
192
203
  if (typeof Bun.Terminal !== "function") {
193
- throw new Error("Bun native PTY is unavailable in this runtime. Rig OpenTUI Pi host requires Bun.Terminal.");
204
+ throw new Error("Bun native PTY is unavailable in this runtime. Pi host requires Bun.Terminal.");
194
205
  }
195
206
  const spawnOptions = {
196
207
  cwd: this.projectRoot,
@@ -214,7 +225,7 @@ class PiPtyHost {
214
225
  this.proc = proc;
215
226
  this.pty = proc.terminal;
216
227
  this.status = "running";
217
- this.message = "bundled Pi running inside Rig";
228
+ this.message = "bundled Pi running inside this app";
218
229
  this.emitSnapshotSoon(0);
219
230
  proc.exited.then((exitCode) => {
220
231
  if (this._disposed)
@@ -265,7 +276,10 @@ class PiPtyHost {
265
276
  this.terminal.resize(nextCols, nextRows);
266
277
  try {
267
278
  this.pty?.resize(nextCols, nextRows);
268
- } catch {}
279
+ this.lastResizeError = null;
280
+ } catch (error) {
281
+ this.lastResizeError = error instanceof Error ? error.message : String(error);
282
+ }
269
283
  this.emitSnapshotSoon(0);
270
284
  }
271
285
  detach() {
@@ -307,7 +321,7 @@ class PiPtyHost {
307
321
  return;
308
322
  const text = this.decoder.decode(data, { stream: true });
309
323
  this.respondToRawTerminalQueries(text);
310
- this.terminal.write(data, () => this.emitSnapshotSoon());
324
+ this.terminal.write(data);
311
325
  }
312
326
  emitSnapshotSoon(delayMs = SNAPSHOT_DELAY_MS) {
313
327
  if (this._disposed || this.notifyTimer)
@@ -336,6 +350,7 @@ class PiPtyHost {
336
350
  lines.push("");
337
351
  styledLines[lines.length - 1] = new StyledText([{ __isChunk: true, text: "" }]);
338
352
  }
353
+ const resolvedMessage = this.lastResizeError ? `resize degraded: ${this.lastResizeError}` : message;
339
354
  return {
340
355
  runId: this.runId,
341
356
  status: this.status,
@@ -343,7 +358,8 @@ class PiPtyHost {
343
358
  rows: this.rows,
344
359
  lines,
345
360
  styledLines,
346
- message,
361
+ message: resolvedMessage,
362
+ ...this.lastResizeError ? { resizeError: this.lastResizeError } : {},
347
363
  ...this.exitCode !== undefined ? { exitCode: this.exitCode } : {},
348
364
  ...this.signal !== undefined ? { signal: this.signal } : {}
349
365
  };
@@ -0,0 +1,9 @@
1
+ import { computeStageLayout } from "../layout";
2
+ import { entryIntentForScene } from "../runtime";
3
+ import { PRIMARY_NAV } from "./nav";
4
+ import type { AppSceneFrame, AppSceneId, AppState } from "../types";
5
+ type SceneRenderer = (state: AppState, layout: ReturnType<typeof computeStageLayout>) => AppSceneFrame;
6
+ export declare function App(props: {
7
+ sceneRenderers?: Partial<Record<AppSceneId, SceneRenderer>>;
8
+ }): React.ReactNode;
9
+ export { PRIMARY_NAV, entryIntentForScene };