@oh-my-pi/pi-tui 18.2.3 → 18.2.5

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 (750) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/README.md +43 -0
  3. package/dist/types/app-keybindings.d.ts +395 -0
  4. package/dist/types/apps/autoresearch-dashboard.d.ts +43 -0
  5. package/dist/types/apps/autoresearch-data.d.ts +15 -0
  6. package/dist/types/apps/cleanse-board.d.ts +66 -0
  7. package/dist/types/apps/cleanse-picker.d.ts +23 -0
  8. package/dist/types/apps/debug/log-formatting.d.ts +6 -0
  9. package/dist/types/apps/debug/log-viewer.d.ts +81 -0
  10. package/dist/types/apps/debug/protocol-probe.d.ts +42 -0
  11. package/dist/types/apps/debug/raw-sse-buffer.d.ts +58 -0
  12. package/dist/types/apps/debug/raw-sse.d.ts +26 -0
  13. package/dist/types/apps/debug/terminal-info.d.ts +34 -0
  14. package/dist/types/apps/debug/viewer-frame.d.ts +52 -0
  15. package/dist/types/apps/git/avatar.d.ts +9 -0
  16. package/dist/types/apps/git/colors.d.ts +49 -0
  17. package/dist/types/apps/git/diff-pane.d.ts +188 -0
  18. package/dist/types/apps/git/git-tui.d.ts +66 -0
  19. package/dist/types/apps/git/sidebar.d.ts +149 -0
  20. package/dist/types/apps/git/state.d.ts +117 -0
  21. package/dist/types/apps/if-bench-board.d.ts +75 -0
  22. package/dist/types/apps/live-visualizer.d.ts +33 -0
  23. package/dist/types/apps/ps-data.d.ts +51 -0
  24. package/dist/types/apps/ps-top.d.ts +33 -0
  25. package/dist/types/apps/session-picker.d.ts +26 -0
  26. package/dist/types/apps/setup-model-picker.d.ts +13 -0
  27. package/dist/types/apps/standalone-picker.d.ts +42 -0
  28. package/dist/types/autocomplete.d.ts +4 -0
  29. package/dist/types/chat/advisor-message.d.ts +11 -0
  30. package/dist/types/chat/assistant-message.d.ts +106 -0
  31. package/dist/types/chat/background-tan-message.d.ts +9 -0
  32. package/dist/types/chat/bash-execution.d.ts +47 -0
  33. package/dist/types/chat/cache-invalidation-marker.d.ts +50 -0
  34. package/dist/types/chat/chat-transcript-builder.d.ts +50 -0
  35. package/dist/types/chat/collab-prompt-message.d.ts +10 -0
  36. package/dist/types/chat/compaction-summary-message.d.ts +54 -0
  37. package/dist/types/chat/custom-message.d.ts +10 -0
  38. package/dist/types/chat/display-preferences.d.ts +13 -0
  39. package/dist/types/chat/eval-execution.d.ts +29 -0
  40. package/dist/types/chat/execution-shared.d.ts +51 -0
  41. package/dist/types/chat/extension-types.d.ts +28 -0
  42. package/dist/types/chat/hook-message.d.ts +10 -0
  43. package/dist/types/chat/image-loading.d.ts +46 -0
  44. package/dist/types/chat/late-diagnostics-message.d.ts +21 -0
  45. package/dist/types/chat/messages.d.ts +189 -0
  46. package/dist/types/chat/reaction.d.ts +30 -0
  47. package/dist/types/chat/read-target.d.ts +4 -0
  48. package/dist/types/chat/read-tool-group.d.ts +67 -0
  49. package/dist/types/chat/served-model-marker.d.ts +47 -0
  50. package/dist/types/chat/skill-message.d.ts +33 -0
  51. package/dist/types/chat/skill-title-input.d.ts +14 -0
  52. package/dist/types/chat/stripped-tool-calls-placeholder.d.ts +12 -0
  53. package/dist/types/chat/thinking-display.d.ts +12 -0
  54. package/dist/types/chat/todo-reminder.d.ts +13 -0
  55. package/dist/types/chat/tool-execution.d.ts +138 -0
  56. package/dist/types/chat/transcript-browser.d.ts +93 -0
  57. package/dist/types/chat/transcript-entry.d.ts +45 -0
  58. package/dist/types/chat/transcript-outline.d.ts +86 -0
  59. package/dist/types/chat/transcript-render-helpers.d.ts +92 -0
  60. package/dist/types/chat/ttsr-notification.d.ts +23 -0
  61. package/dist/types/chat/user-message.d.ts +52 -0
  62. package/dist/types/chrome/chat-block.d.ts +64 -0
  63. package/dist/types/chrome/collab-qrcode.d.ts +28 -0
  64. package/dist/types/chrome/context-thresholds.d.ts +10 -0
  65. package/dist/types/chrome/countdown-timer.d.ts +14 -0
  66. package/dist/types/chrome/diff.d.ts +14 -0
  67. package/dist/types/chrome/dynamic-border.d.ts +16 -0
  68. package/dist/types/chrome/error-block.d.ts +17 -0
  69. package/dist/types/chrome/form-theme.d.ts +3 -0
  70. package/dist/types/chrome/format.d.ts +12 -0
  71. package/dist/types/chrome/index.d.ts +20 -0
  72. package/dist/types/chrome/keybinding-hints.d.ts +40 -0
  73. package/dist/types/chrome/live-board.d.ts +23 -0
  74. package/dist/types/chrome/local-date.d.ts +4 -0
  75. package/dist/types/chrome/message-divider.d.ts +22 -0
  76. package/dist/types/chrome/message-frame.d.ts +52 -0
  77. package/dist/types/chrome/message-notice.d.ts +35 -0
  78. package/dist/types/chrome/overlay-box.d.ts +74 -0
  79. package/dist/types/chrome/qrcode.d.ts +48 -0
  80. package/dist/types/chrome/segment-track.d.ts +27 -0
  81. package/dist/types/chrome/select-list-mouse-routing.d.ts +4 -0
  82. package/dist/types/chrome/selector-helpers.d.ts +52 -0
  83. package/dist/types/chrome/shared.d.ts +5 -0
  84. package/dist/types/chrome/streaming-panel.d.ts +19 -0
  85. package/dist/types/chrome/tool-activity.d.ts +17 -0
  86. package/dist/types/chrome/transcript-container.d.ts +129 -0
  87. package/dist/types/chrome/transcript-status.d.ts +12 -0
  88. package/dist/types/chrome/visual-truncate.d.ts +19 -0
  89. package/dist/types/components/disclosure.d.ts +42 -0
  90. package/dist/types/components/form.d.ts +130 -0
  91. package/dist/types/components/image.d.ts +18 -16
  92. package/dist/types/components/key-value-list.d.ts +24 -0
  93. package/dist/types/components/layout/geometry.d.ts +73 -0
  94. package/dist/types/components/layout/row.d.ts +55 -0
  95. package/dist/types/components/layout/split-pane.d.ts +80 -0
  96. package/dist/types/components/layout/stack.d.ts +50 -0
  97. package/dist/types/components/menu-selection.d.ts +71 -0
  98. package/dist/types/components/metric.d.ts +44 -0
  99. package/dist/types/components/progress-bar.d.ts +36 -0
  100. package/dist/types/components/scroll-view.d.ts +53 -19
  101. package/dist/types/components/scroll-viewport.d.ts +46 -0
  102. package/dist/types/components/section.d.ts +19 -0
  103. package/dist/types/components/select-list.d.ts +46 -2
  104. package/dist/types/components/settings-list.d.ts +20 -0
  105. package/dist/types/components/table.d.ts +32 -0
  106. package/dist/types/components/tree-view.d.ts +130 -0
  107. package/dist/types/components/wizard-step.d.ts +60 -0
  108. package/dist/types/hotkeys-markdown.d.ts +7 -0
  109. package/dist/types/index.d.ts +17 -0
  110. package/dist/types/keybinding-matchers.d.ts +35 -0
  111. package/dist/types/keys.d.ts +2 -2
  112. package/dist/types/lang-from-path.d.ts +9 -0
  113. package/dist/types/overlays/advisor-config.d.ts +114 -0
  114. package/dist/types/overlays/agent-activity.d.ts +41 -0
  115. package/dist/types/overlays/agent-hub-projection.d.ts +33 -0
  116. package/dist/types/overlays/agent-hub-renderer.d.ts +53 -0
  117. package/dist/types/overlays/agent-hub-types.d.ts +99 -0
  118. package/dist/types/overlays/agent-hub.d.ts +126 -0
  119. package/dist/types/overlays/agent-transcript-viewer.d.ts +71 -0
  120. package/dist/types/overlays/agents-hub.d.ts +72 -0
  121. package/dist/types/overlays/ask-dialog.d.ts +88 -0
  122. package/dist/types/overlays/bordered-loader.d.ts +11 -0
  123. package/dist/types/overlays/btw-history-panel.d.ts +29 -0
  124. package/dist/types/overlays/btw-history.d.ts +17 -0
  125. package/dist/types/overlays/btw-panel.d.ts +26 -0
  126. package/dist/types/overlays/cleanse-panel.d.ts +36 -0
  127. package/dist/types/overlays/codex-reset-fireworks.d.ts +52 -0
  128. package/dist/types/overlays/composer-shape-preview.d.ts +47 -0
  129. package/dist/types/overlays/composer-shape-registry.d.ts +50 -0
  130. package/dist/types/overlays/copy-selector.d.ts +48 -0
  131. package/dist/types/overlays/copy-targets.d.ts +63 -0
  132. package/dist/types/overlays/error-banner.d.ts +13 -0
  133. package/dist/types/overlays/extensions/display-text.d.ts +10 -0
  134. package/dist/types/overlays/extensions/extension-dashboard.d.ts +63 -0
  135. package/dist/types/overlays/extensions/extension-list.d.ts +54 -0
  136. package/dist/types/overlays/extensions/inspector-model.d.ts +109 -0
  137. package/dist/types/overlays/extensions/inspector-panel.d.ts +17 -0
  138. package/dist/types/overlays/extensions/live-tool-session.d.ts +28 -0
  139. package/dist/types/overlays/extensions/mcp-runtime.d.ts +107 -0
  140. package/dist/types/overlays/extensions/state-manager.d.ts +42 -0
  141. package/dist/types/overlays/extensions/types.d.ts +165 -0
  142. package/dist/types/overlays/history-search.d.ts +16 -0
  143. package/dist/types/overlays/hook-editor.d.ts +44 -0
  144. package/dist/types/overlays/hook-input.d.ts +20 -0
  145. package/dist/types/overlays/hook-selector.d.ts +71 -0
  146. package/dist/types/overlays/hub-frame.d.ts +77 -0
  147. package/dist/types/overlays/login-dialog.d.ts +43 -0
  148. package/dist/types/overlays/logout-account-selector.d.ts +15 -0
  149. package/dist/types/overlays/mcp-add-wizard.d.ts +87 -0
  150. package/dist/types/overlays/model-browser.d.ts +213 -0
  151. package/dist/types/overlays/model-hub.d.ts +72 -0
  152. package/dist/types/overlays/model-picker.d.ts +74 -0
  153. package/dist/types/overlays/model-selector.d.ts +52 -0
  154. package/dist/types/overlays/move-overlay.d.ts +39 -0
  155. package/dist/types/overlays/oauth-selector.d.ts +41 -0
  156. package/dist/types/overlays/omfg-panel.d.ts +20 -0
  157. package/dist/types/overlays/pause-screen.d.ts +43 -0
  158. package/dist/types/overlays/plan-review-overlay.d.ts +89 -0
  159. package/dist/types/overlays/plan-save-overlay.d.ts +19 -0
  160. package/dist/types/overlays/plan-toc.d.ts +41 -0
  161. package/dist/types/overlays/plugin-selector.d.ts +28 -0
  162. package/dist/types/overlays/plugin-settings.d.ts +180 -0
  163. package/dist/types/overlays/queue-mode-selector.d.ts +11 -0
  164. package/dist/types/overlays/reset-usage-selector.d.ts +23 -0
  165. package/dist/types/overlays/rewind-selector.d.ts +61 -0
  166. package/dist/types/overlays/running-subagent-badge.d.ts +6 -0
  167. package/dist/types/overlays/session-account-selector.d.ts +24 -0
  168. package/dist/types/overlays/session-info-overlay.d.ts +17 -0
  169. package/dist/types/overlays/session-observer-registry.d.ts +77 -0
  170. package/dist/types/overlays/session-selector.d.ts +131 -0
  171. package/dist/types/overlays/settings-defs.d.ts +119 -0
  172. package/dist/types/overlays/settings-selector.d.ts +73 -0
  173. package/dist/types/overlays/show-images-selector.d.ts +11 -0
  174. package/dist/types/overlays/snapcompact-shape-preview.d.ts +31 -0
  175. package/dist/types/overlays/theme-selector.d.ts +12 -0
  176. package/dist/types/overlays/thinking-selector.d.ts +12 -0
  177. package/dist/types/overlays/tiny-title-download-progress.d.ts +21 -0
  178. package/dist/types/overlays/tree-selector.d.ts +92 -0
  179. package/dist/types/overlays/usage-dashboard.d.ts +94 -0
  180. package/dist/types/overlays/usage-display.d.ts +5 -0
  181. package/dist/types/overlays/usage-row.d.ts +17 -0
  182. package/dist/types/prompt/attachment-chips.d.ts +19 -0
  183. package/dist/types/prompt/composer-attachments.d.ts +71 -0
  184. package/dist/types/prompt/composer-cache.d.ts +37 -0
  185. package/dist/types/prompt/composer.d.ts +159 -0
  186. package/dist/types/prompt/custom-editor.d.ts +261 -0
  187. package/dist/types/prompt/editor-top-gap.d.ts +18 -0
  188. package/dist/types/prompt/emoji-autocomplete.d.ts +16 -0
  189. package/dist/types/prompt/github-ref-autocomplete.d.ts +35 -0
  190. package/dist/types/prompt/gradient-highlight.d.ts +32 -0
  191. package/dist/types/prompt/image-format.d.ts +4 -0
  192. package/dist/types/prompt/image-references.d.ts +26 -0
  193. package/dist/types/prompt/interactive-context-helpers.d.ts +43 -0
  194. package/dist/types/prompt/internal-url-autocomplete.d.ts +56 -0
  195. package/dist/types/prompt/macos-spelling.d.ts +44 -0
  196. package/dist/types/prompt/magic-keyword-boundary.d.ts +9 -0
  197. package/dist/types/prompt/magic-keywords.d.ts +26 -0
  198. package/dist/types/prompt/markdown-prose.d.ts +15 -0
  199. package/dist/types/prompt/model-mention-autocomplete.d.ts +25 -0
  200. package/dist/types/prompt/model-mention-syntax.d.ts +24 -0
  201. package/dist/types/prompt/orchestrate.d.ts +13 -0
  202. package/dist/types/prompt/prompt-action-autocomplete.d.ts +56 -0
  203. package/dist/types/prompt/queue-input.d.ts +8 -0
  204. package/dist/types/prompt/skill-tokens.d.ts +13 -0
  205. package/dist/types/prompt/tools-markdown.d.ts +12 -0
  206. package/dist/types/prompt/ultrathink.d.ts +13 -0
  207. package/dist/types/prompt/usage-amounts.d.ts +26 -0
  208. package/dist/types/prompt/video.d.ts +18 -0
  209. package/dist/types/prompt/welcome.d.ts +83 -0
  210. package/dist/types/prompt/workflow.d.ts +13 -0
  211. package/dist/types/render/code-cell.d.ts +51 -0
  212. package/dist/types/render/file-list.d.ts +22 -0
  213. package/dist/types/render/hyperlink.d.ts +80 -0
  214. package/dist/types/render/index.d.ts +16 -0
  215. package/dist/types/render/output-block.d.ts +54 -0
  216. package/dist/types/render/output-pane.d.ts +80 -0
  217. package/dist/types/render/render-utils.d.ts +312 -0
  218. package/dist/types/render/sixel.d.ts +21 -0
  219. package/dist/types/render/status-line.d.ts +23 -0
  220. package/dist/types/render/tool-card.d.ts +71 -0
  221. package/dist/types/render/tree-list.d.ts +29 -0
  222. package/dist/types/render/types.d.ts +17 -0
  223. package/dist/types/render/utils.d.ts +43 -0
  224. package/dist/types/render/width-aware-text.d.ts +23 -0
  225. package/dist/types/setup/lazy.d.ts +3 -0
  226. package/dist/types/setup/scenes/composer.d.ts +3 -0
  227. package/dist/types/setup/scenes/glyph.d.ts +3 -0
  228. package/dist/types/setup/scenes/model.d.ts +3 -0
  229. package/dist/types/setup/scenes/outro.d.ts +2 -0
  230. package/dist/types/setup/scenes/providers.d.ts +3 -0
  231. package/dist/types/setup/scenes/sign-in.d.ts +21 -0
  232. package/dist/types/setup/scenes/splash.d.ts +11 -0
  233. package/dist/types/setup/scenes/theme.d.ts +3 -0
  234. package/dist/types/setup/scenes/types.d.ts +110 -0
  235. package/dist/types/setup/scenes/web-search.d.ts +22 -0
  236. package/dist/types/setup/setup-version.d.ts +11 -0
  237. package/dist/types/setup/startup-splash.d.ts +9 -0
  238. package/dist/types/setup/wizard-overlay.d.ts +16 -0
  239. package/dist/types/setup/wizard.d.ts +25 -0
  240. package/dist/types/status-line/component.d.ts +182 -0
  241. package/dist/types/status-line/context-usage.d.ts +156 -0
  242. package/dist/types/status-line/footer.d.ts +30 -0
  243. package/dist/types/status-line/git-utils.d.ts +22 -0
  244. package/dist/types/status-line/host.d.ts +129 -0
  245. package/dist/types/status-line/index.d.ts +6 -0
  246. package/dist/types/status-line/loop.d.ts +18 -0
  247. package/dist/types/status-line/metrics.d.ts +21 -0
  248. package/dist/types/status-line/presets.d.ts +3 -0
  249. package/dist/types/status-line/schema.d.ts +15 -0
  250. package/dist/types/status-line/segments.d.ts +5 -0
  251. package/dist/types/status-line/separators.d.ts +3 -0
  252. package/dist/types/status-line/types.d.ts +236 -0
  253. package/dist/types/stdin-buffer.d.ts +4 -0
  254. package/dist/types/theme/color.d.ts +24 -0
  255. package/dist/types/theme/defaults/index.d.ts +9489 -0
  256. package/dist/types/theme/index.d.ts +4 -0
  257. package/dist/types/theme/loader.d.ts +23 -0
  258. package/dist/types/theme/mermaid-cache.d.ts +26 -0
  259. package/dist/types/theme/schema-validation.d.ts +3 -0
  260. package/dist/types/theme/schema.d.ts +25 -0
  261. package/dist/types/theme/session-color.d.ts +43 -0
  262. package/dist/types/theme/shimmer.d.ts +44 -0
  263. package/dist/types/theme/symbols.d.ts +34 -0
  264. package/dist/types/theme/theme-class.d.ts +299 -0
  265. package/dist/types/theme/theme.d.ts +111 -0
  266. package/dist/types/theme/tui-adapters.d.ts +30 -0
  267. package/dist/types/thinking.d.ts +165 -0
  268. package/dist/types/tools/agent-tree.d.ts +36 -0
  269. package/dist/types/tools/ask.d.ts +67 -0
  270. package/dist/types/tools/ast-edit.d.ts +53 -0
  271. package/dist/types/tools/ast-grep.d.ts +52 -0
  272. package/dist/types/tools/autoresearch.d.ts +156 -0
  273. package/dist/types/tools/bash-interactive.d.ts +28 -0
  274. package/dist/types/tools/bash.d.ts +103 -0
  275. package/dist/types/tools/conflict-detect.d.ts +43 -0
  276. package/dist/types/tools/debug.d.ts +60 -0
  277. package/dist/types/tools/default-renderer.d.ts +24 -0
  278. package/dist/types/tools/edit.d.ts +158 -0
  279. package/dist/types/tools/eval-format/code-mode-declarations.d.ts +5 -0
  280. package/dist/types/tools/eval-format/index.d.ts +5 -0
  281. package/dist/types/tools/eval-format/javascript.d.ts +2 -0
  282. package/dist/types/tools/eval-format/python.d.ts +2 -0
  283. package/dist/types/tools/eval.d.ts +94 -0
  284. package/dist/types/tools/fetch.d.ts +42 -0
  285. package/dist/types/tools/gh-format.d.ts +8 -0
  286. package/dist/types/tools/github.d.ts +144 -0
  287. package/dist/types/tools/glob.d.ts +44 -0
  288. package/dist/types/tools/goal.d.ts +42 -0
  289. package/dist/types/tools/grep.d.ts +64 -0
  290. package/dist/types/tools/grouped-file-output.d.ts +71 -0
  291. package/dist/types/tools/hashline-format.d.ts +28 -0
  292. package/dist/types/tools/hub.d.ts +340 -0
  293. package/dist/types/tools/index.d.ts +4 -0
  294. package/dist/types/tools/json-tree.d.ts +59 -0
  295. package/dist/types/tools/line-ranges.d.ts +29 -0
  296. package/dist/types/tools/list-limit.d.ts +15 -0
  297. package/dist/types/tools/lsp.d.ts +72 -0
  298. package/dist/types/tools/match-line-format.d.ts +11 -0
  299. package/dist/types/tools/mcp.d.ts +81 -0
  300. package/dist/types/tools/memory.d.ts +67 -0
  301. package/dist/types/tools/output-meta.d.ts +151 -0
  302. package/dist/types/tools/read.d.ts +139 -0
  303. package/dist/types/tools/renderer.d.ts +98 -0
  304. package/dist/types/tools/report-tool-issue.d.ts +8 -0
  305. package/dist/types/tools/resolve.d.ts +47 -0
  306. package/dist/types/tools/streaming-output.d.ts +282 -0
  307. package/dist/types/tools/subprocess.d.ts +24 -0
  308. package/dist/types/tools/task-repair-args.d.ts +53 -0
  309. package/dist/types/tools/task-yield-assembly.d.ts +20 -0
  310. package/dist/types/tools/task.d.ts +425 -0
  311. package/dist/types/tools/terminal-output.d.ts +8 -0
  312. package/dist/types/tools/think.d.ts +13 -0
  313. package/dist/types/tools/todo.d.ts +118 -0
  314. package/dist/types/tools/tool-errors.d.ts +7 -0
  315. package/dist/types/tools/vibe.d.ts +120 -0
  316. package/dist/types/tools/web-search.d.ts +195 -0
  317. package/dist/types/tools/write.d.ts +76 -0
  318. package/dist/types/tools/xd-url.d.ts +13 -0
  319. package/dist/types/tools/xdev.d.ts +52 -0
  320. package/dist/types/tui.d.ts +18 -0
  321. package/dist/types/utils.d.ts +2 -0
  322. package/package.json +37 -3
  323. package/src/app-keybindings.ts +760 -0
  324. package/src/apps/autoresearch-dashboard.ts +500 -0
  325. package/src/apps/autoresearch-data.ts +64 -0
  326. package/src/apps/cleanse-board.ts +341 -0
  327. package/src/apps/cleanse-picker.ts +57 -0
  328. package/src/apps/debug/log-formatting.ts +53 -0
  329. package/src/apps/debug/log-viewer.ts +868 -0
  330. package/src/apps/debug/protocol-probe.ts +267 -0
  331. package/src/apps/debug/raw-sse-buffer.ts +449 -0
  332. package/src/apps/debug/raw-sse.ts +282 -0
  333. package/src/apps/debug/terminal-info.ts +115 -0
  334. package/src/apps/debug/viewer-frame.ts +174 -0
  335. package/src/apps/git/avatar.ts +52 -0
  336. package/src/apps/git/colors.ts +109 -0
  337. package/src/apps/git/diff-pane.ts +1512 -0
  338. package/src/apps/git/git-tui.ts +889 -0
  339. package/src/apps/git/sidebar.ts +1204 -0
  340. package/src/apps/git/state.ts +113 -0
  341. package/src/apps/if-bench-board.ts +324 -0
  342. package/src/apps/live-visualizer.ts +238 -0
  343. package/src/apps/ps-data.ts +116 -0
  344. package/src/apps/ps-top.ts +422 -0
  345. package/src/apps/session-picker.ts +95 -0
  346. package/src/apps/setup-model-picker.ts +21 -0
  347. package/src/apps/standalone-picker.ts +111 -0
  348. package/src/autocomplete.ts +9 -13
  349. package/src/chat/advisor-message.ts +175 -0
  350. package/src/chat/assistant-message.ts +1214 -0
  351. package/src/chat/background-tan-message.ts +35 -0
  352. package/src/chat/bash-execution.ts +394 -0
  353. package/src/chat/cache-invalidation-marker.ts +94 -0
  354. package/src/chat/chat-transcript-builder.ts +593 -0
  355. package/src/chat/collab-prompt-message.ts +34 -0
  356. package/src/chat/compaction-summary-message.ts +261 -0
  357. package/src/chat/custom-message.ts +23 -0
  358. package/src/chat/display-preferences.ts +24 -0
  359. package/src/chat/eval-execution.ts +172 -0
  360. package/src/chat/execution-shared.ts +113 -0
  361. package/src/chat/extension-types.ts +46 -0
  362. package/src/chat/hook-message.ts +20 -0
  363. package/src/chat/image-loading.ts +122 -0
  364. package/src/chat/late-diagnostics-message.ts +92 -0
  365. package/src/chat/messages.ts +305 -0
  366. package/src/chat/reaction.ts +65 -0
  367. package/src/chat/read-target.ts +7 -0
  368. package/src/chat/read-tool-group.ts +873 -0
  369. package/src/chat/served-model-marker.ts +91 -0
  370. package/src/chat/skill-message.ts +220 -0
  371. package/src/chat/skill-title-input.ts +41 -0
  372. package/src/chat/stripped-tool-calls-placeholder.ts +35 -0
  373. package/src/chat/thinking-display.ts +312 -0
  374. package/src/chat/todo-reminder.ts +33 -0
  375. package/src/chat/tool-execution.ts +1395 -0
  376. package/src/chat/transcript-browser.ts +268 -0
  377. package/src/chat/transcript-entry.ts +96 -0
  378. package/src/chat/transcript-outline.ts +260 -0
  379. package/src/chat/transcript-render-helpers.ts +315 -0
  380. package/src/chat/ttsr-notification.ts +123 -0
  381. package/src/chat/user-message.ts +287 -0
  382. package/src/chrome/chat-block.ts +110 -0
  383. package/src/chrome/collab-qrcode.ts +74 -0
  384. package/src/chrome/context-thresholds.ts +85 -0
  385. package/src/chrome/countdown-timer.ts +74 -0
  386. package/src/chrome/diff.ts +266 -0
  387. package/src/chrome/dynamic-border.ts +36 -0
  388. package/src/chrome/error-block.ts +63 -0
  389. package/src/chrome/form-theme.ts +10 -0
  390. package/src/chrome/format.ts +66 -0
  391. package/src/chrome/index.ts +21 -0
  392. package/src/chrome/keybinding-hints.ts +55 -0
  393. package/src/chrome/live-board.ts +123 -0
  394. package/src/chrome/local-date.ts +20 -0
  395. package/src/chrome/message-divider.ts +51 -0
  396. package/src/chrome/message-frame.ts +164 -0
  397. package/src/chrome/message-notice.ts +103 -0
  398. package/src/chrome/overlay-box.ts +301 -0
  399. package/src/chrome/qrcode.ts +539 -0
  400. package/src/chrome/segment-track.ts +86 -0
  401. package/src/chrome/select-list-mouse-routing.ts +11 -0
  402. package/src/chrome/selector-helpers.ts +119 -0
  403. package/src/chrome/shared.ts +27 -0
  404. package/src/chrome/streaming-panel.ts +72 -0
  405. package/src/chrome/tool-activity.ts +44 -0
  406. package/src/chrome/transcript-container.ts +902 -0
  407. package/src/chrome/transcript-status.ts +27 -0
  408. package/src/chrome/visual-truncate.ts +70 -0
  409. package/src/components/disclosure.ts +235 -0
  410. package/src/components/editor.ts +10 -12
  411. package/src/components/form.ts +566 -0
  412. package/src/components/image.ts +80 -53
  413. package/src/components/input.ts +6 -27
  414. package/src/components/key-value-list.ts +88 -0
  415. package/src/components/layout/geometry.ts +202 -0
  416. package/src/components/layout/row.ts +283 -0
  417. package/src/components/layout/split-pane.ts +349 -0
  418. package/src/components/layout/stack.ts +261 -0
  419. package/src/components/markdown.ts +16 -12
  420. package/src/components/menu-selection.ts +248 -0
  421. package/src/components/metric.ts +132 -0
  422. package/src/components/progress-bar.ts +140 -0
  423. package/src/components/scroll-view.ts +372 -70
  424. package/src/components/scroll-viewport.ts +154 -0
  425. package/src/components/section.ts +77 -0
  426. package/src/components/select-list.ts +238 -159
  427. package/src/components/settings-list.ts +103 -80
  428. package/src/components/table.ts +127 -0
  429. package/src/components/tree-view.ts +481 -0
  430. package/src/components/wizard-step.ts +229 -0
  431. package/src/deccara.ts +1 -3
  432. package/src/hotkeys-markdown.ts +100 -0
  433. package/src/index.ts +18 -0
  434. package/src/keybinding-matchers.ts +99 -0
  435. package/src/keys.ts +2 -2
  436. package/src/lang-from-path.ts +252 -0
  437. package/src/overlays/advisor-config.ts +761 -0
  438. package/src/overlays/agent-activity.ts +113 -0
  439. package/src/overlays/agent-hub-projection.ts +250 -0
  440. package/src/overlays/agent-hub-renderer.ts +281 -0
  441. package/src/overlays/agent-hub-types.ts +74 -0
  442. package/src/overlays/agent-hub.ts +1562 -0
  443. package/src/overlays/agent-transcript-viewer.ts +669 -0
  444. package/src/overlays/agents-hub.ts +1203 -0
  445. package/src/overlays/ask-dialog.ts +1202 -0
  446. package/src/overlays/bordered-loader.ts +41 -0
  447. package/src/overlays/btw-history-panel.ts +591 -0
  448. package/src/overlays/btw-history.ts +33 -0
  449. package/src/overlays/btw-panel.ts +167 -0
  450. package/src/overlays/cleanse-panel.ts +167 -0
  451. package/src/overlays/codex-reset-fireworks.ts +375 -0
  452. package/src/overlays/composer-shape-preview.ts +137 -0
  453. package/src/overlays/composer-shape-registry.ts +82 -0
  454. package/src/overlays/copy-selector.ts +618 -0
  455. package/src/overlays/copy-targets.ts +210 -0
  456. package/src/overlays/error-banner.ts +39 -0
  457. package/src/overlays/extensions/display-text.ts +39 -0
  458. package/src/overlays/extensions/extension-dashboard.ts +645 -0
  459. package/src/overlays/extensions/extension-list.ts +667 -0
  460. package/src/overlays/extensions/inspector-model.ts +484 -0
  461. package/src/overlays/extensions/inspector-panel.ts +669 -0
  462. package/src/overlays/extensions/live-tool-session.ts +67 -0
  463. package/src/overlays/extensions/mcp-runtime.ts +289 -0
  464. package/src/overlays/extensions/state-manager.ts +337 -0
  465. package/src/overlays/extensions/types.ts +208 -0
  466. package/src/overlays/history-search.ts +268 -0
  467. package/src/overlays/hook-editor.ts +272 -0
  468. package/src/overlays/hook-input.ts +84 -0
  469. package/src/overlays/hook-selector.ts +635 -0
  470. package/src/overlays/hub-frame.ts +262 -0
  471. package/src/overlays/login-dialog.ts +231 -0
  472. package/src/overlays/logout-account-selector.ts +115 -0
  473. package/src/overlays/mcp-add-wizard.ts +1436 -0
  474. package/src/overlays/model-browser.ts +1176 -0
  475. package/src/overlays/model-hub.ts +2279 -0
  476. package/src/overlays/model-picker.ts +285 -0
  477. package/src/overlays/model-selector.ts +107 -0
  478. package/src/overlays/move-overlay.ts +197 -0
  479. package/src/overlays/oauth-selector.ts +446 -0
  480. package/src/overlays/omfg-panel.ts +136 -0
  481. package/src/overlays/pause-screen.ts +198 -0
  482. package/src/overlays/plan-review-overlay.ts +1227 -0
  483. package/src/overlays/plan-save-overlay.ts +74 -0
  484. package/src/overlays/plan-toc.ts +139 -0
  485. package/src/overlays/plugin-selector.ts +97 -0
  486. package/src/overlays/plugin-settings.ts +839 -0
  487. package/src/overlays/queue-mode-selector.ts +55 -0
  488. package/src/overlays/reset-usage-selector.ts +170 -0
  489. package/src/overlays/rewind-selector.ts +499 -0
  490. package/src/overlays/running-subagent-badge.ts +19 -0
  491. package/src/overlays/session-account-selector.ts +68 -0
  492. package/src/overlays/session-info-overlay.ts +96 -0
  493. package/src/overlays/session-observer-registry.ts +289 -0
  494. package/src/overlays/session-selector.ts +1137 -0
  495. package/src/overlays/settings-defs.ts +315 -0
  496. package/src/overlays/settings-selector.ts +1415 -0
  497. package/src/overlays/show-images-selector.ts +44 -0
  498. package/src/overlays/snapcompact-shape-preview-doc.md +14 -0
  499. package/src/overlays/snapcompact-shape-preview.ts +192 -0
  500. package/src/overlays/theme-selector.ts +62 -0
  501. package/src/overlays/thinking-selector.ts +51 -0
  502. package/src/overlays/tiny-title-download-progress.ts +102 -0
  503. package/src/overlays/tree-selector.ts +1121 -0
  504. package/src/overlays/usage-dashboard.ts +629 -0
  505. package/src/overlays/usage-display.ts +45 -0
  506. package/src/overlays/usage-row.ts +118 -0
  507. package/src/prompt/attachment-chips.ts +201 -0
  508. package/src/prompt/composer-attachments.ts +280 -0
  509. package/src/prompt/composer-cache.ts +304 -0
  510. package/src/prompt/composer.ts +934 -0
  511. package/src/prompt/custom-editor.ts +1392 -0
  512. package/src/prompt/data/emojis.json +1 -0
  513. package/src/prompt/editor-top-gap.ts +28 -0
  514. package/src/prompt/emoji-autocomplete.ts +285 -0
  515. package/src/prompt/github-ref-autocomplete.ts +75 -0
  516. package/src/prompt/gradient-highlight.ts +101 -0
  517. package/src/prompt/image-format.ts +28 -0
  518. package/src/prompt/image-references.ts +102 -0
  519. package/src/prompt/interactive-context-helpers.ts +126 -0
  520. package/src/prompt/internal-url-autocomplete.ts +155 -0
  521. package/src/prompt/macos-spelling.ts +456 -0
  522. package/src/prompt/magic-keyword-boundary.ts +23 -0
  523. package/src/prompt/magic-keywords.ts +42 -0
  524. package/src/prompt/markdown-prose.ts +245 -0
  525. package/src/prompt/model-mention-autocomplete.ts +94 -0
  526. package/src/prompt/model-mention-syntax.ts +41 -0
  527. package/src/prompt/orchestrate.ts +26 -0
  528. package/src/prompt/prompt-action-autocomplete.ts +337 -0
  529. package/src/prompt/queue-input.ts +132 -0
  530. package/src/prompt/skill-tokens.ts +36 -0
  531. package/src/prompt/tips.txt +27 -0
  532. package/src/prompt/tools-markdown.ts +29 -0
  533. package/src/prompt/ultrathink.ts +26 -0
  534. package/src/prompt/usage-amounts.ts +99 -0
  535. package/src/prompt/video.ts +47 -0
  536. package/src/prompt/welcome.ts +605 -0
  537. package/src/prompt/workflow.ts +26 -0
  538. package/src/render/code-cell.ts +244 -0
  539. package/src/render/file-list.ts +58 -0
  540. package/src/render/hyperlink.ts +192 -0
  541. package/src/render/index.ts +17 -0
  542. package/src/render/output-block.ts +267 -0
  543. package/src/render/output-pane.ts +299 -0
  544. package/src/render/render-utils.ts +1182 -0
  545. package/src/render/sixel.ts +69 -0
  546. package/src/render/status-line.ts +55 -0
  547. package/src/render/tool-card.ts +272 -0
  548. package/src/render/tree-list.ts +188 -0
  549. package/src/render/types.ts +19 -0
  550. package/src/render/utils.ts +109 -0
  551. package/src/render/width-aware-text.ts +60 -0
  552. package/src/setup/lazy.ts +17 -0
  553. package/src/setup/scenes/composer.ts +127 -0
  554. package/src/setup/scenes/glyph.ts +120 -0
  555. package/src/setup/scenes/model.ts +138 -0
  556. package/src/setup/scenes/outro.ts +24 -0
  557. package/src/setup/scenes/providers.ts +107 -0
  558. package/src/setup/scenes/sign-in.ts +373 -0
  559. package/src/setup/scenes/splash.ts +192 -0
  560. package/src/setup/scenes/theme.ts +343 -0
  561. package/src/setup/scenes/types.ts +111 -0
  562. package/src/setup/scenes/web-search.ts +165 -0
  563. package/src/setup/setup-version.ts +11 -0
  564. package/src/setup/startup-splash.ts +107 -0
  565. package/src/setup/wizard-overlay.ts +319 -0
  566. package/src/setup/wizard.ts +101 -0
  567. package/src/status-line/component.ts +3003 -0
  568. package/src/status-line/context-usage.ts +688 -0
  569. package/src/status-line/footer.ts +323 -0
  570. package/src/status-line/git-utils.ts +42 -0
  571. package/src/status-line/host.ts +97 -0
  572. package/src/status-line/index.ts +6 -0
  573. package/src/status-line/loop.ts +28 -0
  574. package/src/status-line/metrics.ts +94 -0
  575. package/src/status-line/presets.ts +107 -0
  576. package/src/status-line/schema.ts +57 -0
  577. package/src/status-line/segments.ts +934 -0
  578. package/src/status-line/separators.ts +55 -0
  579. package/src/status-line/types.ts +227 -0
  580. package/src/stdin-buffer.ts +4 -2
  581. package/src/theme/color.ts +95 -0
  582. package/src/theme/dark.json +95 -0
  583. package/src/theme/defaults/alabaster.json +93 -0
  584. package/src/theme/defaults/amethyst.json +96 -0
  585. package/src/theme/defaults/anthracite.json +93 -0
  586. package/src/theme/defaults/basalt.json +91 -0
  587. package/src/theme/defaults/birch.json +95 -0
  588. package/src/theme/defaults/dark-abyss.json +91 -0
  589. package/src/theme/defaults/dark-arctic.json +104 -0
  590. package/src/theme/defaults/dark-aurora.json +95 -0
  591. package/src/theme/defaults/dark-catppuccin.json +107 -0
  592. package/src/theme/defaults/dark-cavern.json +91 -0
  593. package/src/theme/defaults/dark-celestial.json +106 -0
  594. package/src/theme/defaults/dark-copper.json +95 -0
  595. package/src/theme/defaults/dark-cosmos.json +90 -0
  596. package/src/theme/defaults/dark-cyberpunk.json +102 -0
  597. package/src/theme/defaults/dark-dracula.json +98 -0
  598. package/src/theme/defaults/dark-eclipse.json +91 -0
  599. package/src/theme/defaults/dark-ember.json +95 -0
  600. package/src/theme/defaults/dark-equinox.json +90 -0
  601. package/src/theme/defaults/dark-forest.json +96 -0
  602. package/src/theme/defaults/dark-github.json +105 -0
  603. package/src/theme/defaults/dark-gruvbox.json +112 -0
  604. package/src/theme/defaults/dark-lavender.json +95 -0
  605. package/src/theme/defaults/dark-lunar.json +89 -0
  606. package/src/theme/defaults/dark-midnight.json +95 -0
  607. package/src/theme/defaults/dark-monochrome.json +94 -0
  608. package/src/theme/defaults/dark-monokai.json +98 -0
  609. package/src/theme/defaults/dark-nebula.json +90 -0
  610. package/src/theme/defaults/dark-nord.json +98 -0
  611. package/src/theme/defaults/dark-ocean.json +101 -0
  612. package/src/theme/defaults/dark-one.json +100 -0
  613. package/src/theme/defaults/dark-poimandres.json +115 -0
  614. package/src/theme/defaults/dark-rainforest.json +91 -0
  615. package/src/theme/defaults/dark-reef.json +91 -0
  616. package/src/theme/defaults/dark-retro.json +92 -0
  617. package/src/theme/defaults/dark-rose-pine.json +96 -0
  618. package/src/theme/defaults/dark-sakura.json +95 -0
  619. package/src/theme/defaults/dark-slate.json +95 -0
  620. package/src/theme/defaults/dark-solarized.json +97 -0
  621. package/src/theme/defaults/dark-solstice.json +90 -0
  622. package/src/theme/defaults/dark-starfall.json +91 -0
  623. package/src/theme/defaults/dark-sunset.json +99 -0
  624. package/src/theme/defaults/dark-swamp.json +90 -0
  625. package/src/theme/defaults/dark-synthwave.json +103 -0
  626. package/src/theme/defaults/dark-taiga.json +91 -0
  627. package/src/theme/defaults/dark-terminal.json +95 -0
  628. package/src/theme/defaults/dark-tokyo-night.json +101 -0
  629. package/src/theme/defaults/dark-tundra.json +91 -0
  630. package/src/theme/defaults/dark-twilight.json +91 -0
  631. package/src/theme/defaults/dark-volcanic.json +91 -0
  632. package/src/theme/defaults/graphite.json +92 -0
  633. package/src/theme/defaults/index.ts +201 -0
  634. package/src/theme/defaults/light-arctic.json +107 -0
  635. package/src/theme/defaults/light-aurora-day.json +91 -0
  636. package/src/theme/defaults/light-canyon.json +91 -0
  637. package/src/theme/defaults/light-catppuccin.json +106 -0
  638. package/src/theme/defaults/light-cirrus.json +90 -0
  639. package/src/theme/defaults/light-coral.json +95 -0
  640. package/src/theme/defaults/light-cyberpunk.json +96 -0
  641. package/src/theme/defaults/light-dawn.json +90 -0
  642. package/src/theme/defaults/light-dunes.json +91 -0
  643. package/src/theme/defaults/light-eucalyptus.json +95 -0
  644. package/src/theme/defaults/light-forest.json +100 -0
  645. package/src/theme/defaults/light-frost.json +95 -0
  646. package/src/theme/defaults/light-github.json +115 -0
  647. package/src/theme/defaults/light-glacier.json +91 -0
  648. package/src/theme/defaults/light-gruvbox.json +108 -0
  649. package/src/theme/defaults/light-haze.json +90 -0
  650. package/src/theme/defaults/light-honeycomb.json +95 -0
  651. package/src/theme/defaults/light-lagoon.json +91 -0
  652. package/src/theme/defaults/light-lavender.json +95 -0
  653. package/src/theme/defaults/light-meadow.json +91 -0
  654. package/src/theme/defaults/light-mint.json +95 -0
  655. package/src/theme/defaults/light-monochrome.json +101 -0
  656. package/src/theme/defaults/light-ocean.json +99 -0
  657. package/src/theme/defaults/light-one.json +99 -0
  658. package/src/theme/defaults/light-opal.json +91 -0
  659. package/src/theme/defaults/light-orchard.json +91 -0
  660. package/src/theme/defaults/light-paper.json +95 -0
  661. package/src/theme/defaults/light-poimandres.json +115 -0
  662. package/src/theme/defaults/light-prism.json +90 -0
  663. package/src/theme/defaults/light-retro.json +98 -0
  664. package/src/theme/defaults/light-sand.json +95 -0
  665. package/src/theme/defaults/light-savanna.json +91 -0
  666. package/src/theme/defaults/light-solarized.json +102 -0
  667. package/src/theme/defaults/light-soleil.json +90 -0
  668. package/src/theme/defaults/light-sunset.json +99 -0
  669. package/src/theme/defaults/light-synthwave.json +98 -0
  670. package/src/theme/defaults/light-tokyo-night.json +111 -0
  671. package/src/theme/defaults/light-wetland.json +91 -0
  672. package/src/theme/defaults/light-zenith.json +89 -0
  673. package/src/theme/defaults/limestone.json +94 -0
  674. package/src/theme/defaults/mahogany.json +97 -0
  675. package/src/theme/defaults/marble.json +93 -0
  676. package/src/theme/defaults/obsidian.json +91 -0
  677. package/src/theme/defaults/onyx.json +91 -0
  678. package/src/theme/defaults/pearl.json +93 -0
  679. package/src/theme/defaults/porcelain.json +91 -0
  680. package/src/theme/defaults/quartz.json +96 -0
  681. package/src/theme/defaults/sandstone.json +95 -0
  682. package/src/theme/defaults/titanium.json +90 -0
  683. package/src/theme/index.ts +5 -0
  684. package/src/theme/light.json +93 -0
  685. package/src/theme/loader.ts +200 -0
  686. package/src/theme/mermaid-cache.ts +92 -0
  687. package/src/theme/schema-validation.ts +119 -0
  688. package/src/theme/schema.ts +168 -0
  689. package/src/theme/session-color.ts +253 -0
  690. package/src/theme/shimmer.ts +307 -0
  691. package/src/theme/symbols.ts +1433 -0
  692. package/src/theme/theme-class.ts +787 -0
  693. package/src/theme/theme-schema.json +463 -0
  694. package/src/theme/theme.ts +810 -0
  695. package/src/theme/tui-adapters.ts +339 -0
  696. package/src/thinking.ts +380 -0
  697. package/src/tools/agent-tree.ts +128 -0
  698. package/src/tools/ask.ts +482 -0
  699. package/src/tools/ast-edit.ts +210 -0
  700. package/src/tools/ast-grep.ts +171 -0
  701. package/src/tools/autoresearch.ts +287 -0
  702. package/src/tools/bash-interactive.ts +295 -0
  703. package/src/tools/bash.ts +468 -0
  704. package/src/tools/conflict-detect.ts +77 -0
  705. package/src/tools/debug.ts +167 -0
  706. package/src/tools/default-renderer.ts +172 -0
  707. package/src/tools/edit.ts +1258 -0
  708. package/src/tools/eval-format/code-mode-declarations.ts +61 -0
  709. package/src/tools/eval-format/index.ts +16 -0
  710. package/src/tools/eval-format/javascript.ts +952 -0
  711. package/src/tools/eval-format/python.ts +544 -0
  712. package/src/tools/eval.ts +835 -0
  713. package/src/tools/fetch.ts +226 -0
  714. package/src/tools/gh-format.ts +18 -0
  715. package/src/tools/github.ts +686 -0
  716. package/src/tools/glob.ts +213 -0
  717. package/src/tools/goal.ts +153 -0
  718. package/src/tools/grep.ts +385 -0
  719. package/src/tools/grouped-file-output.ts +211 -0
  720. package/src/tools/hashline-format.ts +59 -0
  721. package/src/tools/hub.ts +1488 -0
  722. package/src/tools/index.ts +71 -0
  723. package/src/tools/json-tree.ts +388 -0
  724. package/src/tools/line-ranges.ts +98 -0
  725. package/src/tools/list-limit.ts +43 -0
  726. package/src/tools/lsp.ts +702 -0
  727. package/src/tools/match-line-format.ts +20 -0
  728. package/src/tools/mcp.ts +309 -0
  729. package/src/tools/memory.ts +220 -0
  730. package/src/tools/output-meta.ts +367 -0
  731. package/src/tools/read.ts +628 -0
  732. package/src/tools/renderer.ts +107 -0
  733. package/src/tools/report-tool-issue.ts +13 -0
  734. package/src/tools/resolve.ts +139 -0
  735. package/src/tools/streaming-output.ts +1576 -0
  736. package/src/tools/subprocess.ts +39 -0
  737. package/src/tools/task-repair-args.ts +118 -0
  738. package/src/tools/task-yield-assembly.ts +147 -0
  739. package/src/tools/task.ts +2110 -0
  740. package/src/tools/terminal-output.ts +153 -0
  741. package/src/tools/think.ts +28 -0
  742. package/src/tools/todo.ts +580 -0
  743. package/src/tools/tool-errors.ts +15 -0
  744. package/src/tools/vibe.ts +420 -0
  745. package/src/tools/web-search.ts +409 -0
  746. package/src/tools/write.ts +511 -0
  747. package/src/tools/xd-url.ts +28 -0
  748. package/src/tools/xdev.ts +201 -0
  749. package/src/tui.ts +70 -8
  750. package/src/utils.ts +8 -0
