@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
@@ -4,7 +4,6 @@ import type { SearchManager } from './search.ts';
4
4
  import type { HistorySearch } from './input-history.ts';
5
5
  import type { ConversationManager } from '../core/conversation';
6
6
  import type { AutocompleteEngine } from './autocomplete.ts';
7
- import type { PanelManager } from '../panels/panel-manager.ts';
8
7
  import type { KeybindingsManager } from './keybindings.ts';
9
8
  import type { KillRing } from './kill-ring.ts';
10
9
  import { wordBoundaryBack, wordBoundaryForward } from './kill-ring.ts';
@@ -17,8 +16,6 @@ type WrappedPromptInfo = {
17
16
  };
18
17
 
19
18
  export type GlobalShortcutRouteState = {
20
- panelFocused: boolean;
21
- panelManager: PanelManager;
22
19
  keybindingsManager: KeybindingsManager;
23
20
  prompt: string;
24
21
  cursorPos: number;
@@ -45,7 +42,6 @@ export type GlobalShortcutRouteState = {
45
42
  handleRedo: () => void;
46
43
  handlePaste: () => void;
47
44
  handleEscape: () => void;
48
- cyclePanelTab: (direction: 'next' | 'prev') => void;
49
45
  killRing: KillRing;
50
46
  };
51
47
 
@@ -56,40 +52,27 @@ export function handleGlobalShortcutToken(
56
52
  ): boolean {
57
53
  if (token.type !== 'key') return false;
58
54
 
59
- // Fast-path: BARE pageup/pagedown scroll the transcript. The `!token.ctrl`
60
- // guard is load-bearing: Ctrl+PageUp/PageDown are the panel-tab-prev/next
61
- // chords, so they must fall through to the keybinding lookup below instead of
62
- // being swallowed here as a scroll.
55
+ // Fast-path: BARE pageup/pagedown scroll the transcript (modified ones fall
56
+ // through to the keybinding lookup below).
63
57
  if (token.logicalName === 'pageup' && !token.ctrl) {
64
- if (state.panelFocused) return false;
65
58
  state.scroll(-Math.max(1, viewportHeight - 2));
66
59
  return true;
67
60
  }
68
61
  if (token.logicalName === 'pagedown' && !token.ctrl) {
69
- if (state.panelFocused) return false;
70
62
  state.scroll(Math.max(1, viewportHeight - 2));
71
63
  return true;
72
64
  }
73
65
  // Bare escape is also not in the keybinding table.
74
- if (token.logicalName === 'escape' && !state.panelFocused) {
66
+ if (token.logicalName === 'escape') {
75
67
  state.handleEscape();
76
68
  return true;
77
69
  }
78
70
 
79
- // Bare F2 is also not in the keybinding table (hardcoded, like pageup/
80
- // pagedown/escape above), it must be handled here, GLOBALLY, rather than
81
- // in handlePromptKeyToken (handler-feed-routes.ts) where it used to live.
82
- // That location only ever runs when the panel workspace does NOT already
83
- // own focus (handlePanelFocusToken, which runs before it, swallows every
84
- // unclaimed key once panelFocused is true and reports it handled). The
85
- // practical effect was that F2 could OPEN+focus the Fleet panel exactly
86
- // once; every subsequent press while already focused vanished silently,
87
- // "F2 pressed 4x never closed the panel" (evaluator finding). Routing
88
- // it here, before handlePanelFocusToken ever sees the token, gives F2 the
89
- // same toggle semantics as Ctrl+O below, matching how Ctrl+P/panel-picker
90
- // was already reachable regardless of panelFocused.
71
+ // Bare F2 opens the Agents modal (hardcoded, like pageup/pagedown/escape;
72
+ // F2 inside the Agents modal closes it, see input/agents-modal.ts).
91
73
  if (token.logicalName === 'f2' && !token.ctrl && !token.meta) {
92
- toggleFleetPanel(state);
74
+ state.commandContext?.openAgents?.();
75
+ state.requestRender();
93
76
  return true;
94
77
  }
95
78
 
@@ -98,10 +81,9 @@ export function handleGlobalShortcutToken(
98
81
  // escape/f2, because it is not in the keybinding table and bare Tab is
99
82
  // already heavily overloaded. Arrives as the legacy xterm backtab literal
100
83
  // ('\x1b[Z') OR, under a kitty/CSI-u terminal, as tab-with-shift. Only when
101
- // the composer owns focus (a focused panel keeps its own Shift+Tab, e.g. the
102
- // diff panel's previous-file); modal/picker routes run earlier and swallow
103
- // the token before it reaches here, so overlays keep their reverse-tab too.
104
- if (!state.panelFocused && (token.logicalName === '\x1b[Z' || (token.logicalName === 'tab' && token.shift))) {
84
+ // the composer owns focus; modal/picker routes run earlier and swallow the
85
+ // token before it reaches here, so overlays keep their reverse-tab too.
86
+ if (token.logicalName === '\x1b[Z' || (token.logicalName === 'tab' && token.shift)) {
105
87
  cycleSessionPermissionMode(state);
106
88
  return true;
107
89
  }
@@ -133,10 +115,9 @@ export function handleGlobalShortcutToken(
133
115
  return true;
134
116
 
135
117
  case 'voice-input':
136
- // Start recording, or stop the recording already running. Routed globally so
137
- // the key works whether focus is on the composer or the panel workspace,
138
- // dictation is not a composer-only act. Still consumed when voice input is
139
- // not wired, so a stray Alt+V never lands in the prompt as text.
118
+ // Start recording, or stop the recording already running. Routed globally;
119
+ // still consumed when voice input is not wired, so a stray Alt+V never
120
+ // lands in the prompt as text.
140
121
  state.commandContext?.toggleVoiceInput?.();
141
122
  return true;
142
123
 
@@ -154,110 +135,17 @@ export function handleGlobalShortcutToken(
154
135
  state.commandContext?.clearScreen?.();
155
136
  return true;
156
137
 
157
- case 'panel-close-all': {
158
- const pm = state.panelManager;
159
- for (const p of pm.getAllOpen()) pm.close(p.id);
160
- pm.hide();
161
- state.panelFocused = false;
162
- state.requestRender();
163
- return true;
164
- }
165
-
166
- case 'panel-close': {
167
- const pm = state.panelManager;
168
- const active = pm.getActivePanel();
169
- // Give the active panel a chance to consume Ctrl+X for an
170
- // in-panel action (FleetPanel session-tab detach) before it closes the
171
- // panel outright, see Panel.interceptPanelClose's doc comment.
172
- if (active?.interceptPanelClose?.()) {
173
- // fix: a consumed Ctrl+X (the Fleet panel's session-tab detach)
174
- // used to leave panelFocused untouched, so focus stayed on the panel
175
- //, the evaluator's "Ctrl+X detach landed focus in the panel and a
176
- // typed question became nav keys". Detach is a leave-taking action:
177
- // like the ordinary close below, it hands control back to the
178
- // composer rather than leaving the user stranded on the fleet tree.
179
- state.panelFocused = false;
180
- state.requestRender();
181
- return true;
182
- }
183
- if (active) {
184
- pm.close(active.id);
185
- state.requestRender();
186
- }
187
- state.panelFocused = false;
188
- return true;
189
- }
190
-
191
138
  case 'command-palette':
192
139
  state.commandContext?.openCommandPalette?.();
193
140
  state.requestRender();
194
141
  return true;
195
142
 
196
- case 'panel-picker':
197
- state.commandContext?.openPanelPicker?.();
198
- state.panelFocused = state.panelManager.isVisible() && state.panelManager.getAllOpen().length > 0;
143
+ case 'open-agents':
144
+ // Ctrl+O: the Agents modal (the same as F2).
145
+ state.commandContext?.openAgents?.();
199
146
  state.requestRender();
200
147
  return true;
201
148
 
202
- case 'panel-focus-toggle': {
203
- // Global entry point for the focus-toggle key (Ctrl+G): from the prompt
204
- // it grabs focus for the panel workspace. Once the workspace already has
205
- // focus we let it fall through (return false) so handlePanelFocusToken
206
- // can do the top/bottom pane swap, keeping that behavior in one place.
207
- if (state.panelFocused) return false;
208
- const pm = state.panelManager;
209
- if (pm.isVisible() && pm.getAllOpen().length > 0) {
210
- state.panelFocused = true;
211
- state.requestRender();
212
- return true;
213
- }
214
- return false;
215
- }
216
-
217
- case 'panel-tab-next':
218
- state.cyclePanelTab('next');
219
- return true;
220
-
221
- case 'panel-tab-prev':
222
- state.cyclePanelTab('prev');
223
- return true;
224
-
225
- case 'panel-tab-1':
226
- case 'panel-tab-2':
227
- case 'panel-tab-3':
228
- case 'panel-tab-4':
229
- case 'panel-tab-5':
230
- case 'panel-tab-6':
231
- case 'panel-tab-7':
232
- case 'panel-tab-8':
233
- case 'panel-tab-9': {
234
- // Alt+1..9: jump directly to the Nth workspace tab. Routed globally (like
235
- // panel-tab-next/prev) so the jump works whether focus is on the prompt or
236
- // the workspace; gated on visibility, matching cyclePanelTab semantics.
237
- // a chord jump is "I'm going panel-driving" (focus rule 1a), the
238
- // jump now also grabs keyboard focus, matching F2/Ctrl+O/Ctrl+P, so j/k
239
- // land in the newly-active tab immediately instead of the composer.
240
- const pm = state.panelManager;
241
- if (pm.isVisible()) {
242
- const index = Number(action.slice('panel-tab-'.length)) - 1;
243
- pm.activateWorkspaceIndex(index);
244
- pm.focusPanels();
245
- state.panelFocused = true;
246
- state.requestRender();
247
- }
248
- return true;
249
- }
250
-
251
- case 'panel-ops': {
252
- // Ctrl+O: TOGGLE the Fleet panel (same semantics as F2 above; see
253
- // toggleFleetPanel's doc comment). The former Ops Control panel was
254
- // retired to an 'ops-control' -> 'fleet' alias; rather than route
255
- // through the now-aliased openOpsPanel callback (which opens without
256
- // transferring focus), this operates on 'fleet' directly.
257
- toggleFleetPanel(state);
258
- return true;
259
- }
260
-
261
149
  case 'history-search':
262
150
  state.historySearch.open(state.prompt);
263
151
  state.requestRender();
@@ -433,17 +321,6 @@ export function handleGlobalShortcutToken(
433
321
  }
434
322
  }
435
323
 
436
- /**
437
- * toggleFleetPanel, the shared F2 / Ctrl+O TOGGLE (item 2): if the
438
- * Fleet panel is open AND the panel workspace currently owns keyboard focus
439
- * with Fleet as the active tab, the chord CLOSES it and returns focus to the
440
- * composer; if Fleet is open but not the focused/active tab, the chord brings
441
- * it to front and focuses it; if Fleet isn't open at all, the chord opens and
442
- * focuses it. Uses `state.panelFocused` (not a panelManager query) for the
443
- * focus check, consistent with every other case in this file and with what
444
- * the mocked PanelManager test doubles in global-shortcuts.test.ts actually
445
- * implement.
446
- */
447
324
  /**
448
325
  * Cycle the session permission mode (Shift+Tab). The change goes through the
449
326
  * SDK config surface, configManager.set('permissions.mode', ...), which is
@@ -461,18 +338,3 @@ function cycleSessionPermissionMode(state: GlobalShortcutRouteState): void {
461
338
  state.commandContext?.print(`[Permissions] Mode: ${permissionModeLabel(next)}`);
462
339
  state.requestRender();
463
340
  }
464
-
465
- function toggleFleetPanel(state: GlobalShortcutRouteState): void {
466
- const pm = state.panelManager;
467
- const fleetOpen = pm.getAllOpen().some((p) => p.id === 'fleet');
468
- const fleetIsFocusedActive = fleetOpen && state.panelFocused && pm.getActivePanel()?.id === 'fleet';
469
- if (fleetIsFocusedActive) {
470
- pm.close('fleet');
471
- state.panelFocused = false;
472
- } else {
473
- pm.open('fleet');
474
- pm.focusPanels();
475
- state.panelFocused = true;
476
- }
477
- state.requestRender();
478
- }
@@ -97,8 +97,7 @@ export interface InputHandlerLike {
97
97
  // ── Modal state ───────────────────────────────────────────────────────────
98
98
  commandMode: boolean;
99
99
  modalStack: string[];
100
- modalReturnFocus: 'prompt' | 'panel' | 'indicator';
101
- panelFocused: boolean;
100
+ modalReturnFocus: 'prompt' | 'indicator';
102
101
  indicatorFocused: boolean;
103
102
  helpOverlayActive: boolean;
104
103
  helpScrollOffset: number;
@@ -118,6 +117,9 @@ export interface InputHandlerLike {
118
117
  modelPicker: ModelPickerModal;
119
118
  filePicker: FilePickerModal;
120
119
  blockActionsMenu: BlockActionsMenu;
120
+ surfaceModals: import('./surface-modal-host.ts').SurfaceModalHost;
121
+ sessionView: import('./handler-session-view-route.ts').SessionViewControls | null;
122
+ transcriptScroll: import('./handler-modal-stack.ts').TranscriptScrollControls | null;
121
123
  selectionModal: SelectionModal;
122
124
 
123
125
  // ── Onboarding ────────────────────────────────────────────────────────────
@@ -1,6 +1,8 @@
1
1
  import type { InputToken } from '@pellux/goodvibes-sdk/platform/core';
2
2
  import type { InfiniteBuffer } from '@pellux/goodvibes-terminal-shell';
3
3
  import type { SearchManager } from './search.ts';
4
+ import type { OverlayFilter, OverlayFilters } from './overlay-filter.ts';
5
+ import { isTextBackspace } from './delete-key-policy.ts';
4
6
  import type { HistorySearch } from './input-history.ts';
5
7
  import type { ConversationManager } from '../core/conversation';
6
8
  import type {
@@ -289,36 +291,64 @@ type OverlayRouteState = {
289
291
  helpScrollOffset: number;
290
292
  shortcutsOverlayActive: boolean;
291
293
  shortcutsScrollOffset: number;
294
+ /** The overlays' always-live search rows (absent in minimal test states). */
295
+ overlayFilters?: OverlayFilters;
292
296
  requestRender: () => void;
293
297
  handleEscape: () => void;
294
298
  };
295
299
 
300
+ /**
301
+ * Keys shared by the help and shortcuts overlays: ↑↓ and PgUp/PgDn scroll
302
+ * (never past the end the renderer recorded), printable text goes into the
303
+ * always-live search row (the offset returns to the top as the list
304
+ * narrows), Backspace edits it, Esc closes. Returns the new scroll offset.
305
+ */
306
+ function routeFilteredOverlayKey(token: InputToken, offset: number, filter: OverlayFilter | undefined): number {
307
+ const max = filter ? filter.maxScroll : 100;
308
+ if (token.type === 'key') {
309
+ if (token.logicalName === 'up') return Math.max(0, Math.min(offset, max) - 1);
310
+ if (token.logicalName === 'down') return Math.min(offset + 1, max);
311
+ if (token.logicalName === 'pageup') return Math.max(0, Math.min(offset, max) - 10);
312
+ if (token.logicalName === 'pagedown') return Math.min(offset + 10, max);
313
+ if (filter && isTextBackspace(token.logicalName ?? '') && filter.query.length > 0) {
314
+ filter.query = filter.query.slice(0, -1);
315
+ return 0;
316
+ }
317
+ return offset;
318
+ }
319
+ if (token.type === 'text' && filter) {
320
+ filter.query += token.value;
321
+ return 0;
322
+ }
323
+ return offset;
324
+ }
325
+
296
326
  export function handleOverlayToken(state: OverlayRouteState, token: InputToken): boolean {
297
327
  if (state.helpOverlayActive) {
298
- if (token.type === 'key') {
299
- if (token.logicalName === 'escape') {
300
- state.handleEscape();
301
- return true;
302
- }
303
- if (token.logicalName === 'up') state.helpScrollOffset = Math.max(0, state.helpScrollOffset - 1);
304
- else if (token.logicalName === 'down') state.helpScrollOffset = Math.min(state.helpScrollOffset + 1, 100);
305
- } else if (token.type === 'text' && token.value === '?') {
328
+ const filter = state.overlayFilters?.help;
329
+ if (token.type === 'key' && token.logicalName === 'escape') {
330
+ state.handleEscape();
331
+ return true;
332
+ }
333
+ // '?' toggles help closed, but only while the query is empty; once
334
+ // something is typed, '?' is just another character.
335
+ if (token.type === 'text' && token.value === '?' && (!filter || filter.query.length === 0)) {
306
336
  state.helpOverlayActive = false;
307
337
  state.helpScrollOffset = 0;
338
+ filter?.clear();
339
+ } else {
340
+ state.helpScrollOffset = routeFilteredOverlayKey(token, state.helpScrollOffset, filter);
308
341
  }
309
342
  state.requestRender();
310
343
  return true;
311
344
  }
312
345
 
313
346
  if (state.shortcutsOverlayActive) {
314
- if (token.type === 'key') {
315
- if (token.logicalName === 'escape') {
316
- state.handleEscape();
317
- return true;
318
- }
319
- if (token.logicalName === 'up') state.shortcutsScrollOffset = Math.max(0, state.shortcutsScrollOffset - 1);
320
- else if (token.logicalName === 'down') state.shortcutsScrollOffset = Math.min(state.shortcutsScrollOffset + 1, 50);
347
+ if (token.type === 'key' && token.logicalName === 'escape') {
348
+ state.handleEscape();
349
+ return true;
321
350
  }
351
+ state.shortcutsScrollOffset = routeFilteredOverlayKey(token, state.shortcutsScrollOffset, state.overlayFilters?.shortcuts);
322
352
  state.requestRender();
323
353
  return true;
324
354
  }
@@ -0,0 +1,123 @@
1
+ /**
2
+ * handler-work-tree-route.ts, the keyboard inside the conversation work tree.
3
+ *
4
+ * The `focus-work-tree` binding (Alt+Up, Ctrl+Up) moves the keyboard from the
5
+ * composer onto the work tree's rows. There:
6
+ *
7
+ * ↑ ↓ move between beads (and turn headers and agent lanes)
8
+ * ← → fold / unfold
9
+ * Enter open a bead's body; on an agent lane open that agent full
10
+ * screen; on a ▶ bead open that background process's output
11
+ * y copy the focused row's content
12
+ * Esc back to typing (never stops or cancels anything)
13
+ *
14
+ * Any other key hands the keyboard back to the composer and is typed there,
15
+ * so starting to type never needs an Esc first.
16
+ */
17
+
18
+ import type { InputToken } from '@pellux/goodvibes-sdk/platform/core';
19
+ import type { ConversationManager } from '../core/conversation.ts';
20
+ import { handleBlockCopy } from './handler-content-actions.ts';
21
+
22
+ export interface WorkTreeRouteState {
23
+ readonly conversationManager: ConversationManager | null;
24
+ /** The token matches the `focus-work-tree` binding. */
25
+ readonly enterMatch: boolean;
26
+ /** The last visible transcript line (where focus lands on entry). */
27
+ readonly anchorLine: number;
28
+ readonly scrollTop: number;
29
+ readonly viewportHeight: number;
30
+ readonly scroll: (delta: number) => void;
31
+ readonly requestRender: () => void;
32
+ readonly onCopied: () => void;
33
+ /** Open an agent full screen (Enter on its lane); false when it cannot be opened. */
34
+ readonly openAgent?: (agentId: string) => boolean;
35
+ /** Open a background process's output (Enter on its ▶ bead); false when it cannot be opened. */
36
+ readonly openProcess?: (processId: string) => boolean;
37
+ }
38
+
39
+ /** Scroll so the focused row (and as much of its opened body as fits) is visible. */
40
+ function revealFocus(state: WorkTreeRouteState): void {
41
+ const block = state.conversationManager?.workTree.focusBlock();
42
+ if (!block) return;
43
+ const top = block.startLine;
44
+ const bottom = block.startLine + Math.min(Math.max(1, block.lineCount), state.viewportHeight) - 1;
45
+ if (top < state.scrollTop) state.scroll(top - state.scrollTop);
46
+ else if (bottom >= state.scrollTop + state.viewportHeight) state.scroll(bottom - (state.scrollTop + state.viewportHeight) + 1);
47
+ }
48
+
49
+ /** Returns true when the token was handled here. */
50
+ export function handleWorkTreeToken(state: WorkTreeRouteState, token: InputToken): boolean {
51
+ const cm = state.conversationManager;
52
+ if (!cm) return false;
53
+ const tree = cm.workTree;
54
+
55
+ if (!tree.focused) {
56
+ if (token.type !== 'key' || !state.enterMatch) return false;
57
+ if (tree.enter(state.anchorLine)) revealFocus(state);
58
+ state.requestRender();
59
+ return true;
60
+ }
61
+
62
+ if (token.type === 'text') {
63
+ if (token.value === 'y') {
64
+ const block = tree.focusBlock();
65
+ if (block) handleBlockCopy(cm, () => block.startLine, state.requestRender, state.onCopied);
66
+ return true;
67
+ }
68
+ // Typing goes back to the composer.
69
+ tree.leave();
70
+ state.requestRender();
71
+ return false;
72
+ }
73
+ if (token.type !== 'key') return false;
74
+
75
+ if (!token.ctrl && !token.meta) {
76
+ switch (token.logicalName) {
77
+ case 'escape':
78
+ tree.leave();
79
+ state.requestRender();
80
+ return true;
81
+ case 'up':
82
+ case 'down':
83
+ tree.move(token.logicalName === 'up' ? -1 : 1);
84
+ revealFocus(state);
85
+ state.requestRender();
86
+ return true;
87
+ case 'enter': {
88
+ const wt = tree.focusBlock()?.workTree;
89
+ const opened = wt?.kind === 'lane' && wt.agentId ? state.openAgent?.(wt.agentId)
90
+ : wt?.kind === 'bead' && wt.processId ? state.openProcess?.(wt.processId)
91
+ : false;
92
+ if (opened) {
93
+ tree.leave();
94
+ state.requestRender();
95
+ return true;
96
+ }
97
+ tree.act('activate');
98
+ revealFocus(state);
99
+ state.requestRender();
100
+ return true;
101
+ }
102
+ case 'left':
103
+ case 'right':
104
+ tree.act(token.logicalName === 'left' ? 'fold' : 'unfold');
105
+ revealFocus(state);
106
+ state.requestRender();
107
+ return true;
108
+ case 'y':
109
+ {
110
+ const block = tree.focusBlock();
111
+ if (block) handleBlockCopy(cm, () => block.startLine, state.requestRender, state.onCopied);
112
+ }
113
+ return true;
114
+ default:
115
+ break;
116
+ }
117
+ }
118
+ if (state.enterMatch) return true;
119
+ // Anything else goes back to the composer (and is handled there).
120
+ tree.leave();
121
+ state.requestRender();
122
+ return false;
123
+ }