@pellux/goodvibes-tui 2.0.21 → 2.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (391) hide show
  1. package/CHANGELOG.md +65 -1
  2. package/README.md +30 -29
  3. package/docs/README.md +8 -5
  4. package/docs/foundation-artifacts/operator-contract.json +1 -1
  5. package/package.json +28 -19
  6. package/src/cli/management.ts +5 -2
  7. package/src/cli/tui-startup.ts +34 -39
  8. package/src/core/agent-view-render.ts +157 -0
  9. package/src/core/approval-alert.ts +49 -11
  10. package/src/core/bookmark-navigation.ts +7 -1
  11. package/src/core/budget-breach-notifier.ts +27 -8
  12. package/src/core/compaction-receipt.ts +1 -1
  13. package/src/core/context-usage.ts +1 -1
  14. package/src/core/conversation-compaction-render.ts +3 -3
  15. package/src/core/conversation-display-only.ts +86 -0
  16. package/src/core/conversation-event-navigation.ts +27 -0
  17. package/src/core/conversation-line-cache.ts +216 -447
  18. package/src/core/conversation-render-context.ts +20 -27
  19. package/src/core/conversation-rendering.ts +157 -575
  20. package/src/core/conversation-splash-state.ts +6 -1
  21. package/src/core/conversation-types.ts +35 -0
  22. package/src/core/conversation-usage.ts +12 -0
  23. package/src/core/conversation.ts +130 -131
  24. package/src/core/long-task-notifier.ts +100 -31
  25. package/src/core/notices.ts +75 -0
  26. package/src/core/pairing-tailscale-gateway.ts +1 -1
  27. package/src/core/process-output-log.ts +143 -0
  28. package/src/core/rewind-receipt.ts +1 -1
  29. package/src/core/session-focus.ts +190 -0
  30. package/src/core/session-resume-core.ts +23 -81
  31. package/src/core/stream-event-wiring.ts +31 -5
  32. package/src/core/system-message-noise.ts +2 -2
  33. package/src/core/system-message-router.ts +16 -18
  34. package/src/core/turn-event-wiring.ts +272 -33
  35. package/src/core/work-tree-focus.ts +290 -0
  36. package/src/core/work-tree-fold-store.ts +143 -0
  37. package/src/core/work-tree-model.ts +799 -0
  38. package/src/core/work-tree-render.ts +384 -0
  39. package/src/core/work-tree-sources.ts +184 -0
  40. package/src/core/work-tree-wiring.ts +176 -0
  41. package/src/core/workstream-notification.ts +36 -6
  42. package/src/core/wrfc-notice-titles.ts +37 -0
  43. package/src/input/agents-modal-text.ts +119 -0
  44. package/src/input/agents-modal.ts +699 -0
  45. package/src/input/bookmark-modal.ts +33 -9
  46. package/src/input/changes-git.ts +251 -0
  47. package/src/input/changes-modal.ts +629 -0
  48. package/src/input/changes-model.ts +125 -0
  49. package/src/input/command-palette-types.ts +41 -0
  50. package/src/input/command-palette.ts +272 -0
  51. package/src/input/command-reference.ts +2 -2
  52. package/src/input/command-registry.ts +77 -35
  53. package/src/input/commands/acp-runtime.ts +19 -9
  54. package/src/input/commands/channel-runtime.ts +2 -2
  55. package/src/input/commands/ci-runtime.ts +1 -1
  56. package/src/input/commands/codebase-runtime.ts +1 -1
  57. package/src/input/commands/config.ts +7 -1
  58. package/src/input/commands/context-window.ts +25 -19
  59. package/src/input/commands/control-room-runtime.ts +18 -18
  60. package/src/input/commands/conversation-runtime.ts +0 -1
  61. package/src/input/commands/cost-runtime.ts +29 -20
  62. package/src/input/commands/diff-runtime.ts +35 -181
  63. package/src/input/commands/eval.ts +1 -1
  64. package/src/input/commands/experience-runtime.ts +3 -7
  65. package/src/input/commands/fresh-conversation.ts +86 -0
  66. package/src/input/commands/git-runtime.ts +5 -22
  67. package/src/input/commands/graph-runtime.ts +1 -1
  68. package/src/input/commands/guidance-runtime.ts +1 -1
  69. package/src/input/commands/health-runtime.ts +8 -9
  70. package/src/input/commands/hooks-runtime.ts +2 -2
  71. package/src/input/commands/hosted-runtime.ts +3 -3
  72. package/src/input/commands/incident-runtime.ts +3 -3
  73. package/src/input/commands/intelligence-runtime.ts +6 -9
  74. package/src/input/commands/knowledge.ts +2 -2
  75. package/src/input/commands/legacy-panel-command.ts +57 -0
  76. package/src/input/commands/local-auth-runtime.ts +8 -9
  77. package/src/input/commands/local-provider-runtime.ts +7 -4
  78. package/src/input/commands/local-runtime.ts +12 -15
  79. package/src/input/commands/local-setup-review.ts +1 -1
  80. package/src/input/commands/local-setup.ts +13 -19
  81. package/src/input/commands/memory.ts +1 -1
  82. package/src/input/commands/notify-runtime.ts +9 -0
  83. package/src/input/commands/operator-runtime.ts +10 -12
  84. package/src/input/commands/permissions-provenance.ts +3 -3
  85. package/src/input/commands/planning-runtime.ts +7 -7
  86. package/src/input/commands/platform-sandbox-runtime.ts +2 -2
  87. package/src/input/commands/platform-services-runtime.ts +1 -1
  88. package/src/input/commands/policy-dispatch.ts +2 -2
  89. package/src/input/commands/policy.ts +3 -3
  90. package/src/input/commands/provider.ts +1 -1
  91. package/src/input/commands/remote-runtime.ts +1 -1
  92. package/src/input/commands/review-runtime.ts +39 -94
  93. package/src/input/commands/rewind-runtime.ts +81 -108
  94. package/src/input/commands/runtime-services.ts +15 -17
  95. package/src/input/commands/services-runtime.ts +2 -2
  96. package/src/input/commands/session-content.ts +21 -5
  97. package/src/input/commands/session-workflow.ts +13 -38
  98. package/src/input/commands/settings-sync-runtime.ts +2 -2
  99. package/src/input/commands/shell-core.ts +19 -4
  100. package/src/input/commands/skills-runtime.ts +2 -2
  101. package/src/input/commands/status-runtime.ts +13 -0
  102. package/src/input/commands/subscription-runtime.ts +1 -1
  103. package/src/input/commands/tasks-runtime.ts +2 -8
  104. package/src/input/commands/work-plan-runtime.ts +4 -4
  105. package/src/input/commands/workstream-attempts.ts +24 -47
  106. package/src/input/commands/workstream-runtime.ts +2 -2
  107. package/src/input/commands/worktree-runtime.ts +3 -3
  108. package/src/input/commands.ts +3 -1
  109. package/src/input/composer-editor.ts +44 -0
  110. package/src/input/concealed-input.ts +1 -1
  111. package/src/input/config-modal-types.ts +20 -8
  112. package/src/input/config-modal.ts +106 -105
  113. package/src/input/confirm-dialog-types.ts +28 -0
  114. package/src/input/confirm-dialog.ts +70 -0
  115. package/src/input/delete-key-policy.ts +3 -3
  116. package/src/input/feed-context-factory.ts +15 -16
  117. package/src/input/handler-command-route.ts +7 -42
  118. package/src/input/handler-content-actions.ts +16 -15
  119. package/src/input/handler-feed-routes.ts +26 -211
  120. package/src/input/handler-feed.ts +68 -95
  121. package/src/input/handler-interactions.ts +5 -3
  122. package/src/input/handler-modal-routes.ts +215 -216
  123. package/src/input/handler-modal-stack.ts +81 -11
  124. package/src/input/handler-modal-token-routes.ts +4 -0
  125. package/src/input/handler-onboarding.ts +0 -1
  126. package/src/input/handler-picker-routes.ts +65 -107
  127. package/src/input/handler-session-view-route.ts +149 -0
  128. package/src/input/handler-shortcuts.ts +16 -154
  129. package/src/input/handler-types.ts +4 -2
  130. package/src/input/handler-ui-state.ts +45 -15
  131. package/src/input/handler-work-tree-route.ts +123 -0
  132. package/src/input/handler.ts +25 -70
  133. package/src/input/keybindings.ts +16 -71
  134. package/src/input/masked-entry-modal.ts +117 -0
  135. package/src/input/mcp-workspace.ts +48 -17
  136. package/src/input/model-picker-filter.ts +8 -0
  137. package/src/input/model-picker-open.ts +99 -0
  138. package/src/input/model-picker-types.ts +1 -1
  139. package/src/input/model-picker.ts +92 -9
  140. package/src/input/notifications-modal.ts +123 -0
  141. package/src/input/overlay-filter.ts +26 -0
  142. package/src/input/profile-picker-modal.ts +37 -8
  143. package/src/input/search.ts +3 -3
  144. package/src/input/selection-modal-queue.ts +2 -0
  145. package/src/input/selection-modal.ts +28 -16
  146. package/src/input/session-picker-modal.ts +33 -8
  147. package/src/input/settings-modal-activation.ts +7 -2
  148. package/src/input/settings-modal-data.ts +11 -6
  149. package/src/input/settings-modal-types.ts +1 -1
  150. package/src/input/settings-modal.ts +20 -20
  151. package/src/input/submission-intent.ts +1 -1
  152. package/src/input/submission-router.ts +4 -9
  153. package/src/input/surface-modal-host.ts +110 -0
  154. package/src/input/theme-settings-actions.ts +82 -0
  155. package/src/input/usage-modal.ts +183 -0
  156. package/src/input/views.ts +97 -0
  157. package/src/main.ts +175 -165
  158. package/src/permissions/hunk-selection.ts +1 -1
  159. package/src/permissions/prompt-card.ts +511 -0
  160. package/src/permissions/prompt.ts +59 -622
  161. package/src/renderer/agents-modal.ts +310 -0
  162. package/src/renderer/autocomplete-overlay.ts +42 -220
  163. package/src/renderer/back-to-bottom.ts +80 -0
  164. package/src/renderer/block-actions-overlay.ts +30 -48
  165. package/src/renderer/bookmark-modal.ts +48 -79
  166. package/src/renderer/changes-modal.ts +325 -0
  167. package/src/renderer/code-block.ts +184 -106
  168. package/src/renderer/command-palette.ts +93 -0
  169. package/src/renderer/composer-fragments.ts +4 -4
  170. package/src/renderer/composer.ts +146 -0
  171. package/src/renderer/compositor.ts +26 -160
  172. package/src/renderer/config-modal.ts +185 -81
  173. package/src/renderer/confirm-dialog.ts +50 -0
  174. package/src/renderer/context-inspector.ts +116 -154
  175. package/src/renderer/context-status-hint.ts +4 -4
  176. package/src/renderer/conversation-layout.ts +20 -0
  177. package/src/renderer/conversation-overlays.ts +94 -84
  178. package/src/renderer/conversation-surface.ts +19 -38
  179. package/src/renderer/diff-tint.ts +98 -0
  180. package/src/renderer/file-picker-overlay.ts +63 -90
  181. package/src/renderer/footer-targets.ts +38 -0
  182. package/src/renderer/git-status.ts +3 -4
  183. package/src/renderer/header-line.ts +140 -117
  184. package/src/renderer/help-overlay.ts +133 -219
  185. package/src/renderer/history-search-overlay.ts +15 -12
  186. package/src/renderer/lane-graph/bead.ts +800 -0
  187. package/src/renderer/lane-graph/glyphs.ts +134 -0
  188. package/src/renderer/lane-graph/layout.ts +248 -0
  189. package/src/renderer/lane-graph/paint.ts +537 -0
  190. package/src/renderer/lane-graph/semantic-memo.ts +77 -0
  191. package/src/renderer/layout-engine.ts +2 -57
  192. package/src/renderer/layout.ts +7 -13
  193. package/src/renderer/markdown-inline.ts +2 -1
  194. package/src/renderer/markdown-table.ts +17 -12
  195. package/src/renderer/markdown.ts +92 -34
  196. package/src/renderer/masked-entry-modal.ts +78 -0
  197. package/src/renderer/mcp-workspace.ts +166 -203
  198. package/src/renderer/model-workspace.ts +381 -436
  199. package/src/renderer/notifications-modal.ts +116 -0
  200. package/src/renderer/onboarding/onboarding-wizard.ts +178 -588
  201. package/src/renderer/process-view.ts +192 -0
  202. package/src/renderer/profile-picker-modal.ts +58 -110
  203. package/src/renderer/search-overlay.ts +6 -3
  204. package/src/renderer/selection-modal-overlay.ts +87 -327
  205. package/src/renderer/semantic-diff.ts +2 -2
  206. package/src/renderer/session-chips.ts +102 -0
  207. package/src/renderer/session-picker-modal.ts +177 -297
  208. package/src/renderer/settings-modal-connections.ts +14 -23
  209. package/src/renderer/settings-modal-context.ts +367 -0
  210. package/src/renderer/settings-modal-helpers.ts +6 -11
  211. package/src/renderer/settings-modal.ts +322 -726
  212. package/src/renderer/shell-surface.ts +277 -175
  213. package/src/renderer/shortcuts-overlay.ts +217 -0
  214. package/src/renderer/status-line.ts +475 -0
  215. package/src/renderer/surface-compose.ts +174 -0
  216. package/src/renderer/surface-kit-extra.ts +303 -0
  217. package/src/renderer/surface-kit-list.ts +366 -0
  218. package/src/renderer/surface-kit-parts.ts +360 -0
  219. package/src/renderer/surface-kit.ts +568 -0
  220. package/src/renderer/syntax-highlighter.ts +280 -197
  221. package/src/renderer/syntax-theme.ts +51 -0
  222. package/src/renderer/system-message.ts +0 -1
  223. package/src/renderer/term-caps.ts +42 -1
  224. package/src/renderer/terminal-bg-probe.ts +116 -19
  225. package/src/renderer/terminal-palette-probe.ts +322 -0
  226. package/src/renderer/terminal-palette-reader.ts +183 -0
  227. package/src/renderer/terminal-palette.ts +58 -0
  228. package/src/renderer/theme-mode-config.ts +16 -1
  229. package/src/renderer/theme.ts +234 -207
  230. package/src/renderer/thinking.ts +0 -1
  231. package/src/renderer/throbber.ts +188 -0
  232. package/src/renderer/toast-center.ts +119 -0
  233. package/src/renderer/ui-factory.ts +39 -602
  234. package/src/renderer/ui-primitives.ts +8 -25
  235. package/src/renderer/usage-modal.ts +353 -0
  236. package/src/renderer/user-message.ts +58 -0
  237. package/src/renderer/voice-capture-chip.ts +53 -0
  238. package/src/runtime/bootstrap-command-context.ts +0 -5
  239. package/src/runtime/bootstrap-command-parts.ts +38 -89
  240. package/src/runtime/bootstrap-core.ts +13 -15
  241. package/src/runtime/bootstrap-hook-bridge.ts +12 -21
  242. package/src/runtime/bootstrap-notifier-sync.ts +17 -1
  243. package/src/runtime/bootstrap-shell.ts +16 -50
  244. package/src/runtime/bootstrap.ts +14 -14
  245. package/src/runtime/client/fleet-union.ts +5 -5
  246. package/src/runtime/client/hosted-exit.ts +2 -2
  247. package/src/runtime/client/hosted-sessions.ts +1 -1
  248. package/src/runtime/client/spine-adoption.ts +1 -1
  249. package/src/runtime/context-accounting-source.ts +5 -4
  250. package/src/runtime/index.ts +1 -0
  251. package/src/runtime/notification-dispatch.ts +102 -29
  252. package/src/runtime/recovery-offer-wiring.ts +4 -1
  253. package/src/runtime/recovery-prompt.ts +31 -15
  254. package/src/runtime/runtime-services-types.ts +10 -6
  255. package/src/runtime/services.ts +17 -12
  256. package/src/runtime/session-continuity-hints.ts +2 -5
  257. package/src/runtime/session-inbound-inputs.ts +1 -1
  258. package/src/runtime/session-resume-liveness-confirm.ts +14 -2
  259. package/src/runtime/startup-typeahead-gate.ts +103 -0
  260. package/src/runtime/store/domains/domain-read-matrix.ts +0 -1
  261. package/src/runtime/store/domains/index.ts +0 -8
  262. package/src/runtime/store/selectors/index.ts +0 -28
  263. package/src/runtime/store/state.ts +0 -8
  264. package/src/runtime/ui-services.ts +4 -6
  265. package/src/runtime/usage-tracker.ts +348 -0
  266. package/src/runtime/wrfc-persistence.ts +4 -4
  267. package/src/shell/blocking-input.ts +92 -2
  268. package/src/shell/recovery-input-helpers.ts +1 -1
  269. package/src/shell/session-views.ts +539 -0
  270. package/src/shell/status-report.ts +86 -0
  271. package/src/shell/transcript-scroll.ts +68 -0
  272. package/src/shell/ui-openers.ts +84 -172
  273. package/src/shell/view-openers.ts +205 -0
  274. package/src/tools/wrfc-agent-guard.ts +22 -2
  275. package/src/utils/format-duration.ts +4 -8
  276. package/src/utils/splash-lines.ts +9 -1
  277. package/src/utils/terminal-width.ts +56 -0
  278. package/src/verification/live-verifier.ts +0 -10
  279. package/src/version.ts +1 -1
  280. package/src/{panels → views}/agent-inspector-shared.ts +2 -2
  281. package/src/{panels → views}/builtin-modals.ts +22 -21
  282. package/src/views/builtin-views.ts +135 -0
  283. package/src/{panels → views}/confirm-state.ts +9 -9
  284. package/src/{panels → views}/diff-review-model.ts +10 -3
  285. package/src/{panels → views}/eval-registry.ts +1 -1
  286. package/src/{panels → views}/fleet-acts.ts +49 -85
  287. package/src/{panels/fleet-panel-format.ts → views/fleet-format.ts} +40 -40
  288. package/src/{panels → views}/fleet-gateway.ts +5 -5
  289. package/src/{panels → views}/fleet-observed-render.ts +16 -16
  290. package/src/{panels → views}/fleet-read-model.ts +9 -9
  291. package/src/{panels/fleet-tabs.ts → views/fleet-session-tabs.ts} +13 -13
  292. package/src/{panels → views}/fleet-spawn.ts +33 -49
  293. package/src/{panels → views}/fleet-steer.ts +12 -12
  294. package/src/{panels → views}/fleet-stop.ts +4 -4
  295. package/src/{panels → views}/fleet-transcript.ts +26 -27
  296. package/src/{panels/fleet-panel-worktree-detail.ts → views/fleet-worktree-detail.ts} +7 -7
  297. package/src/{panels → views}/hosted-session-feed.ts +6 -6
  298. package/src/views/modal-surface-registry.ts +41 -0
  299. package/src/{panels → views}/modals/devices-modal.ts +2 -2
  300. package/src/{panels → views}/modals/hooks-modal.ts +13 -13
  301. package/src/{panels → views}/modals/keybindings-modal.ts +19 -27
  302. package/src/{panels → views}/modals/knowledge-modal.ts +6 -5
  303. package/src/{panels → views}/modals/local-auth-modal.ts +22 -21
  304. package/src/{panels → views}/modals/marketplace-modal.ts +11 -11
  305. package/src/{panels → views}/modals/memory-modal.ts +8 -8
  306. package/src/{panels → views}/modals/modal-surface-helpers.ts +15 -5
  307. package/src/{panels → views}/modals/pairing-modal.ts +9 -9
  308. package/src/{panels → views}/modals/planning-modal.ts +15 -20
  309. package/src/{panels → views}/modals/plugins-modal.ts +6 -6
  310. package/src/{panels → views}/modals/policy-modal.ts +13 -5
  311. package/src/{panels → views}/modals/provider-health-modal.ts +4 -4
  312. package/src/{panels → views}/modals/remote-modal.ts +3 -3
  313. package/src/{panels → views}/modals/sandbox-modal.ts +4 -4
  314. package/src/{panels → views}/modals/security-modal.ts +22 -16
  315. package/src/{panels → views}/modals/services-modal.ts +3 -3
  316. package/src/{panels → views}/modals/settings-sync-modal.ts +4 -4
  317. package/src/{panels → views}/modals/skills-modal.ts +9 -9
  318. package/src/{panels → views}/modals/subscription-modal.ts +3 -3
  319. package/src/{panels → views}/modals/work-plan-modal.ts +10 -13
  320. package/src/views/notifications-feed.ts +314 -0
  321. package/src/{panels → views}/polish-core.ts +38 -36
  322. package/src/{panels → views}/polish-tables.ts +35 -26
  323. package/src/{panels → views}/polish.ts +101 -95
  324. package/src/{panels → views}/project-planning-answer-actions.ts +3 -3
  325. package/src/{panels → views}/provider-health-routes.ts +14 -14
  326. package/src/{panels → views}/search-focus.ts +8 -8
  327. package/src/{panels → views}/session-maintenance.ts +11 -11
  328. package/src/views/skills-discovery.ts +159 -0
  329. package/src/views/view-deps.ts +80 -0
  330. package/src/views/view-panel-adapter.ts +53 -0
  331. package/src/{panels → views}/workstream-graph-render.ts +1 -1
  332. package/src/core/conversation-fold.ts +0 -101
  333. package/src/core/conversation-turn-structure.ts +0 -464
  334. package/src/core/conversation-user-receipts.ts +0 -42
  335. package/src/input/commands/operator-panel-runtime.ts +0 -186
  336. package/src/input/panel-integration-actions.ts +0 -33
  337. package/src/input/panel-mouse-geometry.ts +0 -97
  338. package/src/input/panel-paste-flood-guard.ts +0 -86
  339. package/src/panels/base-panel.ts +0 -301
  340. package/src/panels/builtin/agent.ts +0 -27
  341. package/src/panels/builtin/development.ts +0 -92
  342. package/src/panels/builtin/knowledge.ts +0 -12
  343. package/src/panels/builtin/operations.ts +0 -177
  344. package/src/panels/builtin/session.ts +0 -81
  345. package/src/panels/builtin/shared.ts +0 -357
  346. package/src/panels/builtin-panels.ts +0 -28
  347. package/src/panels/cost-tracker-panel.ts +0 -746
  348. package/src/panels/diff-panel.ts +0 -797
  349. package/src/panels/diff-review-panel.ts +0 -395
  350. package/src/panels/expandable-list-panel.ts +0 -189
  351. package/src/panels/fleet-deep-link.ts +0 -31
  352. package/src/panels/fleet-panel.ts +0 -799
  353. package/src/panels/git-panel.ts +0 -800
  354. package/src/panels/hosted-session-panel.ts +0 -221
  355. package/src/panels/index.ts +0 -21
  356. package/src/panels/local-auth-panel.ts +0 -478
  357. package/src/panels/notifications-feed.ts +0 -127
  358. package/src/panels/notifications-panel.ts +0 -160
  359. package/src/panels/panel-confirm-overlay.ts +0 -72
  360. package/src/panels/panel-manager.ts +0 -791
  361. package/src/panels/plugins-panel.ts +0 -371
  362. package/src/panels/scrollable-list-panel.ts +0 -498
  363. package/src/panels/skills-panel.ts +0 -454
  364. package/src/panels/token-budget-panel.ts +0 -688
  365. package/src/panels/types.ts +0 -191
  366. package/src/panels/wrfc-panel-format.ts +0 -133
  367. package/src/renderer/diff-view.ts +0 -134
  368. package/src/renderer/fleet-tab-strip.ts +0 -56
  369. package/src/renderer/footer-tips.ts +0 -53
  370. package/src/renderer/fullscreen-primitives.ts +0 -146
  371. package/src/renderer/fullscreen-workspace.ts +0 -194
  372. package/src/renderer/hint-grammar.ts +0 -52
  373. package/src/renderer/modal-factory.ts +0 -480
  374. package/src/renderer/overlay-box.ts +0 -154
  375. package/src/renderer/overlay-viewport.ts +0 -104
  376. package/src/renderer/panel-composite.ts +0 -145
  377. package/src/renderer/panel-workspace-bar.ts +0 -54
  378. package/src/renderer/process-indicator.ts +0 -163
  379. package/src/renderer/tab-strip.ts +0 -222
  380. package/src/renderer/text-layout.ts +0 -31
  381. package/src/renderer/tool-call.ts +0 -276
  382. package/src/renderer/tool-result-expanded-lines.ts +0 -48
  383. package/src/renderer/tool-result-summary.ts +0 -219
  384. package/src/runtime/diagnostics/panels/index.ts +0 -21
  385. package/src/runtime/diagnostics/panels/ops.ts +0 -156
  386. package/src/runtime/perf/panel-contracts.ts +0 -32
  387. package/src/runtime/store/domains/panels.ts +0 -117
  388. package/src/verification/verification-ledger.ts +0 -707
  389. /package/src/{panels → views}/memory-consolidation-gateway.ts +0 -0
  390. /package/src/{panels → views}/modals/modal-theme.ts +0 -0
  391. /package/src/{panels → views}/provider-health-domains.ts +0 -0
