@pellux/goodvibes-tui 2.0.21 → 2.1.1

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 (391) hide show
  1. package/CHANGELOG.md +65 -1
  2. package/README.md +30 -29
  3. package/docs/README.md +8 -5
  4. package/docs/foundation-artifacts/operator-contract.json +1 -1
  5. package/package.json +28 -19
  6. package/src/cli/management.ts +5 -2
  7. package/src/cli/tui-startup.ts +34 -39
  8. package/src/core/agent-view-render.ts +157 -0
  9. package/src/core/approval-alert.ts +49 -11
  10. package/src/core/bookmark-navigation.ts +7 -1
  11. package/src/core/budget-breach-notifier.ts +27 -8
  12. package/src/core/compaction-receipt.ts +1 -1
  13. package/src/core/context-usage.ts +1 -1
  14. package/src/core/conversation-compaction-render.ts +3 -3
  15. package/src/core/conversation-display-only.ts +86 -0
  16. package/src/core/conversation-event-navigation.ts +27 -0
  17. package/src/core/conversation-line-cache.ts +216 -447
  18. package/src/core/conversation-render-context.ts +20 -27
  19. package/src/core/conversation-rendering.ts +157 -575
  20. package/src/core/conversation-splash-state.ts +6 -1
  21. package/src/core/conversation-types.ts +35 -0
  22. package/src/core/conversation-usage.ts +12 -0
  23. package/src/core/conversation.ts +130 -131
  24. package/src/core/long-task-notifier.ts +100 -31
  25. package/src/core/notices.ts +75 -0
  26. package/src/core/pairing-tailscale-gateway.ts +1 -1
  27. package/src/core/process-output-log.ts +143 -0
  28. package/src/core/rewind-receipt.ts +1 -1
  29. package/src/core/session-focus.ts +190 -0
  30. package/src/core/session-resume-core.ts +23 -81
  31. package/src/core/stream-event-wiring.ts +31 -5
  32. package/src/core/system-message-noise.ts +2 -2
  33. package/src/core/system-message-router.ts +16 -18
  34. package/src/core/turn-event-wiring.ts +272 -33
  35. package/src/core/work-tree-focus.ts +290 -0
  36. package/src/core/work-tree-fold-store.ts +143 -0
  37. package/src/core/work-tree-model.ts +799 -0
  38. package/src/core/work-tree-render.ts +384 -0
  39. package/src/core/work-tree-sources.ts +184 -0
  40. package/src/core/work-tree-wiring.ts +176 -0
  41. package/src/core/workstream-notification.ts +36 -6
  42. package/src/core/wrfc-notice-titles.ts +37 -0
  43. package/src/input/agents-modal-text.ts +119 -0
  44. package/src/input/agents-modal.ts +699 -0
  45. package/src/input/bookmark-modal.ts +33 -9
  46. package/src/input/changes-git.ts +251 -0
  47. package/src/input/changes-modal.ts +629 -0
  48. package/src/input/changes-model.ts +125 -0
  49. package/src/input/command-palette-types.ts +41 -0
  50. package/src/input/command-palette.ts +272 -0
  51. package/src/input/command-reference.ts +2 -2
  52. package/src/input/command-registry.ts +77 -35
  53. package/src/input/commands/acp-runtime.ts +19 -9
  54. package/src/input/commands/channel-runtime.ts +2 -2
  55. package/src/input/commands/ci-runtime.ts +1 -1
  56. package/src/input/commands/codebase-runtime.ts +1 -1
  57. package/src/input/commands/config.ts +7 -1
  58. package/src/input/commands/context-window.ts +25 -19
  59. package/src/input/commands/control-room-runtime.ts +18 -18
  60. package/src/input/commands/conversation-runtime.ts +0 -1
  61. package/src/input/commands/cost-runtime.ts +29 -20
  62. package/src/input/commands/diff-runtime.ts +35 -181
  63. package/src/input/commands/eval.ts +1 -1
  64. package/src/input/commands/experience-runtime.ts +3 -7
  65. package/src/input/commands/fresh-conversation.ts +86 -0
  66. package/src/input/commands/git-runtime.ts +5 -22
  67. package/src/input/commands/graph-runtime.ts +1 -1
  68. package/src/input/commands/guidance-runtime.ts +1 -1
  69. package/src/input/commands/health-runtime.ts +8 -9
  70. package/src/input/commands/hooks-runtime.ts +2 -2
  71. package/src/input/commands/hosted-runtime.ts +3 -3
  72. package/src/input/commands/incident-runtime.ts +3 -3
  73. package/src/input/commands/intelligence-runtime.ts +6 -9
  74. package/src/input/commands/knowledge.ts +2 -2
  75. package/src/input/commands/legacy-panel-command.ts +57 -0
  76. package/src/input/commands/local-auth-runtime.ts +8 -9
  77. package/src/input/commands/local-provider-runtime.ts +7 -4
  78. package/src/input/commands/local-runtime.ts +12 -15
  79. package/src/input/commands/local-setup-review.ts +1 -1
  80. package/src/input/commands/local-setup.ts +13 -19
  81. package/src/input/commands/memory.ts +1 -1
  82. package/src/input/commands/notify-runtime.ts +9 -0
  83. package/src/input/commands/operator-runtime.ts +10 -12
  84. package/src/input/commands/permissions-provenance.ts +3 -3
  85. package/src/input/commands/planning-runtime.ts +7 -7
  86. package/src/input/commands/platform-sandbox-runtime.ts +2 -2
  87. package/src/input/commands/platform-services-runtime.ts +1 -1
  88. package/src/input/commands/policy-dispatch.ts +2 -2
  89. package/src/input/commands/policy.ts +3 -3
  90. package/src/input/commands/provider.ts +1 -1
  91. package/src/input/commands/remote-runtime.ts +1 -1
  92. package/src/input/commands/review-runtime.ts +39 -94
  93. package/src/input/commands/rewind-runtime.ts +81 -108
  94. package/src/input/commands/runtime-services.ts +15 -17
  95. package/src/input/commands/services-runtime.ts +2 -2
  96. package/src/input/commands/session-content.ts +21 -5
  97. package/src/input/commands/session-workflow.ts +13 -38
  98. package/src/input/commands/settings-sync-runtime.ts +2 -2
  99. package/src/input/commands/shell-core.ts +19 -4
  100. package/src/input/commands/skills-runtime.ts +2 -2
  101. package/src/input/commands/status-runtime.ts +13 -0
  102. package/src/input/commands/subscription-runtime.ts +1 -1
  103. package/src/input/commands/tasks-runtime.ts +2 -8
  104. package/src/input/commands/work-plan-runtime.ts +4 -4
  105. package/src/input/commands/workstream-attempts.ts +24 -47
  106. package/src/input/commands/workstream-runtime.ts +2 -2
  107. package/src/input/commands/worktree-runtime.ts +3 -3
  108. package/src/input/commands.ts +3 -1
  109. package/src/input/composer-editor.ts +44 -0
  110. package/src/input/concealed-input.ts +1 -1
  111. package/src/input/config-modal-types.ts +20 -8
  112. package/src/input/config-modal.ts +106 -105
  113. package/src/input/confirm-dialog-types.ts +28 -0
  114. package/src/input/confirm-dialog.ts +70 -0
  115. package/src/input/delete-key-policy.ts +3 -3
  116. package/src/input/feed-context-factory.ts +15 -16
  117. package/src/input/handler-command-route.ts +7 -42
  118. package/src/input/handler-content-actions.ts +16 -15
  119. package/src/input/handler-feed-routes.ts +26 -211
  120. package/src/input/handler-feed.ts +68 -95
  121. package/src/input/handler-interactions.ts +5 -3
  122. package/src/input/handler-modal-routes.ts +215 -216
  123. package/src/input/handler-modal-stack.ts +81 -11
  124. package/src/input/handler-modal-token-routes.ts +4 -0
  125. package/src/input/handler-onboarding.ts +0 -1
  126. package/src/input/handler-picker-routes.ts +65 -107
  127. package/src/input/handler-session-view-route.ts +149 -0
  128. package/src/input/handler-shortcuts.ts +16 -154
  129. package/src/input/handler-types.ts +4 -2
  130. package/src/input/handler-ui-state.ts +45 -15
  131. package/src/input/handler-work-tree-route.ts +123 -0
  132. package/src/input/handler.ts +25 -70
  133. package/src/input/keybindings.ts +16 -71
  134. package/src/input/masked-entry-modal.ts +117 -0
  135. package/src/input/mcp-workspace.ts +48 -17
  136. package/src/input/model-picker-filter.ts +8 -0
  137. package/src/input/model-picker-open.ts +99 -0
  138. package/src/input/model-picker-types.ts +1 -1
  139. package/src/input/model-picker.ts +92 -9
  140. package/src/input/notifications-modal.ts +123 -0
  141. package/src/input/overlay-filter.ts +26 -0
  142. package/src/input/profile-picker-modal.ts +37 -8
  143. package/src/input/search.ts +3 -3
  144. package/src/input/selection-modal-queue.ts +2 -0
  145. package/src/input/selection-modal.ts +28 -16
  146. package/src/input/session-picker-modal.ts +33 -8
  147. package/src/input/settings-modal-activation.ts +7 -2
  148. package/src/input/settings-modal-data.ts +11 -6
  149. package/src/input/settings-modal-types.ts +1 -1
  150. package/src/input/settings-modal.ts +20 -20
  151. package/src/input/submission-intent.ts +1 -1
  152. package/src/input/submission-router.ts +4 -9
  153. package/src/input/surface-modal-host.ts +110 -0
  154. package/src/input/theme-settings-actions.ts +82 -0
  155. package/src/input/usage-modal.ts +183 -0
  156. package/src/input/views.ts +97 -0
  157. package/src/main.ts +175 -165
  158. package/src/permissions/hunk-selection.ts +1 -1
  159. package/src/permissions/prompt-card.ts +511 -0
  160. package/src/permissions/prompt.ts +59 -622
  161. package/src/renderer/agents-modal.ts +310 -0
  162. package/src/renderer/autocomplete-overlay.ts +42 -220
  163. package/src/renderer/back-to-bottom.ts +80 -0
  164. package/src/renderer/block-actions-overlay.ts +30 -48
  165. package/src/renderer/bookmark-modal.ts +48 -79
  166. package/src/renderer/changes-modal.ts +325 -0
  167. package/src/renderer/code-block.ts +184 -106
  168. package/src/renderer/command-palette.ts +93 -0
  169. package/src/renderer/composer-fragments.ts +4 -4
  170. package/src/renderer/composer.ts +146 -0
  171. package/src/renderer/compositor.ts +26 -160
  172. package/src/renderer/config-modal.ts +185 -81
  173. package/src/renderer/confirm-dialog.ts +50 -0
  174. package/src/renderer/context-inspector.ts +116 -154
  175. package/src/renderer/context-status-hint.ts +4 -4
  176. package/src/renderer/conversation-layout.ts +20 -0
  177. package/src/renderer/conversation-overlays.ts +94 -84
  178. package/src/renderer/conversation-surface.ts +19 -38
  179. package/src/renderer/diff-tint.ts +98 -0
  180. package/src/renderer/file-picker-overlay.ts +63 -90
  181. package/src/renderer/footer-targets.ts +38 -0
  182. package/src/renderer/git-status.ts +3 -4
  183. package/src/renderer/header-line.ts +140 -117
  184. package/src/renderer/help-overlay.ts +133 -219
  185. package/src/renderer/history-search-overlay.ts +15 -12
  186. package/src/renderer/lane-graph/bead.ts +800 -0
  187. package/src/renderer/lane-graph/glyphs.ts +134 -0
  188. package/src/renderer/lane-graph/layout.ts +248 -0
  189. package/src/renderer/lane-graph/paint.ts +537 -0
  190. package/src/renderer/lane-graph/semantic-memo.ts +77 -0
  191. package/src/renderer/layout-engine.ts +2 -57
  192. package/src/renderer/layout.ts +7 -13
  193. package/src/renderer/markdown-inline.ts +2 -1
  194. package/src/renderer/markdown-table.ts +17 -12
  195. package/src/renderer/markdown.ts +92 -34
  196. package/src/renderer/masked-entry-modal.ts +78 -0
  197. package/src/renderer/mcp-workspace.ts +166 -203
  198. package/src/renderer/model-workspace.ts +381 -436
  199. package/src/renderer/notifications-modal.ts +116 -0
  200. package/src/renderer/onboarding/onboarding-wizard.ts +178 -588
  201. package/src/renderer/process-view.ts +192 -0
  202. package/src/renderer/profile-picker-modal.ts +58 -110
  203. package/src/renderer/search-overlay.ts +6 -3
  204. package/src/renderer/selection-modal-overlay.ts +87 -327
  205. package/src/renderer/semantic-diff.ts +2 -2
  206. package/src/renderer/session-chips.ts +102 -0
  207. package/src/renderer/session-picker-modal.ts +177 -297
  208. package/src/renderer/settings-modal-connections.ts +14 -23
  209. package/src/renderer/settings-modal-context.ts +367 -0
  210. package/src/renderer/settings-modal-helpers.ts +6 -11
  211. package/src/renderer/settings-modal.ts +322 -726
  212. package/src/renderer/shell-surface.ts +277 -175
  213. package/src/renderer/shortcuts-overlay.ts +217 -0
  214. package/src/renderer/status-line.ts +475 -0
  215. package/src/renderer/surface-compose.ts +174 -0
  216. package/src/renderer/surface-kit-extra.ts +303 -0
  217. package/src/renderer/surface-kit-list.ts +366 -0
  218. package/src/renderer/surface-kit-parts.ts +360 -0
  219. package/src/renderer/surface-kit.ts +568 -0
  220. package/src/renderer/syntax-highlighter.ts +280 -197
  221. package/src/renderer/syntax-theme.ts +51 -0
  222. package/src/renderer/system-message.ts +0 -1
  223. package/src/renderer/term-caps.ts +42 -1
  224. package/src/renderer/terminal-bg-probe.ts +116 -19
  225. package/src/renderer/terminal-palette-probe.ts +322 -0
  226. package/src/renderer/terminal-palette-reader.ts +183 -0
  227. package/src/renderer/terminal-palette.ts +58 -0
  228. package/src/renderer/theme-mode-config.ts +16 -1
  229. package/src/renderer/theme.ts +234 -207
  230. package/src/renderer/thinking.ts +0 -1
  231. package/src/renderer/throbber.ts +188 -0
  232. package/src/renderer/toast-center.ts +119 -0
  233. package/src/renderer/ui-factory.ts +39 -602
  234. package/src/renderer/ui-primitives.ts +8 -25
  235. package/src/renderer/usage-modal.ts +353 -0
  236. package/src/renderer/user-message.ts +58 -0
  237. package/src/renderer/voice-capture-chip.ts +53 -0
  238. package/src/runtime/bootstrap-command-context.ts +0 -5
  239. package/src/runtime/bootstrap-command-parts.ts +38 -89
  240. package/src/runtime/bootstrap-core.ts +13 -15
  241. package/src/runtime/bootstrap-hook-bridge.ts +12 -21
  242. package/src/runtime/bootstrap-notifier-sync.ts +17 -1
  243. package/src/runtime/bootstrap-shell.ts +16 -50
  244. package/src/runtime/bootstrap.ts +14 -14
  245. package/src/runtime/client/fleet-union.ts +5 -5
  246. package/src/runtime/client/hosted-exit.ts +2 -2
  247. package/src/runtime/client/hosted-sessions.ts +1 -1
  248. package/src/runtime/client/spine-adoption.ts +1 -1
  249. package/src/runtime/context-accounting-source.ts +5 -4
  250. package/src/runtime/index.ts +1 -0
  251. package/src/runtime/notification-dispatch.ts +102 -29
  252. package/src/runtime/recovery-offer-wiring.ts +4 -1
  253. package/src/runtime/recovery-prompt.ts +31 -15
  254. package/src/runtime/runtime-services-types.ts +10 -6
  255. package/src/runtime/services.ts +17 -12
  256. package/src/runtime/session-continuity-hints.ts +2 -5
  257. package/src/runtime/session-inbound-inputs.ts +1 -1
  258. package/src/runtime/session-resume-liveness-confirm.ts +14 -2
  259. package/src/runtime/startup-typeahead-gate.ts +103 -0
  260. package/src/runtime/store/domains/domain-read-matrix.ts +0 -1
  261. package/src/runtime/store/domains/index.ts +0 -8
  262. package/src/runtime/store/selectors/index.ts +0 -28
  263. package/src/runtime/store/state.ts +0 -8
  264. package/src/runtime/ui-services.ts +4 -6
  265. package/src/runtime/usage-tracker.ts +348 -0
  266. package/src/runtime/wrfc-persistence.ts +4 -4
  267. package/src/shell/blocking-input.ts +92 -2
  268. package/src/shell/recovery-input-helpers.ts +1 -1
  269. package/src/shell/session-views.ts +539 -0
  270. package/src/shell/status-report.ts +86 -0
  271. package/src/shell/transcript-scroll.ts +68 -0
  272. package/src/shell/ui-openers.ts +84 -172
  273. package/src/shell/view-openers.ts +205 -0
  274. package/src/tools/wrfc-agent-guard.ts +22 -2
  275. package/src/utils/format-duration.ts +4 -8
  276. package/src/utils/splash-lines.ts +9 -1
  277. package/src/utils/terminal-width.ts +56 -0
  278. package/src/verification/live-verifier.ts +0 -10
  279. package/src/version.ts +1 -1
  280. package/src/{panels → views}/agent-inspector-shared.ts +2 -2
  281. package/src/{panels → views}/builtin-modals.ts +22 -21
  282. package/src/views/builtin-views.ts +135 -0
  283. package/src/{panels → views}/confirm-state.ts +9 -9
  284. package/src/{panels → views}/diff-review-model.ts +10 -3
  285. package/src/{panels → views}/eval-registry.ts +1 -1
  286. package/src/{panels → views}/fleet-acts.ts +49 -85
  287. package/src/{panels/fleet-panel-format.ts → views/fleet-format.ts} +40 -40
  288. package/src/{panels → views}/fleet-gateway.ts +5 -5
  289. package/src/{panels → views}/fleet-observed-render.ts +16 -16
  290. package/src/{panels → views}/fleet-read-model.ts +9 -9
  291. package/src/{panels/fleet-tabs.ts → views/fleet-session-tabs.ts} +13 -13
  292. package/src/{panels → views}/fleet-spawn.ts +33 -49
  293. package/src/{panels → views}/fleet-steer.ts +12 -12
  294. package/src/{panels → views}/fleet-stop.ts +4 -4
  295. package/src/{panels → views}/fleet-transcript.ts +26 -27
  296. package/src/{panels/fleet-panel-worktree-detail.ts → views/fleet-worktree-detail.ts} +7 -7
  297. package/src/{panels → views}/hosted-session-feed.ts +6 -6
  298. package/src/views/modal-surface-registry.ts +41 -0
  299. package/src/{panels → views}/modals/devices-modal.ts +2 -2
  300. package/src/{panels → views}/modals/hooks-modal.ts +13 -13
  301. package/src/{panels → views}/modals/keybindings-modal.ts +19 -27
  302. package/src/{panels → views}/modals/knowledge-modal.ts +6 -5
  303. package/src/{panels → views}/modals/local-auth-modal.ts +22 -21
  304. package/src/{panels → views}/modals/marketplace-modal.ts +11 -11
  305. package/src/{panels → views}/modals/memory-modal.ts +8 -8
  306. package/src/{panels → views}/modals/modal-surface-helpers.ts +15 -5
  307. package/src/{panels → views}/modals/pairing-modal.ts +9 -9
  308. package/src/{panels → views}/modals/planning-modal.ts +15 -20
  309. package/src/{panels → views}/modals/plugins-modal.ts +6 -6
  310. package/src/{panels → views}/modals/policy-modal.ts +13 -5
  311. package/src/{panels → views}/modals/provider-health-modal.ts +4 -4
  312. package/src/{panels → views}/modals/remote-modal.ts +3 -3
  313. package/src/{panels → views}/modals/sandbox-modal.ts +4 -4
  314. package/src/{panels → views}/modals/security-modal.ts +22 -16
  315. package/src/{panels → views}/modals/services-modal.ts +3 -3
  316. package/src/{panels → views}/modals/settings-sync-modal.ts +4 -4
  317. package/src/{panels → views}/modals/skills-modal.ts +9 -9
  318. package/src/{panels → views}/modals/subscription-modal.ts +3 -3
  319. package/src/{panels → views}/modals/work-plan-modal.ts +10 -13
  320. package/src/views/notifications-feed.ts +314 -0
  321. package/src/{panels → views}/polish-core.ts +38 -36
  322. package/src/{panels → views}/polish-tables.ts +35 -26
  323. package/src/{panels → views}/polish.ts +101 -95
  324. package/src/{panels → views}/project-planning-answer-actions.ts +3 -3
  325. package/src/{panels → views}/provider-health-routes.ts +14 -14
  326. package/src/{panels → views}/search-focus.ts +8 -8
  327. package/src/{panels → views}/session-maintenance.ts +11 -11
  328. package/src/views/skills-discovery.ts +159 -0
  329. package/src/views/view-deps.ts +80 -0
  330. package/src/views/view-panel-adapter.ts +53 -0
  331. package/src/{panels → views}/workstream-graph-render.ts +1 -1
  332. package/src/core/conversation-fold.ts +0 -101
  333. package/src/core/conversation-turn-structure.ts +0 -464
  334. package/src/core/conversation-user-receipts.ts +0 -42
  335. package/src/input/commands/operator-panel-runtime.ts +0 -186
  336. package/src/input/panel-integration-actions.ts +0 -33
  337. package/src/input/panel-mouse-geometry.ts +0 -97
  338. package/src/input/panel-paste-flood-guard.ts +0 -86
  339. package/src/panels/base-panel.ts +0 -301
  340. package/src/panels/builtin/agent.ts +0 -27
  341. package/src/panels/builtin/development.ts +0 -92
  342. package/src/panels/builtin/knowledge.ts +0 -12
  343. package/src/panels/builtin/operations.ts +0 -177
  344. package/src/panels/builtin/session.ts +0 -81
  345. package/src/panels/builtin/shared.ts +0 -357
  346. package/src/panels/builtin-panels.ts +0 -28
  347. package/src/panels/cost-tracker-panel.ts +0 -746
  348. package/src/panels/diff-panel.ts +0 -797
  349. package/src/panels/diff-review-panel.ts +0 -395
  350. package/src/panels/expandable-list-panel.ts +0 -189
  351. package/src/panels/fleet-deep-link.ts +0 -31
  352. package/src/panels/fleet-panel.ts +0 -799
  353. package/src/panels/git-panel.ts +0 -800
  354. package/src/panels/hosted-session-panel.ts +0 -221
  355. package/src/panels/index.ts +0 -21
  356. package/src/panels/local-auth-panel.ts +0 -478
  357. package/src/panels/notifications-feed.ts +0 -127
  358. package/src/panels/notifications-panel.ts +0 -160
  359. package/src/panels/panel-confirm-overlay.ts +0 -72
  360. package/src/panels/panel-manager.ts +0 -791
  361. package/src/panels/plugins-panel.ts +0 -371
  362. package/src/panels/scrollable-list-panel.ts +0 -498
  363. package/src/panels/skills-panel.ts +0 -454
  364. package/src/panels/token-budget-panel.ts +0 -688
  365. package/src/panels/types.ts +0 -191
  366. package/src/panels/wrfc-panel-format.ts +0 -133
  367. package/src/renderer/diff-view.ts +0 -134
  368. package/src/renderer/fleet-tab-strip.ts +0 -56
  369. package/src/renderer/footer-tips.ts +0 -53
  370. package/src/renderer/fullscreen-primitives.ts +0 -146
  371. package/src/renderer/fullscreen-workspace.ts +0 -194
  372. package/src/renderer/hint-grammar.ts +0 -52
  373. package/src/renderer/modal-factory.ts +0 -480
  374. package/src/renderer/overlay-box.ts +0 -154
  375. package/src/renderer/overlay-viewport.ts +0 -104
  376. package/src/renderer/panel-composite.ts +0 -145
  377. package/src/renderer/panel-workspace-bar.ts +0 -54
  378. package/src/renderer/process-indicator.ts +0 -163
  379. package/src/renderer/tab-strip.ts +0 -222
  380. package/src/renderer/text-layout.ts +0 -31
  381. package/src/renderer/tool-call.ts +0 -276
  382. package/src/renderer/tool-result-expanded-lines.ts +0 -48
  383. package/src/renderer/tool-result-summary.ts +0 -219
  384. package/src/runtime/diagnostics/panels/index.ts +0 -21
  385. package/src/runtime/diagnostics/panels/ops.ts +0 -156
  386. package/src/runtime/perf/panel-contracts.ts +0 -32
  387. package/src/runtime/store/domains/panels.ts +0 -117
  388. package/src/verification/verification-ledger.ts +0 -707
  389. /package/src/{panels → views}/memory-consolidation-gateway.ts +0 -0
  390. /package/src/{panels → views}/modals/modal-theme.ts +0 -0
  391. /package/src/{panels → views}/provider-health-domains.ts +0 -0
