@oh-my-pi/pi-tui 18.2.4 → 18.2.6

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 (748) hide show
  1. package/CHANGELOG.md +23 -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/key-value-list.d.ts +24 -0
  92. package/dist/types/components/layout/geometry.d.ts +73 -0
  93. package/dist/types/components/layout/row.d.ts +55 -0
  94. package/dist/types/components/layout/split-pane.d.ts +80 -0
  95. package/dist/types/components/layout/stack.d.ts +50 -0
  96. package/dist/types/components/menu-selection.d.ts +71 -0
  97. package/dist/types/components/metric.d.ts +44 -0
  98. package/dist/types/components/progress-bar.d.ts +36 -0
  99. package/dist/types/components/scroll-view.d.ts +53 -19
  100. package/dist/types/components/scroll-viewport.d.ts +46 -0
  101. package/dist/types/components/section.d.ts +19 -0
  102. package/dist/types/components/select-list.d.ts +46 -2
  103. package/dist/types/components/settings-list.d.ts +20 -0
  104. package/dist/types/components/table.d.ts +32 -0
  105. package/dist/types/components/tree-view.d.ts +130 -0
  106. package/dist/types/components/wizard-step.d.ts +60 -0
  107. package/dist/types/hotkeys-markdown.d.ts +7 -0
  108. package/dist/types/index.d.ts +17 -0
  109. package/dist/types/keybinding-matchers.d.ts +35 -0
  110. package/dist/types/keys.d.ts +2 -2
  111. package/dist/types/lang-from-path.d.ts +9 -0
  112. package/dist/types/overlays/advisor-config.d.ts +114 -0
  113. package/dist/types/overlays/agent-activity.d.ts +41 -0
  114. package/dist/types/overlays/agent-hub-projection.d.ts +33 -0
  115. package/dist/types/overlays/agent-hub-renderer.d.ts +53 -0
  116. package/dist/types/overlays/agent-hub-types.d.ts +99 -0
  117. package/dist/types/overlays/agent-hub.d.ts +126 -0
  118. package/dist/types/overlays/agent-transcript-viewer.d.ts +71 -0
  119. package/dist/types/overlays/agents-hub.d.ts +72 -0
  120. package/dist/types/overlays/ask-dialog.d.ts +88 -0
  121. package/dist/types/overlays/bordered-loader.d.ts +11 -0
  122. package/dist/types/overlays/btw-history-panel.d.ts +29 -0
  123. package/dist/types/overlays/btw-history.d.ts +17 -0
  124. package/dist/types/overlays/btw-panel.d.ts +26 -0
  125. package/dist/types/overlays/cleanse-panel.d.ts +36 -0
  126. package/dist/types/overlays/codex-reset-fireworks.d.ts +52 -0
  127. package/dist/types/overlays/composer-shape-preview.d.ts +47 -0
  128. package/dist/types/overlays/composer-shape-registry.d.ts +50 -0
  129. package/dist/types/overlays/copy-selector.d.ts +48 -0
  130. package/dist/types/overlays/copy-targets.d.ts +63 -0
  131. package/dist/types/overlays/error-banner.d.ts +13 -0
  132. package/dist/types/overlays/extensions/display-text.d.ts +10 -0
  133. package/dist/types/overlays/extensions/extension-dashboard.d.ts +63 -0
  134. package/dist/types/overlays/extensions/extension-list.d.ts +54 -0
  135. package/dist/types/overlays/extensions/inspector-model.d.ts +109 -0
  136. package/dist/types/overlays/extensions/inspector-panel.d.ts +17 -0
  137. package/dist/types/overlays/extensions/live-tool-session.d.ts +28 -0
  138. package/dist/types/overlays/extensions/mcp-runtime.d.ts +107 -0
  139. package/dist/types/overlays/extensions/state-manager.d.ts +42 -0
  140. package/dist/types/overlays/extensions/types.d.ts +165 -0
  141. package/dist/types/overlays/history-search.d.ts +16 -0
  142. package/dist/types/overlays/hook-editor.d.ts +44 -0
  143. package/dist/types/overlays/hook-input.d.ts +20 -0
  144. package/dist/types/overlays/hook-selector.d.ts +71 -0
  145. package/dist/types/overlays/hub-frame.d.ts +77 -0
  146. package/dist/types/overlays/login-dialog.d.ts +43 -0
  147. package/dist/types/overlays/logout-account-selector.d.ts +15 -0
  148. package/dist/types/overlays/mcp-add-wizard.d.ts +87 -0
  149. package/dist/types/overlays/model-browser.d.ts +213 -0
  150. package/dist/types/overlays/model-hub.d.ts +72 -0
  151. package/dist/types/overlays/model-picker.d.ts +74 -0
  152. package/dist/types/overlays/model-selector.d.ts +52 -0
  153. package/dist/types/overlays/move-overlay.d.ts +39 -0
  154. package/dist/types/overlays/oauth-selector.d.ts +41 -0
  155. package/dist/types/overlays/omfg-panel.d.ts +20 -0
  156. package/dist/types/overlays/pause-screen.d.ts +43 -0
  157. package/dist/types/overlays/plan-review-overlay.d.ts +89 -0
  158. package/dist/types/overlays/plan-save-overlay.d.ts +19 -0
  159. package/dist/types/overlays/plan-toc.d.ts +41 -0
  160. package/dist/types/overlays/plugin-selector.d.ts +28 -0
  161. package/dist/types/overlays/plugin-settings.d.ts +180 -0
  162. package/dist/types/overlays/queue-mode-selector.d.ts +11 -0
  163. package/dist/types/overlays/reset-usage-selector.d.ts +23 -0
  164. package/dist/types/overlays/rewind-selector.d.ts +61 -0
  165. package/dist/types/overlays/running-subagent-badge.d.ts +6 -0
  166. package/dist/types/overlays/session-account-selector.d.ts +24 -0
  167. package/dist/types/overlays/session-info-overlay.d.ts +17 -0
  168. package/dist/types/overlays/session-observer-registry.d.ts +77 -0
  169. package/dist/types/overlays/session-selector.d.ts +131 -0
  170. package/dist/types/overlays/settings-defs.d.ts +119 -0
  171. package/dist/types/overlays/settings-selector.d.ts +73 -0
  172. package/dist/types/overlays/show-images-selector.d.ts +11 -0
  173. package/dist/types/overlays/snapcompact-shape-preview.d.ts +31 -0
  174. package/dist/types/overlays/theme-selector.d.ts +12 -0
  175. package/dist/types/overlays/thinking-selector.d.ts +12 -0
  176. package/dist/types/overlays/tiny-title-download-progress.d.ts +21 -0
  177. package/dist/types/overlays/tree-selector.d.ts +92 -0
  178. package/dist/types/overlays/usage-dashboard.d.ts +94 -0
  179. package/dist/types/overlays/usage-display.d.ts +5 -0
  180. package/dist/types/overlays/usage-row.d.ts +17 -0
  181. package/dist/types/prompt/attachment-chips.d.ts +19 -0
  182. package/dist/types/prompt/composer-attachments.d.ts +71 -0
  183. package/dist/types/prompt/composer-cache.d.ts +37 -0
  184. package/dist/types/prompt/composer.d.ts +159 -0
  185. package/dist/types/prompt/custom-editor.d.ts +261 -0
  186. package/dist/types/prompt/editor-top-gap.d.ts +18 -0
  187. package/dist/types/prompt/emoji-autocomplete.d.ts +16 -0
  188. package/dist/types/prompt/github-ref-autocomplete.d.ts +35 -0
  189. package/dist/types/prompt/gradient-highlight.d.ts +32 -0
  190. package/dist/types/prompt/image-format.d.ts +4 -0
  191. package/dist/types/prompt/image-references.d.ts +26 -0
  192. package/dist/types/prompt/interactive-context-helpers.d.ts +43 -0
  193. package/dist/types/prompt/internal-url-autocomplete.d.ts +56 -0
  194. package/dist/types/prompt/macos-spelling.d.ts +44 -0
  195. package/dist/types/prompt/magic-keyword-boundary.d.ts +9 -0
  196. package/dist/types/prompt/magic-keywords.d.ts +26 -0
  197. package/dist/types/prompt/markdown-prose.d.ts +15 -0
  198. package/dist/types/prompt/model-mention-autocomplete.d.ts +25 -0
  199. package/dist/types/prompt/model-mention-syntax.d.ts +24 -0
  200. package/dist/types/prompt/orchestrate.d.ts +13 -0
  201. package/dist/types/prompt/prompt-action-autocomplete.d.ts +56 -0
  202. package/dist/types/prompt/queue-input.d.ts +8 -0
  203. package/dist/types/prompt/skill-tokens.d.ts +13 -0
  204. package/dist/types/prompt/tools-markdown.d.ts +12 -0
  205. package/dist/types/prompt/ultrathink.d.ts +13 -0
  206. package/dist/types/prompt/usage-amounts.d.ts +26 -0
  207. package/dist/types/prompt/video.d.ts +18 -0
  208. package/dist/types/prompt/welcome.d.ts +83 -0
  209. package/dist/types/prompt/workflow.d.ts +13 -0
  210. package/dist/types/render/code-cell.d.ts +51 -0
  211. package/dist/types/render/file-list.d.ts +22 -0
  212. package/dist/types/render/hyperlink.d.ts +80 -0
  213. package/dist/types/render/index.d.ts +16 -0
  214. package/dist/types/render/output-block.d.ts +54 -0
  215. package/dist/types/render/output-pane.d.ts +80 -0
  216. package/dist/types/render/render-utils.d.ts +312 -0
  217. package/dist/types/render/sixel.d.ts +21 -0
  218. package/dist/types/render/status-line.d.ts +23 -0
  219. package/dist/types/render/tool-card.d.ts +71 -0
  220. package/dist/types/render/tree-list.d.ts +29 -0
  221. package/dist/types/render/types.d.ts +17 -0
  222. package/dist/types/render/utils.d.ts +43 -0
  223. package/dist/types/render/width-aware-text.d.ts +23 -0
  224. package/dist/types/setup/lazy.d.ts +3 -0
  225. package/dist/types/setup/scenes/composer.d.ts +3 -0
  226. package/dist/types/setup/scenes/glyph.d.ts +3 -0
  227. package/dist/types/setup/scenes/model.d.ts +3 -0
  228. package/dist/types/setup/scenes/outro.d.ts +2 -0
  229. package/dist/types/setup/scenes/providers.d.ts +3 -0
  230. package/dist/types/setup/scenes/sign-in.d.ts +21 -0
  231. package/dist/types/setup/scenes/splash.d.ts +11 -0
  232. package/dist/types/setup/scenes/theme.d.ts +3 -0
  233. package/dist/types/setup/scenes/types.d.ts +110 -0
  234. package/dist/types/setup/scenes/web-search.d.ts +22 -0
  235. package/dist/types/setup/setup-version.d.ts +11 -0
  236. package/dist/types/setup/startup-splash.d.ts +9 -0
  237. package/dist/types/setup/wizard-overlay.d.ts +16 -0
  238. package/dist/types/setup/wizard.d.ts +25 -0
  239. package/dist/types/status-line/component.d.ts +182 -0
  240. package/dist/types/status-line/context-usage.d.ts +156 -0
  241. package/dist/types/status-line/footer.d.ts +30 -0
  242. package/dist/types/status-line/git-utils.d.ts +22 -0
  243. package/dist/types/status-line/host.d.ts +129 -0
  244. package/dist/types/status-line/index.d.ts +6 -0
  245. package/dist/types/status-line/loop.d.ts +18 -0
  246. package/dist/types/status-line/metrics.d.ts +21 -0
  247. package/dist/types/status-line/presets.d.ts +3 -0
  248. package/dist/types/status-line/schema.d.ts +15 -0
  249. package/dist/types/status-line/segments.d.ts +5 -0
  250. package/dist/types/status-line/separators.d.ts +3 -0
  251. package/dist/types/status-line/types.d.ts +236 -0
  252. package/dist/types/stdin-buffer.d.ts +4 -0
  253. package/dist/types/theme/color.d.ts +24 -0
  254. package/dist/types/theme/defaults/index.d.ts +9489 -0
  255. package/dist/types/theme/index.d.ts +4 -0
  256. package/dist/types/theme/loader.d.ts +23 -0
  257. package/dist/types/theme/mermaid-cache.d.ts +26 -0
  258. package/dist/types/theme/schema-validation.d.ts +3 -0
  259. package/dist/types/theme/schema.d.ts +25 -0
  260. package/dist/types/theme/session-color.d.ts +43 -0
  261. package/dist/types/theme/shimmer.d.ts +44 -0
  262. package/dist/types/theme/symbols.d.ts +34 -0
  263. package/dist/types/theme/theme-class.d.ts +299 -0
  264. package/dist/types/theme/theme.d.ts +111 -0
  265. package/dist/types/theme/tui-adapters.d.ts +30 -0
  266. package/dist/types/thinking.d.ts +165 -0
  267. package/dist/types/tools/agent-tree.d.ts +36 -0
  268. package/dist/types/tools/ask.d.ts +67 -0
  269. package/dist/types/tools/ast-edit.d.ts +53 -0
  270. package/dist/types/tools/ast-grep.d.ts +52 -0
  271. package/dist/types/tools/autoresearch.d.ts +156 -0
  272. package/dist/types/tools/bash-interactive.d.ts +28 -0
  273. package/dist/types/tools/bash.d.ts +103 -0
  274. package/dist/types/tools/conflict-detect.d.ts +43 -0
  275. package/dist/types/tools/debug.d.ts +60 -0
  276. package/dist/types/tools/default-renderer.d.ts +24 -0
  277. package/dist/types/tools/edit.d.ts +158 -0
  278. package/dist/types/tools/eval-format/code-mode-declarations.d.ts +5 -0
  279. package/dist/types/tools/eval-format/index.d.ts +5 -0
  280. package/dist/types/tools/eval-format/javascript.d.ts +2 -0
  281. package/dist/types/tools/eval-format/python.d.ts +2 -0
  282. package/dist/types/tools/eval.d.ts +94 -0
  283. package/dist/types/tools/fetch.d.ts +42 -0
  284. package/dist/types/tools/gh-format.d.ts +8 -0
  285. package/dist/types/tools/github.d.ts +144 -0
  286. package/dist/types/tools/glob.d.ts +44 -0
  287. package/dist/types/tools/goal.d.ts +42 -0
  288. package/dist/types/tools/grep.d.ts +64 -0
  289. package/dist/types/tools/grouped-file-output.d.ts +71 -0
  290. package/dist/types/tools/hashline-format.d.ts +28 -0
  291. package/dist/types/tools/hub.d.ts +340 -0
  292. package/dist/types/tools/index.d.ts +4 -0
  293. package/dist/types/tools/json-tree.d.ts +59 -0
  294. package/dist/types/tools/line-ranges.d.ts +29 -0
  295. package/dist/types/tools/list-limit.d.ts +15 -0
  296. package/dist/types/tools/lsp.d.ts +72 -0
  297. package/dist/types/tools/match-line-format.d.ts +11 -0
  298. package/dist/types/tools/mcp.d.ts +81 -0
  299. package/dist/types/tools/memory.d.ts +67 -0
  300. package/dist/types/tools/output-meta.d.ts +151 -0
  301. package/dist/types/tools/read.d.ts +139 -0
  302. package/dist/types/tools/renderer.d.ts +98 -0
  303. package/dist/types/tools/report-tool-issue.d.ts +8 -0
  304. package/dist/types/tools/resolve.d.ts +47 -0
  305. package/dist/types/tools/streaming-output.d.ts +282 -0
  306. package/dist/types/tools/subprocess.d.ts +24 -0
  307. package/dist/types/tools/task-repair-args.d.ts +53 -0
  308. package/dist/types/tools/task-yield-assembly.d.ts +20 -0
  309. package/dist/types/tools/task.d.ts +425 -0
  310. package/dist/types/tools/terminal-output.d.ts +8 -0
  311. package/dist/types/tools/think.d.ts +13 -0
  312. package/dist/types/tools/todo.d.ts +118 -0
  313. package/dist/types/tools/tool-errors.d.ts +7 -0
  314. package/dist/types/tools/vibe.d.ts +120 -0
  315. package/dist/types/tools/web-search.d.ts +195 -0
  316. package/dist/types/tools/write.d.ts +76 -0
  317. package/dist/types/tools/xd-url.d.ts +13 -0
  318. package/dist/types/tools/xdev.d.ts +52 -0
  319. package/dist/types/tui.d.ts +18 -0
  320. package/dist/types/utils.d.ts +2 -0
  321. package/package.json +37 -3
  322. package/src/app-keybindings.ts +760 -0
  323. package/src/apps/autoresearch-dashboard.ts +500 -0
  324. package/src/apps/autoresearch-data.ts +64 -0
  325. package/src/apps/cleanse-board.ts +341 -0
  326. package/src/apps/cleanse-picker.ts +57 -0
  327. package/src/apps/debug/log-formatting.ts +53 -0
  328. package/src/apps/debug/log-viewer.ts +868 -0
  329. package/src/apps/debug/protocol-probe.ts +267 -0
  330. package/src/apps/debug/raw-sse-buffer.ts +449 -0
  331. package/src/apps/debug/raw-sse.ts +282 -0
  332. package/src/apps/debug/terminal-info.ts +115 -0
  333. package/src/apps/debug/viewer-frame.ts +174 -0
  334. package/src/apps/git/avatar.ts +52 -0
  335. package/src/apps/git/colors.ts +109 -0
  336. package/src/apps/git/diff-pane.ts +1512 -0
  337. package/src/apps/git/git-tui.ts +889 -0
  338. package/src/apps/git/sidebar.ts +1204 -0
  339. package/src/apps/git/state.ts +113 -0
  340. package/src/apps/if-bench-board.ts +324 -0
  341. package/src/apps/live-visualizer.ts +238 -0
  342. package/src/apps/ps-data.ts +116 -0
  343. package/src/apps/ps-top.ts +422 -0
  344. package/src/apps/session-picker.ts +95 -0
  345. package/src/apps/setup-model-picker.ts +21 -0
  346. package/src/apps/standalone-picker.ts +111 -0
  347. package/src/autocomplete.ts +9 -13
  348. package/src/chat/advisor-message.ts +175 -0
  349. package/src/chat/assistant-message.ts +1214 -0
  350. package/src/chat/background-tan-message.ts +35 -0
  351. package/src/chat/bash-execution.ts +394 -0
  352. package/src/chat/cache-invalidation-marker.ts +94 -0
  353. package/src/chat/chat-transcript-builder.ts +593 -0
  354. package/src/chat/collab-prompt-message.ts +34 -0
  355. package/src/chat/compaction-summary-message.ts +261 -0
  356. package/src/chat/custom-message.ts +23 -0
  357. package/src/chat/display-preferences.ts +24 -0
  358. package/src/chat/eval-execution.ts +172 -0
  359. package/src/chat/execution-shared.ts +113 -0
  360. package/src/chat/extension-types.ts +46 -0
  361. package/src/chat/hook-message.ts +20 -0
  362. package/src/chat/image-loading.ts +122 -0
  363. package/src/chat/late-diagnostics-message.ts +92 -0
  364. package/src/chat/messages.ts +305 -0
  365. package/src/chat/reaction.ts +65 -0
  366. package/src/chat/read-target.ts +7 -0
  367. package/src/chat/read-tool-group.ts +873 -0
  368. package/src/chat/served-model-marker.ts +91 -0
  369. package/src/chat/skill-message.ts +220 -0
  370. package/src/chat/skill-title-input.ts +41 -0
  371. package/src/chat/stripped-tool-calls-placeholder.ts +35 -0
  372. package/src/chat/thinking-display.ts +312 -0
  373. package/src/chat/todo-reminder.ts +33 -0
  374. package/src/chat/tool-execution.ts +1395 -0
  375. package/src/chat/transcript-browser.ts +268 -0
  376. package/src/chat/transcript-entry.ts +96 -0
  377. package/src/chat/transcript-outline.ts +260 -0
  378. package/src/chat/transcript-render-helpers.ts +315 -0
  379. package/src/chat/ttsr-notification.ts +123 -0
  380. package/src/chat/user-message.ts +287 -0
  381. package/src/chrome/chat-block.ts +110 -0
  382. package/src/chrome/collab-qrcode.ts +74 -0
  383. package/src/chrome/context-thresholds.ts +85 -0
  384. package/src/chrome/countdown-timer.ts +74 -0
  385. package/src/chrome/diff.ts +266 -0
  386. package/src/chrome/dynamic-border.ts +36 -0
  387. package/src/chrome/error-block.ts +63 -0
  388. package/src/chrome/form-theme.ts +10 -0
  389. package/src/chrome/format.ts +66 -0
  390. package/src/chrome/index.ts +21 -0
  391. package/src/chrome/keybinding-hints.ts +55 -0
  392. package/src/chrome/live-board.ts +123 -0
  393. package/src/chrome/local-date.ts +20 -0
  394. package/src/chrome/message-divider.ts +51 -0
  395. package/src/chrome/message-frame.ts +164 -0
  396. package/src/chrome/message-notice.ts +103 -0
  397. package/src/chrome/overlay-box.ts +301 -0
  398. package/src/chrome/qrcode.ts +539 -0
  399. package/src/chrome/segment-track.ts +86 -0
  400. package/src/chrome/select-list-mouse-routing.ts +11 -0
  401. package/src/chrome/selector-helpers.ts +119 -0
  402. package/src/chrome/shared.ts +27 -0
  403. package/src/chrome/streaming-panel.ts +72 -0
  404. package/src/chrome/tool-activity.ts +44 -0
  405. package/src/chrome/transcript-container.ts +902 -0
  406. package/src/chrome/transcript-status.ts +27 -0
  407. package/src/chrome/visual-truncate.ts +70 -0
  408. package/src/components/disclosure.ts +235 -0
  409. package/src/components/editor.ts +10 -12
  410. package/src/components/form.ts +566 -0
  411. package/src/components/input.ts +6 -27
  412. package/src/components/key-value-list.ts +88 -0
  413. package/src/components/layout/geometry.ts +202 -0
  414. package/src/components/layout/row.ts +283 -0
  415. package/src/components/layout/split-pane.ts +349 -0
  416. package/src/components/layout/stack.ts +261 -0
  417. package/src/components/markdown.ts +16 -12
  418. package/src/components/menu-selection.ts +248 -0
  419. package/src/components/metric.ts +132 -0
  420. package/src/components/progress-bar.ts +140 -0
  421. package/src/components/scroll-view.ts +372 -70
  422. package/src/components/scroll-viewport.ts +154 -0
  423. package/src/components/section.ts +77 -0
  424. package/src/components/select-list.ts +238 -159
  425. package/src/components/settings-list.ts +103 -80
  426. package/src/components/table.ts +127 -0
  427. package/src/components/tree-view.ts +481 -0
  428. package/src/components/wizard-step.ts +229 -0
  429. package/src/deccara.ts +1 -3
  430. package/src/hotkeys-markdown.ts +100 -0
  431. package/src/index.ts +18 -0
  432. package/src/keybinding-matchers.ts +99 -0
  433. package/src/keys.ts +2 -2
  434. package/src/lang-from-path.ts +252 -0
  435. package/src/overlays/advisor-config.ts +761 -0
  436. package/src/overlays/agent-activity.ts +113 -0
  437. package/src/overlays/agent-hub-projection.ts +250 -0
  438. package/src/overlays/agent-hub-renderer.ts +281 -0
  439. package/src/overlays/agent-hub-types.ts +74 -0
  440. package/src/overlays/agent-hub.ts +1562 -0
  441. package/src/overlays/agent-transcript-viewer.ts +669 -0
  442. package/src/overlays/agents-hub.ts +1203 -0
  443. package/src/overlays/ask-dialog.ts +1202 -0
  444. package/src/overlays/bordered-loader.ts +41 -0
  445. package/src/overlays/btw-history-panel.ts +591 -0
  446. package/src/overlays/btw-history.ts +33 -0
  447. package/src/overlays/btw-panel.ts +167 -0
  448. package/src/overlays/cleanse-panel.ts +167 -0
  449. package/src/overlays/codex-reset-fireworks.ts +375 -0
  450. package/src/overlays/composer-shape-preview.ts +137 -0
  451. package/src/overlays/composer-shape-registry.ts +82 -0
  452. package/src/overlays/copy-selector.ts +618 -0
  453. package/src/overlays/copy-targets.ts +210 -0
  454. package/src/overlays/error-banner.ts +39 -0
  455. package/src/overlays/extensions/display-text.ts +39 -0
  456. package/src/overlays/extensions/extension-dashboard.ts +645 -0
  457. package/src/overlays/extensions/extension-list.ts +667 -0
  458. package/src/overlays/extensions/inspector-model.ts +484 -0
  459. package/src/overlays/extensions/inspector-panel.ts +669 -0
  460. package/src/overlays/extensions/live-tool-session.ts +67 -0
  461. package/src/overlays/extensions/mcp-runtime.ts +289 -0
  462. package/src/overlays/extensions/state-manager.ts +337 -0
  463. package/src/overlays/extensions/types.ts +208 -0
  464. package/src/overlays/history-search.ts +268 -0
  465. package/src/overlays/hook-editor.ts +272 -0
  466. package/src/overlays/hook-input.ts +84 -0
  467. package/src/overlays/hook-selector.ts +635 -0
  468. package/src/overlays/hub-frame.ts +262 -0
  469. package/src/overlays/login-dialog.ts +231 -0
  470. package/src/overlays/logout-account-selector.ts +115 -0
  471. package/src/overlays/mcp-add-wizard.ts +1436 -0
  472. package/src/overlays/model-browser.ts +1176 -0
  473. package/src/overlays/model-hub.ts +2279 -0
  474. package/src/overlays/model-picker.ts +285 -0
  475. package/src/overlays/model-selector.ts +107 -0
  476. package/src/overlays/move-overlay.ts +197 -0
  477. package/src/overlays/oauth-selector.ts +446 -0
  478. package/src/overlays/omfg-panel.ts +136 -0
  479. package/src/overlays/pause-screen.ts +198 -0
  480. package/src/overlays/plan-review-overlay.ts +1227 -0
  481. package/src/overlays/plan-save-overlay.ts +74 -0
  482. package/src/overlays/plan-toc.ts +139 -0
  483. package/src/overlays/plugin-selector.ts +97 -0
  484. package/src/overlays/plugin-settings.ts +839 -0
  485. package/src/overlays/queue-mode-selector.ts +55 -0
  486. package/src/overlays/reset-usage-selector.ts +170 -0
  487. package/src/overlays/rewind-selector.ts +499 -0
  488. package/src/overlays/running-subagent-badge.ts +19 -0
  489. package/src/overlays/session-account-selector.ts +68 -0
  490. package/src/overlays/session-info-overlay.ts +96 -0
  491. package/src/overlays/session-observer-registry.ts +289 -0
  492. package/src/overlays/session-selector.ts +1137 -0
  493. package/src/overlays/settings-defs.ts +315 -0
  494. package/src/overlays/settings-selector.ts +1415 -0
  495. package/src/overlays/show-images-selector.ts +44 -0
  496. package/src/overlays/snapcompact-shape-preview-doc.md +14 -0
  497. package/src/overlays/snapcompact-shape-preview.ts +192 -0
  498. package/src/overlays/theme-selector.ts +62 -0
  499. package/src/overlays/thinking-selector.ts +51 -0
  500. package/src/overlays/tiny-title-download-progress.ts +102 -0
  501. package/src/overlays/tree-selector.ts +1121 -0
  502. package/src/overlays/usage-dashboard.ts +629 -0
  503. package/src/overlays/usage-display.ts +45 -0
  504. package/src/overlays/usage-row.ts +118 -0
  505. package/src/prompt/attachment-chips.ts +201 -0
  506. package/src/prompt/composer-attachments.ts +280 -0
  507. package/src/prompt/composer-cache.ts +304 -0
  508. package/src/prompt/composer.ts +934 -0
  509. package/src/prompt/custom-editor.ts +1392 -0
  510. package/src/prompt/data/emojis.json +1 -0
  511. package/src/prompt/editor-top-gap.ts +28 -0
  512. package/src/prompt/emoji-autocomplete.ts +285 -0
  513. package/src/prompt/github-ref-autocomplete.ts +75 -0
  514. package/src/prompt/gradient-highlight.ts +101 -0
  515. package/src/prompt/image-format.ts +28 -0
  516. package/src/prompt/image-references.ts +102 -0
  517. package/src/prompt/interactive-context-helpers.ts +126 -0
  518. package/src/prompt/internal-url-autocomplete.ts +155 -0
  519. package/src/prompt/macos-spelling.ts +456 -0
  520. package/src/prompt/magic-keyword-boundary.ts +23 -0
  521. package/src/prompt/magic-keywords.ts +42 -0
  522. package/src/prompt/markdown-prose.ts +245 -0
  523. package/src/prompt/model-mention-autocomplete.ts +94 -0
  524. package/src/prompt/model-mention-syntax.ts +41 -0
  525. package/src/prompt/orchestrate.ts +26 -0
  526. package/src/prompt/prompt-action-autocomplete.ts +337 -0
  527. package/src/prompt/queue-input.ts +132 -0
  528. package/src/prompt/skill-tokens.ts +36 -0
  529. package/src/prompt/tips.txt +27 -0
  530. package/src/prompt/tools-markdown.ts +29 -0
  531. package/src/prompt/ultrathink.ts +26 -0
  532. package/src/prompt/usage-amounts.ts +99 -0
  533. package/src/prompt/video.ts +47 -0
  534. package/src/prompt/welcome.ts +605 -0
  535. package/src/prompt/workflow.ts +26 -0
  536. package/src/render/code-cell.ts +244 -0
  537. package/src/render/file-list.ts +58 -0
  538. package/src/render/hyperlink.ts +192 -0
  539. package/src/render/index.ts +17 -0
  540. package/src/render/output-block.ts +267 -0
  541. package/src/render/output-pane.ts +299 -0
  542. package/src/render/render-utils.ts +1182 -0
  543. package/src/render/sixel.ts +69 -0
  544. package/src/render/status-line.ts +55 -0
  545. package/src/render/tool-card.ts +272 -0
  546. package/src/render/tree-list.ts +188 -0
  547. package/src/render/types.ts +19 -0
  548. package/src/render/utils.ts +109 -0
  549. package/src/render/width-aware-text.ts +60 -0
  550. package/src/setup/lazy.ts +17 -0
  551. package/src/setup/scenes/composer.ts +127 -0
  552. package/src/setup/scenes/glyph.ts +120 -0
  553. package/src/setup/scenes/model.ts +138 -0
  554. package/src/setup/scenes/outro.ts +24 -0
  555. package/src/setup/scenes/providers.ts +107 -0
  556. package/src/setup/scenes/sign-in.ts +373 -0
  557. package/src/setup/scenes/splash.ts +192 -0
  558. package/src/setup/scenes/theme.ts +343 -0
  559. package/src/setup/scenes/types.ts +111 -0
  560. package/src/setup/scenes/web-search.ts +165 -0
  561. package/src/setup/setup-version.ts +11 -0
  562. package/src/setup/startup-splash.ts +107 -0
  563. package/src/setup/wizard-overlay.ts +319 -0
  564. package/src/setup/wizard.ts +101 -0
  565. package/src/status-line/component.ts +3003 -0
  566. package/src/status-line/context-usage.ts +688 -0
  567. package/src/status-line/footer.ts +323 -0
  568. package/src/status-line/git-utils.ts +42 -0
  569. package/src/status-line/host.ts +97 -0
  570. package/src/status-line/index.ts +6 -0
  571. package/src/status-line/loop.ts +28 -0
  572. package/src/status-line/metrics.ts +94 -0
  573. package/src/status-line/presets.ts +107 -0
  574. package/src/status-line/schema.ts +57 -0
  575. package/src/status-line/segments.ts +934 -0
  576. package/src/status-line/separators.ts +55 -0
  577. package/src/status-line/types.ts +227 -0
  578. package/src/stdin-buffer.ts +4 -2
  579. package/src/theme/color.ts +95 -0
  580. package/src/theme/dark.json +95 -0
  581. package/src/theme/defaults/alabaster.json +93 -0
  582. package/src/theme/defaults/amethyst.json +96 -0
  583. package/src/theme/defaults/anthracite.json +93 -0
  584. package/src/theme/defaults/basalt.json +91 -0
  585. package/src/theme/defaults/birch.json +95 -0
  586. package/src/theme/defaults/dark-abyss.json +91 -0
  587. package/src/theme/defaults/dark-arctic.json +104 -0
  588. package/src/theme/defaults/dark-aurora.json +95 -0
  589. package/src/theme/defaults/dark-catppuccin.json +107 -0
  590. package/src/theme/defaults/dark-cavern.json +91 -0
  591. package/src/theme/defaults/dark-celestial.json +106 -0
  592. package/src/theme/defaults/dark-copper.json +95 -0
  593. package/src/theme/defaults/dark-cosmos.json +90 -0
  594. package/src/theme/defaults/dark-cyberpunk.json +102 -0
  595. package/src/theme/defaults/dark-dracula.json +98 -0
  596. package/src/theme/defaults/dark-eclipse.json +91 -0
  597. package/src/theme/defaults/dark-ember.json +95 -0
  598. package/src/theme/defaults/dark-equinox.json +90 -0
  599. package/src/theme/defaults/dark-forest.json +96 -0
  600. package/src/theme/defaults/dark-github.json +105 -0
  601. package/src/theme/defaults/dark-gruvbox.json +112 -0
  602. package/src/theme/defaults/dark-lavender.json +95 -0
  603. package/src/theme/defaults/dark-lunar.json +89 -0
  604. package/src/theme/defaults/dark-midnight.json +95 -0
  605. package/src/theme/defaults/dark-monochrome.json +94 -0
  606. package/src/theme/defaults/dark-monokai.json +98 -0
  607. package/src/theme/defaults/dark-nebula.json +90 -0
  608. package/src/theme/defaults/dark-nord.json +98 -0
  609. package/src/theme/defaults/dark-ocean.json +101 -0
  610. package/src/theme/defaults/dark-one.json +100 -0
  611. package/src/theme/defaults/dark-poimandres.json +115 -0
  612. package/src/theme/defaults/dark-rainforest.json +91 -0
  613. package/src/theme/defaults/dark-reef.json +91 -0
  614. package/src/theme/defaults/dark-retro.json +92 -0
  615. package/src/theme/defaults/dark-rose-pine.json +96 -0
  616. package/src/theme/defaults/dark-sakura.json +95 -0
  617. package/src/theme/defaults/dark-slate.json +95 -0
  618. package/src/theme/defaults/dark-solarized.json +97 -0
  619. package/src/theme/defaults/dark-solstice.json +90 -0
  620. package/src/theme/defaults/dark-starfall.json +91 -0
  621. package/src/theme/defaults/dark-sunset.json +99 -0
  622. package/src/theme/defaults/dark-swamp.json +90 -0
  623. package/src/theme/defaults/dark-synthwave.json +103 -0
  624. package/src/theme/defaults/dark-taiga.json +91 -0
  625. package/src/theme/defaults/dark-terminal.json +95 -0
  626. package/src/theme/defaults/dark-tokyo-night.json +101 -0
  627. package/src/theme/defaults/dark-tundra.json +91 -0
  628. package/src/theme/defaults/dark-twilight.json +91 -0
  629. package/src/theme/defaults/dark-volcanic.json +91 -0
  630. package/src/theme/defaults/graphite.json +92 -0
  631. package/src/theme/defaults/index.ts +201 -0
  632. package/src/theme/defaults/light-arctic.json +107 -0
  633. package/src/theme/defaults/light-aurora-day.json +91 -0
  634. package/src/theme/defaults/light-canyon.json +91 -0
  635. package/src/theme/defaults/light-catppuccin.json +106 -0
  636. package/src/theme/defaults/light-cirrus.json +90 -0
  637. package/src/theme/defaults/light-coral.json +95 -0
  638. package/src/theme/defaults/light-cyberpunk.json +96 -0
  639. package/src/theme/defaults/light-dawn.json +90 -0
  640. package/src/theme/defaults/light-dunes.json +91 -0
  641. package/src/theme/defaults/light-eucalyptus.json +95 -0
  642. package/src/theme/defaults/light-forest.json +100 -0
  643. package/src/theme/defaults/light-frost.json +95 -0
  644. package/src/theme/defaults/light-github.json +115 -0
  645. package/src/theme/defaults/light-glacier.json +91 -0
  646. package/src/theme/defaults/light-gruvbox.json +108 -0
  647. package/src/theme/defaults/light-haze.json +90 -0
  648. package/src/theme/defaults/light-honeycomb.json +95 -0
  649. package/src/theme/defaults/light-lagoon.json +91 -0
  650. package/src/theme/defaults/light-lavender.json +95 -0
  651. package/src/theme/defaults/light-meadow.json +91 -0
  652. package/src/theme/defaults/light-mint.json +95 -0
  653. package/src/theme/defaults/light-monochrome.json +101 -0
  654. package/src/theme/defaults/light-ocean.json +99 -0
  655. package/src/theme/defaults/light-one.json +99 -0
  656. package/src/theme/defaults/light-opal.json +91 -0
  657. package/src/theme/defaults/light-orchard.json +91 -0
  658. package/src/theme/defaults/light-paper.json +95 -0
  659. package/src/theme/defaults/light-poimandres.json +115 -0
  660. package/src/theme/defaults/light-prism.json +90 -0
  661. package/src/theme/defaults/light-retro.json +98 -0
  662. package/src/theme/defaults/light-sand.json +95 -0
  663. package/src/theme/defaults/light-savanna.json +91 -0
  664. package/src/theme/defaults/light-solarized.json +102 -0
  665. package/src/theme/defaults/light-soleil.json +90 -0
  666. package/src/theme/defaults/light-sunset.json +99 -0
  667. package/src/theme/defaults/light-synthwave.json +98 -0
  668. package/src/theme/defaults/light-tokyo-night.json +111 -0
  669. package/src/theme/defaults/light-wetland.json +91 -0
  670. package/src/theme/defaults/light-zenith.json +89 -0
  671. package/src/theme/defaults/limestone.json +94 -0
  672. package/src/theme/defaults/mahogany.json +97 -0
  673. package/src/theme/defaults/marble.json +93 -0
  674. package/src/theme/defaults/obsidian.json +91 -0
  675. package/src/theme/defaults/onyx.json +91 -0
  676. package/src/theme/defaults/pearl.json +93 -0
  677. package/src/theme/defaults/porcelain.json +91 -0
  678. package/src/theme/defaults/quartz.json +96 -0
  679. package/src/theme/defaults/sandstone.json +95 -0
  680. package/src/theme/defaults/titanium.json +90 -0
  681. package/src/theme/index.ts +5 -0
  682. package/src/theme/light.json +93 -0
  683. package/src/theme/loader.ts +200 -0
  684. package/src/theme/mermaid-cache.ts +92 -0
  685. package/src/theme/schema-validation.ts +119 -0
  686. package/src/theme/schema.ts +168 -0
  687. package/src/theme/session-color.ts +253 -0
  688. package/src/theme/shimmer.ts +307 -0
  689. package/src/theme/symbols.ts +1433 -0
  690. package/src/theme/theme-class.ts +787 -0
  691. package/src/theme/theme-schema.json +463 -0
  692. package/src/theme/theme.ts +810 -0
  693. package/src/theme/tui-adapters.ts +339 -0
  694. package/src/thinking.ts +380 -0
  695. package/src/tools/agent-tree.ts +128 -0
  696. package/src/tools/ask.ts +482 -0
  697. package/src/tools/ast-edit.ts +210 -0
  698. package/src/tools/ast-grep.ts +171 -0
  699. package/src/tools/autoresearch.ts +287 -0
  700. package/src/tools/bash-interactive.ts +295 -0
  701. package/src/tools/bash.ts +468 -0
  702. package/src/tools/conflict-detect.ts +77 -0
  703. package/src/tools/debug.ts +167 -0
  704. package/src/tools/default-renderer.ts +172 -0
  705. package/src/tools/edit.ts +1258 -0
  706. package/src/tools/eval-format/code-mode-declarations.ts +61 -0
  707. package/src/tools/eval-format/index.ts +16 -0
  708. package/src/tools/eval-format/javascript.ts +952 -0
  709. package/src/tools/eval-format/python.ts +544 -0
  710. package/src/tools/eval.ts +835 -0
  711. package/src/tools/fetch.ts +226 -0
  712. package/src/tools/gh-format.ts +18 -0
  713. package/src/tools/github.ts +686 -0
  714. package/src/tools/glob.ts +213 -0
  715. package/src/tools/goal.ts +153 -0
  716. package/src/tools/grep.ts +385 -0
  717. package/src/tools/grouped-file-output.ts +211 -0
  718. package/src/tools/hashline-format.ts +59 -0
  719. package/src/tools/hub.ts +1488 -0
  720. package/src/tools/index.ts +71 -0
  721. package/src/tools/json-tree.ts +388 -0
  722. package/src/tools/line-ranges.ts +98 -0
  723. package/src/tools/list-limit.ts +43 -0
  724. package/src/tools/lsp.ts +702 -0
  725. package/src/tools/match-line-format.ts +20 -0
  726. package/src/tools/mcp.ts +309 -0
  727. package/src/tools/memory.ts +220 -0
  728. package/src/tools/output-meta.ts +367 -0
  729. package/src/tools/read.ts +628 -0
  730. package/src/tools/renderer.ts +107 -0
  731. package/src/tools/report-tool-issue.ts +13 -0
  732. package/src/tools/resolve.ts +139 -0
  733. package/src/tools/streaming-output.ts +1576 -0
  734. package/src/tools/subprocess.ts +39 -0
  735. package/src/tools/task-repair-args.ts +118 -0
  736. package/src/tools/task-yield-assembly.ts +147 -0
  737. package/src/tools/task.ts +2110 -0
  738. package/src/tools/terminal-output.ts +153 -0
  739. package/src/tools/think.ts +28 -0
  740. package/src/tools/todo.ts +580 -0
  741. package/src/tools/tool-errors.ts +15 -0
  742. package/src/tools/vibe.ts +420 -0
  743. package/src/tools/web-search.ts +409 -0
  744. package/src/tools/write.ts +511 -0
  745. package/src/tools/xd-url.ts +28 -0
  746. package/src/tools/xdev.ts +201 -0
  747. package/src/tui.ts +57 -4
  748. package/src/utils.ts +8 -0