@@ -1,31 +0,0 @@
1
- import { getDisplayWidth, truncateDisplay, wrapText } from '../utils/terminal-width.ts';
2
-
3
- export function wrapWithHangingIndent(
4
- text: string,
5
- width: number,
6
- indent: string,
7
- maxLines?: number,
8
- ): string[] {
9
- const safeWidth = Math.max(1, width);
10
- const indentWidth = getDisplayWidth(indent);
11
- const wrapped = wrapText(text, safeWidth);
12
- const lines = wrapped.map((line, index) => {
13
- if (index === 0) return truncateDisplay(line, safeWidth);
14
- return `${indent}${truncateDisplay(line, Math.max(1, safeWidth - indentWidth))}`;
15
- });
16
- return typeof maxLines === 'number' ? lines.slice(0, maxLines) : lines;
17
- }
18
-
19
- export function fitLabelDetailColumns(
20
- label: string,
21
- detail: string,
22
- totalWidth: number,
23
- labelRatio = 0.55,
24
- ): { labelWidth: number; detailWidth: number } {
25
- const safeWidth = Math.max(8, totalWidth);
26
- const labelWidth = Math.max(10, Math.min(safeWidth - 2, Math.floor(safeWidth * labelRatio)));
27
- return {
28
- labelWidth,
29
- detailWidth: Math.max(0, safeWidth - labelWidth - 2),
30
- };
31
- }
@@ -1,276 +0,0 @@
1
- import { type Line, createStyledCell, createEmptyLine } from '@pellux/goodvibes-sdk/platform/types';
2
- import { LAYOUT, TOOL_STATUS } from './layout.ts';
3
- import { getDisplayWidth, truncateDisplay } from '../utils/terminal-width.ts';
4
- import type { ToolCall } from '@pellux/goodvibes-sdk/platform/types';
5
- import { stripDangerousAnsi } from './ansi-sanitize.ts';
6
- import { formatElapsed } from '../utils/format-elapsed.ts';
7
- import { GLYPHS } from './ui-primitives.ts';
8
- import { activeUiTones } from './theme.ts';
9
- import { treeContentCol, treeTextCol, writeTreeStatusMarker } from '@pellux/goodvibes-terminal-shell';
10
-
11
- const TOOL_NAME_MIN_WIDTH = 8;
12
- const TOOL_NAME_MAX_WIDTH = 20;
13
-
14
- /** Tree placement for a tool-call row rendered as a branch of its turn. */
15
- export interface ToolCallTreeOptions {
16
- /** Effective indent in columns, already clamped by treeIndentCols(). */
17
- readonly indentCols?: number;
18
- readonly branchFg?: string;
19
- /** Suppress the tool label because the turn header already carries it. */
20
- readonly omitToolName?: boolean;
21
- }
22
-
23
- function writeStyledText(
24
- line: Line,
25
- startCol: number,
26
- endColExclusive: number,
27
- text: string,
28
- style: { readonly fg: string; readonly bold?: boolean; readonly dim?: boolean },
29
- ): number {
30
- let col = startCol;
31
- for (const ch of text) {
32
- const width = getDisplayWidth(ch);
33
- if (width <= 0) continue;
34
- if (col + width > endColExclusive) break;
35
- line[col] = createStyledCell(ch, {
36
- fg: style.fg,
37
- bold: style.bold ?? false,
38
- dim: style.dim ?? false,
39
- });
40
- if (width > 1 && col + 1 < endColExclusive) {
41
- line[col + 1] = createStyledCell('', {
42
- fg: style.fg,
43
- bold: style.bold ?? false,
44
- dim: style.dim ?? false,
45
- });
46
- }
47
- col += width;
48
- }
49
- return col;
50
- }
51
-
52
- function buildLeftSegments(
53
- toolName: string,
54
- keyArg: string,
55
- suffixText: string,
56
- leftBudget: number,
57
- omitToolName = false,
58
- ): Array<{ text: string; fg: string; bold?: boolean; dim?: boolean }> {
59
- if (leftBudget <= 0) return [];
60
-
61
- // When every call in the turn shares one label, the label rides on the turn
62
- // header and each row leads with the argument that actually distinguishes it
63
- // (`config.get`, `services.restart`). Falls back to showing the name when
64
- // there is no key argument, so a row can never render empty.
65
- if (omitToolName && keyArg) {
66
- return buildLeftSegments(keyArg, '', suffixText, leftBudget, false);
67
- }
68
-
69
- const t = activeUiTones();
70
- const segments: Array<{ text: string; fg: string; bold?: boolean; dim?: boolean }> = [];
71
- const suffixBudget = suffixText ? Math.min(Math.max(12, Math.floor(leftBudget * 0.3)), 20) : 0;
72
- const suffixDisplay = suffixBudget > 0 ? truncateDisplay(suffixText, suffixBudget) : '';
73
- const suffixWidth = getDisplayWidth(suffixDisplay);
74
- const separatorBeforeSuffix = suffixDisplay ? 2 : 0;
75
- const mainBudget = Math.max(1, leftBudget - suffixWidth - separatorBeforeSuffix);
76
-
77
- let toolNameDisplay = '';
78
- let keyArgDisplay = '';
79
- if (keyArg) {
80
- const rawToolWidth = getDisplayWidth(toolName);
81
- const preferredToolWidth = Math.min(
82
- Math.max(rawToolWidth, TOOL_NAME_MIN_WIDTH),
83
- TOOL_NAME_MAX_WIDTH,
84
- Math.max(TOOL_NAME_MIN_WIDTH, Math.floor(mainBudget * 0.4)),
85
- );
86
- const toolNameWidth = Math.min(preferredToolWidth, Math.max(1, mainBudget - 3));
87
- const keyArgWidth = Math.max(0, mainBudget - toolNameWidth - 2);
88
- toolNameDisplay = truncateDisplay(toolName, toolNameWidth);
89
- keyArgDisplay = truncateDisplay(keyArg, keyArgWidth);
90
- } else {
91
- toolNameDisplay = truncateDisplay(toolName, mainBudget);
92
- }
93
-
94
- if (toolNameDisplay) {
95
- segments.push({ text: toolNameDisplay, fg: '#00ffcc', bold: true });
96
- }
97
- if (keyArgDisplay) {
98
- segments.push({ text: ' ', fg: t.fg.primary });
99
- segments.push({ text: keyArgDisplay, fg: '252' });
100
- }
101
- if (suffixDisplay) {
102
- segments.push({ text: ' ', fg: t.fg.primary });
103
- segments.push({
104
- text: suffixDisplay,
105
- fg: suffixText.startsWith('- ') ? t.chrome.bad : '244',
106
- dim: true,
107
- });
108
- }
109
- return segments;
110
- }
111
-
112
- /**
113
- * Extract the most meaningful argument from a tool call for display.
114
- */
115
- function extractKeyArg(toolCall: ToolCall): string {
116
- const args = toolCall.arguments;
117
- // Path-based tools
118
- if (typeof args.path === 'string') return args.path;
119
- if (typeof args.file === 'string') return args.file;
120
- if (typeof args.query === 'string') return args.query;
121
- if (typeof args.title === 'string') return args.title;
122
- // Array-based (read/write)
123
- if (Array.isArray(args.files) && args.files.length > 0) {
124
- const first = args.files[0];
125
- if (typeof first === 'string') return first;
126
- if (first && typeof first === 'object' && typeof (first as Record<string, unknown>).path === 'string')
127
- return (first as Record<string, unknown>).path as string;
128
- }
129
- // Exec
130
- if (typeof args.command === 'string') return args.command;
131
- if (typeof args.cmd === 'string') return args.cmd;
132
- if (Array.isArray(args.commands) && args.commands.length > 0) {
133
- const first = args.commands[0];
134
- if (first && typeof first === 'object' && typeof (first as Record<string, unknown>).cmd === 'string')
135
- return (first as Record<string, unknown>).cmd as string;
136
- }
137
- // Find/grep
138
- if (typeof args.pattern === 'string') return args.pattern;
139
- if (Array.isArray(args.queries) && args.queries.length > 0) {
140
- const first = args.queries[0];
141
- if (first && typeof first === 'object') {
142
- const firstRecord = first as Record<string, unknown>;
143
- if (typeof firstRecord.query === 'string') return firstRecord.query;
144
- if (typeof firstRecord.pattern === 'string') return firstRecord.pattern;
145
- }
146
- }
147
- // Fetch
148
- if (Array.isArray(args.urls) && args.urls.length > 0) {
149
- const first = args.urls[0];
150
- if (first && typeof first === 'object' && typeof (first as Record<string, unknown>).url === 'string')
151
- return (first as Record<string, unknown>).url as string;
152
- }
153
- // Agent
154
- if (typeof args.task === 'string') return args.task.slice(0, 40);
155
- if (typeof args.mode === 'string') return args.mode;
156
- // Fallback: first string value
157
- for (const val of Object.values(args)) {
158
- if (typeof val === 'string' && val.length > 0) return val.slice(0, 40);
159
- }
160
- return '';
161
- }
162
-
163
- /**
164
- * Render a tool call as a single collapsed line.
165
- *
166
- * Layout: [margin] [icon] [space] [tool name padded] [key arg] [summary] [duration]
167
- *
168
- * @param toolCall - The tool call being executed
169
- * @param status - 'executing' | 'done' | 'error' | 'pending' | 'cancelled'
170
- * @param resultSummary - Optional brief summary (e.g., "3 files", "exit 0")
171
- * @param width - Terminal width
172
- * @param durationMs - Optional duration in milliseconds
173
- * @param errorMsg - Optional error message for failed calls
174
- * @param frameIndex - Spinner frame index for animated icon
175
- * @param startedAtMs - Wall-clock ms when execution started; enables live elapsed timer
176
- */
177
- export function renderToolCallBlock(
178
- toolCall: ToolCall,
179
- status: 'executing' | 'done' | 'error' | 'pending' | 'cancelled',
180
- resultSummary: string | undefined,
181
- width: number,
182
- durationMs?: number,
183
- errorMsg?: string,
184
- frameIndex?: number,
185
- startedAtMs?: number,
186
- tree?: ToolCallTreeOptions,
187
- ): Line[] {
188
- const line = createEmptyLine(width);
189
- const t = activeUiTones();
190
- const indent = Math.max(0, tree?.indentCols ?? 0);
191
- const inTree = indent > 0;
192
- // In tree mode the row's columns come from the shared grid: the branch glyph
193
- // where the parent's content began, the status marker in the bullet column,
194
- // and the row's text at this depth's text column.
195
- const margin = inTree ? treeContentCol(indent) : LAYOUT.LEFT_MARGIN;
196
- const rightMargin = LAYOUT.RIGHT_MARGIN;
197
- const contentEnd = width - rightMargin;
198
-
199
-
200
- // Status icon. 'pending' means the tool is still awaiting a decision
201
- // (e.g. an approval prompt) and has NOT run yet, it uses the hollow idle
202
- // glyph so a not-yet-run tool never shows the completed green ✓ (2c).
203
- // 'cancelled' means the user stopped THIS call mid-flight, the blocked glyph
204
- // in the warn tone, distinct from both success and a real error.
205
- const icon = status === 'done' ? TOOL_STATUS.SUCCESS_ICON
206
- : status === 'error' ? TOOL_STATUS.FAIL_ICON
207
- : status === 'cancelled' ? GLYPHS.status.blocked
208
- : status === 'pending' ? GLYPHS.status.idle
209
- : TOOL_STATUS.SPINNER_FRAMES[(frameIndex ?? 0) % TOOL_STATUS.SPINNER_FRAMES.length];
210
- const iconColor = status === 'done' ? t.chrome.good
211
- : status === 'error' ? t.chrome.bad
212
- : status === 'cancelled' ? t.chrome.warn
213
- : '244';
214
- const rightText = (() => {
215
- if (durationMs !== undefined && status === 'done') {
216
- return formatElapsed(durationMs);
217
- }
218
- if (status === 'executing') {
219
- if (startedAtMs !== undefined) {
220
- return formatElapsed(Date.now() - startedAtMs);
221
- }
222
- return '...';
223
- }
224
- return '';
225
- })();
226
- const rightWidth = getDisplayWidth(rightText);
227
- const rightStart = rightText
228
- ? Math.max(margin + 2, contentEnd - rightWidth)
229
- : contentEnd;
230
- const leftStart = inTree ? treeTextCol(indent) : margin;
231
- const leftEndExclusive = rightText
232
- ? Math.max(leftStart, rightStart - 1)
233
- : contentEnd;
234
- let col: number = leftStart;
235
-
236
- // In tree mode the status glyph goes in the bullet column, the same column
237
- // as the `●` of the `● assistant` header this row hangs under, so a turn's
238
- // markers read as that bullet's column continuing down the turn. The row's
239
- // own text then starts at its depth's text column with no inline icon slot.
240
- if (inTree) {
241
- writeTreeStatusMarker(line, icon, iconColor, width);
242
- } else {
243
- if (col < leftEndExclusive) {
244
- line[col] = createStyledCell(icon, { fg: iconColor, bold: status === 'done' || status === 'error' || status === 'cancelled' });
245
- }
246
- col += 2; // icon + space
247
- }
248
-
249
- // Tool name, extract short name for long MCP tool names, but keep a readable dynamic width.
250
- const rawName = toolCall.name.includes('__')
251
- ? toolCall.name.split('__').pop()!
252
- : toolCall.name;
253
- const keyArg = stripDangerousAnsi(extractKeyArg(toolCall));
254
- const suffixText = status === 'error' && errorMsg
255
- ? `- ${stripDangerousAnsi(errorMsg).slice(0, 40)}`
256
- : status === 'cancelled'
257
- ? '- cancelled'
258
- : status === 'done' && resultSummary
259
- ? `(${stripDangerousAnsi(resultSummary)})`
260
- : '';
261
- const leftBudget = Math.max(0, leftEndExclusive - col);
262
- const leftSegments = buildLeftSegments(rawName, keyArg, suffixText, leftBudget, tree?.omitToolName ?? false);
263
- for (const segment of leftSegments) {
264
- col = writeStyledText(line, col, leftEndExclusive, segment.text, {
265
- fg: segment.fg,
266
- bold: segment.bold ?? false,
267
- dim: segment.dim ?? false,
268
- });
269
- }
270
-
271
- if (rightText) {
272
- writeStyledText(line, rightStart, contentEnd, rightText, { fg: '238', dim: true });
273
- }
274
-
275
- return [line];
276
- }
@@ -1,48 +0,0 @@
1
- /**
2
- * tool-result-expanded-lines.ts, the single source of truth for how many
3
- * screen lines a tool-result message's EXPANDED form actually renders to.
4
- *
5
- * Tool-result content gets pretty-printed (JSON.stringify(parsed, null, 2))
6
- * or diff-rendered before display, so the raw message's `content.split('\n')`
7
- * length is not what the user sees once expanded, a one-line JSON blob can
8
- * pretty-print to 50 lines. Both the per-block "N lines" badge
9
- * (conversation-rendering.ts) and the folded-group total (conversation-tool-
10
- * groups.ts) must count the SAME post-render lines, or the two disagree with
11
- * each other and both can disagree with what Tab actually reveals.
12
- */
13
-
14
- import type { Line } from '@pellux/goodvibes-sdk/platform/types';
15
- import { renderMarkdownTracked } from './markdown.ts';
16
- import { renderDiffView } from './diff-view.ts';
17
-
18
- /** True when `content` looks like a unified diff (matches the detection used
19
- * by renderConversationToolMessage to pick the diff block type). */
20
- export function isDiffContent(content: string): boolean {
21
- const contentLines = content.split('\n');
22
- const hasDiffHeader = contentLines.some((l) => l.startsWith('--- ')) && contentLines.some((l) => l.startsWith('+++ '));
23
- const hasHunk = contentLines.some((l) => l.startsWith('@@ '));
24
- return hasDiffHeader && hasHunk;
25
- }
26
-
27
- /**
28
- * Render a tool result's content exactly as its EXPANDED form would appear in
29
- * the transcript (diff view for diffs; pretty-printed JSON, when parseable,
30
- * for everything else). The caller decides whether to actually display these
31
- * lines or just count them.
32
- */
33
- export function renderExpandedToolResultLines(content: string, width: number): Line[] {
34
- if (isDiffContent(content)) {
35
- return renderDiffView(content, width);
36
- }
37
- let contentToRender = content;
38
- const trimmed = contentToRender.trimStart();
39
- if ((trimmed.startsWith('{') || trimmed.startsWith('[')) && contentToRender.length < 100_000) {
40
- try {
41
- const parsed = JSON.parse(contentToRender);
42
- contentToRender = `\`\`\`json\n${JSON.stringify(parsed, null, 2)}\n\`\`\``;
43
- } catch {
44
- // Leave invalid JSON as-is, falls through to the plain markdown render below.
45
- }
46
- }
47
- return renderMarkdownTracked(contentToRender, width).lines;
48
- }
@@ -1,219 +0,0 @@
1
- /**
2
- * summarizeToolResult, one-line human summaries for tool RESULTS, so the
3
- * transcript (and the fleet attach view, which shares the same rendering seam
4
- * in conversation-rendering.ts) shows "wrote haiku.txt (532 B)" instead of a
5
- * raw `{"files_written":1,"bytes_written":532,...}` JSON blob. The full payload
6
- * stays reachable behind the existing collapse/expand toggle, this only
7
- * changes the collapsed preview line, never destroys data. (item 3.)
8
- *
9
- * Returning `null` means "no honest summary for this shape", the caller then
10
- * falls back to the previous raw-first-line preview, so an unrecognised tool or
11
- * an unexpected payload is never mis-summarised.
12
- */
13
-
14
- /** Compact byte count: "87 B", "1.2 KB", "3.4 MB". */
15
- function formatBytes(n: number): string {
16
- if (!Number.isFinite(n) || n < 0) return '? B';
17
- if (n < 1024) return `${n} B`;
18
- if (n < 1024 * 1024) return `${(n / 1024).toFixed(1)} KB`;
19
- return `${(n / (1024 * 1024)).toFixed(1)} MB`;
20
- }
21
-
22
- /** Compact duration: "820ms", "1.2s", "1m3s". */
23
- function formatDuration(ms: number): string {
24
- if (!Number.isFinite(ms) || ms < 0) return '?';
25
- if (ms < 1000) return `${Math.round(ms)}ms`;
26
- if (ms < 60_000) return `${(ms / 1000).toFixed(1)}s`;
27
- const s = Math.round(ms / 1000);
28
- return `${Math.floor(s / 60)}m${s % 60}s`;
29
- }
30
-
31
- /** Trailing filename for compact display (paths can be long/absolute). */
32
- function baseName(p: string): string {
33
- const cleaned = p.replace(/[/\\]+$/, '');
34
- const idx = Math.max(cleaned.lastIndexOf('/'), cleaned.lastIndexOf('\\'));
35
- return idx >= 0 ? cleaned.slice(idx + 1) : cleaned;
36
- }
37
-
38
- function asNumber(v: unknown): number | undefined {
39
- return typeof v === 'number' && Number.isFinite(v) ? v : undefined;
40
- }
41
-
42
- function firstPath(files: unknown): string | undefined {
43
- if (!Array.isArray(files) || files.length === 0) return undefined;
44
- const first = files[0];
45
- if (typeof first === 'string') return first;
46
- if (first && typeof first === 'object') {
47
- const rec = first as Record<string, unknown>;
48
- if (typeof rec.path === 'string') return rec.path;
49
- if (typeof rec.resolved_path === 'string') return rec.resolved_path;
50
- }
51
- return undefined;
52
- }
53
-
54
- /** write: { files_written, bytes_written, files?: [{path, bytes_written}], dry_run? } */
55
- function summarizeWrite(obj: Record<string, unknown>): string | null {
56
- const count = asNumber(obj.files_written);
57
- const bytes = asNumber(obj.bytes_written);
58
- if (count === undefined) return null;
59
- const verb = obj.dry_run === true ? 'would write' : 'wrote';
60
- const size = bytes !== undefined ? ` (${formatBytes(bytes)})` : '';
61
- if (count === 1) {
62
- const path = firstPath(obj.files);
63
- return path ? `${verb} ${baseName(path)}${size}` : `${verb} 1 file${size}`;
64
- }
65
- return `${verb} ${count} files${size}`;
66
- }
67
-
68
- /** read: { summary: { files_read, total_lines }, files?: [{path, lineCount}] } */
69
- function summarizeRead(obj: Record<string, unknown>): string | null {
70
- const summary = (obj.summary && typeof obj.summary === 'object')
71
- ? obj.summary as Record<string, unknown>
72
- : obj;
73
- const count = asNumber(summary.files_read);
74
- const lines = asNumber(summary.total_lines);
75
- if (count === undefined && lines === undefined) return null;
76
- const lineText = lines !== undefined ? ` (${lines} line${lines === 1 ? '' : 's'})` : '';
77
- if (count === 1) {
78
- const path = firstPath(obj.files);
79
- return path ? `read ${baseName(path)}${lineText}` : `read 1 file${lineText}`;
80
- }
81
- return `read ${count ?? '?'} files${lineText}`;
82
- }
83
-
84
- /** edit: { applied, failed, dry_run } or richer with a path. */
85
- function summarizeEdit(obj: Record<string, unknown>): string | null {
86
- const applied = asNumber(obj.applied);
87
- if (applied === undefined) return null;
88
- const failed = asNumber(obj.failed) ?? 0;
89
- const verb = obj.dry_run === true ? 'would apply' : 'applied';
90
- const path = typeof obj.path === 'string' ? obj.path : firstPath(obj.files);
91
- const target = path ? ` to ${baseName(path)}` : '';
92
- const failText = failed > 0 ? `, ${failed} failed` : '';
93
- return `${verb} ${applied} edit${applied === 1 ? '' : 's'}${target}${failText}`;
94
- }
95
-
96
- // The credential scrub's withheld_env report stays OUT of the collapsed line
97
- // entirely. It withholds the same standing set of names on every spawn, so any
98
- // per-result rendering repeats identical env-var noise all session long, the
99
- // dominant transcript spam for anyone with several keys exported. The report
100
- // only matters when a command fails because a needed credential was scrubbed,
101
- // and for that case the full name list is one expand away in the raw payload.
102
-
103
- /**
104
- * Compact per-command exec-sandbox suffix: `sandboxed` fields are present
105
- * only when the sandbox was active for the run (SDK's attachSandboxMeta stays
106
- * quiet otherwise), so absence here means "ran unsandboxed" and the suffix is
107
- * empty, never a fabricated claim either way.
108
- *
109
- * sandboxed, network disabled -> " · sandboxed (net off)"
110
- * sandboxed, network enabled, escalation -> " · sandboxed (net on, +1 escalation)"
111
- * requested but host couldn't provide it -> " · sandbox unavailable (<reason>)"
112
- */
113
- function sandboxSuffix(obj: Record<string, unknown>): string {
114
- const sandboxed = obj.sandboxed;
115
- if (sandboxed === undefined) return '';
116
- if (sandboxed === false) {
117
- const reason = typeof obj.sandbox_boundary === 'string' ? obj.sandbox_boundary : undefined;
118
- return reason ? ` · sandbox unavailable (${reason})` : ' · sandbox unavailable';
119
- }
120
- const network = typeof obj.sandbox_network === 'string' ? obj.sandbox_network : undefined;
121
- const escalations = Array.isArray(obj.sandbox_escalations)
122
- ? obj.sandbox_escalations.filter((e): e is string => typeof e === 'string')
123
- : [];
124
- const netText = network ? `net ${network}` : undefined;
125
- const escText = escalations.length > 0 ? `+${escalations.length} escalation${escalations.length === 1 ? '' : 's'}` : undefined;
126
- const detail = [netText, escText].filter((s): s is string => s !== undefined).join(', ');
127
- return detail ? ` · sandboxed (${detail})` : ' · sandboxed';
128
- }
129
-
130
- /** A single exec command result. */
131
- function summarizeExecOne(obj: Record<string, unknown>): string | null {
132
- const exit = obj.exit_code;
133
- const dur = asNumber(obj.duration_ms);
134
- const durText = dur !== undefined ? ` · ${formatDuration(dur)}` : '';
135
- const sandboxText = sandboxSuffix(obj);
136
- if (obj.timed_out === true) return `timed out${durText}${sandboxText}`;
137
- if (obj.cancelled === true) return `cancelled${durText}${sandboxText}`;
138
- const stdout = typeof obj.stdout === 'string' ? obj.stdout : '';
139
- const lineCount = stdout.length === 0
140
- ? 0
141
- : stdout.replace(/\n$/, '').split('\n').length;
142
- const lineText = lineCount > 0 ? ` · ${lineCount} line${lineCount === 1 ? '' : 's'}` : '';
143
- const code = typeof exit === 'number' ? String(exit) : '?';
144
- return `exit ${code}${durText}${lineText}${sandboxText}`;
145
- }
146
-
147
- /** exec: single { cmd, exit_code, ... } or multi { commands: [...], total }. */
148
- function summarizeExec(obj: Record<string, unknown>): string | null {
149
- if (Array.isArray(obj.commands)) {
150
- const total = asNumber(obj.total) ?? obj.commands.length;
151
- const failed = obj.commands.filter(
152
- (c) => c && typeof c === 'object' && (c as Record<string, unknown>).success === false,
153
- ).length;
154
- // Count sandboxed commands across the batch, a compact "N sandboxed" beats
155
- // repeating each command's full boundary detail on the collapsed line.
156
- const sandboxedCount = obj.commands.filter(
157
- (c) => c && typeof c === 'object' && (c as Record<string, unknown>).sandboxed === true,
158
- ).length;
159
- const sandboxText = sandboxedCount > 0 ? ` · ${sandboxedCount} sandboxed` : '';
160
- return failed > 0
161
- ? `${total} commands · ${failed} failed${sandboxText}`
162
- : `${total} commands · all ok${sandboxText}`;
163
- }
164
- if ('exit_code' in obj || 'timed_out' in obj || 'cancelled' in obj) {
165
- return summarizeExecOne(obj);
166
- }
167
- return null;
168
- }
169
-
170
- /**
171
- * agent status/get/wait: an optional `failure` field (ChildFailureEnvelope,
172
- * see the SDK's tools/agent/child-failure-envelope.ts) is present once the
173
- * child agent terminated abnormally (max_turns, circuit_breaker,
174
- * watchdog_timeout, budget_exhausted, claim_unverified, api_error, killed,
175
- * interrupted, error). Renders it compactly on the collapsed preview line so
176
- * a failed child is visible without expanding the full result; absent
177
- * `failure` (the common, successful case) falls through to the raw preview.
178
- */
179
- function summarizeAgentFailure(obj: Record<string, unknown>): string | null {
180
- const failure = obj.failure;
181
- if (!failure || typeof failure !== 'object') return null;
182
- const f = failure as Record<string, unknown>;
183
- const agentId = typeof f.agentId === 'string' ? f.agentId : '?';
184
- const phase = typeof f.phase === 'string' ? f.phase : undefined;
185
- const reason = f.reason && typeof f.reason === 'object' ? f.reason as Record<string, unknown> : undefined;
186
- const code = reason && typeof reason.code === 'string' ? reason.code : 'error';
187
- const message = reason && typeof reason.message === 'string' ? reason.message : '';
188
- const partialOutputs = f.partialOutputs && typeof f.partialOutputs === 'object' ? f.partialOutputs as Record<string, unknown> : undefined;
189
- const turnsCompleted = asNumber(partialOutputs?.turnsCompleted);
190
-
191
- const MAX_MSG_LEN = 80;
192
- const truncatedMessage = message.length > MAX_MSG_LEN ? `${message.slice(0, MAX_MSG_LEN - 3)}...` : message;
193
- const phaseText = phase ? ` at ${phase}` : '';
194
- const turnsText = turnsCompleted !== undefined ? ` (${turnsCompleted} turn${turnsCompleted === 1 ? '' : 's'} completed)` : '';
195
- const msgText = truncatedMessage.length > 0 ? `: ${truncatedMessage}` : '';
196
- return `agent ${agentId} failed [${code}]${phaseText}${msgText}${turnsText}`;
197
- }
198
-
199
- export function summarizeToolResult(toolName: string | undefined, content: string): string | null {
200
- if (!toolName) return null;
201
- const family = toolName.includes('__') ? toolName.split('__').pop()! : toolName;
202
- let data: unknown;
203
- try {
204
- data = JSON.parse(content);
205
- } catch {
206
- return null;
207
- }
208
- if (data === null || typeof data !== 'object' || Array.isArray(data)) return null;
209
- const obj = data as Record<string, unknown>;
210
-
211
- switch (family) {
212
- case 'write': return summarizeWrite(obj);
213
- case 'read': return summarizeRead(obj);
214
- case 'edit': return summarizeEdit(obj);
215
- case 'exec': return summarizeExec(obj);
216
- case 'agent': return summarizeAgentFailure(obj);
217
- default: return null;
218
- }
219
- }
@@ -1,21 +0,0 @@
1
- /**
2
- * Diagnostics panels barrel, re-exports all panel data provider classes.
3
- *
4
- * Import from this module to access the individual diagnostic panel providers.
5
- */
6
- export { ToolCallsPanel } from '@/runtime/index.ts';
7
- export { AgentsPanel } from '@/runtime/index.ts';
8
- export { TasksPanel } from '@/runtime/index.ts';
9
- export { EventsPanel } from '@/runtime/index.ts';
10
- export { StateInspectorPanel } from '@/runtime/index.ts';
11
- export type { InspectableDomain } from '@/runtime/index.ts';
12
- export { HealthPanel } from '@/runtime/index.ts';
13
- export { DivergencePanel } from '@/runtime/index.ts';
14
- export { ReplayPanel } from '@/runtime/index.ts';
15
- export { ToolContractsPanel } from '@/runtime/index.ts';
16
- export { TransportPanel } from '@/runtime/index.ts';
17
- export type { TransportPanelSnapshot } from '@/runtime/index.ts';
18
- export { OpsPanel } from './ops.ts';
19
- export type { OpsAuditEntry } from './ops.ts';
20
- export { SecurityPanel } from '@/runtime/index.ts';
21
- export type { SecurityPanelSnapshot } from '@/runtime/index.ts';