@pellux/goodvibes-tui 2.0.20 → 2.1.0

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 (388) hide show
  1. package/CHANGELOG.md +70 -0
  2. package/README.md +16 -16
  3. package/docs/README.md +4 -4
  4. package/docs/foundation-artifacts/operator-contract.json +59 -4
  5. package/package.json +16 -6
  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-registry.ts +77 -35
  52. package/src/input/commands/acp-runtime.ts +19 -9
  53. package/src/input/commands/channel-runtime.ts +2 -2
  54. package/src/input/commands/ci-runtime.ts +1 -1
  55. package/src/input/commands/codebase-runtime.ts +1 -1
  56. package/src/input/commands/config.ts +7 -1
  57. package/src/input/commands/context-window.ts +25 -19
  58. package/src/input/commands/control-room-runtime.ts +18 -18
  59. package/src/input/commands/conversation-runtime.ts +0 -1
  60. package/src/input/commands/cost-runtime.ts +29 -20
  61. package/src/input/commands/diff-runtime.ts +35 -181
  62. package/src/input/commands/eval.ts +1 -1
  63. package/src/input/commands/experience-runtime.ts +3 -7
  64. package/src/input/commands/fresh-conversation.ts +86 -0
  65. package/src/input/commands/git-runtime.ts +5 -22
  66. package/src/input/commands/graph-runtime.ts +1 -1
  67. package/src/input/commands/guidance-runtime.ts +1 -1
  68. package/src/input/commands/health-runtime.ts +8 -9
  69. package/src/input/commands/hooks-runtime.ts +2 -2
  70. package/src/input/commands/hosted-runtime.ts +3 -3
  71. package/src/input/commands/incident-runtime.ts +3 -3
  72. package/src/input/commands/intelligence-runtime.ts +6 -9
  73. package/src/input/commands/knowledge.ts +2 -2
  74. package/src/input/commands/legacy-panel-command.ts +57 -0
  75. package/src/input/commands/local-auth-runtime.ts +8 -9
  76. package/src/input/commands/local-provider-runtime.ts +7 -4
  77. package/src/input/commands/local-runtime.ts +12 -15
  78. package/src/input/commands/local-setup-review.ts +1 -1
  79. package/src/input/commands/local-setup.ts +13 -19
  80. package/src/input/commands/memory.ts +1 -1
  81. package/src/input/commands/notify-runtime.ts +9 -0
  82. package/src/input/commands/operator-runtime.ts +10 -12
  83. package/src/input/commands/permissions-provenance.ts +3 -3
  84. package/src/input/commands/planning-runtime.ts +7 -7
  85. package/src/input/commands/platform-sandbox-runtime.ts +2 -2
  86. package/src/input/commands/platform-services-runtime.ts +1 -1
  87. package/src/input/commands/policy-dispatch.ts +2 -2
  88. package/src/input/commands/policy.ts +3 -3
  89. package/src/input/commands/provider.ts +1 -1
  90. package/src/input/commands/remote-runtime.ts +1 -1
  91. package/src/input/commands/review-runtime.ts +39 -94
  92. package/src/input/commands/rewind-runtime.ts +81 -108
  93. package/src/input/commands/runtime-services.ts +15 -17
  94. package/src/input/commands/services-runtime.ts +2 -2
  95. package/src/input/commands/session-content.ts +21 -5
  96. package/src/input/commands/session-workflow.ts +13 -38
  97. package/src/input/commands/settings-sync-runtime.ts +2 -2
  98. package/src/input/commands/shell-core.ts +19 -4
  99. package/src/input/commands/skills-runtime.ts +2 -2
  100. package/src/input/commands/status-runtime.ts +13 -0
  101. package/src/input/commands/subscription-runtime.ts +1 -1
  102. package/src/input/commands/tasks-runtime.ts +2 -8
  103. package/src/input/commands/work-plan-runtime.ts +4 -4
  104. package/src/input/commands/workstream-attempts.ts +24 -47
  105. package/src/input/commands/workstream-runtime.ts +2 -2
  106. package/src/input/commands/worktree-runtime.ts +3 -3
  107. package/src/input/commands.ts +3 -1
  108. package/src/input/composer-editor.ts +44 -0
  109. package/src/input/concealed-input.ts +1 -1
  110. package/src/input/config-modal-types.ts +20 -8
  111. package/src/input/config-modal.ts +106 -105
  112. package/src/input/confirm-dialog-types.ts +28 -0
  113. package/src/input/confirm-dialog.ts +70 -0
  114. package/src/input/delete-key-policy.ts +3 -3
  115. package/src/input/feed-context-factory.ts +15 -16
  116. package/src/input/handler-command-route.ts +7 -42
  117. package/src/input/handler-content-actions.ts +16 -15
  118. package/src/input/handler-feed-routes.ts +26 -211
  119. package/src/input/handler-feed.ts +68 -95
  120. package/src/input/handler-interactions.ts +5 -3
  121. package/src/input/handler-modal-routes.ts +215 -216
  122. package/src/input/handler-modal-stack.ts +81 -11
  123. package/src/input/handler-modal-token-routes.ts +4 -0
  124. package/src/input/handler-onboarding.ts +0 -1
  125. package/src/input/handler-picker-routes.ts +65 -107
  126. package/src/input/handler-session-view-route.ts +149 -0
  127. package/src/input/handler-shortcuts.ts +16 -154
  128. package/src/input/handler-types.ts +4 -2
  129. package/src/input/handler-ui-state.ts +45 -15
  130. package/src/input/handler-work-tree-route.ts +123 -0
  131. package/src/input/handler.ts +25 -70
  132. package/src/input/keybindings.ts +16 -71
  133. package/src/input/masked-entry-modal.ts +117 -0
  134. package/src/input/mcp-workspace.ts +48 -17
  135. package/src/input/model-picker-filter.ts +8 -0
  136. package/src/input/model-picker-open.ts +99 -0
  137. package/src/input/model-picker-types.ts +1 -1
  138. package/src/input/model-picker.ts +92 -9
  139. package/src/input/notifications-modal.ts +123 -0
  140. package/src/input/overlay-filter.ts +26 -0
  141. package/src/input/profile-picker-modal.ts +37 -8
  142. package/src/input/search.ts +3 -3
  143. package/src/input/selection-modal-queue.ts +2 -0
  144. package/src/input/selection-modal.ts +28 -16
  145. package/src/input/session-picker-modal.ts +33 -8
  146. package/src/input/settings-modal-activation.ts +7 -2
  147. package/src/input/settings-modal-data.ts +11 -6
  148. package/src/input/settings-modal-types.ts +1 -1
  149. package/src/input/settings-modal.ts +20 -20
  150. package/src/input/submission-intent.ts +1 -1
  151. package/src/input/submission-router.ts +4 -9
  152. package/src/input/surface-modal-host.ts +110 -0
  153. package/src/input/theme-settings-actions.ts +82 -0
  154. package/src/input/usage-modal.ts +183 -0
  155. package/src/input/views.ts +97 -0
  156. package/src/main.ts +175 -165
  157. package/src/permissions/hunk-selection.ts +1 -1
  158. package/src/permissions/prompt-card.ts +511 -0
  159. package/src/permissions/prompt.ts +59 -622
  160. package/src/renderer/agents-modal.ts +310 -0
  161. package/src/renderer/autocomplete-overlay.ts +42 -220
  162. package/src/renderer/back-to-bottom.ts +80 -0
  163. package/src/renderer/block-actions-overlay.ts +30 -48
  164. package/src/renderer/bookmark-modal.ts +48 -79
  165. package/src/renderer/changes-modal.ts +325 -0
  166. package/src/renderer/code-block.ts +184 -106
  167. package/src/renderer/command-palette.ts +93 -0
  168. package/src/renderer/composer-fragments.ts +4 -4
  169. package/src/renderer/composer.ts +146 -0
  170. package/src/renderer/compositor.ts +26 -160
  171. package/src/renderer/config-modal.ts +185 -81
  172. package/src/renderer/confirm-dialog.ts +50 -0
  173. package/src/renderer/context-inspector.ts +116 -154
  174. package/src/renderer/context-status-hint.ts +4 -4
  175. package/src/renderer/conversation-layout.ts +20 -0
  176. package/src/renderer/conversation-overlays.ts +94 -84
  177. package/src/renderer/conversation-surface.ts +19 -38
  178. package/src/renderer/diff-tint.ts +98 -0
  179. package/src/renderer/file-picker-overlay.ts +63 -90
  180. package/src/renderer/footer-targets.ts +38 -0
  181. package/src/renderer/git-status.ts +3 -4
  182. package/src/renderer/header-line.ts +140 -117
  183. package/src/renderer/help-overlay.ts +133 -219
  184. package/src/renderer/history-search-overlay.ts +15 -12
  185. package/src/renderer/lane-graph/bead.ts +800 -0
  186. package/src/renderer/lane-graph/glyphs.ts +134 -0
  187. package/src/renderer/lane-graph/layout.ts +248 -0
  188. package/src/renderer/lane-graph/paint.ts +537 -0
  189. package/src/renderer/lane-graph/semantic-memo.ts +77 -0
  190. package/src/renderer/layout-engine.ts +2 -57
  191. package/src/renderer/layout.ts +7 -13
  192. package/src/renderer/markdown-inline.ts +2 -1
  193. package/src/renderer/markdown-table.ts +17 -12
  194. package/src/renderer/markdown.ts +92 -34
  195. package/src/renderer/masked-entry-modal.ts +78 -0
  196. package/src/renderer/mcp-workspace.ts +166 -203
  197. package/src/renderer/model-workspace.ts +381 -436
  198. package/src/renderer/notifications-modal.ts +116 -0
  199. package/src/renderer/onboarding/onboarding-wizard.ts +178 -588
  200. package/src/renderer/process-view.ts +192 -0
  201. package/src/renderer/profile-picker-modal.ts +58 -110
  202. package/src/renderer/search-overlay.ts +6 -3
  203. package/src/renderer/selection-modal-overlay.ts +87 -327
  204. package/src/renderer/semantic-diff.ts +2 -2
  205. package/src/renderer/session-chips.ts +102 -0
  206. package/src/renderer/session-picker-modal.ts +177 -297
  207. package/src/renderer/settings-modal-connections.ts +14 -23
  208. package/src/renderer/settings-modal-context.ts +367 -0
  209. package/src/renderer/settings-modal-helpers.ts +6 -11
  210. package/src/renderer/settings-modal.ts +322 -726
  211. package/src/renderer/shell-surface.ts +277 -175
  212. package/src/renderer/shortcuts-overlay.ts +217 -0
  213. package/src/renderer/status-line.ts +475 -0
  214. package/src/renderer/surface-compose.ts +174 -0
  215. package/src/renderer/surface-kit-extra.ts +303 -0
  216. package/src/renderer/surface-kit-list.ts +366 -0
  217. package/src/renderer/surface-kit-parts.ts +360 -0
  218. package/src/renderer/surface-kit.ts +568 -0
  219. package/src/renderer/syntax-highlighter.ts +280 -197
  220. package/src/renderer/syntax-theme.ts +51 -0
  221. package/src/renderer/system-message.ts +0 -1
  222. package/src/renderer/term-caps.ts +42 -1
  223. package/src/renderer/terminal-bg-probe.ts +116 -19
  224. package/src/renderer/terminal-palette-probe.ts +322 -0
  225. package/src/renderer/terminal-palette-reader.ts +183 -0
  226. package/src/renderer/terminal-palette.ts +58 -0
  227. package/src/renderer/theme-mode-config.ts +16 -1
  228. package/src/renderer/theme.ts +234 -207
  229. package/src/renderer/thinking.ts +0 -1
  230. package/src/renderer/throbber.ts +188 -0
  231. package/src/renderer/toast-center.ts +119 -0
  232. package/src/renderer/ui-factory.ts +39 -602
  233. package/src/renderer/ui-primitives.ts +8 -25
  234. package/src/renderer/usage-modal.ts +353 -0
  235. package/src/renderer/user-message.ts +58 -0
  236. package/src/renderer/voice-capture-chip.ts +53 -0
  237. package/src/runtime/bootstrap-command-context.ts +0 -5
  238. package/src/runtime/bootstrap-command-parts.ts +38 -89
  239. package/src/runtime/bootstrap-core.ts +13 -15
  240. package/src/runtime/bootstrap-hook-bridge.ts +12 -21
  241. package/src/runtime/bootstrap-notifier-sync.ts +17 -1
  242. package/src/runtime/bootstrap-shell.ts +16 -50
  243. package/src/runtime/bootstrap.ts +14 -14
  244. package/src/runtime/client/fleet-union.ts +5 -5
  245. package/src/runtime/client/hosted-exit.ts +2 -2
  246. package/src/runtime/client/hosted-sessions.ts +1 -1
  247. package/src/runtime/client/spine-adoption.ts +1 -1
  248. package/src/runtime/context-accounting-source.ts +5 -4
  249. package/src/runtime/index.ts +1 -0
  250. package/src/runtime/notification-dispatch.ts +102 -29
  251. package/src/runtime/recovery-offer-wiring.ts +4 -1
  252. package/src/runtime/recovery-prompt.ts +31 -15
  253. package/src/runtime/runtime-services-types.ts +10 -6
  254. package/src/runtime/services.ts +17 -12
  255. package/src/runtime/session-continuity-hints.ts +2 -5
  256. package/src/runtime/session-inbound-inputs.ts +1 -1
  257. package/src/runtime/session-resume-liveness-confirm.ts +14 -2
  258. package/src/runtime/startup-typeahead-gate.ts +103 -0
  259. package/src/runtime/store/domains/domain-read-matrix.ts +0 -1
  260. package/src/runtime/store/domains/index.ts +0 -8
  261. package/src/runtime/store/selectors/index.ts +0 -28
  262. package/src/runtime/store/state.ts +0 -8
  263. package/src/runtime/ui-services.ts +4 -6
  264. package/src/runtime/usage-tracker.ts +348 -0
  265. package/src/runtime/wrfc-persistence.ts +4 -4
  266. package/src/shell/blocking-input.ts +92 -2
  267. package/src/shell/recovery-input-helpers.ts +1 -1
  268. package/src/shell/session-views.ts +539 -0
  269. package/src/shell/status-report.ts +86 -0
  270. package/src/shell/transcript-scroll.ts +68 -0
  271. package/src/shell/ui-openers.ts +84 -172
  272. package/src/shell/view-openers.ts +205 -0
  273. package/src/tools/wrfc-agent-guard.ts +22 -2
  274. package/src/utils/format-duration.ts +4 -8
  275. package/src/utils/splash-lines.ts +9 -1
  276. package/src/utils/terminal-width.ts +56 -0
  277. package/src/verification/verification-ledger.ts +18 -16
  278. package/src/{panels → views}/agent-inspector-shared.ts +2 -2
  279. package/src/{panels → views}/builtin-modals.ts +22 -21
  280. package/src/views/builtin-views.ts +135 -0
  281. package/src/{panels → views}/confirm-state.ts +9 -9
  282. package/src/{panels → views}/diff-review-model.ts +10 -3
  283. package/src/{panels → views}/eval-registry.ts +1 -1
  284. package/src/{panels → views}/fleet-acts.ts +49 -85
  285. package/src/{panels/fleet-panel-format.ts → views/fleet-format.ts} +40 -40
  286. package/src/{panels → views}/fleet-gateway.ts +5 -5
  287. package/src/{panels → views}/fleet-observed-render.ts +16 -16
  288. package/src/{panels → views}/fleet-read-model.ts +9 -9
  289. package/src/{panels/fleet-tabs.ts → views/fleet-session-tabs.ts} +13 -13
  290. package/src/{panels → views}/fleet-spawn.ts +33 -49
  291. package/src/{panels → views}/fleet-steer.ts +12 -12
  292. package/src/{panels → views}/fleet-stop.ts +4 -4
  293. package/src/{panels → views}/fleet-transcript.ts +26 -27
  294. package/src/{panels/fleet-panel-worktree-detail.ts → views/fleet-worktree-detail.ts} +7 -7
  295. package/src/{panels → views}/hosted-session-feed.ts +6 -6
  296. package/src/views/modal-surface-registry.ts +41 -0
  297. package/src/{panels → views}/modals/devices-modal.ts +2 -2
  298. package/src/{panels → views}/modals/hooks-modal.ts +13 -13
  299. package/src/{panels → views}/modals/keybindings-modal.ts +19 -27
  300. package/src/{panels → views}/modals/knowledge-modal.ts +6 -5
  301. package/src/{panels → views}/modals/local-auth-modal.ts +22 -21
  302. package/src/{panels → views}/modals/marketplace-modal.ts +11 -11
  303. package/src/{panels → views}/modals/memory-modal.ts +8 -8
  304. package/src/{panels → views}/modals/modal-surface-helpers.ts +15 -5
  305. package/src/{panels → views}/modals/pairing-modal.ts +9 -9
  306. package/src/{panels → views}/modals/planning-modal.ts +15 -20
  307. package/src/{panels → views}/modals/plugins-modal.ts +6 -6
  308. package/src/{panels → views}/modals/policy-modal.ts +13 -5
  309. package/src/{panels → views}/modals/provider-health-modal.ts +4 -4
  310. package/src/{panels → views}/modals/remote-modal.ts +3 -3
  311. package/src/{panels → views}/modals/sandbox-modal.ts +4 -4
  312. package/src/{panels → views}/modals/security-modal.ts +22 -16
  313. package/src/{panels → views}/modals/services-modal.ts +3 -3
  314. package/src/{panels → views}/modals/settings-sync-modal.ts +4 -4
  315. package/src/{panels → views}/modals/skills-modal.ts +9 -9
  316. package/src/{panels → views}/modals/subscription-modal.ts +3 -3
  317. package/src/{panels → views}/modals/work-plan-modal.ts +10 -13
  318. package/src/views/notifications-feed.ts +314 -0
  319. package/src/{panels → views}/polish-core.ts +38 -36
  320. package/src/{panels → views}/polish-tables.ts +35 -26
  321. package/src/{panels → views}/polish.ts +101 -95
  322. package/src/{panels → views}/project-planning-answer-actions.ts +3 -3
  323. package/src/{panels → views}/provider-health-routes.ts +14 -14
  324. package/src/{panels → views}/search-focus.ts +8 -8
  325. package/src/{panels → views}/session-maintenance.ts +11 -11
  326. package/src/views/skills-discovery.ts +159 -0
  327. package/src/views/view-deps.ts +80 -0
  328. package/src/views/view-panel-adapter.ts +53 -0
  329. package/src/{panels → views}/workstream-graph-render.ts +1 -1
  330. package/src/core/conversation-fold.ts +0 -101
  331. package/src/core/conversation-turn-structure.ts +0 -464
  332. package/src/core/conversation-user-receipts.ts +0 -42
  333. package/src/input/commands/operator-panel-runtime.ts +0 -186
  334. package/src/input/panel-integration-actions.ts +0 -33
  335. package/src/input/panel-mouse-geometry.ts +0 -97
  336. package/src/input/panel-paste-flood-guard.ts +0 -86
  337. package/src/panels/base-panel.ts +0 -301
  338. package/src/panels/builtin/agent.ts +0 -27
  339. package/src/panels/builtin/development.ts +0 -92
  340. package/src/panels/builtin/knowledge.ts +0 -12
  341. package/src/panels/builtin/operations.ts +0 -177
  342. package/src/panels/builtin/session.ts +0 -81
  343. package/src/panels/builtin/shared.ts +0 -357
  344. package/src/panels/builtin-panels.ts +0 -28
  345. package/src/panels/cost-tracker-panel.ts +0 -746
  346. package/src/panels/diff-panel.ts +0 -797
  347. package/src/panels/diff-review-panel.ts +0 -395
  348. package/src/panels/expandable-list-panel.ts +0 -189
  349. package/src/panels/fleet-deep-link.ts +0 -31
  350. package/src/panels/fleet-panel.ts +0 -799
  351. package/src/panels/git-panel.ts +0 -800
  352. package/src/panels/hosted-session-panel.ts +0 -221
  353. package/src/panels/index.ts +0 -21
  354. package/src/panels/local-auth-panel.ts +0 -478
  355. package/src/panels/notifications-feed.ts +0 -127
  356. package/src/panels/notifications-panel.ts +0 -160
  357. package/src/panels/panel-confirm-overlay.ts +0 -72
  358. package/src/panels/panel-manager.ts +0 -791
  359. package/src/panels/plugins-panel.ts +0 -371
  360. package/src/panels/scrollable-list-panel.ts +0 -498
  361. package/src/panels/skills-panel.ts +0 -454
  362. package/src/panels/token-budget-panel.ts +0 -688
  363. package/src/panels/types.ts +0 -191
  364. package/src/panels/wrfc-panel-format.ts +0 -133
  365. package/src/renderer/diff-view.ts +0 -134
  366. package/src/renderer/fleet-tab-strip.ts +0 -56
  367. package/src/renderer/footer-tips.ts +0 -53
  368. package/src/renderer/fullscreen-primitives.ts +0 -146
  369. package/src/renderer/fullscreen-workspace.ts +0 -194
  370. package/src/renderer/hint-grammar.ts +0 -52
  371. package/src/renderer/modal-factory.ts +0 -480
  372. package/src/renderer/overlay-box.ts +0 -154
  373. package/src/renderer/overlay-viewport.ts +0 -104
  374. package/src/renderer/panel-composite.ts +0 -145
  375. package/src/renderer/panel-workspace-bar.ts +0 -54
  376. package/src/renderer/process-indicator.ts +0 -163
  377. package/src/renderer/tab-strip.ts +0 -222
  378. package/src/renderer/text-layout.ts +0 -31
  379. package/src/renderer/tool-call.ts +0 -276
  380. package/src/renderer/tool-result-expanded-lines.ts +0 -48
  381. package/src/renderer/tool-result-summary.ts +0 -219
  382. package/src/runtime/diagnostics/panels/index.ts +0 -21
  383. package/src/runtime/diagnostics/panels/ops.ts +0 -156
  384. package/src/runtime/perf/panel-contracts.ts +0 -32
  385. package/src/runtime/store/domains/panels.ts +0 -117
  386. /package/src/{panels → views}/memory-consolidation-gateway.ts +0 -0
  387. /package/src/{panels → views}/modals/modal-theme.ts +0 -0
  388. /package/src/{panels → views}/provider-health-domains.ts +0 -0