@@ -0,0 +1,385 @@
1
+ import type { Component } from "../tui";
2
+ import { Text } from "../components/text";
3
+ import type { RenderResultOptions, ToolRenderer } from "./renderer";
4
+ import { type Theme } from "../theme/theme";
5
+ import type { OutputMeta } from "./output-meta";
6
+ import type { TruncationResult } from "./streaming-output";
7
+ import { toPathList } from "../render/render-utils";
8
+ import {
9
+ Ellipsis,
10
+ fileHyperlink,
11
+ getTreeBranch,
12
+ getTreeContinuePrefix,
13
+ renderStatusLine,
14
+ renderTreeList,
15
+ truncateToWidth,
16
+ uriHyperlink,
17
+ } from "../render";
18
+ import {
19
+ createCachedComponent,
20
+ formatCount,
21
+ formatEmptyMessage,
22
+ formatErrorMessage,
23
+ formatMoreItems,
24
+ PREVIEW_LIMITS,
25
+ replaceTabs,
26
+ } from "../render/render-utils";
27
+ import { classifyGroupedLines, groupLineIndicesByBlank } from "./grouped-file-output";
28
+
29
+ /** Display metadata for grep tool results. */
30
+ export interface GrepToolDetails {
31
+ truncation?: TruncationResult;
32
+ fileLimitReached?: number;
33
+ perFileLimitReached?: number;
34
+ linesTruncated?: boolean;
35
+ meta?: OutputMeta;
36
+ scopePath?: string;
37
+ matchCount?: number;
38
+ fileCount?: number;
39
+ files?: string[];
40
+ fileMatches?: Array<{ path: string; count: number }>;
41
+ truncated?: boolean;
42
+ error?: string;
43
+ /** Pre-formatted text for the user-visible TUI render. Mirrors the model-facing
44
+ * `result.text` lines but uses a `│` gutter and `*` to mark match lines (vs space for
45
+ * context). The TUI uses this directly so it never parses model-facing hashline anchors. */
46
+ displayContent?: string;
47
+ /** Filesystem hyperlink targets resolved for internal URL headers at execution time. */
48
+ displayTargets?: Record<string, string>;
49
+ /** Absolute base directory used during search. Used by the renderer to resolve
50
+ * display-relative paths to absolute paths for OSC 8 hyperlinks. */
51
+ searchPath?: string;
52
+ /** Session cwd at search time. The renderer resolves the display-relative
53
+ * (cwd-relative) header/match paths against this for OSC 8 hyperlinks;
54
+ * `searchPath` is the scope label target, not the display-path base. */
55
+ cwd?: string;
56
+ /** User-supplied paths whose base directory was missing on disk. The tool
57
+ * skipped these and continued with the surviving entries; surfaced as a
58
+ * non-fatal warning in the renderer and in the model-facing text. */
59
+ missingPaths?: string[];
60
+ }
61
+
62
+ // =============================================================================
63
+ // TUI Renderer
64
+ // =============================================================================
65
+
66
+ interface GrepRenderArgs {
67
+ pattern: string;
68
+ path?: string | string[];
69
+ /** Legacy pre-`path` argument name; kept so historical transcripts still render a scope. */
70
+ paths?: string | string[];
71
+ case?: boolean;
72
+ gitignore?: boolean;
73
+ skip?: number;
74
+ }
75
+
76
+ const COLLAPSED_TEXT_LIMIT = PREVIEW_LIMITS.COLLAPSED_LINES * 2;
77
+ /** Line budget for the expanded view. Larger than collapsed so expanding
78
+ * reveals more matches with context, but still bounded so a single hot file
79
+ * whose matches span the whole file can't dump its entire length. */
80
+ const EXPANDED_TEXT_LIMIT = PREVIEW_LIMITS.EXPANDED_LINES * 2;
81
+
82
+ const SEARCH_CODE_FRAME_LINE_RE = /^\s*\*?(\d+)│/;
83
+
84
+ function searchScopeMeta(details: GrepToolDetails | undefined): string | undefined {
85
+ if (!details?.scopePath) return undefined;
86
+ const label = details.searchPath ? fileHyperlink(details.searchPath, details.scopePath) : details.scopePath;
87
+ return `in ${label}`;
88
+ }
89
+
90
+ function linkUrlLikeSearchHeader(
91
+ raw: string,
92
+ styled: string,
93
+ resolvedPath?: string,
94
+ ): { line: string; absPath?: string } {
95
+ if (resolvedPath) return { line: fileHyperlink(resolvedPath, styled), absPath: resolvedPath };
96
+ return { line: uriHyperlink(raw, styled) };
97
+ }
98
+
99
+ function parseSearchDisplayLineNumber(line: string): number | undefined {
100
+ const match = SEARCH_CODE_FRAME_LINE_RE.exec(line);
101
+ if (!match) return undefined;
102
+ return Number.parseInt(match[1]!, 10);
103
+ }
104
+
105
+ const SEARCH_MATCH_LINE_RE = /^\s*\*\d+(?:│|[:|])/;
106
+
107
+ interface RenderedSearchLine {
108
+ raw: string;
109
+ styled: string;
110
+ }
111
+
112
+ function isSearchMatchLine(line: string): boolean {
113
+ return SEARCH_MATCH_LINE_RE.test(line);
114
+ }
115
+
116
+ function isSearchHeaderLine(line: string): boolean {
117
+ return /^#+ /.test(line);
118
+ }
119
+
120
+ const URL_HEADER_PREFIX_RE = /^#+\s+/;
121
+
122
+ function renderSearchDisplayLines(
123
+ lines: readonly string[],
124
+ headerBase: string | undefined,
125
+ fileScope: string | undefined,
126
+ uiTheme: Theme,
127
+ displayTargets: Record<string, string> | undefined,
128
+ ): RenderedSearchLine[] {
129
+ const contexts = classifyGroupedLines(lines, headerBase, fileScope);
130
+ // `classifyGroupedLines` can't resolve internal URLs (TUI-only), so track the
131
+ // resolved URL target here and use it for the body lines that follow.
132
+ let urlFile: string | undefined;
133
+ return lines.map((line, index) => {
134
+ const ctx = contexts[index]!;
135
+ if (ctx.kind === "dir") {
136
+ urlFile = undefined;
137
+ const styled = uiTheme.fg("accent", line);
138
+ return { raw: line, styled: ctx.headerPath ? fileHyperlink(ctx.headerPath, styled) : styled };
139
+ }
140
+ if (ctx.kind === "file") {
141
+ if (ctx.isUrl) {
142
+ const raw = line
143
+ .replace(URL_HEADER_PREFIX_RE, "")
144
+ .trimEnd()
145
+ .replace(/\s+\([^)]*\)\s*$/, "");
146
+ const linked = linkUrlLikeSearchHeader(raw, uiTheme.fg("accent", line), displayTargets?.[raw]);
147
+ urlFile = linked.absPath;
148
+ return { raw: line, styled: linked.line };
149
+ }
150
+ urlFile = undefined;
151
+ // Root-level files keep the bright accent; nested file headers are dimmed.
152
+ const styled = uiTheme.fg(ctx.depth === 1 ? "accent" : "dim", line);
153
+ return { raw: line, styled: ctx.headerPath ? fileHyperlink(ctx.headerPath, styled) : styled };
154
+ }
155
+ const styled = uiTheme.fg("toolOutput", line);
156
+ const lineNumber = parseSearchDisplayLineNumber(line);
157
+ const filePath = ctx.filePath ?? urlFile;
158
+ return {
159
+ raw: line,
160
+ styled: filePath && lineNumber !== undefined ? fileHyperlink(filePath, styled, { line: lineNumber }) : styled,
161
+ };
162
+ });
163
+ }
164
+
165
+ function compactSearchPreviewGroup(group: RenderedSearchLine[]): RenderedSearchLine[] {
166
+ const compact = group.filter(line => isSearchHeaderLine(line.raw) || isSearchMatchLine(line.raw));
167
+ return compact.length > 0 ? compact : group;
168
+ }
169
+
170
+ function countPreviewMatches(lines: readonly RenderedSearchLine[], hasMarkedMatches: boolean): number {
171
+ if (hasMarkedMatches) return lines.reduce((count, line) => count + (isSearchMatchLine(line.raw) ? 1 : 0), 0);
172
+ return lines.reduce((count, line) => count + (!isSearchHeaderLine(line.raw) && line.raw.length > 0 ? 1 : 0), 0);
173
+ }
174
+
175
+ function renderBudgetedSearchGroups(
176
+ groups: RenderedSearchLine[][],
177
+ maxLines: number,
178
+ matchCount: number,
179
+ uiTheme: Theme,
180
+ compact: boolean,
181
+ ): string[] {
182
+ if (maxLines <= 0) return [];
183
+ const renderedGroups = groups
184
+ .map(group => (compact ? compactSearchPreviewGroup(group) : group))
185
+ .filter(group => group.length > 0);
186
+ if (renderedGroups.length === 0) return [];
187
+
188
+ let totalLines = 0;
189
+ let totalMarkedMatches = 0;
190
+ let totalFallbackMatches = 0;
191
+ for (const group of renderedGroups) {
192
+ totalLines += group.length;
193
+ totalMarkedMatches += countPreviewMatches(group, true);
194
+ totalFallbackMatches += countPreviewMatches(group, false);
195
+ }
196
+ const hasMarkedMatches = totalMarkedMatches > 0;
197
+ const needsSummary = totalLines > maxLines;
198
+ const contentBudget = needsSummary ? Math.max(maxLines - 1, 0) : maxLines;
199
+ const visibleGroups: RenderedSearchLine[][] = [];
200
+ let visibleLineCount = 0;
201
+ let visibleMatches = 0;
202
+ for (const group of renderedGroups) {
203
+ if (visibleLineCount >= contentBudget) break;
204
+ const available = contentBudget - visibleLineCount;
205
+ const take = Math.min(group.length, available);
206
+ if (take <= 0) break;
207
+ const visibleGroup = group.slice(0, take);
208
+ visibleGroups.push(visibleGroup);
209
+ visibleLineCount += visibleGroup.length;
210
+ visibleMatches += countPreviewMatches(visibleGroup, hasMarkedMatches);
211
+ }
212
+
213
+ const totalMatches = hasMarkedMatches ? totalMarkedMatches : Math.max(matchCount, totalFallbackMatches);
214
+ const hiddenMatches = Math.max(totalMatches - visibleMatches, 0);
215
+ const hiddenLines = Math.max(totalLines - visibleLineCount, 0);
216
+ const hasSummary = needsSummary && (hiddenMatches > 0 || hiddenLines > 0);
217
+ const lines: string[] = [];
218
+ for (let i = 0; i < visibleGroups.length; i++) {
219
+ const group = visibleGroups[i]!;
220
+ const isLast = !hasSummary && i === visibleGroups.length - 1;
221
+ const prefix = `${uiTheme.fg("dim", getTreeBranch(isLast, uiTheme))} `;
222
+ const continuePrefix = uiTheme.fg("dim", getTreeContinuePrefix(isLast, uiTheme));
223
+ lines.push(`${prefix}${replaceTabs(group[0]!.styled)}`);
224
+ for (let j = 1; j < group.length; j++) {
225
+ lines.push(`${continuePrefix}${replaceTabs(group[j]!.styled)}`);
226
+ }
227
+ }
228
+ if (hasSummary) {
229
+ const hiddenLabel =
230
+ hiddenMatches > 0 ? formatMoreItems(hiddenMatches, "match") : formatMoreItems(hiddenLines, "line");
231
+ lines.push(`${uiTheme.fg("dim", uiTheme.tree.last)} ${uiTheme.fg("muted", hiddenLabel)}`);
232
+ }
233
+ return lines;
234
+ }
235
+
236
+ function grepStatusIcon(uiTheme: Theme): string {
237
+ return uiTheme.fg("toolTitle", uiTheme.symbol("icon.search"));
238
+ }
239
+
240
+ /** Render grep calls and results in the transcript. */
241
+ export const grepToolRenderer = {
242
+ inline: true,
243
+ renderCall(args: GrepRenderArgs, _options: RenderResultOptions, uiTheme: Theme): Component {
244
+ const paths = toPathList(args.path ?? args.paths);
245
+ const meta: string[] = [];
246
+ if (paths.length) meta.push(`in ${paths.join(", ")}`);
247
+ if (args.case === false) meta.push("case:insensitive");
248
+ if (args.gitignore === false) meta.push("gitignore:false");
249
+ if (args.skip !== undefined && args.skip > 0) meta.push(`skip:${args.skip}`);
250
+
251
+ const text = renderStatusLine(
252
+ { icon: "pending", title: "Grep", titleColor: "toolTitle", description: args.pattern || "?", meta },
253
+ uiTheme,
254
+ );
255
+ return new Text(text, 1, 0);
256
+ },
257
+
258
+ renderResult(
259
+ result: { content: Array<{ type: string; text?: string }>; details?: GrepToolDetails; isError?: boolean },
260
+ options: RenderResultOptions,
261
+ uiTheme: Theme,
262
+ args?: GrepRenderArgs,
263
+ ): Component {
264
+ const details = result.details;
265
+
266
+ if (result.isError || details?.error) {
267
+ const errorText = details?.error || result.content?.find(c => c.type === "text")?.text || "Unknown error";
268
+ return new Text(formatErrorMessage(errorText, uiTheme), 1, 0);
269
+ }
270
+
271
+ const hasDetailedData = details?.matchCount !== undefined || details?.fileCount !== undefined;
272
+
273
+ if (!hasDetailedData) {
274
+ const textContent = result.details?.displayContent ?? result.content?.find(c => c.type === "text")?.text;
275
+ if (!textContent || textContent === "No matches found") {
276
+ return new Text(formatEmptyMessage("No matches found", uiTheme), 1, 0);
277
+ }
278
+ const lines = textContent.split("\n").filter(line => line.trim() !== "");
279
+ const description = args?.pattern ?? undefined;
280
+ const header = renderStatusLine(
281
+ {
282
+ iconOverride: grepStatusIcon(uiTheme),
283
+ title: "Grep",
284
+ titleColor: "toolTitle",
285
+ description,
286
+ meta: [formatCount("item", lines.length)],
287
+ },
288
+ uiTheme,
289
+ );
290
+ return createCachedComponent(
291
+ () => options.expanded,
292
+ width => {
293
+ const listLines = renderTreeList(
294
+ {
295
+ items: lines,
296
+ expanded: options.expanded,
297
+ maxCollapsed: COLLAPSED_TEXT_LIMIT,
298
+ maxCollapsedLines: COLLAPSED_TEXT_LIMIT,
299
+ itemType: "item",
300
+ renderItem: line => uiTheme.fg("toolOutput", line),
301
+ },
302
+ uiTheme,
303
+ );
304
+ return [header, ...listLines].map(l => truncateToWidth(l, width, Ellipsis.Omit));
305
+ },
306
+ { paddingX: 1 },
307
+ );
308
+ }
309
+
310
+ const matchCount = details?.matchCount ?? 0;
311
+ const fileCount = details?.fileCount ?? 0;
312
+ const truncation = details?.meta?.truncation;
313
+ const limits = details?.meta?.limits;
314
+ const truncated = Boolean(details?.truncated || truncation || limits?.columnTruncated);
315
+
316
+ const missingPathsList = details?.missingPaths ?? [];
317
+ const missingNote =
318
+ missingPathsList.length > 0
319
+ ? uiTheme.fg("warning", `skipped missing: ${missingPathsList.join(", ")}`)
320
+ : undefined;
321
+
322
+ if (matchCount === 0) {
323
+ const meta = ["0 matches"];
324
+ const scopeMeta = searchScopeMeta(details);
325
+ if (scopeMeta) meta.push(scopeMeta);
326
+ const header = renderStatusLine(
327
+ { icon: "warning", title: "Grep", titleColor: "toolTitle", description: args?.pattern, meta },
328
+ uiTheme,
329
+ );
330
+ const lines = [header, formatEmptyMessage("No matches found", uiTheme)];
331
+ if (missingNote) lines.push(missingNote);
332
+ return new Text(lines.join("\n"), 1, 0);
333
+ }
334
+
335
+ const summaryParts = [formatCount("match", matchCount), formatCount("file", fileCount)];
336
+ const meta = [...summaryParts];
337
+ const scopeMeta = searchScopeMeta(details);
338
+ if (scopeMeta) meta.push(scopeMeta);
339
+ if (truncated) meta.push(uiTheme.fg("warning", "truncated"));
340
+ const description = args?.pattern ?? undefined;
341
+ const header = renderStatusLine(
342
+ {
343
+ ...(truncated ? { icon: "warning" as const } : { iconOverride: grepStatusIcon(uiTheme) }),
344
+ title: "Grep",
345
+ titleColor: "toolTitle",
346
+ description,
347
+ meta,
348
+ },
349
+ uiTheme,
350
+ );
351
+
352
+ const textContent = result.details?.displayContent ?? result.content?.find(c => c.type === "text")?.text ?? "";
353
+ const allLines = textContent.split("\n");
354
+ // Resolve hyperlinks once over the whole output so a nested directory stack
355
+ // reconstructs correctly across blank-line group boundaries.
356
+ // Header/match display paths are cwd-relative, so resolve them against cwd
357
+ // (falling back to searchPath for legacy results that predate `cwd`); the
358
+ // scoped file's absolute path seeds body lines in single-file searches.
359
+ const renderedLines = renderSearchDisplayLines(
360
+ allLines,
361
+ details?.cwd ?? details?.searchPath,
362
+ details?.searchPath,
363
+ uiTheme,
364
+ details?.displayTargets,
365
+ );
366
+ const matchGroups = groupLineIndicesByBlank(allLines).map(indices => indices.map(i => renderedLines[i]!));
367
+
368
+ const extraLines: string[] = [];
369
+ if (missingNote) extraLines.push(missingNote);
370
+
371
+ return createCachedComponent(
372
+ () => options.expanded,
373
+ width => {
374
+ const budget = Math.max(
375
+ (options.expanded ? EXPANDED_TEXT_LIMIT : COLLAPSED_TEXT_LIMIT) - extraLines.length,
376
+ 0,
377
+ );
378
+ const matchLines = renderBudgetedSearchGroups(matchGroups, budget, matchCount, uiTheme, !options.expanded);
379
+ return [header, ...matchLines, ...extraLines].map(l => truncateToWidth(l, width, Ellipsis.Omit));
380
+ },
381
+ { paddingX: 1 },
382
+ );
383
+ },
384
+ mergeCallAndResult: true,
385
+ } satisfies ToolRenderer<GrepRenderArgs, GrepToolDetails>;
@@ -0,0 +1,211 @@
1
+ import * as path from "node:path";
2
+
3
+ import { buildPathTree, isUrlLikePath, type PathTreeInput, walkPathTree } from "@oh-my-pi/pi-utils";
4
+
5
+ // =============================================================================
6
+ // Grouped file output (grep / ast-grep / ast-edit / lsp diagnostics)
7
+ // =============================================================================
8
+
9
+ /**
10
+ * One file's contribution to a grouped file output. The header itself is generated
11
+ * by `formatGroupedFiles` (one `#` per nesting level); use `headerSuffix` to tack
12
+ * on extras like ` (1 replacement)`.
13
+ */
14
+ export interface GroupedFileSection {
15
+ /** Optional suffix appended to the file header. */
16
+ headerSuffix?: string;
17
+ /** Body lines emitted into the textual model output. */
18
+ modelLines: string[];
19
+ /** Body lines emitted into the display output. Defaults to `modelLines`. */
20
+ displayLines?: string[];
21
+ /** When true, the file (and its header) is omitted entirely. */
22
+ skip?: boolean;
23
+ }
24
+
25
+ /** Parallel model-facing and display-facing lines for grouped files. */
26
+ export interface GroupedFilesOutput {
27
+ model: string[];
28
+ display: string[];
29
+ }
30
+
31
+ /**
32
+ * Render a list of files as a multi-level, prefix-folded directory tree shared by
33
+ * grep, ast-grep, ast-edit, and the LSP diagnostic formatter.
34
+ *
35
+ * Layout (one `#` per level; the shared prefix folds into the top header):
36
+ * # packages/pkg/src/
37
+ * ## root.ts
38
+ * …body…
39
+ * ## nested/
40
+ * ### child.ts
41
+ * …body…
42
+ *
43
+ * Files in the (folded) project root become single-`#` headers with no parent
44
+ * directory line. A blank line precedes every directory header and every
45
+ * root-level file so the renderers can split the output into collapsible groups.
46
+ */
47
+ export function formatGroupedFiles(
48
+ files: string[],
49
+ renderFile: (filePath: string) => GroupedFileSection,
50
+ ): GroupedFilesOutput {
51
+ const sections = new Map<string, GroupedFileSection>();
52
+ const inputs: PathTreeInput[] = [];
53
+ for (const filePath of files) {
54
+ if (sections.has(filePath)) continue;
55
+ const section = renderFile(filePath);
56
+ if (section.skip) continue;
57
+ sections.set(filePath, section);
58
+ inputs.push({ path: filePath, isDir: false, key: filePath });
59
+ }
60
+
61
+ const tree = buildPathTree(inputs);
62
+ const model: string[] = [];
63
+ const display: string[] = [];
64
+ let emitted = false;
65
+
66
+ for (const event of walkPathTree(tree)) {
67
+ const hashes = "#".repeat(event.depth + 1);
68
+ const needsSeparator = emitted && (event.depth === 0 || event.kind === "dir");
69
+ if (needsSeparator) {
70
+ model.push("");
71
+ display.push("");
72
+ }
73
+ emitted = true;
74
+ if (event.kind === "dir") {
75
+ const header = `${hashes} ${event.name}/`;
76
+ model.push(header);
77
+ display.push(header);
78
+ continue;
79
+ }
80
+ const section = sections.get(event.key)!;
81
+ const header = `${hashes} ${event.name}${section.headerSuffix ?? ""}`;
82
+ model.push(header, ...section.modelLines);
83
+ display.push(header, ...(section.displayLines ?? section.modelLines));
84
+ }
85
+
86
+ return { model, display };
87
+ }
88
+
89
+ // =============================================================================
90
+ // Parsing grouped output back into per-line context (TUI renderers)
91
+ // =============================================================================
92
+
93
+ const GROUPED_HEADER_RE = /^(#+)\s+(.*)$/;
94
+ const HEADER_SUFFIX_RE = /\s+\([^)]*\)\s*$/;
95
+ const HEADER_HASH_TAG_RE = /#[0-9a-f]+$/i;
96
+
97
+ /** Per-line classification of grouped output, used by renderers for hyperlinks. */
98
+ export interface GroupedLineContext {
99
+ /** Directory header, file header, or any non-header body/content line. */
100
+ kind: "dir" | "file" | "content";
101
+ /** Number of leading `#` for headers; 0 for content lines. */
102
+ depth: number;
103
+ /** Resolved absolute path of the dir/file a header points at (when resolvable). */
104
+ headerPath?: string;
105
+ /** For content lines, the absolute path of the owning file (line hyperlinks). */
106
+ filePath?: string;
107
+ /** Header is an internal/url-like target the caller resolves itself. */
108
+ isUrl?: boolean;
109
+ }
110
+
111
+ function resolveGroupedPath(parent: string | undefined, name: string): string | undefined {
112
+ if (parent === undefined) return undefined;
113
+ if (name === "" || name === ".") return parent;
114
+ // `path.resolve` keeps an absolute `name` intact (out-of-cwd results) while
115
+ // joining a relative folded chain (`packages/pkg/src`) onto the parent.
116
+ return path.resolve(parent, name);
117
+ }
118
+
119
+ /**
120
+ * Walk grouped output lines, tracking a directory stack keyed by header depth, so
121
+ * each header and body line can be linked back to its absolute filesystem path.
122
+ * Reconstruction is stack-based (not per-blank-group) so nested directory headers
123
+ * resolve correctly across the whole output.
124
+ *
125
+ * `headerBase` is the directory the displayed (folded) header paths are relative
126
+ * to — for grep/ast tools that is the session cwd, since display paths are
127
+ * formatted relative to cwd regardless of the (sub)directory the search was
128
+ * scoped to. `fileScope` is the initial owning file for body lines that appear
129
+ * before any header (single-file scopes have no `#` headers); it defaults to
130
+ * `headerBase` and should be passed the scoped file's absolute path.
131
+ */
132
+ export function classifyGroupedLines(
133
+ lines: readonly string[],
134
+ headerBase: string | undefined,
135
+ fileScope: string | undefined = headerBase,
136
+ ): GroupedLineContext[] {
137
+ const result: GroupedLineContext[] = [];
138
+ const dirAtDepth = new Map<number, string>();
139
+ // Body lines before any header (single-file scopes) link to the scoped file.
140
+ let currentFile = fileScope;
141
+
142
+ const clearDeeper = (depth: number) => {
143
+ for (const key of dirAtDepth.keys()) {
144
+ if (key >= depth) dirAtDepth.delete(key);
145
+ }
146
+ };
147
+
148
+ for (const line of lines) {
149
+ const match = GROUPED_HEADER_RE.exec(line);
150
+ if (!match) {
151
+ result.push({ kind: "content", depth: 0, filePath: currentFile });
152
+ continue;
153
+ }
154
+ const depth = match[1]!.length;
155
+ const rest = match[2]!.trimEnd();
156
+ if (isUrlLikePath(rest)) {
157
+ clearDeeper(depth);
158
+ currentFile = undefined;
159
+ result.push({ kind: "file", depth, isUrl: true });
160
+ continue;
161
+ }
162
+ const parent = depth > 1 ? dirAtDepth.get(depth - 1) : headerBase;
163
+ if (rest.endsWith("/")) {
164
+ const name = rest.slice(0, -1).replace(HEADER_SUFFIX_RE, "");
165
+ const abs = resolveGroupedPath(parent, name);
166
+ clearDeeper(depth);
167
+ if (abs !== undefined) dirAtDepth.set(depth, abs);
168
+ currentFile = undefined;
169
+ result.push({ kind: "dir", depth, headerPath: abs });
170
+ continue;
171
+ }
172
+ const name = rest.replace(HEADER_SUFFIX_RE, "").replace(HEADER_HASH_TAG_RE, "");
173
+ const abs = name ? resolveGroupedPath(parent, name) : undefined;
174
+ currentFile = abs;
175
+ result.push({ kind: "file", depth, headerPath: abs });
176
+ }
177
+
178
+ return result;
179
+ }
180
+
181
+ /**
182
+ * Split line indices into blank-line-separated groups, mirroring
183
+ * `splitGroupsByBlankLine`: when any blank line is present, break on runs of
184
+ * blanks; otherwise return a single group of the non-empty lines. Returning
185
+ * indices lets callers slice parallel arrays (raw lines, styled lines, contexts).
186
+ */
187
+ export function groupLineIndicesByBlank(rawLines: readonly string[]): number[][] {
188
+ const hasSeparators = rawLines.some(line => line.trim().length === 0);
189
+ const groups: number[][] = [];
190
+ if (hasSeparators) {
191
+ let current: number[] = [];
192
+ for (let i = 0; i < rawLines.length; i++) {
193
+ if (rawLines[i]!.trim().length === 0) {
194
+ if (current.length > 0) {
195
+ groups.push(current);
196
+ current = [];
197
+ }
198
+ continue;
199
+ }
200
+ current.push(i);
201
+ }
202
+ if (current.length > 0) groups.push(current);
203
+ } else {
204
+ const current: number[] = [];
205
+ for (let i = 0; i < rawLines.length; i++) {
206
+ if (rawLines[i]!.trim().length > 0) current.push(i);
207
+ }
208
+ if (current.length > 0) groups.push(current);
209
+ }
210
+ return groups;
211
+ }
@@ -0,0 +1,59 @@
1
+ import {
2
+ hashlineFileHash,
3
+ hashlineFormatHeader,
4
+ hashlineFormatNumberedLines,
5
+ hashlineIsReadTruncationNotice,
6
+ hashlineStripPrefixes,
7
+ } from "@oh-my-pi/pi-natives";
8
+
9
+ /** Opening delimiter of a hashline file header. */
10
+ export const HL_FILE_PREFIX = "[";
11
+ /** Closing delimiter of a hashline file header. */
12
+ export const HL_FILE_SUFFIX = "]";
13
+ /** Separator between the file path and content hash. */
14
+ export const HL_FILE_HASH_SEP = "#";
15
+ /** Number of characters in a displayed file hash. */
16
+ export const HL_FILE_HASH_LENGTH = 4;
17
+ /** Keyword identifying a file move operation. */
18
+ export const HL_MOVE_KEYWORD = "MV";
19
+ /** Keyword identifying a file removal operation. */
20
+ export const HL_REM_KEYWORD = "REM";
21
+ /** Separator between a line number and its body. */
22
+ export const HL_LINE_BODY_SEP = ":";
23
+
24
+ /** Format a file path and content hash as a hashline header. */
25
+ export function formatHashlineHeader(path: string, tag: string): string {
26
+ return hashlineFormatHeader(path, tag);
27
+ }
28
+
29
+ /** Prefix each addressable line with its file line number. */
30
+ export function formatNumberedLines(text: string, startLine?: number): string {
31
+ return hashlineFormatNumberedLines(text, startLine);
32
+ }
33
+
34
+ /** Prefix one line with its file line number. */
35
+ export function formatNumberedLine(lineNumber: number, line: string): string {
36
+ return `${lineNumber}:${line}`;
37
+ }
38
+
39
+ /** Split file lines without treating a trailing newline as an empty address. */
40
+ export function splitAddressableFileLines(text: string): string[] {
41
+ const lines = text.split("\n");
42
+ if (lines.at(-1) === "") lines.pop();
43
+ return lines;
44
+ }
45
+
46
+ /** Remove model-facing hashline anchors from copied file content. */
47
+ export function stripHashlinePrefixes(lines: string[]): string[] {
48
+ return hashlineStripPrefixes(lines);
49
+ }
50
+
51
+ /** Whether a row is a truncation notice emitted by `read`. */
52
+ export function isReadTruncationNotice(line: string): boolean {
53
+ return hashlineIsReadTruncationNotice(line);
54
+ }
55
+
56
+ /** Compute the native hashline content fingerprint. */
57
+ export function computeFileHash(text: string): string {
58
+ return hashlineFileHash(text);
59
+ }