@@ -0,0 +1,580 @@
1
+ import type { ToolRenderer } from "./renderer";
2
+
3
+ import type { Component } from "../index";
4
+ import { Text } from "../index";
5
+ import { sanitizeText } from "@oh-my-pi/pi-utils";
6
+ import chalk from "@oh-my-pi/pi-utils/chalk";
7
+ import type { RenderResultOptions } from "./renderer";
8
+ import type { Theme } from "../theme/theme";
9
+
10
+ import { renderStatusLine, renderTreeList } from "../render";
11
+ import { framedToolCard } from "../render/tool-card";
12
+
13
+ import { formatErrorDetail, formatMoreItems, PREVIEW_LIMITS, pluralize, replaceTabs } from "../render/render-utils";
14
+
15
+ // =============================================================================
16
+ // Types
17
+ // =============================================================================
18
+
19
+ /** Lifecycle state of a todo item. */
20
+ export type TodoStatus = "pending" | "in_progress" | "completed" | "abandoned" | "blocked";
21
+
22
+ /** Operation names accepted by the todo tool and echoed in successful result details. */
23
+ export type TodoOperation = "init" | "start" | "done" | "rm" | "drop" | "block" | "unblock" | "append" | "view";
24
+
25
+ /** A task displayed within a todo phase. */
26
+ export interface TodoItem {
27
+ content: string;
28
+ status: TodoStatus;
29
+ /** When `status === "blocked"`, an optional note on what the task is waiting for. */
30
+ blocker?: string;
31
+ details?: string;
32
+ notes?: string[];
33
+ }
34
+
35
+ /** A named group of todo tasks. */
36
+ export interface TodoPhase {
37
+ name: string;
38
+ tasks: TodoItem[];
39
+ }
40
+
41
+ /** A task that became complete in the latest update. */
42
+ export interface TodoCompletionTransition {
43
+ phase: string;
44
+ content: string;
45
+ }
46
+
47
+ /** Todo snapshot and transitions displayed after an operation. */
48
+ export interface TodoToolDetails {
49
+ /** Operation that produced this snapshot; absent on legacy transcript entries. */
50
+ op?: TodoOperation;
51
+ phases: TodoPhase[];
52
+ storage: "session" | "memory";
53
+ completedTasks?: TodoCompletionTransition[];
54
+ }
55
+
56
+ /** Minimum overlap (after normalization) required for a substring match.
57
+ * Picked at six chars to admit single-word identifiers like "review" /
58
+ * "Sonnet" without admitting tiny common substrings like "test" / "fix"
59
+ * that would collide across unrelated todos. */
60
+ const TODO_DESCRIPTION_MIN_OVERLAP = 6;
61
+
62
+ function normalizeForTodoMatch(value: string): string {
63
+ return value
64
+ .toLowerCase()
65
+ .replace(/[^\p{L}\p{N}]+/gu, " ")
66
+ .trim();
67
+ }
68
+
69
+ /**
70
+ * Report whether `content` likely names the same work as any entry in
71
+ * `descriptions`. Used by the sticky todo panel to light up a pending todo
72
+ * when an in-flight subagent is doing the work for it, without requiring
73
+ * the caller to flip the todo's status.
74
+ *
75
+ * Matching is normalize-then-equal first (lowercased; punctuation and
76
+ * whitespace runs both collapsed to a single space; trimmed), with a
77
+ * substring fallback in either direction so minor wording drift
78
+ * ("Sonnet #2: bug scan" vs "Sonnet #2") still links up. The substring
79
+ * fallback requires at least {@link TODO_DESCRIPTION_MIN_OVERLAP} chars on
80
+ * the contained side.
81
+ */
82
+ export function todoMatchesAnyDescription(content: string, descriptions: readonly string[]): boolean {
83
+ const target = normalizeForTodoMatch(content);
84
+ if (!target) return false;
85
+ for (const desc of descriptions) {
86
+ const candidate = normalizeForTodoMatch(desc);
87
+ if (!candidate) continue;
88
+ if (target === candidate) return true;
89
+ if (target.length >= TODO_DESCRIPTION_MIN_OVERLAP && candidate.includes(target)) return true;
90
+ if (candidate.length >= TODO_DESCRIPTION_MIN_OVERLAP && target.includes(candidate)) return true;
91
+ }
92
+ return false;
93
+ }
94
+
95
+ /** Whether a todo is settled: completed or deliberately abandoned. Shared so
96
+ * the collapsed viewport, the HUD progress counters, and the HUD's closed-todo
97
+ * auto-clear can never disagree about what "done" hides. */
98
+ export function isClosedTodo<T extends { status: TodoStatus }>(task: T): boolean {
99
+ return task.status === "completed" || task.status === "abandoned";
100
+ }
101
+
102
+ /**
103
+ * A todo the collapsed viewport treats as current work: the literal
104
+ * `in_progress` task or a pending task a live subagent is executing. Both
105
+ * collapsed views (transient tool result + sticky HUD) run this same policy so
106
+ * they can never disagree about what the agent is doing (#5873).
107
+ */
108
+ function isActiveTodo<T extends { status: TodoStatus }>(task: T, isMatched: (task: T) => boolean): boolean {
109
+ return task.status === "in_progress" || (task.status === "pending" && isMatched(task));
110
+ }
111
+
112
+ /** Result of {@link selectCollapsedTodos}: the rows to render plus an optional
113
+ * summary line (empty string ⇒ no summary row). */
114
+ export interface CollapsedTodoSelection<T> {
115
+ items: T[];
116
+ summary: string;
117
+ }
118
+
119
+ /**
120
+ * Closed rows kept directly above the open window so finishing a task is
121
+ * visible as it happens. Without this the collapsed viewport only ever renders
122
+ * unchecked boxes while a phase has open work: every completion silently
123
+ * removes a row, so a plan mid-flight looks untouched, and the card's
124
+ * completion strike animation (`completedTasks` → {@link TODO_STRIKE_TOTAL_FRAMES})
125
+ * animated a row that was never rendered.
126
+ */
127
+ const COLLAPSED_CLOSED_CONTEXT = 1;
128
+
129
+ /**
130
+ * Rows to show for a display base already reduced to the relevant tasks.
131
+ *
132
+ * 1. Every active task (in-progress, or pending matched to a live subagent) is
133
+ * placed at the head in stable todo order — never dropped for lying outside
134
+ * an ordinary window.
135
+ * 2. Remaining rows up to `cap` are filled with the pending tasks that follow
136
+ * the first active one, in todo order (falling back to leading pending tasks
137
+ * when no active task exists), so a freshly-promoted task leads the preview.
138
+ * 3. When active tasks alone exceed `cap`, only the first `cap` active tasks are
139
+ * shown and the summary counts the hidden *active* todos, never replacing
140
+ * them with unrelated pending rows.
141
+ */
142
+ function selectWithinCap<T extends { status: TodoStatus }>(
143
+ base: T[],
144
+ isMatched: (task: T) => boolean,
145
+ cap: number,
146
+ ): CollapsedTodoSelection<T> {
147
+ if (base.length <= cap) return { items: base, summary: "" };
148
+
149
+ const active = base.filter(task => isActiveTodo(task, isMatched));
150
+ // Only when active work strictly exceeds the cap do we drop pending rows and
151
+ // count hidden *actives*. At exactly `cap` actives, fall through so the normal
152
+ // branch still surfaces any following pending work in the summary.
153
+ if (active.length > cap) {
154
+ const hiddenActive = active.length - cap;
155
+ return {
156
+ items: active.slice(0, cap),
157
+ summary: `… ${hiddenActive} more active ${pluralize("todo", hiddenActive)}`,
158
+ };
159
+ }
160
+
161
+ // Fill trailing rows with tasks following the first active one, so the
162
+ // promoted/current task leads and its successors follow in todo order.
163
+ const firstActiveIdx = active.length > 0 ? base.indexOf(active[0]) : 0;
164
+ const fill: T[] = [];
165
+ for (let i = firstActiveIdx; i < base.length && active.length + fill.length < cap; i++) {
166
+ const task = base[i];
167
+ if (isActiveTodo(task, isMatched)) continue;
168
+ fill.push(task);
169
+ }
170
+ const items = [...active, ...fill];
171
+ const hidden = base.length - items.length;
172
+ return { items, summary: hidden > 0 ? formatMoreItems(hidden, "todo") : "" };
173
+ }
174
+
175
+ /**
176
+ * Walking-viewport selection for a phase's collapsed todo preview (#5873).
177
+ *
178
+ * Applied to `tasks` in todo order: the open tasks run through
179
+ * {@link selectWithinCap}, led by the last {@link COLLAPSED_CLOSED_CONTEXT}
180
+ * closed tasks in todo order so a checked row remains visible even when callers
181
+ * complete work out of sequence. The lead is additive — it never costs an open
182
+ * row — and a phase with no open work left falls back to its closed tasks so the
183
+ * sticky HUD's closed-todo persistence still has something to render.
184
+ *
185
+ * `summary` counts the open tasks that did not fit; the closed lead is context,
186
+ * not part of the budget.
187
+ */
188
+ export function selectCollapsedTodos<T extends { status: TodoStatus }>(
189
+ tasks: T[],
190
+ isMatched: (task: T) => boolean,
191
+ cap: number,
192
+ ): CollapsedTodoSelection<T> {
193
+ const open = tasks.filter(task => !isClosedTodo(task));
194
+ // Closed tasks are never active, so a settled phase selects over itself.
195
+ if (open.length === 0) return selectWithinCap(tasks, isMatched, cap);
196
+ // `done` accepts any named task, so closed tasks are not necessarily a prefix.
197
+ const lead = tasks.filter(isClosedTodo).slice(-COLLAPSED_CLOSED_CONTEXT);
198
+ const selected = selectWithinCap(open, isMatched, cap);
199
+ return { items: [...lead, ...selected.items], summary: selected.summary };
200
+ }
201
+
202
+ // =============================================================================
203
+ // TUI Renderer
204
+ // =============================================================================
205
+
206
+ type TodoRenderOp = {
207
+ op?: string;
208
+ task?: string;
209
+ phase?: string;
210
+ items?: string[];
211
+ };
212
+
213
+ /** New single-op shape `{op,...}`; legacy `{ops:[...]}` still seen in old transcripts. */
214
+ type TodoRenderArgs = TodoRenderOp & {
215
+ ops?: TodoRenderOp[];
216
+ };
217
+
218
+ /**
219
+ * Normalize streaming/legacy render args to a flat op list. Accepts the new
220
+ * top-level `{op,...}` shape (returned as a one-element list), the legacy
221
+ * `{ops:[...]}` batch from old transcripts/collab-web, and partially-parsed
222
+ * streaming deltas (non-array `ops`, non-object entries) without crashing.
223
+ */
224
+ function normalizeTodoArg(args: TodoRenderArgs | undefined): TodoRenderOp[] {
225
+ if (!args || typeof args !== "object") return [];
226
+ if (Array.isArray(args.ops)) {
227
+ return args.ops.filter((entry): entry is TodoRenderOp => !!entry && typeof entry === "object");
228
+ }
229
+ return typeof args.op === "string" ? [args] : [];
230
+ }
231
+
232
+ // =============================================================================
233
+ // Phase numbering (display-only)
234
+ // =============================================================================
235
+
236
+ const ROMAN_PAIRS: Array<[number, string]> = [
237
+ [1000, "M"],
238
+ [900, "CM"],
239
+ [500, "D"],
240
+ [400, "CD"],
241
+ [100, "C"],
242
+ [90, "XC"],
243
+ [50, "L"],
244
+ [40, "XL"],
245
+ [10, "X"],
246
+ [9, "IX"],
247
+ [5, "V"],
248
+ [4, "IV"],
249
+ [1, "I"],
250
+ ];
251
+
252
+ /** One-based ASCII roman numeral for display (I, II, III, IV, …). */
253
+ export function phaseRomanNumeral(oneBasedIndex: number): string {
254
+ if (oneBasedIndex <= 0) return "";
255
+ let out = "";
256
+ let rem = oneBasedIndex;
257
+ for (const [value, sym] of ROMAN_PAIRS) {
258
+ while (rem >= value) {
259
+ out += sym;
260
+ rem -= value;
261
+ }
262
+ }
263
+ return out;
264
+ }
265
+
266
+ /**
267
+ * Every render boundary in this file funnels display text through here.
268
+ *
269
+ * `sanitizeText` strips ANSI/C0 sequences but deliberately preserves tabs, and
270
+ * a raw tab punches holes in bordered TUI output, so both are needed. The raw
271
+ * value stays untouched everywhere else: task content and phase names are the
272
+ * identity keys the local list is looked up by, and what gets persisted.
273
+ */
274
+ function forDisplay(text: string): string {
275
+ return replaceTabs(sanitizeText(text));
276
+ }
277
+
278
+ /**
279
+ * Display-only phase header: `I. Foundation`. State and prompts never see this.
280
+ *
281
+ * Sanitized for the same reason task labels are: this is a render boundary and
282
+ * the name may carry provider or session text holding control sequences. The
283
+ * raw `phase.name` stays the lookup key everywhere else.
284
+ */
285
+ export function formatPhaseDisplayName(name: string, oneBasedIndex: number): string {
286
+ return `${phaseRomanNumeral(oneBasedIndex)}. ${forDisplay(name)}`;
287
+ }
288
+
289
+ /** Frames held before revealing a completion strike. */
290
+ export const TODO_STRIKE_HOLD_FRAMES = 2;
291
+
292
+ /** Frames used to reveal a completion strike. */
293
+ export const TODO_STRIKE_REVEAL_FRAMES = 12;
294
+
295
+ /** Total frames in the completion strike animation. */
296
+ export const TODO_STRIKE_TOTAL_FRAMES = TODO_STRIKE_HOLD_FRAMES + TODO_STRIKE_REVEAL_FRAMES;
297
+
298
+ const EMPTY_COMPLETION_KEYS = new Set<string>();
299
+
300
+ const STRIKE_START = "\x1b[9m";
301
+
302
+ const STRIKE_END = "\x1b[29m";
303
+
304
+ function strikethroughText(text: string): string {
305
+ return `${STRIKE_START}${text}${STRIKE_END}`;
306
+ }
307
+
308
+ function partialStrikethrough(text: string, visibleChars: number): string {
309
+ if (visibleChars <= 0) return text;
310
+ const chars = [...text];
311
+ if (visibleChars >= chars.length) return strikethroughText(text);
312
+ return `${strikethroughText(chars.slice(0, visibleChars).join(""))}${chars.slice(visibleChars).join("")}`;
313
+ }
314
+
315
+ function strikeRevealCount(text: string, frame: number | undefined): number | undefined {
316
+ if (frame === undefined) return undefined;
317
+ if (frame <= TODO_STRIKE_HOLD_FRAMES) return 0;
318
+ const chars = [...text];
319
+ if (chars.length === 0) return undefined;
320
+ const revealFrame = Math.min(frame - TODO_STRIKE_HOLD_FRAMES, TODO_STRIKE_REVEAL_FRAMES);
321
+ return Math.ceil((chars.length * revealFrame) / TODO_STRIKE_REVEAL_FRAMES);
322
+ }
323
+
324
+ function formatTodoLine(
325
+ item: TodoItem,
326
+ uiTheme: Theme,
327
+ prefix: string,
328
+ completionKeys: Set<string>,
329
+ frame: number | undefined,
330
+ matched = false,
331
+ ): string {
332
+ const checkbox = uiTheme.checkbox;
333
+ // Sanitize only for display. A mirrored Cursor snapshot carries provider text
334
+ // verbatim, and a label holding ANSI/C0 sequences would otherwise rewrite the
335
+ // terminal every time the list renders or replays. `item.content` stays raw
336
+ // everywhere else: it is the identity key the local list is looked up by
337
+ // (`findTaskByContent`) and what gets persisted.
338
+ const label = forDisplay(item.content);
339
+ switch (item.status) {
340
+ case "completed": {
341
+ const revealCount = completionKeys.has(item.content) ? strikeRevealCount(label, frame) : undefined;
342
+ const content =
343
+ revealCount === undefined ? strikethroughText(label) : partialStrikethrough(label, revealCount);
344
+ return uiTheme.fg("success", `${prefix}${checkbox.checked} ${content}`);
345
+ }
346
+ case "in_progress":
347
+ return uiTheme.fg("accent", `${prefix}${checkbox.unchecked} ${label}`);
348
+ case "abandoned":
349
+ return uiTheme.fg("error", `${prefix}${checkbox.unchecked} ${strikethroughText(label)}`);
350
+ case "blocked": {
351
+ const note = item.blocker ? `blocked: ${forDisplay(item.blocker)}` : "blocked";
352
+ return uiTheme.fg("warning", `${prefix}${checkbox.unchecked} ${label} (${note})`);
353
+ }
354
+ default:
355
+ // A pending todo lit by a live subagent match renders accent, matching
356
+ // the sticky HUD's convention (#5873).
357
+ return uiTheme.fg(matched ? "accent" : "dim", `${prefix}${checkbox.unchecked} ${label}`);
358
+ }
359
+ }
360
+
361
+ /**
362
+ * Phases the latest update touched, plus the active (in_progress) phase.
363
+ * Returns `null` when there is no usable signal, meaning "render every phase
364
+ * fully" — this preserves the legacy view and the manual-expand path.
365
+ */
366
+ function computeTouchedPhases(
367
+ args: TodoRenderArgs | undefined,
368
+ phases: TodoPhase[],
369
+ completedTasks: TodoCompletionTransition[],
370
+ ): Set<string> | null {
371
+ const touched = new Set<string>();
372
+ // The phase holding the in_progress task is where attention sits after the
373
+ // auto-promotion that follows every completion.
374
+ for (const phase of phases) {
375
+ if (phase.tasks.some(task => task.status === "in_progress")) touched.add(phase.name);
376
+ }
377
+ // Phases with a task that just transitioned to completed in this update.
378
+ for (const transition of completedTasks) touched.add(transition.phase);
379
+ // Phases explicitly named by the ops that ran. `init` replaces the whole
380
+ // list, so the entire plan is fresh and every phase counts as touched.
381
+ const ops = normalizeTodoArg(args);
382
+ for (const op of ops) {
383
+ if (!op || typeof op !== "object") continue;
384
+ if (op.op === "init") {
385
+ for (const phase of phases) touched.add(phase.name);
386
+ break;
387
+ }
388
+ if (typeof op.phase === "string" && op.phase) {
389
+ const named = phases.find(phase => phase.name === op.phase);
390
+ if (named) touched.add(named.name);
391
+ }
392
+ if (typeof op.task === "string" && op.task) {
393
+ const phase = phases.find(phase => phase.tasks.some(task => task.content === op.task));
394
+ if (phase) touched.add(phase.name);
395
+ }
396
+ }
397
+ return touched.size > 0 ? touched : null;
398
+ }
399
+
400
+ /**
401
+ * Dim `closed/total` suffix for a phase header. Counts closed tasks, not just
402
+ * completed ones: the collapsed viewport hides both, so an abandoned task has to
403
+ * move the counter or its phase reads as permanently stuck.
404
+ */
405
+ function formatPhaseProgress(phase: TodoPhase, uiTheme: Theme): string {
406
+ const done = phase.tasks.filter(isClosedTodo).length;
407
+ return uiTheme.fg("dim", ` ${done}/${phase.tasks.length}`);
408
+ }
409
+
410
+ /** One-line summary for a collapsed (untouched) phase: dim header + progress. */
411
+ function formatPhaseSummary(phase: TodoPhase, oneBasedIndex: number, uiTheme: Theme): string {
412
+ const name = uiTheme.fg("dim", chalk.bold(formatPhaseDisplayName(phase.name, oneBasedIndex)));
413
+ return `${name}${formatPhaseProgress(phase, uiTheme)}`;
414
+ }
415
+
416
+ /**
417
+ * Live subagent descriptions the transient tool result uses to detect
418
+ * pending todos being executed by an in-flight subagent, so its collapsed
419
+ * viewport surfaces the same active work the sticky HUD does (#5873). Wired
420
+ * once by interactive mode from its observer registry; returns `[]` outside an
421
+ * interactive session (tests, SDK, transcript rebuilds), where only literal
422
+ * `in_progress` counts as active.
423
+ */
424
+ let activeTodoDescriptionsProvider: () => readonly string[] = () => [];
425
+
426
+ /** Wire the live-subagent description source for {@link todoToolRenderer}. */
427
+ export function setActiveTodoDescriptionsProvider(provider: () => readonly string[]): void {
428
+ activeTodoDescriptionsProvider = provider;
429
+ }
430
+
431
+ /** Render todo operations and phased task snapshots. */
432
+ export const todoToolRenderer = {
433
+ renderCall(args: TodoRenderArgs, options: RenderResultOptions, uiTheme: Theme): Component {
434
+ // `args` is the raw partially-parsed JSON from the streaming tool-call
435
+ // delta and may not satisfy `TodoRenderArgs` at runtime:
436
+ // `parseStreamingJson` can hand back `{ op: 1 }` mid-delta, or a legacy
437
+ // `{ ops: "[" }` shape before fields stream. `normalizeTodoArg` guards
438
+ // both the new single-op and legacy batch shapes so a malformed delta
439
+ // never breaks the TUI render loop (#2005).
440
+ const opsList = normalizeTodoArg(args);
441
+ // Model-authored, partially-streamed strings going straight into a header:
442
+ // `renderStatusLine` only flattens CR/LF and leaves the rest to the caller.
443
+ const ops =
444
+ opsList.length === 0
445
+ ? ["update"]
446
+ : opsList.map(e => {
447
+ const parts = [forDisplay(e.op ?? "update")];
448
+ if (e.task) parts.push(forDisplay(e.task));
449
+ if (e.phase) parts.push(forDisplay(e.phase));
450
+ if (Array.isArray(e.items) && e.items.length) {
451
+ parts.push(`${e.items.length} item${e.items.length === 1 ? "" : "s"}`);
452
+ }
453
+ return parts.join(" ");
454
+ });
455
+ // No body worth boxing while the call streams — a lone status line reads
456
+ // cleaner than an empty frame. The container renders it without chrome.
457
+ const header = renderStatusLine(
458
+ { icon: "pending", spinnerFrame: options?.spinnerFrame, title: "Todo", meta: ops },
459
+ uiTheme,
460
+ );
461
+ return new Text(header, 0, 0);
462
+ },
463
+
464
+ renderResult(
465
+ result: { content: Array<{ type: string; text?: string }>; details?: TodoToolDetails; isError?: boolean },
466
+ options: RenderResultOptions,
467
+ uiTheme: Theme,
468
+ args?: TodoRenderArgs,
469
+ ): Component {
470
+ if (result.isError) {
471
+ const errorText = result.content?.find(content => content.type === "text")?.text ?? "Todo operation failed";
472
+ const header = renderStatusLine({ icon: "error", title: "Todo" }, uiTheme);
473
+ return framedToolCard(uiTheme, () => ({
474
+ header,
475
+ sections: [{ content: formatErrorDetail(errorText, uiTheme).split("\n") }],
476
+ phase: "error",
477
+ borderColor: "error",
478
+ }));
479
+ }
480
+
481
+ const phases = (result.details?.phases ?? []).filter(phase => phase.tasks.length > 0);
482
+ const completedTasks = result.details?.completedTasks ?? [];
483
+ const completionKeysByPhase = new Map<string, Set<string>>();
484
+ for (const task of completedTasks) {
485
+ let keys = completionKeysByPhase.get(task.phase);
486
+ if (!keys) {
487
+ keys = new Set<string>();
488
+ completionKeysByPhase.set(task.phase, keys);
489
+ }
490
+ keys.add(task.content);
491
+ }
492
+ const allTasks = phases.flatMap(phase => phase.tasks);
493
+ const header = renderStatusLine(
494
+ {
495
+ iconOverride: uiTheme.styledSymbol("tool.todo", "accent"),
496
+ title: "Todo",
497
+ meta: [`${allTasks.length} tasks`],
498
+ },
499
+ uiTheme,
500
+ );
501
+ if (allTasks.length === 0) {
502
+ // Provider text on the Cursor path (the todo summary or a refusal note),
503
+ // so sanitize like every other label. The error branch above already
504
+ // goes through `formatErrorDetail`.
505
+ const fallback = forDisplay(result.content?.find(content => content.type === "text")?.text ?? "No todos");
506
+ return new Text(`${header}\n ${uiTheme.fg("dim", fallback)}`, 0, 0);
507
+ }
508
+
509
+ return framedToolCard(uiTheme, () => {
510
+ const { expanded, spinnerFrame } = options;
511
+ const multiPhase = phases.length > 1;
512
+ const indent = multiPhase ? " " : "";
513
+ // Collapse phases this update didn't touch down to a one-line summary so
514
+ // a single task flip doesn't redraw every phase's full task list. The
515
+ // manual expand toggle (and the no-signal fallback) still shows all.
516
+ const touched = expanded || !multiPhase ? null : computeTouchedPhases(args, phases, completedTasks);
517
+ // A pending todo counts as active work when an in-flight subagent is
518
+ // executing it — the transient result surfaces the same active set the
519
+ // sticky HUD does (#5873). Empty outside an interactive session.
520
+ const activeDescs = expanded ? [] : activeTodoDescriptionsProvider();
521
+ const isMatched = (task: TodoItem): boolean =>
522
+ activeDescs.length > 0 && todoMatchesAnyDescription(task.content, activeDescs);
523
+ const bodyLines: string[] = [];
524
+ for (let p = 0; p < phases.length; p++) {
525
+ const phase = phases[p];
526
+ if (touched && !touched.has(phase.name)) {
527
+ bodyLines.push(formatPhaseSummary(phase, p + 1, uiTheme));
528
+ continue;
529
+ }
530
+ if (multiPhase) {
531
+ // Progress belongs on the expanded header too: the collapsed
532
+ // viewport below hides closed rows, so without it the phase the
533
+ // agent is actually working in is the one phase with no visible
534
+ // completion signal at all.
535
+ const name = uiTheme.fg("accent", chalk.bold(formatPhaseDisplayName(phase.name, p + 1)));
536
+ bodyLines.push(`${name}${formatPhaseProgress(phase, uiTheme)}`);
537
+ }
538
+ const completionKeys = completionKeysByPhase.get(phase.name) ?? EMPTY_COMPLETION_KEYS;
539
+ // Collapsed: walking viewport — the last closed task leads, then
540
+ // active work (in-progress / subagent-matched), then following
541
+ // pending tasks (#5873). Expanded: every task in order.
542
+ const treeLines = expanded
543
+ ? renderTreeList(
544
+ {
545
+ items: phase.tasks,
546
+ expanded,
547
+ itemType: "todo",
548
+ renderItem: todo => formatTodoLine(todo, uiTheme, "", completionKeys, spinnerFrame),
549
+ },
550
+ uiTheme,
551
+ )
552
+ : (() => {
553
+ const selection = selectCollapsedTodos(phase.tasks, isMatched, PREVIEW_LIMITS.COLLAPSED_ITEMS);
554
+ return renderTreeList(
555
+ {
556
+ items: selection.items,
557
+ itemType: "todo",
558
+ trailingSummary: selection.summary,
559
+ renderItem: todo =>
560
+ formatTodoLine(todo, uiTheme, "", completionKeys, spinnerFrame, isMatched(todo)),
561
+ },
562
+ uiTheme,
563
+ );
564
+ })();
565
+ for (const line of treeLines) {
566
+ bodyLines.push(`${indent}${line}`);
567
+ }
568
+ }
569
+ while (bodyLines.length > 0 && bodyLines[0].trim() === "") bodyLines.shift();
570
+ return {
571
+ header,
572
+ sections: bodyLines.length > 0 ? [{ content: bodyLines }] : [],
573
+ phase: options.isPartial ? "partial" : "success",
574
+ borderColor: "borderMuted",
575
+ applyBg: false,
576
+ };
577
+ });
578
+ },
579
+ mergeCallAndResult: true,
580
+ } satisfies ToolRenderer<TodoRenderArgs, TodoToolDetails>;
@@ -0,0 +1,15 @@
1
+ /** Structured tool failure shared by selector parsing and host tool execution. */
2
+ export class ToolError extends Error {
3
+ constructor(
4
+ message: string,
5
+ readonly context?: Record<string, unknown>,
6
+ ) {
7
+ super(message);
8
+ this.name = "ToolError";
9
+ }
10
+
11
+ /** Render error for LLM consumption. Override for custom formatting. */
12
+ render(): string {
13
+ return this.message;
14
+ }
15
+ }