@@ -1,11 +1,11 @@
1
1
  // ---------------------------------------------------------------------------
2
2
  // fleet-read-model.ts
3
3
  //
4
- // (Fleet tree panel), pure, testable read-model over the SDK's live
4
+ // (Agents modal tree), pure, testable read-model over the SDK's live
5
5
  // process registry (@pellux/goodvibes-sdk/platform/runtime/fleet, landed on
6
- // SDK main as). No BasePanel/rendering dependency: this module owns the
6
+ // SDK main as). No rendering dependency: this module owns the
7
7
  // flat ProcessNode[] -> tree transformation, the honest cost/token
8
- // aggregates, and the state->glyph/tone mapping that FleetPanel renders.
8
+ // aggregates, and the state->glyph/tone mapping that the Agents modal renders.
9
9
  //
10
10
  // Design notes:
11
11
  // - The brief predates the real SDK API and sketched a bespoke
@@ -55,7 +55,7 @@ export interface FleetTreeRow {
55
55
  readonly hasChildren: boolean;
56
56
  }
57
57
 
58
- /** Aggregate snapshot the fleet panel renders from. */
58
+ /** Aggregate snapshot the Agents modal renders from. */
59
59
  export interface FleetSnapshot {
60
60
  readonly rows: readonly FleetTreeRow[];
61
61
  /** Sum of costUsd across nodes with a real (non-unpriced) reading; null when none do. */
@@ -68,7 +68,7 @@ export interface FleetSnapshot {
68
68
  * Ids of the nodes that are "blocked on me", waiting on a user approval or
69
69
  * user input right now (see isBlockedOnUserState), in display (row) order.
70
70
  * This is a DERIVED view over the same node states the rows already carry,
71
- * never a second source of truth: the panel reads it to badge/jump, it is
71
+ * never a second source of truth: the Agents modal reads it to badge/jump, it is
72
72
  * not a store. Empty when nothing is waiting on the operator.
73
73
  */
74
74
  readonly blockedNodeIds: readonly string[];
@@ -85,9 +85,9 @@ export type FleetStateTone = 'active' | 'success' | 'failure' | 'warn' | 'muted'
85
85
  // contract's STATE_GLYPHS (@pellux/goodvibes-sdk/platform/presentation), that
86
86
  // one is a 4-state semantic alias (good/warn/bad/info) shared by the TUI and
87
87
  // agent renderers; this one is a 12-state ProcessNode taxonomy specific to the
88
- // Fleet tree panel (thinking/executing-tool/awaiting-approval/streaming/
88
+ // Agents modal tree (thinking/executing-tool/awaiting-approval/streaming/
89
89
  // stalled/retrying/done/failed/killed/interrupted/idle/queued/paused), and no
90
- // other surface (checked: the agent has no fleet-panel renderer) consumes it
90
+ // other surface (checked: the agent has no Agents modal renderer) consumes it
91
91
  // today. Per the presentation-parity brief, a table only moves to the SDK
92
92
  // contract when 2+ surfaces need it, this one stays TUI-renderer-local.
93
93
  const STATE_GLYPHS: Record<ProcessState, string> = {
@@ -176,7 +176,7 @@ const KIND_TAGS: Record<ProcessKind, string> = {
176
176
  // that goodvibes did NOT spawn, observed read-only from OS signals. The row's
177
177
  // first job is visibility ("it's in claude or codex"); it is never counted in
178
178
  // any our-fleet count, never carries a stop affordance, and steer is drill-in
179
- // only. See ObservedProcess handling in fleet-panel-format.ts.
179
+ // only. See ObservedProcess handling in fleet-format.ts.
180
180
  'observed-external': 'observed',
181
181
  };
182
182
 
@@ -525,7 +525,7 @@ export function buildFleetSnapshot(nodes: readonly ProcessNode[], capturedAt: nu
525
525
  if (isFleetRunningLeaf(node)) runningCount++;
526
526
  }
527
527
 
528
- // Blocked ids in display (row) order so the panel's jump key steps through
528
+ // Blocked ids in display (row) order so the Agents modal's jump key steps through
529
529
  // them top-to-bottom exactly as they appear on screen.
530
530
  const blockedNodeIds = rows
531
531
  .filter((row) => isBlockedOnUserNode(row.node))
@@ -1,13 +1,13 @@
1
1
  // ---------------------------------------------------------------------------
2
- // fleet-tabs.ts
2
+ // fleet-session-tabs.ts
3
3
  //
4
- // Pure, testable tab-state model for FleetPanel's
5
- // session tabs. No BasePanel/rendering dependency, mirroring the
4
+ // Pure, testable tab-state model for the Agents modal's
5
+ // session tabs. No rendering dependency, mirroring the
6
6
  // fleet-read-model.ts convention: this module owns attach/detach/switch as
7
7
  // pure state transitions over a small immutable FleetTabsState, so the tab
8
- // lifecycle is unit-testable without a live registry or a rendered panel.
8
+ // lifecycle is unit-testable without a live registry or a rendered view.
9
9
  //
10
- // Tab-index convention: index 0 is always the fleet TREE (the panel's root
10
+ // Tab-index convention: index 0 is always the fleet TREE (the Agents modal's root
11
11
  // view, never stored in `tabs`); `activeTabIndex` 1..N addresses
12
12
  // `tabs[0..N-1]`. This mirrors the brief's "tree is the root/home tab"
13
13
  // framing while keeping the array itself simple (only attached tabs).
@@ -16,7 +16,7 @@
16
16
  // attaching to (a transcript for an agent; a live member summary for a
17
17
  // chain, see fleet-transcript.ts). workflow/trigger/schedule/watcher/
18
18
  // background-process/wrfc-subtask nodes have no transcript and are never
19
- // attachable (FleetPanel shows a status message instead, matching the
19
+ // attachable (the Agents modal shows a status message instead, matching the
20
20
  // existing i/K "not supported" convention).
21
21
  // ---------------------------------------------------------------------------
22
22
 
@@ -39,9 +39,9 @@ export function isAttachableFleetKind(kind: ProcessKind): kind is FleetAttachabl
39
39
  * event matching this badge's `messageId`). `dropped` is a TUI-side
40
40
  * inference: the SDK emits no "expired"/"cancelled" signal for a queued
41
41
  * steer, so if the target node goes terminal (done/failed/killed/
42
- * interrupted) while the badge is still `queued`, FleetPanel resolves it to
42
+ * interrupted) while the badge is still `queued`, the Agents modal resolves it to
43
43
  * `dropped` itself rather than leaving the badge hanging forever (see
44
- * fleet-panel.ts reconcileSteerBadges, cross-WO note: the SDK engineer
44
+ * src/input/agents-modal.ts reconcileSteerBadges, cross-WO note: the SDK engineer
45
45
  * confirmed no dropped signal exists).
46
46
  */
47
47
  export type SteerBadgeStatus = 'queued' | 'consumed' | 'dropped';
@@ -52,7 +52,7 @@ export interface SteerBadge {
52
52
  readonly status: SteerBadgeStatus;
53
53
  /** Present for 'dropped', a one-line honest explanation shown in the tab. */
54
54
  readonly note?: string;
55
- /** epoch ms when status left 'queued' (consumed or dropped), drives FleetPanel's linger-then-clear tick. */
55
+ /** epoch ms when status left 'queued' (consumed or dropped), drives the Agents modal's linger-then-clear tick. */
56
56
  readonly resolvedAt?: number;
57
57
  /**
58
58
  * epoch ms when status entered 'queued' (set once, at submit time). Drives
@@ -119,10 +119,10 @@ export interface FleetTab {
119
119
  ledgerLoadStarted: boolean;
120
120
  /**
121
121
  * The one-line steer composer's in-progress text, or `null`
122
- * when not composing. Mirrors git-panel.ts's `commitMessage` mutable-slot
123
- * convention (FleetPanel.isCapturingTextBurst() gates on this being
122
+ * when not composing. Mirrors the git view's `commitMessage` mutable-slot
123
+ * convention (the Agents modal's text-capture check gates on this being
124
124
  * non-null so a burst/paste lands here char-by-char, never as tree/tab
125
- * hotkeys, see FleetPanel.handleSteerInput).
125
+ * hotkeys, see the Agents modal's steer input handler).
126
126
  */
127
127
  steerDraft: string | null;
128
128
  /** This tab's most recent steer message's lifecycle, or null. */
@@ -173,7 +173,7 @@ export function activeFleetTab(state: FleetTabsState): FleetTab | null {
173
173
  * Attach a node as a tab (Enter on an attachable tree row). Re-focuses an
174
174
  * already-open tab for the same node instead of creating a duplicate.
175
175
  * Returns `state` unchanged if `node.kind` is not attachable, callers
176
- * (FleetPanel) are expected to guard with `isAttachableFleetKind` first and
176
+ * (the Agents modal) are expected to guard with `isAttachableFleetKind` first and
177
177
  * report a status message rather than silently doing nothing; this
178
178
  * function's own no-op fallback is defense in depth.
179
179
  */
@@ -1,7 +1,7 @@
1
1
  // ---------------------------------------------------------------------------
2
2
  // fleet-spawn.ts
3
3
  //
4
- // The Fleet panel's ACP spawn affordance: 'n' on the fleet surface lists the
4
+ // The Agents modal's ACP spawn affordance: 'n' lists the
5
5
  // third-party coding agents the daemon discovered (acp.agents.list, read-only,
6
6
  // quiet when none), you pick one, then pick a working directory from the known
7
7
  // candidates (the registered workspaces + the current dir, no free-text path
@@ -13,24 +13,16 @@
13
13
  // never a hung row: the daemon bounds the handshake and returns a 'failed'
14
14
  // record, and this controller reports its three honest fields.
15
15
  //
16
- // The controller owns the fleet view + input while a pick is in flight (mirrors
17
- // FleetActs' pick mode), so fleet-panel.ts stays a thin delegator under the
18
- // architecture line cap. The gateway is injectable so the flow round-trips
16
+ // The controller owns the Agents modal's input while a pick is in flight
17
+ // (mirrors FleetActs' pick mode); the modal draws spawnView(). The gateway is
18
+ // injectable so the flow round-trips
19
19
  // against a mocked daemon in tests; the live builder is createAcpSpawnGateway.
20
20
  // ---------------------------------------------------------------------------
21
21
 
22
22
  import type { ConfigManager } from '@pellux/goodvibes-sdk/platform/config';
23
23
  import type { OperatorMethodOutput } from '@pellux/goodvibes-sdk';
24
24
  import { summarizeError } from '@pellux/goodvibes-sdk/platform/utils';
25
- import type { Line } from '@pellux/goodvibes-sdk/platform/types';
26
25
  import { resolveOperatorRpc } from '../input/commands/operator-rpc.ts';
27
- import {
28
- buildKeyboardHints,
29
- buildPanelWorkspace,
30
- buildPanelLine,
31
- DEFAULT_PANEL_PALETTE,
32
- type PanelPalette,
33
- } from './polish.ts';
34
26
 
35
27
  /** One discovered third-party ACP agent (acp.agents.list). */
36
28
  export type AcpDiscoveredAgent = OperatorMethodOutput<'acp.agents.list'>['agents'][number];
@@ -111,7 +103,15 @@ interface DirStep {
111
103
  }
112
104
  type SpawnMode = AgentStep | DirStep | null;
113
105
 
114
- const C = DEFAULT_PANEL_PALETTE;
106
+ /** The spawn picker, as data. */
107
+ export interface FleetSpawnView {
108
+ readonly step: 'agent' | 'dir';
109
+ readonly title: string;
110
+ readonly intro: string;
111
+ readonly options: ReadonlyArray<{ readonly label: string; readonly detail: string; readonly selected: boolean }>;
112
+ /** A create round-trip is in flight. */
113
+ readonly creating: boolean;
114
+ }
115
115
 
116
116
  export class FleetSpawn {
117
117
  private mode: SpawnMode = null;
@@ -218,44 +218,28 @@ export class FleetSpawn {
218
218
  }
219
219
  }
220
220
 
221
- /** The spawn picker view (replaces the tree while a pick is in flight). */
222
- public renderSpawnMode(width: number, height: number, palette: PanelPalette = C): Line[] {
223
- const P = palette;
224
- if (!this.mode) return [];
225
- const lines: Line[] = [];
226
- if (this.creating) {
227
- lines.push(buildPanelLine(width, [[' Hosting the agent…', P.dim]]));
228
- return buildPanelWorkspace(width, height, { title: 'Fleet: Host an agent', sections: [{ lines }], footerLines: [], palette: P });
229
- }
221
+ /** The spawn picker as data the Agents modal draws, or null when it is not open. */
222
+ public spawnView(): FleetSpawnView | null {
223
+ if (!this.mode) return null;
224
+ if (this.creating) return { step: this.mode.step, title: 'Hosting the agent…', intro: '', options: [], creating: true };
230
225
  if (this.mode.step === 'agent') {
231
- lines.push(buildPanelLine(width, [[' Host a third-party coding agent; pick one, then a directory.', P.dim]]));
232
- lines.push(buildPanelLine(width, [['', P.dim]]));
233
- this.mode.agents.forEach((agent, i) => {
234
- const selected = i === (this.mode as AgentStep).index;
235
- lines.push(buildPanelLine(width, [
236
- [selected ? ' ▸ ' : ' ', selected ? P.info : P.dim],
237
- [agent.title, selected ? P.value : P.dim],
238
- [`, ${agent.binaryPath}`, P.dim],
239
- ]));
240
- });
241
- } else {
242
- lines.push(buildPanelLine(width, [[` Directory for ${this.mode.agent.title}: a known dir, no path to type.`, P.dim]]));
243
- lines.push(buildPanelLine(width, [['', P.dim]]));
244
- this.mode.candidates.forEach((cand, i) => {
245
- const selected = i === (this.mode as DirStep).index;
246
- lines.push(buildPanelLine(width, [
247
- [selected ? ' ▸ ' : ' ', selected ? P.info : P.dim],
248
- [cand.label, selected ? P.value : P.dim],
249
- [`, ${cand.path}`, P.dim],
250
- ]));
251
- });
226
+ const index = this.mode.index;
227
+ return {
228
+ step: 'agent',
229
+ title: 'Host an agent',
230
+ intro: 'Host a third-party coding agent here: pick one, then a directory.',
231
+ options: this.mode.agents.map((agent, i) => ({ label: agent.title, detail: agent.binaryPath, selected: i === index })),
232
+ creating: false,
233
+ };
252
234
  }
253
- const footerLines = [buildKeyboardHints(width, [
254
- { keys: '↑↓', label: 'choose' },
255
- { keys: 'Enter', label: this.mode.step === 'agent' ? 'pick agent' : 'host here' },
256
- { keys: 'Esc', label: 'cancel' },
257
- ], P)];
258
- return buildPanelWorkspace(width, height, { title: 'Fleet: Host an agent', sections: [{ lines }], footerLines, palette: P });
235
+ const index = this.mode.index;
236
+ return {
237
+ step: 'dir',
238
+ title: this.mode.agent.title,
239
+ intro: `Where ${this.mode.agent.title} runs: a known directory, no path to type.`,
240
+ options: this.mode.candidates.map((cand, i) => ({ label: cand.label, detail: cand.path, selected: i === index })),
241
+ creating: false,
242
+ };
259
243
  }
260
244
 
261
245
  private requireGateway(): AcpSpawnGateway | null {
@@ -2,17 +2,17 @@
2
2
  // fleet-steer.ts
3
3
  //
4
4
  // Steer-badge rendering helpers and the "dropped inference"
5
- // reconciliation pass, split out of fleet-panel.ts to keep that file under
5
+ // reconciliation pass, split out of src/input/agents-modal.ts to keep that file under
6
6
  // the architecture line cap (see check-architecture.ts's 800-line gate).
7
- // Pure functions only; FleetPanel still owns the mutable FleetTab.steerBadge
8
- // state itself (see fleet-tabs.ts's SteerBadge doc) and calls into this
7
+ // Pure functions only; the Agents modal still owns the mutable FleetTab.steerBadge
8
+ // state itself (see fleet-session-tabs.ts's SteerBadge doc) and calls into this
9
9
  // module rather than duplicating the logic inline.
10
10
  // ---------------------------------------------------------------------------
11
11
 
12
12
  import { STEER_TTL_MS, type ProcessNode } from '@pellux/goodvibes-sdk/platform/runtime/fleet';
13
13
  import { isTerminalProcessState } from './fleet-read-model.ts';
14
- import type { FleetTab, SteerBadge, SteerBadgeStatus } from './fleet-tabs.ts';
15
- import { buildPanelLine, DEFAULT_PANEL_PALETTE, type PanelPalette } from './polish.ts';
14
+ import type { FleetTab, SteerBadge, SteerBadgeStatus } from './fleet-session-tabs.ts';
15
+ import { buildViewLine, DEFAULT_VIEW_PALETTE, type ViewPalette } from './polish.ts';
16
16
  import type { Line } from '@pellux/goodvibes-sdk/platform/types';
17
17
 
18
18
  /** Linger before an auto-resolved (consumed/dropped) steer badge is cleared from the tab. */
@@ -26,11 +26,11 @@ export function steerBadgeGlyph(status: SteerBadgeStatus): string {
26
26
  }
27
27
  }
28
28
 
29
- export function steerBadgeTone(status: SteerBadgeStatus, palette: PanelPalette): string {
29
+ export function steerBadgeTone(status: SteerBadgeStatus, palette: ViewPalette): string {
30
30
  switch (status) {
31
- case 'queued': return palette.warn ?? DEFAULT_PANEL_PALETTE.warn;
32
- case 'consumed': return palette.good ?? DEFAULT_PANEL_PALETTE.good;
33
- case 'dropped': return palette.bad ?? DEFAULT_PANEL_PALETTE.bad;
31
+ case 'queued': return palette.warn ?? DEFAULT_VIEW_PALETTE.warn;
32
+ case 'consumed': return palette.good ?? DEFAULT_VIEW_PALETTE.good;
33
+ case 'dropped': return palette.bad ?? DEFAULT_VIEW_PALETTE.bad;
34
34
  }
35
35
  }
36
36
 
@@ -50,7 +50,7 @@ export function steerRefusalMessage(reason: string, siblingLabels: readonly stri
50
50
  }
51
51
 
52
52
  /** One-line honest status for a tab's steer badge; the queued line names the target and points at the ⧗ delivery badge (WO item 4). */
53
- export function renderSteerBadgeLine(badge: SteerBadge, width: number, palette: PanelPalette, targetLabel?: string): Line {
53
+ export function renderSteerBadgeLine(badge: SteerBadge, width: number, palette: ViewPalette, targetLabel?: string): Line {
54
54
  const glyph = steerBadgeGlyph(badge.status);
55
55
  const tone = steerBadgeTone(badge.status, palette);
56
56
  const forTarget = targetLabel ? ` for ${targetLabel}` : '';
@@ -59,7 +59,7 @@ export function renderSteerBadgeLine(badge: SteerBadge, width: number, palette:
59
59
  : badge.status === 'consumed'
60
60
  ? 'steer consumed'
61
61
  : `steer dropped: ${badge.note ?? 'the target ended before delivery'}`;
62
- return buildPanelLine(width, [
62
+ return buildViewLine(width, [
63
63
  [' ', palette.dim],
64
64
  [glyph, tone],
65
65
  [` ${label}`, palette.dim],
@@ -75,7 +75,7 @@ export function renderSteerBadgeLine(badge: SteerBadge, width: number, palette:
75
75
  * its short linger so a tab doesn't accumulate stale indicators.
76
76
  *
77
77
  * Mutates `tab.steerBadge` in place (same mutable-slot convention as
78
- * `FleetTab.ledgerEntries`, see fleet-panel.ts's ensureLedgerLoaded).
78
+ * `FleetTab.ledgerEntries`, see src/input/agents-modal.ts's ensureLedgerLoaded).
79
79
  * Returns true when anything changed, so the caller knows whether to mark
80
80
  * itself dirty.
81
81
  */
@@ -1,9 +1,9 @@
1
1
  // ---------------------------------------------------------------------------
2
2
  // fleet-stop.ts
3
3
  //
4
- // d1, the "stopping…" write-window overlay, split out of fleet-panel.ts
4
+ // d1, the "stopping…" write-window overlay, split out of src/input/agents-modal.ts
5
5
  // to keep that file under the architecture 800-line gate (same rationale as
6
- // fleet-steer.ts). FleetPanel owns nothing here beyond a FleetStopTracker
6
+ // fleet-steer.ts). The Agents modal owns nothing here beyond a FleetStopTracker
7
7
  // instance; all the state->display logic lives in these pure helpers.
8
8
  // ---------------------------------------------------------------------------
9
9
 
@@ -76,7 +76,7 @@ export function fleetStateDisplay(state: ProcessState, stopping: boolean, blocke
76
76
  return { glyph: fleetStateGlyph(state), label: state, tone: fleetStateTone(state) };
77
77
  }
78
78
 
79
- /** The narrow action + side-effect surface `toggleFleetPause` needs from FleetPanel. */
79
+ /** The narrow action + side-effect surface `toggleFleetPause` needs from the Agents modal. */
80
80
  export interface FleetPauseDeps {
81
81
  readonly interrupt: (id: string) => boolean;
82
82
  readonly resume: (id: string) => boolean;
@@ -196,7 +196,7 @@ export function countDescendantStats(rows: readonly FleetTreeRow[], nodeId: stri
196
196
  /**
197
197
  * Build the confirm-overlay arm options for a cascade Kill of one node, the
198
198
  * label carries the descendant count so the operator sees what a confirm takes
199
- * down. Extracted from FleetPanel to keep that file under the 800-line cap.
199
+ * down. Extracted from the Agents modal to keep that file under the 800-line cap.
200
200
  */
201
201
  export function fleetKillConfirmArgs(
202
202
  node: ProcessNode,
@@ -1,7 +1,7 @@
1
1
  // ---------------------------------------------------------------------------
2
2
  // fleet-transcript.ts
3
3
  //
4
- // Renders the content of an attached FleetPanel
4
+ // Renders the content of an attached Agents modal
5
5
  // session tab. Three sources, chosen by what the SDK can actually provide
6
6
  // (see the design brief's "central reality check", a full-fidelity live
7
7
  // transcript needs a ConversationMessageSnapshot[] history source, which
@@ -19,7 +19,7 @@
19
19
  // - 'unavailable' , a terminal agent whose snapshot came back empty
20
20
  // (evicted past the retention bound, or an agent kind, e.g. the WRFC
21
21
  // owner, that never registered a live conversation source at all).
22
- // FleetPanel degrades to the on-disk event ledger (renderFleetLedgerFallback)
22
+ // the Agents modal degrades to the on-disk event ledger (renderFleetLedgerFallback)
23
23
  // for this case; this module never fabricates transcript content.
24
24
  //
25
25
  // A 'wrfc-chain' tab has no single conversation of its own (it coordinates
@@ -33,7 +33,7 @@ import { createEmptyLine, type Line } from '@pellux/goodvibes-sdk/platform/types
33
33
  import type { MessageLineCache } from '../core/conversation-line-cache.ts';
34
34
  import type { ConversationRenderContext } from '../core/conversation-rendering.ts';
35
35
  import { renderConversationEventLine, renderConversationNotice } from '../renderer/conversation-surface.ts';
36
- import { buildPanelLine, DEFAULT_PANEL_PALETTE, type PanelPalette } from './polish.ts';
36
+ import { buildViewLine, DEFAULT_VIEW_PALETTE, type ViewPalette } from './polish.ts';
37
37
  import { formatElapsed } from '../utils/format-elapsed.ts';
38
38
  import { truncateDisplay } from '../utils/terminal-width.ts';
39
39
  import {
@@ -44,16 +44,16 @@ import {
44
44
  type FleetTreeRow,
45
45
  } from './fleet-read-model.ts';
46
46
 
47
- /** Duplicated from fleet-panel.ts's private helper (same tiny mapping) rather than
48
- * cross-importing, fleet-panel.ts imports THIS module to render tab content, so
49
- * importing back would form a cycle. See fleet-panel.ts's own toneColor for the
47
+ /** Duplicated from src/input/agents-modal.ts's private helper (same tiny mapping) rather than
48
+ * cross-importing, src/input/agents-modal.ts imports THIS module to render tab content, so
49
+ * importing back would form a cycle. See src/input/agents-modal.ts's own toneColor for the
50
50
  * canonical copy; keep both in sync if the tone set ever changes. */
51
- function toneColor(tone: FleetStateTone, palette: PanelPalette): string {
51
+ function toneColor(tone: FleetStateTone, palette: ViewPalette): string {
52
52
  switch (tone) {
53
- case 'active': return palette.info ?? DEFAULT_PANEL_PALETTE.info;
54
- case 'success': return palette.good ?? DEFAULT_PANEL_PALETTE.good;
55
- case 'failure': return palette.bad ?? DEFAULT_PANEL_PALETTE.bad;
56
- case 'warn': return palette.warn ?? DEFAULT_PANEL_PALETTE.warn;
53
+ case 'active': return palette.info ?? DEFAULT_VIEW_PALETTE.info;
54
+ case 'success': return palette.good ?? DEFAULT_VIEW_PALETTE.good;
55
+ case 'failure': return palette.bad ?? DEFAULT_VIEW_PALETTE.bad;
56
+ case 'warn': return palette.warn ?? DEFAULT_VIEW_PALETTE.warn;
57
57
  case 'muted': return palette.dim;
58
58
  }
59
59
  }
@@ -83,11 +83,10 @@ export interface FleetTranscriptRender {
83
83
  const FROZEN_TRANSCRIPT_NOTICE = 'Read-only: this agent finished; not a live view.';
84
84
 
85
85
  function renderFrozenTranscriptNotice(width: number): Line[] {
86
- const palette = DEFAULT_PANEL_PALETTE;
86
+ const palette = DEFAULT_VIEW_PALETTE;
87
87
  return renderConversationNotice(FROZEN_TRANSCRIPT_NOTICE, width, {
88
- accent: palette.warn ?? DEFAULT_PANEL_PALETTE.warn,
88
+ accent: palette.warn ?? DEFAULT_VIEW_PALETTE.warn,
89
89
  text: palette.dim,
90
- dim: true,
91
90
  });
92
91
  }
93
92
 
@@ -115,7 +114,7 @@ export function renderFleetAgentTranscript(
115
114
  ): FleetTranscriptRender {
116
115
  if (snapshot.length === 0) {
117
116
  if (isTerminal) return { mode: 'unavailable', lines: [] };
118
- return { mode: 'live', lines: [buildPanelLine(width, [[' (no messages yet)', DEFAULT_PANEL_PALETTE.dim]])] };
117
+ return { mode: 'live', lines: [buildViewLine(width, [[' (no messages yet)', DEFAULT_VIEW_PALETTE.dim]])] };
119
118
  }
120
119
 
121
120
  const historyLines: Line[] = [];
@@ -174,17 +173,17 @@ export function renderFleetChainSummary(
174
173
  width: number,
175
174
  chainDoneOrAbsent: boolean,
176
175
  ): Line[] {
177
- const C = DEFAULT_PANEL_PALETTE;
176
+ const C = DEFAULT_VIEW_PALETTE;
178
177
  if (memberRows.length === 0) {
179
178
  const message = chainDoneOrAbsent
180
179
  ? ' chain completed: members no longer tracked'
181
180
  : ' (no member agents yet)';
182
- return [buildPanelLine(width, [[message, C.dim]])];
181
+ return [buildViewLine(width, [[message, C.dim]])];
183
182
  }
184
183
  return memberRows.map((row) => {
185
184
  const node = row.node;
186
185
  const color = toneColor(fleetStateTone(node.state), C);
187
- return buildPanelLine(width, [
186
+ return buildViewLine(width, [
188
187
  [' ', C.dim],
189
188
  [fleetStateGlyph(node.state), color],
190
189
  [` ${fleetKindTag(node.kind)} `, C.dim],
@@ -224,7 +223,7 @@ function formatLedgerDuration(ms: unknown): string {
224
223
  return typeof ms === 'number' ? ` (${formatElapsed(ms)})` : '';
225
224
  }
226
225
 
227
- function renderLedgerEntry(width: number, entry: Record<string, unknown>, palette: PanelPalette): Line {
226
+ function renderLedgerEntry(width: number, entry: Record<string, unknown>, palette: ViewPalette): Line {
228
227
  const type = typeof entry['type'] === 'string' ? entry['type'] : 'unknown';
229
228
  switch (type) {
230
229
  case 'meta': {
@@ -256,7 +255,7 @@ function renderLedgerEntry(width: number, entry: Record<string, unknown>, palett
256
255
  case 'tool_execution': {
257
256
  const toolName = typeof entry['toolName'] === 'string' ? entry['toolName'] : 'tool';
258
257
  const success = entry['success'] !== false;
259
- const bad = palette.bad ?? DEFAULT_PANEL_PALETTE.bad;
258
+ const bad = palette.bad ?? DEFAULT_VIEW_PALETTE.bad;
260
259
  // the writer already truncates this to 500 chars (session.ts's
261
260
  // resultPreview field), passed through verbatim (collapsed to one
262
261
  // line), never re-summarized or fabricated, then tail-truncated again
@@ -276,9 +275,9 @@ function renderLedgerEntry(width: number, entry: Record<string, unknown>, palett
276
275
  }
277
276
  case 'session_end': {
278
277
  const status = typeof entry['status'] === 'string' ? entry['status'] : 'ended';
279
- const good = palette.good ?? DEFAULT_PANEL_PALETTE.good;
280
- const bad = palette.bad ?? DEFAULT_PANEL_PALETTE.bad;
281
- const warn = palette.warn ?? DEFAULT_PANEL_PALETTE.warn;
278
+ const good = palette.good ?? DEFAULT_VIEW_PALETTE.good;
279
+ const bad = palette.bad ?? DEFAULT_VIEW_PALETTE.bad;
280
+ const warn = palette.warn ?? DEFAULT_VIEW_PALETTE.warn;
282
281
  const tone = status === 'completed' ? good : status === 'failed' ? bad : warn;
283
282
  return renderConversationEventLine(width, { marker: '■', markerFg: tone, label: 'session', labelFg: tone }, [
284
283
  { text: `${status}${formatLedgerDuration(entry['durationMs'])}`, fg: tone },
@@ -334,14 +333,14 @@ export function renderFleetLedgerFallback(
334
333
  width: number,
335
334
  height: number,
336
335
  ): Line[] {
337
- const palette = DEFAULT_PANEL_PALETTE;
336
+ const palette = DEFAULT_VIEW_PALETTE;
338
337
  const notice = renderConversationNotice(
339
338
  'Read-only. Full transcript unavailable for this agent; showing its activity log instead.',
340
339
  width,
341
- { accent: palette.warn, text: palette.dim, dim: true },
340
+ { accent: palette.warn, text: palette.dim },
342
341
  );
343
342
  const body = entries.length === 0
344
- ? [buildPanelLine(width, [[' (no activity recorded)', palette.dim]])]
343
+ ? [buildViewLine(width, [[' (no activity recorded)', palette.dim]])]
345
344
  : entries.map((entry) => renderLedgerEntry(width, entry, palette));
346
345
  const budgetHeight = Math.max(0, height - notice.length);
347
346
  const visible = body.length > budgetHeight
@@ -352,5 +351,5 @@ export function renderFleetLedgerFallback(
352
351
 
353
352
  /** A blank tab-content placeholder (e.g. while a ledger load is in flight). */
354
353
  export function renderFleetTranscriptLoading(width: number): Line[] {
355
- return [buildPanelLine(width, [[' Loading…', DEFAULT_PANEL_PALETTE.dim]]), createEmptyLine(width)];
354
+ return [buildViewLine(width, [[' Loading…', DEFAULT_VIEW_PALETTE.dim]]), createEmptyLine(width)];
356
355
  }
@@ -1,17 +1,17 @@
1
1
  // ---------------------------------------------------------------------------
2
- // fleet-panel-worktree-detail.ts
2
+ // fleet-worktree-detail.ts
3
3
  //
4
- // NET-NEW helper (not moved code, it was authored here because fleet-panel.ts
4
+ // NET-NEW helper (not moved code, it was authored here because src/input/agents-modal.ts
5
5
  // sits at the architecture check's 800-line cap, scripts/check-architecture.ts):
6
- // a single pure helper for the Fleet panel's per-work-item detail view, so a
7
- // new panel feature doesn't have to fight that cap inline.
6
+ // a single pure helper for the Agents modal's per-work-item detail view, so a
7
+ // new view feature doesn't have to fight that cap inline.
8
8
  // ---------------------------------------------------------------------------
9
9
 
10
10
  import type { WorkItem } from '@pellux/goodvibes-sdk/platform/orchestration';
11
11
 
12
12
  /**
13
- * Per-item worktree-isolation detail text for the Fleet panel's expanded
14
- * node detail (fleet-panel.ts renderDetail), or null for a shared-isolation
13
+ * Per-item worktree-isolation detail text for the Agents modal's expanded
14
+ * node detail (src/input/agents-modal.ts renderDetail), or null for a shared-isolation
15
15
  * item (or any node that isn't a work item). Inferred from the item's OWN
16
16
  * fields (worktreePath/worktreeBranch/mergeState) rather than a
17
17
  * workstream-level flag, adaptWorkItem's ProcessNode.raw carries
@@ -41,7 +41,7 @@ export function formatWorkItemIsolationDetail(item: WorkItem): string | null {
41
41
  }
42
42
  }
43
43
 
44
- /** `node.raw` for a 'work-item' ProcessNode is `{ item, workstreamId }` (unknown to the panel's own types), this narrows without fleet-panel.ts needing its own WorkItem import at the call site. Non-work-item nodes (raw is undefined/some other shape) fall through to null. */
44
+ /** `node.raw` for a 'work-item' ProcessNode is `{ item, workstreamId }` (unknown to the Agents modal's own types), this narrows without src/input/agents-modal.ts needing its own WorkItem import at the call site. Non-work-item nodes (raw is undefined/some other shape) fall through to null. */
45
45
  export function formatWorkItemIsolationDetailFromRaw(raw: unknown): string | null {
46
46
  const item = (raw as { item?: WorkItem } | undefined)?.item;
47
47
  return item ? formatWorkItemIsolationDetail(item) : null;
@@ -3,11 +3,11 @@
3
3
  * session it is attached to.
4
4
  *
5
5
  * One place holds it because two surfaces read it: the `/hosted` command family
6
- * (which prints status and drives the verbs) and the Hosted Session panel
6
+ * (which prints status and drives the verbs) and the Hosted Session view
7
7
  * (which renders the conversation). The same shared-feed shape
8
8
  * notifications-feed.ts already uses in this repo, a module-level instance a
9
- * command writes and a panel subscribes to, rather than threading a service
10
- * through the command context and the panel deps for one feature.
9
+ * command writes and a view subscribes to, rather than threading a service
10
+ * through the command context and the Hosted Session view deps for one feature.
11
11
  *
12
12
  * ── What is a fact here, and what is a rendering ──────────────────────────
13
13
  *
@@ -18,7 +18,7 @@
18
18
  *
19
19
  * The ROWS are this terminal's rendering of the transcript: the history
20
20
  * `attach` backfilled, plus what the live `turn` and `tools` frames have said
21
- * since. A row that is still being streamed is marked `streaming` so the panel
21
+ * since. A row that is still being streamed is marked `streaming` so the Hosted Session view
22
22
  * can show it growing rather than waiting for the turn to end, the same thing
23
23
  * a local turn does.
24
24
  *
@@ -57,7 +57,7 @@ export interface HostedRunningToolCall {
57
57
  readonly startedAt: number;
58
58
  }
59
59
 
60
- /** Everything the panel renders and the command reports. */
60
+ /** Everything the Hosted Session view renders and the command reports. */
61
61
  export interface HostedSessionFeedState {
62
62
  readonly record: HostedSessionRecord | null;
63
63
  readonly rows: readonly HostedSessionRow[];
@@ -340,7 +340,7 @@ export class HostedSessionFeed {
340
340
 
341
341
  let sharedFeed: HostedSessionFeed | null = null;
342
342
 
343
- /** The one feed the `/hosted` command writes and the Hosted Session panel reads. */
343
+ /** The one feed the `/hosted` command writes and the Hosted Session view reads. */
344
344
  export function getSharedHostedSessionFeed(): HostedSessionFeed {
345
345
  sharedFeed ??= new HostedSessionFeed();
346
346
  return sharedFeed;
@@ -0,0 +1,41 @@
1
+ /**
2
+ * modal-surface-registry.ts, the config-modal surfaces by name.
3
+ *
4
+ * Every settings-style modal (services, providers, plugins, hooks, memory and
5
+ * the rest) is a ConfigModalSurface registered here once at startup, with the
6
+ * old names that should open it (for example 'providers' and 'accounts' both
7
+ * open 'providers-modal'). The config-modal host resolves a name through
8
+ * getModalSurface; ctx.openModal and the view router (views.ts) resolve an old
9
+ * name through getModalRedirect first.
10
+ */
11
+
12
+ import type { ConfigModalSurface, ConfigModalSurfaceRegistry } from '../input/config-modal-types.ts';
13
+
14
+ export class ModalSurfaceRegistry implements ConfigModalSurfaceRegistry {
15
+ private readonly surfaces = new Map<string, ConfigModalSurface>();
16
+ private readonly redirects = new Map<string, string>();
17
+
18
+ /** Register (or replace) the surface for its name. */
19
+ registerModalSurface(surface: ConfigModalSurface): void {
20
+ this.surfaces.set(surface.name, surface);
21
+ }
22
+
23
+ /** Make an old name open a modal (e.g. 'accounts' opens 'providers-modal'). */
24
+ registerModalRedirect(name: string, modalName: string): void {
25
+ this.redirects.set(name, modalName);
26
+ }
27
+
28
+ getModalSurface(name: string): ConfigModalSurface | undefined {
29
+ return this.surfaces.get(name);
30
+ }
31
+
32
+ /** The modal an old name opens, or undefined. */
33
+ getModalRedirect(name: string): string | undefined {
34
+ return this.redirects.get(name);
35
+ }
36
+
37
+ /** Every old name that opens a modal, with the modal it opens. */
38
+ listRedirects(): ReadonlyArray<readonly [string, string]> {
39
+ return [...this.redirects.entries()];
40
+ }
41
+ }
@@ -62,7 +62,7 @@ class DevicesModalSurface implements ConfigModalSurface {
62
62
  const now = this.deps.now?.() ?? Date.now();
63
63
  const tokens = this.deps.pairingTokens.list();
64
64
  const rows: ConfigModalRow[] = [];
65
- rows.push(infoRow('intro', 'Devices paired to this daemon. Each has its own token; revoke one without affecting the others.', { dim: true }));
65
+ rows.push(infoRow('intro', 'Devices paired to this daemon. Each has its own token; revoke one without affecting the others.', { fg: MODAL_TONES.dim }));
66
66
 
67
67
  if (tokens.length === 0) {
68
68
  rows.push(infoRow('empty', 'No devices paired yet: run /pair (or open the pairing QR) to add one.'));
@@ -78,7 +78,7 @@ class DevicesModalSurface implements ConfigModalSurface {
78
78
  legacyRevoked
79
79
  ? 'Legacy shared token: revoked.'
80
80
  : 'Legacy shared token: active; migrate a device off it (m), then revoke it (s).',
81
- legacyRevoked ? { dim: true } : { fg: MODAL_TONES.reasoning },
81
+ legacyRevoked ? { fg: MODAL_TONES.dim } : { fg: MODAL_TONES.reasoning },
82
82
  ));
83
83
 
84
84
  return {