@@ -1,7 +1,7 @@
1
1
  import { mkdirSync, readFileSync, writeFileSync } from 'node:fs';
2
2
  import { dirname, resolve } from 'node:path';
3
3
  import type { CommandRegistry } from '../command-registry.ts';
4
- import { requirePanelManager, requireShellPaths } from './runtime-services.ts';
4
+ import { requireShellPaths } from './runtime-services.ts';
5
5
  import { createVoiceProvisionGateway, renderVoiceProvision, runVoiceSetupWithProgress, VOICE_SETUP_ANNOUNCEMENT } from '../../core/voice-provision-gateway.ts';
6
6
  import { resolveWakeRuntimeSettings } from '@pellux/goodvibes-sdk/platform/voice/wake/runtime';
7
7
  import { terminalWakeCapabilities } from '../../core/wake-provision-status.ts';
@@ -158,12 +158,8 @@ export function registerExperienceRuntimeCommands(registry: CommandRegistry): vo
158
158
  handler(args, ctx) {
159
159
  const sub = (args[0] ?? 'matrix').toLowerCase();
160
160
  if (sub === 'open' || sub === 'panel') {
161
- if (ctx.showPanel) ctx.showPanel('approval');
162
- else {
163
- const panelManager = requirePanelManager(ctx);
164
- panelManager.open('approval');
165
- panelManager.show();
166
- }
161
+ // Approvals waiting on you are rows in the Agents view (b jumps to them).
162
+ if (!ctx.openView?.('approval')) ctx.print('The Agents view is not available in this session.');
167
163
  return;
168
164
  }
169
165
  const matrix = [
@@ -0,0 +1,86 @@
1
+ /**
2
+ * fresh-conversation.ts, what /clear does: start a fresh conversation in this
3
+ * terminal session without losing the one on screen.
4
+ *
5
+ * /clear used to hide the transcript while keeping every message in the
6
+ * model's context, so the header kept the old title and the status line kept
7
+ * the old context usage, both true of a conversation the screen no longer
8
+ * showed. Now the conversation on screen is first saved as its own session
9
+ * (resumable by id, like /session fork, taking its view sidecar and rewind
10
+ * anchors with it), then the live conversation is reset: no messages, no
11
+ * title, the system prompt reloaded, no rewind anchors, and the usage counters
12
+ * recomputed from the (empty) transcript, so the header and status line
13
+ * describe the fresh conversation.
14
+ */
15
+
16
+ import { randomBytes } from 'node:crypto';
17
+ import { rmSync } from 'node:fs';
18
+ import { join } from 'node:path';
19
+ import type { SessionMeta } from '@pellux/goodvibes-sdk/platform/sessions';
20
+ import { clearTurnAnchors, getTurnAnchors, persistTurnAnchors, recordTurnAnchor } from '@pellux/goodvibes-sdk/platform/rewind';
21
+ import type { CommandContext } from '../command-registry.ts';
22
+ import { saveWorkTreeFolds } from '../../core/work-tree-fold-store.ts';
23
+
24
+ export interface FreshConversationResult {
25
+ /** Session id the previous conversation was saved under, or null when there was nothing to keep. */
26
+ readonly savedAs: string | null;
27
+ }
28
+
29
+ /** Whether a transcript holds a conversation worth keeping (anything the user or the model said). */
30
+ function hasConversation(ctx: CommandContext): boolean {
31
+ return ctx.session.conversationManager.getMessageSnapshot().some((m) => m.role === 'user' || m.role === 'assistant');
32
+ }
33
+
34
+ /**
35
+ * Save the conversation on screen as its own session, then reset the live one.
36
+ * Throws (and changes nothing) when the save fails, so a conversation is never
37
+ * dropped without a saved copy.
38
+ */
39
+ export function startFreshConversation(ctx: CommandContext): FreshConversationResult {
40
+ const conversation = ctx.session.conversationManager;
41
+ const surface = ctx.workspace.surface;
42
+ let savedAs: string | null = null;
43
+ if (hasConversation(ctx) && ctx.session.sessionManager) {
44
+ const id = `user-${randomBytes(4).toString('hex')}`;
45
+ const exported = conversation.toJSON() as { messages?: unknown[] };
46
+ const meta: SessionMeta = {
47
+ title: conversation.title,
48
+ model: ctx.session.runtime.model,
49
+ provider: ctx.session.runtime.provider,
50
+ timestamp: Date.now(),
51
+ titleSource: conversation.getTitleSource(),
52
+ // The user asked for this conversation to be set aside; it is not turn machinery.
53
+ saveSource: 'user',
54
+ };
55
+ ctx.session.sessionManager.save(id, (exported.messages ?? []) as never[], meta);
56
+ if (surface) {
57
+ // The saved copy keeps its view (folds, failed/cancelled turn headers)
58
+ // and its rewind anchors, which describe exactly that transcript.
59
+ saveWorkTreeFolds(surface.sessionsDir, id, conversation.workTree.foldState(), conversation.workTree.turnOutcomes());
60
+ for (const anchor of getTurnAnchors(ctx.session.runtime.sessionId)) recordTurnAnchor(id, anchor);
61
+ persistTurnAnchors(id, surface);
62
+ }
63
+ savedAs = id;
64
+ }
65
+
66
+ const liveId = ctx.session.runtime.sessionId;
67
+ conversation.resetAll();
68
+ if (ctx.reloadSystemPrompt) ctx.session.runtime.systemPrompt = ctx.reloadSystemPrompt();
69
+ // Rewind anchors and the view sidecar point into the old transcript.
70
+ clearTurnAnchors(liveId);
71
+ if (surface) {
72
+ // persistTurnAnchors writes nothing for an empty list, so the old sidecar
73
+ // (`<sessionId>.anchors.json`, the SDK's rewind/turn-anchors.ts name) is
74
+ // removed here, or a later resume would bring the old anchors back.
75
+ try {
76
+ if (!/[\\/]/.test(liveId)) rmSync(join(surface.sessionsDir, `${liveId}.anchors.json`), { force: true });
77
+ } catch {
78
+ // best effort: the in-memory anchors are already gone
79
+ }
80
+ saveWorkTreeFolds(surface.sessionsDir, liveId, [], []);
81
+ }
82
+ // Token counters and context usage come from the transcript: now empty.
83
+ ctx.session.hydrateSessionUsage?.();
84
+ conversation.rebuildHistory();
85
+ return { savedAs };
86
+ }
@@ -1,6 +1,6 @@
1
1
  import type { CommandRegistry } from '../command-registry.ts';
2
2
  import { GitService } from '@pellux/goodvibes-sdk/platform/git';
3
- import { requireShellPaths, requirePanelManager } from './runtime-services.ts';
3
+ import { requireShellPaths } from './runtime-services.ts';
4
4
  import { summarizeError } from '@pellux/goodvibes-sdk/platform/utils';
5
5
 
6
6
  export function registerGitRuntimeCommands(registry: CommandRegistry): void {
@@ -64,34 +64,17 @@ export function registerGitRuntimeCommands(registry: CommandRegistry): void {
64
64
  break;
65
65
  }
66
66
  case 'diff': {
67
- // Route the full, uncapped working-tree diff (GitService.diffStructured
68
- //, parsed per-file/per-hunk with no size limit) into the real diff
69
- // panel. The old path sliced the raw text at 4,000 chars and printed a
70
- // stub; a large diff now renders complete.
67
+ // The full, uncapped working-tree diff, in the Changes modal's
68
+ // "not staged" view (hunks can be staged from there).
71
69
  try {
72
70
  const structured = await git.diffStructured();
73
71
  if (structured.files.length === 0) {
74
72
  ctx.print('No unstaged changes.');
75
73
  break;
76
74
  }
77
- const { DiffPanel } = await import('../../panels/diff-panel.ts');
78
- const pm = requirePanelManager(ctx);
79
- let panel = pm.getAllOpen().find((p) => p.id === 'diff');
80
- if (!panel) {
81
- try {
82
- panel = pm.open('diff');
83
- } catch {
84
- ctx.print('Could not open diff panel.');
85
- break;
86
- }
87
- }
88
- pm.activateById('diff');
89
- if (!pm.isVisible()) pm.show();
90
- ctx.focusPanels?.();
91
- (panel as InstanceType<typeof DiffPanel>).loadStructuredDiff(structured);
92
75
  const fileWord = structured.files.length === 1 ? 'file' : 'files';
93
- ctx.print(`Diff panel updated: ${structured.files.length} ${fileWord}, +${structured.additions} -${structured.deletions} (complete, uncapped).`);
94
- ctx.renderRequest();
76
+ ctx.print(`Unstaged: ${structured.files.length} ${fileWord}, +${structured.additions} -${structured.deletions}.`);
77
+ if (ctx.openChanges) ctx.openChanges({ source: 'working' });
95
78
  } catch (e) {
96
79
  ctx.print(`Git diff failed: ${summarizeError(e)}`);
97
80
  }
@@ -1,6 +1,6 @@
1
1
  import type { CommandRegistry } from '../command-registry.ts';
2
2
  import { getOperatorRpc, describeOperatorRpcError } from './operator-rpc.ts';
3
- import { renderWorkstreamGraphLines } from '../../panels/workstream-graph-render.ts';
3
+ import { renderWorkstreamGraphLines } from '../../views/workstream-graph-render.ts';
4
4
 
5
5
  // ---------------------------------------------------------------------------
6
6
  // /graph, a workstream's task graph (fleet.graph.get) rendered legibly.
@@ -78,7 +78,7 @@ export function registerGuidanceRuntimeCommands(registry: CommandRegistry): void
78
78
  const maintenance = evaluateSessionMaintenance({
79
79
  configManager: ctx.platform.configManager,
80
80
  currentTokens: estimateConversationTokens(llmMessages),
81
- contextWindow: ctx.provider.providerRegistry.getContextWindowForModel(ctx.provider.providerRegistry.getCurrentModel()),
81
+ contextWindow: ctx.provider.providerRegistry.getKnownContextWindowForModel(ctx.provider.providerRegistry.getCurrentModel()) ?? 0,
82
82
  messageCount: llmMessages.length,
83
83
  sessionMemoryCount: requireSessionMemoryStore(ctx).list().length,
84
84
  session: session.session,
@@ -8,7 +8,6 @@ import { buildProviderAccountSnapshot } from '@/runtime/index.ts';
8
8
  import { getSettingsControlPlaneSnapshot } from '@/runtime/index.ts';
9
9
  import { listPersistedWorktreeMeta, summarizeWorktreeOwnership } from '@/runtime/index.ts';
10
10
  import {
11
- openCommandPanel,
12
11
  requireLocalUserAuthManager,
13
12
  requireOperatorClient,
14
13
  requireReadModels,
@@ -48,7 +47,7 @@ export function registerHealthRuntimeCommands(registry: CommandRegistry): void {
48
47
  const readModels = requireReadModels(ctx);
49
48
 
50
49
  if (sub === 'open' || sub === 'panel' || sub === 'provider') {
51
- ctx.openModal?.('providers-modal'); // provider-health panel -> config modal
50
+ ctx.openModal?.('providers-modal'); // provider-health view -> config modal
52
51
  return;
53
52
  }
54
53
 
@@ -305,11 +304,11 @@ export function registerHealthRuntimeCommands(registry: CommandRegistry): void {
305
304
  if (sub === 'maintenance') {
306
305
  const session = readModels.session.getSnapshot();
307
306
  const providerRegistry = ctx.provider.providerRegistry;
308
- // Resolve the context window the same way the Tokens panel does so the
307
+ // Resolve the context window the same way the Usage modal does so the
309
308
  // maintenance usage %/remaining agree across every diagnostics surface.
310
- const contextWindow = providerRegistry.getContextWindowForModel(
309
+ const contextWindow = providerRegistry.getKnownContextWindowForModel(
311
310
  providerRegistry.getCurrentModel(),
312
- );
311
+ ) ?? 0; // 0: unknown window, no usage percentage
313
312
  const llmMessages = typeof ctx.session.conversationManager.getMessagesForLLM === 'function'
314
313
  ? ctx.session.conversationManager.getMessagesForLLM()
315
314
  : [];
@@ -431,7 +430,7 @@ export function registerHealthRuntimeCommands(registry: CommandRegistry): void {
431
430
  lines.push(' /health maintenance');
432
431
  lines.push(' /guidance review');
433
432
  lines.push(' /compact');
434
- lines.push(' /panel tokens');
433
+ lines.push(' /usage');
435
434
  lines.push(' verify: /health maintenance');
436
435
  } else if (domain === 'worktrees') {
437
436
  lines.push(' domain: worktrees');
@@ -458,11 +457,11 @@ export function registerHealthRuntimeCommands(registry: CommandRegistry): void {
458
457
  const llmMessages = typeof ctx.session.conversationManager.getMessagesForLLM === 'function'
459
458
  ? ctx.session.conversationManager.getMessagesForLLM()
460
459
  : [];
461
- // Resolve the context window the same way the Tokens panel does so the
460
+ // Resolve the context window the same way the Usage modal does so the
462
461
  // maintenance usage %/remaining agree across every diagnostics surface.
463
- const contextWindow = providerRegistry.getContextWindowForModel(
462
+ const contextWindow = providerRegistry.getKnownContextWindowForModel(
464
463
  providerRegistry.getCurrentModel(),
465
- );
464
+ ) ?? 0; // 0: unknown window, no usage percentage
466
465
  const maintenance = evaluateSessionMaintenance({
467
466
  configManager: ctx.platform.configManager,
468
467
  currentTokens: estimateConversationTokens(llmMessages),
@@ -11,8 +11,8 @@ export function registerHooksRuntimeCommands(registry: CommandRegistry): void {
11
11
  async handler(args, ctx) {
12
12
  const hookApi = requireHookApi(ctx);
13
13
  const workbench = hookApi.workbench;
14
- if (args.length === 0 && ctx.openHooksPanel) {
15
- ctx.openHooksPanel();
14
+ if (args.length === 0 && ctx.openHooksView) {
15
+ ctx.openHooksView();
16
16
  return;
17
17
  }
18
18
 
@@ -44,7 +44,7 @@ import {
44
44
  } from '../../runtime/client/hosted-sessions.ts';
45
45
  import { watchHostedSession, type HostedSessionSubscription } from '../../runtime/client/hosted-session-stream.ts';
46
46
  import { getOrCreateCompanionToken } from '@pellux/goodvibes-sdk/platform/pairing';
47
- import { getSharedHostedSessionFeed, type HostedSessionFeed } from '../../panels/hosted-session-feed.ts';
47
+ import { getSharedHostedSessionFeed, type HostedSessionFeed } from '../../views/hosted-session-feed.ts';
48
48
  import { getSharedHostedSessionRoster } from '../../runtime/client/hosted-roster.ts';
49
49
 
50
50
  /** The last list this terminal printed, so `attach 2` means what the user just read. */
@@ -194,7 +194,7 @@ async function attachSession(
194
194
  `[hosted] attached to ${hostedSessionLabel(attachment.session)} (${attachment.history.length} message(s) backfilled)`,
195
195
  ` ${describeDetachEffect(attachment.session)}`,
196
196
  ].join('\n'));
197
- context.showPanel?.('hosted');
197
+ context.openAgents?.({ hosted: true });
198
198
  }
199
199
 
200
200
  /** Turn `attach 2` into the id the user just read off `/hosted list`. */
@@ -278,7 +278,7 @@ export function registerHostedRuntimeCommands(registry: CommandRegistry): void {
278
278
  if (sub === 'say') await seams.client.steer(attachedId, body);
279
279
  else await seams.client.followUp(attachedId, body);
280
280
  ctx.print(sub === 'say'
281
- ? '[hosted] sent: its output arrives on the Hosted Session panel.'
281
+ ? '[hosted] sent: its output arrives in the Agents view under Hosted (/agents).'
282
282
  : '[hosted] queued: it runs after the current turn.');
283
283
  return;
284
284
  }
@@ -16,11 +16,11 @@ export function registerIncidentRuntimeCommands(registry: CommandRegistry): void
16
16
  const subcommand = (args[0] ?? 'open').toLowerCase();
17
17
  const forensicRegistry = ctx.extensions.forensicsRegistry;
18
18
  if (subcommand === 'open') {
19
- if (ctx.openIncidentPanel) {
20
- ctx.openIncidentPanel();
19
+ if (ctx.openIncidentView) {
20
+ ctx.openIncidentView();
21
21
  return;
22
22
  }
23
- ctx.print('Incident panel is not available in this runtime.');
23
+ ctx.print('The Agents view is not available in this runtime.');
24
24
  return;
25
25
  }
26
26
  if (!forensicRegistry) {
@@ -4,7 +4,7 @@ import type { CommandContext, CommandRegistry } from '../command-registry.ts';
4
4
  import { CodeIntelligence } from '@pellux/goodvibes-sdk/platform/intelligence';
5
5
  import type { DocumentSymbol } from '@pellux/goodvibes-sdk/platform/intelligence';
6
6
  import type { SymbolInfo } from '@pellux/goodvibes-sdk/platform/intelligence';
7
- import { openCommandPanel, requireReadModels, requireShellPaths } from './runtime-services.ts';
7
+ import { openCommandView, requireReadModels, requireShellPaths } from './runtime-services.ts';
8
8
 
9
9
  function resolveTargetPath(pathArg: string, ctx: CommandContext): string {
10
10
  return requireShellPaths(ctx).resolveWorkspacePath(pathArg);
@@ -55,16 +55,13 @@ export function registerIntelligenceRuntimeCommands(registry: CommandRegistry):
55
55
  async handler(args, ctx) {
56
56
  const sub = (args[0] ?? 'review').toLowerCase();
57
57
  if (sub === 'panel' || sub === 'open') {
58
- // (the purge): 'intelligence'/IntelligencePanel was
59
- // DELETE-disposition (no surviving human surface, its read model
60
- // stays and still backs every subcommand below). There is no alias
61
- // to resolve through, so this prints an honest notice and opens
62
- // Fleet instead of throwing "Unknown panel".
63
- ctx.print('Intelligence panel retired: use /intelligence review|diagnostics|symbols|outline|definition|references|hover|repair for the live data. Opening Fleet.');
58
+ // There is no intelligence view; its read model backs every
59
+ // subcommand below. Say so and open Agents rather than failing.
60
+ ctx.print('There is no intelligence view: use /intelligence review|diagnostics|symbols|outline|definition|references|hover|repair for the live data. Opening Agents.');
64
61
  try {
65
- openCommandPanel(ctx, 'fleet');
62
+ openCommandView(ctx, 'agents');
66
63
  } catch {
67
- // Panel registry may be unavailable in lightweight command-only contexts.
64
+ // The view openers may be absent in lightweight command-only contexts.
68
65
  }
69
66
  return;
70
67
  }
@@ -141,8 +141,8 @@ export const knowledgeCommand: SlashCommand = {
141
141
  if (!knowledge) {
142
142
  return;
143
143
  }
144
- if (args.length === 0 && context.openKnowledgePanel) {
145
- context.openKnowledgePanel();
144
+ if (args.length === 0 && context.openKnowledgeView) {
145
+ context.openKnowledgeView();
146
146
  return;
147
147
  }
148
148
  const sub = (args[0] ?? 'status').toLowerCase();
@@ -0,0 +1,57 @@
1
+ import type { CommandRegistry } from '../command-registry.ts';
2
+ import { AGENT_VIEW_NAMES, CHANGES_VIEW_NAMES, USAGE_VIEW_NAMES, takeTargetFlag } from '../views.ts';
3
+
4
+ /**
5
+ * `/panel` is the legacy alias for the old pane names. Every view lives in a
6
+ * modal, and the old names still arrive from muscle memory, notes, scripts and
7
+ * deep links (`/panel open fleet --target <id>`). `/panel <name>` and
8
+ * `/panel open <name>` open the modal that holds that content now;
9
+ * `/panel list` says where each old name goes. The verbs that only made sense
10
+ * for side panes (close, move, focus, split, width, height) have nothing to
11
+ * act on and say so.
12
+ */
13
+ export function registerLegacyPanelCommand(registry: CommandRegistry): void {
14
+ registry.register({
15
+ name: 'panel',
16
+ aliases: ['panels'],
17
+ description: 'Open a view by its old pane name (fleet, tokens, git, …) in its modal; /panel list shows where each goes',
18
+ usage: '[<name> | open <name> [--target <id>[:<kind>]] | list]',
19
+ argsHint: '<name> | open <name> | list',
20
+ handler(args, ctx) {
21
+ const rest = [...args];
22
+ const target = takeTargetFlag(rest);
23
+ const sub = rest[0]?.toLowerCase() ?? '';
24
+ if (!sub || sub === 'toggle') {
25
+ ctx.print('There are no panes any more: views open as modals. Try /agents, /usage, /changes or /notifications, or ctrl+p to search.');
26
+ return;
27
+ }
28
+ if (sub === 'list') {
29
+ ctx.print([
30
+ 'Where the old panes went:',
31
+ ` Agents (/agents, F2): ${AGENT_VIEW_NAMES.filter((n) => n !== 'agents').join(', ')}, hosted`,
32
+ ` Usage (/usage): ${USAGE_VIEW_NAMES.filter((n) => n !== 'usage').join(', ')}`,
33
+ ` Changes (/changes): ${CHANGES_VIEW_NAMES.filter((n) => n !== 'changes').join(', ')}`,
34
+ ' Notifications (/notifications): notifications',
35
+ ' Sessions (/sessions): sessions',
36
+ ' Local Auth (/local-auth): local-auth',
37
+ 'Settings-style views (services, providers, plugins, hooks, memory, …) open their own modals by the same names.',
38
+ ].join('\n'));
39
+ return;
40
+ }
41
+ if (sub === 'close' || sub === 'move' || sub === 'focus' || sub === 'split' || sub === 'width' || sub === 'height') {
42
+ ctx.print(`There are no panes to ${sub}: views open as modals and Esc closes them.`);
43
+ return;
44
+ }
45
+ const name = sub === 'open' ? rest[1] : rest[0];
46
+ if (!name) {
47
+ ctx.print('Usage: /panel open <name> [--target <id>[:<kind>]]');
48
+ return;
49
+ }
50
+ if (!ctx.openView) {
51
+ ctx.print('Views are not available in this session.');
52
+ return;
53
+ }
54
+ if (!ctx.openView(name, target)) ctx.print(`Nothing holds "${name}". /panel list shows where the old names go.`);
55
+ },
56
+ });
57
+ }
@@ -1,5 +1,5 @@
1
1
  import type { CommandContext, CommandRegistry } from '../command-registry.ts';
2
- import { openCommandPanel, requireLocalUserAuthManager } from './runtime-services.ts';
2
+ import { requireLocalUserAuthManager } from './runtime-services.ts';
3
3
  import { summarizeError } from '@pellux/goodvibes-sdk/platform/utils';
4
4
 
5
5
  function formatRoles(roles: readonly string[]): string {
@@ -7,12 +7,11 @@ function formatRoles(roles: readonly string[]): string {
7
7
  }
8
8
 
9
9
  export function handleLocalAuthCommand(args: string[], ctx: CommandContext): void {
10
- const sub = (args[0] ?? 'review').toLowerCase();
10
+ // Bare /local-auth opens the Local Auth modal where one can open; the text
11
+ // review stays at /local-auth review.
12
+ const sub = (args[0] ?? (ctx.openModal ? 'open' : 'review')).toLowerCase();
11
13
  const auth = requireLocalUserAuthManager(ctx);
12
14
  if (sub === 'panel' || sub === 'open') {
13
- // browse view moved to local-auth-modal. The LocalAuthPanel itself is
14
- // kept (masked password-entry host) but is no longer the /local-auth panel
15
- // destination, masked entry is reached via add-user/rotate-password below.
16
15
  ctx.openModal?.('local-auth-modal');
17
16
  return;
18
17
  }
@@ -21,11 +20,11 @@ export function handleLocalAuthCommand(args: string[], ctx: CommandContext): voi
21
20
  const username = args[1];
22
21
  const password = args[2];
23
22
  if (!username) {
24
- ctx.print('Usage: /auth local add-user <username> <password> [roles]\nTip: invoke without a password to use the masked panel: /auth local add-user <username>');
23
+ ctx.print('Usage: /auth local add-user <username> <password> [roles]\nTip: invoke without a password to type it in the masked prompt: /auth local add-user <username>');
25
24
  return;
26
25
  }
27
26
  if (!password) {
28
- // No password supplied, open masked-entry mode on the LocalAuthPanel.
27
+ // No password supplied: open the masked password prompt.
29
28
  if (ctx.openLocalAuthMaskedEntry) {
30
29
  ctx.openLocalAuthMaskedEntry('add-user', username);
31
30
  } else {
@@ -64,11 +63,11 @@ export function handleLocalAuthCommand(args: string[], ctx: CommandContext): voi
64
63
  const username = args[1];
65
64
  const password = args[2];
66
65
  if (!username) {
67
- ctx.print('Usage: /auth local rotate-password <username> <password>\nTip: invoke without a password to use the masked panel: /auth local rotate-password <username>');
66
+ ctx.print('Usage: /auth local rotate-password <username> <password>\nTip: invoke without a password to type it in the masked prompt: /auth local rotate-password <username>');
68
67
  return;
69
68
  }
70
69
  if (!password) {
71
- // No password supplied, open masked-entry mode on the LocalAuthPanel.
70
+ // No password supplied: open the masked password prompt.
72
71
  if (ctx.openLocalAuthMaskedEntry) {
73
72
  ctx.openLocalAuthMaskedEntry('rotate-password', username);
74
73
  } else {
@@ -79,21 +79,24 @@ export function registerLocalProviderRuntimeCommands(registry: CommandRegistry):
79
79
  contextWindows = await fetchModelContextWindows(parsedUrl.hostname, parseInt(parsedUrl.port) || 80, 'unknown', discoveredModelIds);
80
80
  } catch {}
81
81
  } else {
82
- ctx.print('Note: Context window detection is only supported for http:// URLs. Using defaults.');
82
+ ctx.print('Note: Context window detection is only supported for http:// URLs. Windows the endpoint does not report are left unknown.');
83
83
  }
84
84
  }
85
85
  const defaultModel = `${name}-model`;
86
+ // A window is written only when the endpoint reported one. A guessed
87
+ // number written here would read as the model's real window forever
88
+ // after (the meter, compaction and prompt tier all trust it), so an
89
+ // unreported window is left out and the model's window is unknown.
86
90
  const models: CustomProviderConfig['models'] = discoveredModelIds.length === 0
87
91
  ? [{
88
92
  id: defaultModel,
89
93
  displayName: defaultModel,
90
- contextWindow: 8192,
91
94
  capabilities: { toolCalling: true, codeEditing: true, reasoning: false, multimodal: false },
92
95
  }]
93
96
  : discoveredModelIds.map((id) => ({
94
97
  id,
95
98
  displayName: id,
96
- contextWindow: contextWindows[id] ?? 8192,
99
+ ...(contextWindows[id] !== undefined && contextWindows[id] > 0 ? { contextWindow: contextWindows[id] } : {}),
97
100
  capabilities: { toolCalling: true, codeEditing: true, reasoning: false, multimodal: false },
98
101
  }));
99
102
  // The key is never embedded in the provider JSON. The config references
@@ -115,7 +118,7 @@ export function registerLocalProviderRuntimeCommands(registry: CommandRegistry):
115
118
  ctx.print(`Error writing provider file: ${summarizeError(e)}`);
116
119
  return;
117
120
  }
118
- ctx.print(`Provider '${name}' added with ${models.length} model(s):\n${discoveredModelIds.length > 0 ? discoveredModelIds.map((id) => ` • ${id} (${(contextWindows[id] ?? 8192).toLocaleString()} ctx)`).join('\n') : ` • ${defaultModel} (starter entry)`}\nThe file watcher will auto-register it shortly.`);
121
+ ctx.print(`Provider '${name}' added with ${models.length} model(s):\n${discoveredModelIds.length > 0 ? discoveredModelIds.map((id) => ` • ${id} (${contextWindows[id] !== undefined && contextWindows[id] > 0 ? `${contextWindows[id].toLocaleString()} ctx` : 'context window unknown'})`).join('\n') : ` • ${defaultModel} (starter entry)`}\nThe file watcher will auto-register it shortly.`);
119
122
  // Capture the key with the keystrokes masked, straight into the secrets
120
123
  // manager, never a cleartext argument, never written into the JSON.
121
124
  if (ctx.beginConcealedInput) {
@@ -7,7 +7,7 @@ import type { ContentPart } from '@pellux/goodvibes-sdk/platform/providers';
7
7
  import { formatModelDiscoveryReport } from '@pellux/goodvibes-sdk/platform/providers';
8
8
  import { resolveAndValidatePath } from '@pellux/goodvibes-sdk/platform/utils';
9
9
  import { BUILTIN_SECRET_PROVIDER_SOURCES, describeSecretRef, isSecretRefInput, resolveSecretRef } from '@pellux/goodvibes-sdk/platform/config';
10
- import { openCommandPanel, requireBookmarkManager, requireProviderApi, requireSecretsManager } from './runtime-services.ts';
10
+ import { openCommandView, requireBookmarkManager, requireProviderApi, requireSecretsManager } from './runtime-services.ts';
11
11
  import { summarizeError } from '@pellux/goodvibes-sdk/platform/utils';
12
12
 
13
13
  function isGoodVibesSecretRefInput(value: string): boolean {
@@ -55,8 +55,8 @@ function toggleBlocks(typeFilter: string, collapsed: boolean, ctx: CommandContex
55
55
  // state, needing a second pass. '/collapse tool' needs no matching step:
56
56
  // collapsing the turn hides every result regardless of its own key.
57
57
  if (!collapsed && block.type === 'assistant_turn' && block.groupMemberIndexes) {
58
- for (const memberIdx of block.groupMemberIndexes) {
59
- const memberKey = `msg_${memberIdx}`;
58
+ for (const [k, memberIdx] of block.groupMemberIndexes.entries()) {
59
+ const memberKey = block.groupMemberKeys?.[k] ?? `msg_${memberIdx}`;
60
60
  ctx.session.conversationManager.setCollapsed(memberKey, false);
61
61
  // An explicit /expand is a deliberate user action on this key, same
62
62
  // as Tab/Ctrl+Y/Ctrl+B, exempts it from search's close-time
@@ -77,11 +77,11 @@ export function registerLocalRuntimeCommands(registry: CommandRegistry): void {
77
77
  aliases: [],
78
78
  description: 'Alias for /incident open',
79
79
  handler(_args, ctx) {
80
- if (ctx.openIncidentPanel) {
81
- ctx.openIncidentPanel();
80
+ if (ctx.openIncidentView) {
81
+ ctx.openIncidentView();
82
82
  return;
83
83
  }
84
- ctx.print('Incident panel is not available in this runtime.');
84
+ ctx.print('The Agents view is not available in this runtime.');
85
85
  },
86
86
  });
87
87
 
@@ -93,16 +93,13 @@ export function registerLocalRuntimeCommands(registry: CommandRegistry): void {
93
93
  handler(args, ctx) {
94
94
  const sub = (args[0] ?? '').toLowerCase();
95
95
  if (sub === 'panel' || sub === 'review') {
96
- // (the purge): 'tools'/ToolInspectorPanel was DELETE-disposition
97
- // (no surviving human surface, tool results render inline in the
98
- // transcript, plus a per-node tool list in Fleet). There is no alias
99
- // to resolve through, so this prints an honest notice and opens
100
- // Fleet instead of the retired inspector.
101
- ctx.print('Tools panel retired: tool activity now renders inline in the transcript and per-agent in the Fleet panel. Opening Fleet.');
96
+ // Tool results render inline in the transcript and per agent in the
97
+ // Agents modal; there is no separate tools view.
98
+ ctx.print('Tool activity renders inline in the transcript and per agent in the Agents view. Opening Agents.');
102
99
  try {
103
- openCommandPanel(ctx, 'fleet');
100
+ openCommandView(ctx, 'agents');
104
101
  } catch {
105
- // Panel registry may be unavailable in lightweight command-only contexts.
102
+ // The view openers may be absent in lightweight command-only contexts.
106
103
  }
107
104
  if (sub === 'review') {
108
105
  ctx.print([
@@ -110,7 +107,7 @@ export function registerLocalRuntimeCommands(registry: CommandRegistry): void {
110
107
  ' Native file tools stay compact by default.',
111
108
  ' Read/write/edit/notebook capabilities are available through the native tool stack, with detail routed inline and to approval surfaces instead of transcript bloat.',
112
109
  ' Shell and native tool approvals classify work into read, mutation, destructive, dependency, config, notebook, network, remote, and lifecycle risk families.',
113
- ' Use /tools panel to jump to the Fleet panel for live per-agent tool activity.',
110
+ ' Use /tools panel to open Agents for live per-agent tool activity.',
114
111
  ' Use /approval review shell or /approval review file when you need the action-specific why-prompted posture.',
115
112
  ].join('\n'));
116
113
  }
@@ -1,7 +1,7 @@
1
1
  import { dirname, join, resolve } from 'node:path';
2
2
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
3
3
  import type { CommandContext } from '../command-registry.ts';
4
- import { discoverSkills } from '../../panels/skills-panel.ts';
4
+ import { discoverSkills } from '../../views/skills-discovery.ts';
5
5
  import { buildSandboxReview, isRunningInWsl } from '@/runtime/index.ts';
6
6
  import { renderQemuWrapperTemplate } from '@/runtime/index.ts';
7
7
  import { getPluginDirectories } from '@pellux/goodvibes-sdk/platform/plugins';
@@ -15,7 +15,7 @@ import {
15
15
  parseSetupLink,
16
16
  } from './local-setup-transfer.ts';
17
17
  import { buildSetupReviewSnapshot, exportSetupSupportBundle, renderSetupSandboxReview } from './local-setup-review.ts';
18
- import { openOnboardingWizard, requirePanelManager, requireShellPaths } from './runtime-services.ts';
18
+ import { openOnboardingWizard, requireShellPaths } from './runtime-services.ts';
19
19
  import { summarizeError } from '@pellux/goodvibes-sdk/platform/utils';
20
20
 
21
21
  type SetupSnapshot = Awaited<ReturnType<typeof buildSetupReviewSnapshot>>;
@@ -247,32 +247,26 @@ export function registerLocalSetupCommands(registry: CommandRegistry): void {
247
247
  ctx.print(`Invalid setup link: ${link}`);
248
248
  return;
249
249
  }
250
- const panelOpeners: Record<string, (() => void) | undefined> = {
251
- cockpit: ctx.openCockpitPanel,
252
- security: ctx.openSecurityPanel,
253
- remote: ctx.openRemotePanel,
254
- knowledge: ctx.openKnowledgePanel,
255
- incident: ctx.openIncidentPanel,
256
- hooks: ctx.openHooksPanel,
257
- orchestration: ctx.openOrchestrationPanel,
250
+ const viewOpeners: Record<string, (() => void) | undefined> = {
251
+ cockpit: ctx.openCockpitView,
252
+ security: ctx.openSecurityView,
253
+ remote: ctx.openRemoteView,
254
+ knowledge: ctx.openKnowledgeView,
255
+ incident: ctx.openIncidentView,
256
+ hooks: ctx.openHooksView,
257
+ orchestration: ctx.openOrchestrationView,
258
258
  };
259
259
  if (parsed.surface === 'tasks') {
260
- if (ctx.showPanel) ctx.showPanel('tasks');
261
- else {
262
- const panelManager = requirePanelManager(ctx);
263
- panelManager.open('tasks');
264
- panelManager.show();
265
- ctx.renderRequest();
266
- }
260
+ ctx.openView?.('tasks');
267
261
  ctx.print(`Opened setup link for tasks${parsed.target ? ` (${parsed.target})` : ''}.`);
268
262
  return;
269
263
  }
270
- const openPanel = panelOpeners[parsed.surface];
271
- if (!openPanel) {
264
+ const openSurface = viewOpeners[parsed.surface];
265
+ if (!openSurface) {
272
266
  ctx.print(`Unsupported setup link surface: ${parsed.surface}`);
273
267
  return;
274
268
  }
275
- openPanel();
269
+ openSurface();
276
270
  ctx.print(`Opened setup link for ${parsed.surface}${parsed.target ? ` (${parsed.target})` : ''}.`);
277
271
  return;
278
272
  }
@@ -38,7 +38,7 @@ import { handleRecallFilesApply, handleRecallFilesReview, handleRecallFilesSync
38
38
  * now registered here as a real alias of `/recall`, the word means the same
39
39
  * durable Project Memory Substrate on both surfaces. The modal that exists
40
40
  * for this data, the Project Memory Substrate, is still `memory-modal.ts`,
41
- * owned by THIS command, confirmed by the panel-id redirect
41
+ * owned by THIS command, confirmed by the view-id redirect
42
42
  * `registerModalRedirect('memory', 'memory-modal')` in builtin-modals.ts.
43
43
  */
44
44
  function printRecallUsage(context: CommandContext): void {