@linxiraos/pi-tui 1.1.26 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (423) hide show
  1. package/CHANGELOG.md +51 -491
  2. package/README.md +13 -7
  3. package/dist/types/active-terminal.d.ts +30 -0
  4. package/dist/types/app-keybindings.d.ts +7 -2
  5. package/dist/types/apps/cleanse-board.d.ts +1 -1
  6. package/dist/types/apps/debug/log-viewer.d.ts +4 -0
  7. package/dist/types/apps/debug/raw-sse-buffer.d.ts +2 -0
  8. package/dist/types/apps/git/git-tui.d.ts +5 -4
  9. package/dist/types/apps/git/help.d.ts +3 -1
  10. package/dist/types/apps/if-bench-board.d.ts +2 -2
  11. package/dist/types/apps/setup-model-picker.d.ts +1 -1
  12. package/dist/types/autocomplete.d.ts +5 -2
  13. package/dist/types/charts/chart-plan.d.ts +674 -0
  14. package/dist/types/charts/chart-svg.d.ts +59 -0
  15. package/dist/types/charts/table-data.d.ts +175 -0
  16. package/dist/types/chat/assistant-message.d.ts +11 -1
  17. package/dist/types/chat/chat-transcript-builder.d.ts +3 -0
  18. package/dist/types/chat/compaction-summary-message.d.ts +1 -0
  19. package/dist/types/chat/execution-shared.d.ts +6 -5
  20. package/dist/types/chat/fence-figure.d.ts +42 -0
  21. package/dist/types/chat/figure-markdown.d.ts +42 -0
  22. package/dist/types/chat/messages.d.ts +1 -1
  23. package/dist/types/chat/svg-figure.d.ts +33 -0
  24. package/dist/types/chat/svg-source.d.ts +49 -0
  25. package/dist/types/chat/table-chart.d.ts +89 -0
  26. package/dist/types/chat/tool-execution.d.ts +2 -0
  27. package/dist/types/chat/user-message.d.ts +17 -4
  28. package/dist/types/chrome/shared.d.ts +9 -0
  29. package/dist/types/chrome/status-notice.d.ts +15 -3
  30. package/dist/types/chrome/transcript-container.d.ts +6 -0
  31. package/dist/types/components/box.d.ts +1 -0
  32. package/dist/types/components/disclosure.d.ts +1 -0
  33. package/dist/types/components/editor.d.ts +23 -5
  34. package/dist/types/components/form.d.ts +1 -0
  35. package/dist/types/components/image.d.ts +26 -44
  36. package/dist/types/components/input.d.ts +2 -1
  37. package/dist/types/components/key-value-list.d.ts +1 -0
  38. package/dist/types/components/layout/row.d.ts +1 -0
  39. package/dist/types/components/layout/stack.d.ts +1 -0
  40. package/dist/types/components/loader.d.ts +5 -6
  41. package/dist/types/components/markdown.d.ts +47 -5
  42. package/dist/types/components/scroll-view.d.ts +1 -0
  43. package/dist/types/components/section.d.ts +1 -0
  44. package/dist/types/components/table.d.ts +1 -0
  45. package/dist/types/components/text.d.ts +1 -0
  46. package/dist/types/components/tree-view.d.ts +7 -0
  47. package/dist/types/components/truncated-text.d.ts +1 -0
  48. package/dist/types/fuzzy.d.ts +29 -1
  49. package/dist/types/key-hint-format.d.ts +9 -1
  50. package/dist/types/keybinding-matchers.d.ts +3 -0
  51. package/dist/types/keybindings.d.ts +1 -1
  52. package/dist/types/kitty-graphics.d.ts +2 -2
  53. package/dist/types/loop-watchdog.d.ts +8 -7
  54. package/dist/types/multiplexers/cmux.d.ts +16 -0
  55. package/dist/types/multiplexers/herdr.d.ts +26 -0
  56. package/dist/types/multiplexers/notify.d.ts +13 -0
  57. package/dist/types/multiplexers/orca.d.ts +12 -0
  58. package/dist/types/multiplexers/screen.d.ts +9 -0
  59. package/dist/types/multiplexers/tmux.d.ts +29 -0
  60. package/dist/types/multiplexers/types.d.ts +100 -0
  61. package/dist/types/multiplexers/wmux.d.ts +12 -0
  62. package/dist/types/multiplexers/zellij.d.ts +12 -0
  63. package/dist/types/native/apply.d.ts +4 -3
  64. package/dist/types/native/backend.d.ts +5 -4
  65. package/dist/types/native/blobs.d.ts +7 -3
  66. package/dist/types/native/encode.d.ts +8 -6
  67. package/dist/types/native/node.d.ts +36 -5
  68. package/dist/types/native/overlay.d.ts +8 -3
  69. package/dist/types/native/settle.d.ts +4 -3
  70. package/dist/types/overlays/agent-hub-projection.d.ts +6 -5
  71. package/dist/types/overlays/agent-hub-types.d.ts +9 -0
  72. package/dist/types/overlays/agent-hub.d.ts +3 -0
  73. package/dist/types/overlays/agent-transcript-viewer.d.ts +12 -2
  74. package/dist/types/overlays/agents-hub.d.ts +9 -0
  75. package/dist/types/overlays/annotation-overlay.d.ts +19 -2
  76. package/dist/types/overlays/annotation-types.d.ts +2 -0
  77. package/dist/types/overlays/ask-dialog.d.ts +5 -2
  78. package/dist/types/overlays/btw-history-panel.d.ts +13 -1
  79. package/dist/types/overlays/copy-selector.d.ts +1 -0
  80. package/dist/types/overlays/history-search.d.ts +10 -0
  81. package/dist/types/overlays/hook-selector.d.ts +9 -4
  82. package/dist/types/overlays/hub-frame.d.ts +4 -1
  83. package/dist/types/overlays/jobs-panel.d.ts +1 -7
  84. package/dist/types/overlays/model-browser.d.ts +54 -7
  85. package/dist/types/overlays/model-hub.d.ts +37 -0
  86. package/dist/types/overlays/oauth-selector.d.ts +0 -1
  87. package/dist/types/overlays/plan-review-overlay.d.ts +3 -2
  88. package/dist/types/overlays/report-panel.d.ts +68 -0
  89. package/dist/types/overlays/rewind-selector.d.ts +1 -0
  90. package/dist/types/overlays/session-observer-registry.d.ts +2 -0
  91. package/dist/types/overlays/session-selector.d.ts +6 -2
  92. package/dist/types/overlays/settings-defs.d.ts +1 -0
  93. package/dist/types/overlays/thinking-selector.d.ts +2 -2
  94. package/dist/types/overlays/usage-dashboard.d.ts +12 -8
  95. package/dist/types/overlays/usage-display.d.ts +3 -1
  96. package/dist/types/prompt/composer-cache.d.ts +0 -16
  97. package/dist/types/prompt/composer.d.ts +18 -3
  98. package/dist/types/prompt/custom-editor.d.ts +25 -13
  99. package/dist/types/prompt/image-source.d.ts +2 -1
  100. package/dist/types/prompt/interactive-context-helpers.d.ts +5 -1
  101. package/dist/types/prompt/model-mention-autocomplete.d.ts +1 -1
  102. package/dist/types/prompt/welcome.d.ts +7 -2
  103. package/dist/types/render/composite.d.ts +2 -0
  104. package/dist/types/render/output-pane.d.ts +1 -0
  105. package/dist/types/render/render-utils.d.ts +1 -0
  106. package/dist/types/render/tool-card.d.ts +6 -0
  107. package/dist/types/render/width-aware-text.d.ts +2 -0
  108. package/dist/types/setup/scenes/types.d.ts +1 -0
  109. package/dist/types/space-hold.d.ts +40 -25
  110. package/dist/types/status-line/component.d.ts +3 -0
  111. package/dist/types/status-line/context-usage.d.ts +7 -5
  112. package/dist/types/status-line/host.d.ts +4 -1
  113. package/dist/types/status-line/segments.d.ts +2 -0
  114. package/dist/types/status-line/types.d.ts +14 -3
  115. package/dist/types/terminal-capabilities.d.ts +41 -36
  116. package/dist/types/terminal-multiplexer.d.ts +127 -14
  117. package/dist/types/terminal.d.ts +23 -16
  118. package/dist/types/theme/active-symbols.d.ts +1 -1
  119. package/dist/types/theme/schema.d.ts +11 -2
  120. package/dist/types/theme/symbols.d.ts +1 -1
  121. package/dist/types/theme/theme-class.d.ts +7 -0
  122. package/dist/types/theme/theme.d.ts +1 -1
  123. package/dist/types/theme/tui-adapters.d.ts +3 -0
  124. package/dist/types/thinking.d.ts +1 -1
  125. package/dist/types/tmux.d.ts +11 -4
  126. package/dist/types/tools/bash.d.ts +7 -2
  127. package/dist/types/tools/daemon.d.ts +1 -1
  128. package/dist/types/tools/eval.d.ts +22 -3
  129. package/dist/types/tools/glob.d.ts +4 -0
  130. package/dist/types/tools/native-view.d.ts +47 -0
  131. package/dist/types/tools/output-meta.d.ts +11 -1
  132. package/dist/types/tools/renderer.d.ts +37 -2
  133. package/dist/types/tools/streaming-output.d.ts +20 -1
  134. package/dist/types/tools/task.d.ts +2 -3
  135. package/dist/types/tools/write.d.ts +9 -2
  136. package/dist/types/tools/yield.d.ts +22 -0
  137. package/dist/types/tui.d.ts +36 -0
  138. package/dist/types/utils.d.ts +6 -0
  139. package/dist/types/vim.d.ts +19 -5
  140. package/dist/types/windows-input-mode.d.ts +33 -1
  141. package/package.json +13 -9
  142. package/src/active-terminal.d.ts +30 -0
  143. package/src/active-terminal.ts +80 -0
  144. package/src/app-keybindings.d.ts +7 -2
  145. package/src/app-keybindings.ts +7 -2
  146. package/src/apps/autoresearch-dashboard.ts +7 -3
  147. package/src/apps/cleanse-board.ts +2 -2
  148. package/src/apps/cleanse-picker.ts +1 -1
  149. package/src/apps/debug/log-viewer.ts +188 -72
  150. package/src/apps/debug/raw-sse-buffer.ts +8 -0
  151. package/src/apps/debug/raw-sse.ts +39 -5
  152. package/src/apps/git/diff-pane.ts +96 -23
  153. package/src/apps/git/git-tui.ts +23 -16
  154. package/src/apps/git/help.ts +29 -20
  155. package/src/apps/git/sidebar.ts +8 -3
  156. package/src/apps/if-bench-board.ts +2 -2
  157. package/src/apps/ps-top.ts +2 -2
  158. package/src/apps/setup-model-picker.ts +1 -1
  159. package/src/autocomplete.d.ts +5 -2
  160. package/src/autocomplete.ts +67 -43
  161. package/src/bracketed-paste.ts +10 -3
  162. package/src/charts/chart-plan.d.ts +674 -0
  163. package/src/charts/chart-plan.ts +5081 -0
  164. package/src/charts/chart-svg.d.ts +59 -0
  165. package/src/charts/chart-svg.ts +4657 -0
  166. package/src/charts/table-data.d.ts +175 -0
  167. package/src/charts/table-data.ts +1478 -0
  168. package/src/chat/advisor-message.ts +11 -0
  169. package/src/chat/assistant-message.d.ts +11 -1
  170. package/src/chat/assistant-message.ts +245 -54
  171. package/src/chat/chat-transcript-builder.d.ts +3 -0
  172. package/src/chat/chat-transcript-builder.ts +9 -3
  173. package/src/chat/compaction-summary-message.d.ts +1 -0
  174. package/src/chat/compaction-summary-message.ts +8 -0
  175. package/src/chat/execution-shared.d.ts +6 -5
  176. package/src/chat/execution-shared.ts +42 -25
  177. package/src/chat/fence-figure.d.ts +42 -0
  178. package/src/chat/fence-figure.ts +80 -0
  179. package/src/chat/figure-markdown.d.ts +42 -0
  180. package/src/chat/figure-markdown.ts +174 -0
  181. package/src/chat/messages.d.ts +1 -1
  182. package/src/chat/messages.ts +1 -1
  183. package/src/chat/read-tool-group.ts +6 -4
  184. package/src/chat/skill-message.ts +6 -0
  185. package/src/chat/svg-figure.d.ts +33 -0
  186. package/src/chat/svg-figure.ts +399 -0
  187. package/src/chat/svg-source.d.ts +49 -0
  188. package/src/chat/svg-source.ts +188 -0
  189. package/src/chat/table-chart.d.ts +89 -0
  190. package/src/chat/table-chart.ts +294 -0
  191. package/src/chat/tool-execution.d.ts +2 -0
  192. package/src/chat/tool-execution.ts +86 -7
  193. package/src/chat/user-message.d.ts +17 -4
  194. package/src/chat/user-message.ts +71 -8
  195. package/src/chrome/shared.ts +53 -0
  196. package/src/chrome/status-notice.ts +25 -7
  197. package/src/chrome/transcript-container.d.ts +6 -0
  198. package/src/chrome/transcript-container.ts +162 -19
  199. package/src/components/box.d.ts +1 -0
  200. package/src/components/box.ts +5 -0
  201. package/src/components/disclosure.d.ts +1 -0
  202. package/src/components/disclosure.ts +8 -0
  203. package/src/components/editor.d.ts +23 -5
  204. package/src/components/editor.ts +316 -47
  205. package/src/components/form.d.ts +1 -0
  206. package/src/components/form.ts +8 -0
  207. package/src/components/image.d.ts +26 -44
  208. package/src/components/image.ts +115 -152
  209. package/src/components/input.d.ts +2 -1
  210. package/src/components/input.ts +17 -7
  211. package/src/components/key-value-list.d.ts +1 -0
  212. package/src/components/key-value-list.ts +4 -0
  213. package/src/components/layout/row.d.ts +1 -0
  214. package/src/components/layout/row.ts +7 -0
  215. package/src/components/layout/stack.d.ts +1 -0
  216. package/src/components/layout/stack.ts +7 -0
  217. package/src/components/loader.d.ts +5 -6
  218. package/src/components/loader.ts +10 -17
  219. package/src/components/markdown.d.ts +47 -5
  220. package/src/components/markdown.ts +786 -303
  221. package/src/components/scroll-view.d.ts +1 -0
  222. package/src/components/scroll-view.ts +5 -0
  223. package/src/components/section.d.ts +1 -0
  224. package/src/components/section.ts +5 -0
  225. package/src/components/settings-list.ts +2 -0
  226. package/src/components/table.d.ts +1 -0
  227. package/src/components/table.ts +4 -0
  228. package/src/components/text.d.ts +1 -0
  229. package/src/components/text.ts +7 -0
  230. package/src/components/tree-view.d.ts +7 -0
  231. package/src/components/tree-view.ts +38 -8
  232. package/src/components/truncated-text.d.ts +1 -0
  233. package/src/components/truncated-text.ts +5 -0
  234. package/src/desktop-notify.ts +3 -2
  235. package/src/fuzzy.d.ts +29 -1
  236. package/src/fuzzy.ts +115 -30
  237. package/src/hotkeys-markdown.ts +9 -2
  238. package/src/key-hint-format.d.ts +9 -1
  239. package/src/key-hint-format.ts +26 -11
  240. package/src/keybinding-matchers.d.ts +3 -0
  241. package/src/keybinding-matchers.ts +6 -2
  242. package/src/keybindings.d.ts +1 -1
  243. package/src/keybindings.ts +1 -1
  244. package/src/kitty-graphics.d.ts +2 -2
  245. package/src/kitty-graphics.ts +11 -5
  246. package/src/loop-watchdog.d.ts +8 -7
  247. package/src/loop-watchdog.ts +18 -13
  248. package/src/multiplexers/cmux.d.ts +16 -0
  249. package/src/multiplexers/cmux.ts +29 -0
  250. package/src/multiplexers/herdr.d.ts +26 -0
  251. package/src/multiplexers/herdr.ts +64 -0
  252. package/src/multiplexers/notify.d.ts +13 -0
  253. package/src/multiplexers/notify.ts +24 -0
  254. package/src/multiplexers/orca.d.ts +12 -0
  255. package/src/multiplexers/orca.ts +16 -0
  256. package/src/multiplexers/screen.d.ts +9 -0
  257. package/src/multiplexers/screen.ts +15 -0
  258. package/src/multiplexers/tmux.d.ts +29 -0
  259. package/src/multiplexers/tmux.ts +40 -0
  260. package/src/multiplexers/types.d.ts +100 -0
  261. package/src/multiplexers/types.ts +110 -0
  262. package/src/multiplexers/wmux.d.ts +12 -0
  263. package/src/multiplexers/wmux.ts +16 -0
  264. package/src/multiplexers/zellij.d.ts +12 -0
  265. package/src/multiplexers/zellij.ts +24 -0
  266. package/src/native/apply.d.ts +4 -3
  267. package/src/native/apply.ts +4 -3
  268. package/src/native/backend.d.ts +5 -4
  269. package/src/native/backend.ts +199 -22
  270. package/src/native/blobs.d.ts +7 -3
  271. package/src/native/blobs.ts +47 -12
  272. package/src/native/encode.d.ts +8 -6
  273. package/src/native/encode.ts +76 -34
  274. package/src/native/node.d.ts +36 -5
  275. package/src/native/node.ts +31 -5
  276. package/src/native/overlay.d.ts +8 -3
  277. package/src/native/overlay.ts +17 -4
  278. package/src/native/reconcile.ts +16 -4
  279. package/src/native/settle.d.ts +4 -3
  280. package/src/native/settle.ts +4 -3
  281. package/src/overlays/agent-hub-projection.d.ts +6 -5
  282. package/src/overlays/agent-hub-projection.ts +124 -13
  283. package/src/overlays/agent-hub-types.d.ts +9 -0
  284. package/src/overlays/agent-hub-types.ts +6 -0
  285. package/src/overlays/agent-hub.ts +48 -29
  286. package/src/overlays/agent-transcript-viewer.ts +93 -23
  287. package/src/overlays/agents-hub.ts +28 -8
  288. package/src/overlays/annotation-overlay.ts +293 -90
  289. package/src/overlays/annotation-types.ts +2 -0
  290. package/src/overlays/ask-dialog.ts +10 -17
  291. package/src/overlays/btw-history-panel.ts +136 -39
  292. package/src/overlays/copy-selector.d.ts +1 -0
  293. package/src/overlays/copy-selector.ts +32 -8
  294. package/src/overlays/extensions/extension-dashboard.ts +4 -4
  295. package/src/overlays/extensions/state-manager.ts +52 -12
  296. package/src/overlays/history-search.ts +100 -7
  297. package/src/overlays/hook-selector.ts +12 -5
  298. package/src/overlays/hub-frame.ts +19 -1
  299. package/src/overlays/jobs-panel.ts +33 -52
  300. package/src/overlays/model-browser.ts +367 -122
  301. package/src/overlays/model-hub.ts +435 -59
  302. package/src/overlays/move-overlay.ts +28 -14
  303. package/src/overlays/oauth-selector.ts +54 -70
  304. package/src/overlays/pause-screen.ts +2 -2
  305. package/src/overlays/plan-review-overlay.ts +208 -70
  306. package/src/overlays/plugin-settings.ts +3 -3
  307. package/src/overlays/report-panel.ts +191 -0
  308. package/src/overlays/rewind-selector.ts +88 -17
  309. package/src/overlays/session-observer-registry.d.ts +2 -0
  310. package/src/overlays/session-observer-registry.ts +10 -2
  311. package/src/overlays/session-selector.ts +64 -26
  312. package/src/overlays/settings-defs.ts +5 -4
  313. package/src/overlays/settings-selector.ts +33 -8
  314. package/src/overlays/snapcompact-shape-preview.ts +2 -3
  315. package/src/overlays/stats-notice.ts +1 -1
  316. package/src/overlays/thinking-selector.ts +11 -10
  317. package/src/overlays/tree-selector.ts +41 -20
  318. package/src/overlays/usage-dashboard.ts +117 -58
  319. package/src/overlays/usage-display.ts +10 -4
  320. package/src/overlays/usage-row.ts +22 -8
  321. package/src/prompt/attachment-chips.ts +15 -11
  322. package/src/prompt/composer-attachments.ts +6 -4
  323. package/src/prompt/composer-cache.ts +7 -86
  324. package/src/prompt/composer.ts +37 -26
  325. package/src/prompt/custom-editor.ts +282 -105
  326. package/src/prompt/image-source.ts +2 -1
  327. package/src/prompt/interactive-context-helpers.ts +32 -18
  328. package/src/prompt/macos-spelling.ts +7 -0
  329. package/src/prompt/magic-keywords.ts +11 -2
  330. package/src/prompt/model-mention-autocomplete.ts +14 -14
  331. package/src/prompt/queued-messages.ts +6 -4
  332. package/src/prompt/tips.txt +13 -9
  333. package/src/prompt/welcome.ts +64 -46
  334. package/src/prompt/word-completion.ts +38 -5
  335. package/src/render/composite.d.ts +2 -0
  336. package/src/render/composite.ts +64 -0
  337. package/src/render/output-pane.d.ts +1 -0
  338. package/src/render/output-pane.ts +6 -0
  339. package/src/render/render-utils.d.ts +1 -0
  340. package/src/render/render-utils.ts +16 -1
  341. package/src/render/tool-card.d.ts +6 -0
  342. package/src/render/tool-card.ts +15 -0
  343. package/src/render/width-aware-text.d.ts +2 -0
  344. package/src/render/width-aware-text.ts +5 -0
  345. package/src/setup/scenes/model.ts +2 -1
  346. package/src/setup/scenes/types.ts +1 -0
  347. package/src/space-hold.d.ts +40 -25
  348. package/src/space-hold.ts +156 -52
  349. package/src/status-line/component.ts +292 -78
  350. package/src/status-line/context-usage.ts +21 -46
  351. package/src/status-line/host.ts +4 -1
  352. package/src/status-line/segments.ts +40 -22
  353. package/src/status-line/types.ts +15 -3
  354. package/src/terminal-capabilities.d.ts +41 -36
  355. package/src/terminal-capabilities.ts +137 -213
  356. package/src/terminal-multiplexer.d.ts +127 -14
  357. package/src/terminal-multiplexer.ts +112 -33
  358. package/src/terminal.d.ts +23 -16
  359. package/src/terminal.ts +203 -99
  360. package/src/theme/active-symbols.d.ts +1 -1
  361. package/src/theme/active-symbols.ts +1 -1
  362. package/src/theme/schema-validation.ts +1 -0
  363. package/src/theme/schema.d.ts +11 -2
  364. package/src/theme/schema.ts +14 -1
  365. package/src/theme/session-color.ts +1 -7
  366. package/src/theme/symbols.d.ts +1 -1
  367. package/src/theme/symbols.ts +11 -4
  368. package/src/theme/theme-class.d.ts +7 -0
  369. package/src/theme/theme-class.ts +26 -1
  370. package/src/theme/theme-schema.json +5 -1
  371. package/src/theme/theme.d.ts +1 -1
  372. package/src/theme/theme.ts +8 -4
  373. package/src/theme/tui-adapters.d.ts +3 -0
  374. package/src/theme/tui-adapters.ts +68 -0
  375. package/src/thinking.d.ts +1 -1
  376. package/src/thinking.ts +1 -1
  377. package/src/tmux.d.ts +11 -4
  378. package/src/tmux.ts +47 -11
  379. package/src/tools/ast-edit.ts +59 -35
  380. package/src/tools/ast-grep.ts +35 -16
  381. package/src/tools/bash.d.ts +7 -2
  382. package/src/tools/bash.ts +116 -47
  383. package/src/tools/daemon.d.ts +1 -1
  384. package/src/tools/daemon.ts +1 -1
  385. package/src/tools/default-renderer.ts +35 -19
  386. package/src/tools/edit.ts +142 -120
  387. package/src/tools/eval-format/index.ts +28 -2
  388. package/src/tools/eval-format/javascript.ts +7 -5
  389. package/src/tools/eval.d.ts +22 -3
  390. package/src/tools/eval.ts +364 -208
  391. package/src/tools/fetch.ts +5 -6
  392. package/src/tools/glob.d.ts +4 -0
  393. package/src/tools/glob.ts +33 -65
  394. package/src/tools/grep.ts +81 -48
  395. package/src/tools/index.ts +2 -0
  396. package/src/tools/lsp.ts +81 -59
  397. package/src/tools/mcp.ts +111 -68
  398. package/src/tools/native-view.d.ts +47 -0
  399. package/src/tools/native-view.ts +102 -1
  400. package/src/tools/output-meta.d.ts +11 -1
  401. package/src/tools/output-meta.ts +23 -3
  402. package/src/tools/read.ts +7 -5
  403. package/src/tools/renderer.d.ts +37 -2
  404. package/src/tools/renderer.ts +42 -2
  405. package/src/tools/streaming-output.d.ts +20 -1
  406. package/src/tools/streaming-output.ts +154 -50
  407. package/src/tools/task.d.ts +2 -3
  408. package/src/tools/task.ts +115 -62
  409. package/src/tools/todo.ts +119 -30
  410. package/src/tools/wait.ts +34 -24
  411. package/src/tools/web-search.ts +1 -1
  412. package/src/tools/write.d.ts +9 -2
  413. package/src/tools/write.ts +147 -95
  414. package/src/tools/yield.d.ts +22 -0
  415. package/src/tools/yield.ts +225 -0
  416. package/src/tui.d.ts +36 -0
  417. package/src/tui.ts +666 -217
  418. package/src/utils.d.ts +6 -0
  419. package/src/utils.ts +19 -0
  420. package/src/vim.d.ts +19 -5
  421. package/src/vim.ts +333 -18
  422. package/src/windows-input-mode.d.ts +33 -1
  423. package/src/windows-input-mode.ts +212 -6
@@ -31,6 +31,15 @@ export interface OutputSummary {
31
31
  columnDroppedBytes?: number;
32
32
  /** Number of distinct lines that hit the per-line column cap. */
33
33
  columnTruncatedLines?: number;
34
+ /**
35
+ * 1-indexed first and last lines the column cap cut, numbered as in the
36
+ * artifact. Absent when the numbering cannot match the artifact (an inline
37
+ * substitute was capped, or `replace()` rewrote the buffer).
38
+ */
39
+ columnTruncatedRange?: {
40
+ first: number;
41
+ last: number;
42
+ };
34
43
  /** Configured per-line column cap in effect (UTF-8 bytes), when > 0. */
35
44
  columnMax?: number;
36
45
  /** Artifact ID for internal URL access (artifact://<id>) when truncated */
@@ -236,7 +245,8 @@ export declare class OutputSink {
236
245
  constructor(options?: OutputSinkOptions);
237
246
  /**
238
247
  * Push a chunk of output. The buffer management and onChunk callback run
239
- * synchronously. File sink writes are deferred and serialized internally.
248
+ * synchronously; onChunk fires after the chunk is stored, so {@link preview}
249
+ * already includes it. File sink writes are deferred and serialized internally.
240
250
  *
241
251
  * `inline` substitutes a bounded representation for the in-memory buffer and
242
252
  * live preview while the complete chunk is mirrored to the artifact.
@@ -260,6 +270,15 @@ export declare class OutputSink {
260
270
  * branch in `dump()` against stale totals.
261
271
  */
262
272
  replace(text: string): void;
273
+ /**
274
+ * Current inline view without finalizing: the body {@link dump} would
275
+ * return right now (head + elision marker + rolling tail), minus any notice
276
+ * and minus the newline `dump()` appends after output that ends in a bare
277
+ * carriage return. Each call trims the rolling tail to its budget (a copy
278
+ * of the tail window once it overflowed), so call it from a throttled
279
+ * onChunk (`chunkThrottleMs`), not once per raw chunk.
280
+ */
281
+ preview(): string;
263
282
  dump(notice?: string): Promise<OutputSummary>;
264
283
  /**
265
284
  * Release the artifact spill descriptor on an exit path that skips
@@ -1,3 +1,4 @@
1
+ import * as fs from "node:fs";
1
2
  import type { AgentToolUpdateCallback } from "@linxiraos/pi-agent-core";
2
3
  import { formatBytes, materializeString, sanitizeText } from "@linxiraos/pi-utils";
3
4
  import { sanitizeWithOptionalSixelPassthrough } from "../render/sixel";
@@ -51,6 +52,12 @@ export interface OutputSummary {
51
52
  columnDroppedBytes?: number;
52
53
  /** Number of distinct lines that hit the per-line column cap. */
53
54
  columnTruncatedLines?: number;
55
+ /**
56
+ * 1-indexed first and last lines the column cap cut, numbered as in the
57
+ * artifact. Absent when the numbering cannot match the artifact (an inline
58
+ * substitute was capped, or `replace()` rewrote the buffer).
59
+ */
60
+ columnTruncatedRange?: { first: number; last: number };
54
61
  /** Configured per-line column cap in effect (UTF-8 bytes), when > 0. */
55
62
  columnMax?: number;
56
63
  /** Artifact ID for internal URL access (artifact://<id>) when truncated */
@@ -232,6 +239,10 @@ function truncateBytesWindowed(
232
239
  ? data.substring(0, Math.min(data.length, maxBytes))
233
240
  : data.substring(Math.max(0, data.length - maxBytes));
234
241
 
242
+ // All-ASCII window: one byte per char, so it is exactly `maxBytes` bytes on a boundary.
243
+ const windowBytes = Buffer.byteLength(window, "utf-8");
244
+ if (windowBytes === window.length) return { text: window, bytes: windowBytes };
245
+
235
246
  const buf = Buffer.from(window, "utf-8");
236
247
 
237
248
  if (mode === "head") {
@@ -875,6 +886,8 @@ export class TailBuffer {
875
886
  export class OutputSink {
876
887
  #buffer = "";
877
888
  #bufferBytes = 0;
889
+ /** The overflowed tail window may exceed its budget until {@link #trimTail} runs. */
890
+ #tailUntrimmed = false;
878
891
  #head = "";
879
892
  #headBytes = 0;
880
893
  #headLines = 0; // newline count inside #head
@@ -894,6 +907,10 @@ export class OutputSink {
894
907
  #columnEllipsisAdded = false;
895
908
  #columnDroppedBytes = 0;
896
909
  #columnTruncatedLines = 0;
910
+ #columnFirstCutLine = 0;
911
+ #columnLastCutLine = 0;
912
+ /** Set once a cut line's number may not match the artifact; the range is then withheld. */
913
+ #columnCutLinesUnmapped = false;
897
914
  #file?: {
898
915
  path: string;
899
916
  artifactId?: string;
@@ -1001,7 +1018,8 @@ export class OutputSink {
1001
1018
 
1002
1019
  /**
1003
1020
  * Push a chunk of output. The buffer management and onChunk callback run
1004
- * synchronously. File sink writes are deferred and serialized internally.
1021
+ * synchronously; onChunk fires after the chunk is stored, so {@link preview}
1022
+ * already includes it. File sink writes are deferred and serialized internally.
1005
1023
  *
1006
1024
  * `inline` substitutes a bounded representation for the in-memory buffer and
1007
1025
  * live preview while the complete chunk is mirrored to the artifact.
@@ -1014,6 +1032,8 @@ export class OutputSink {
1014
1032
  const substituted = inline !== undefined;
1015
1033
  const inlineChunk = inline === undefined ? chunk : sanitizeText(inline);
1016
1034
 
1035
+ this.#store(chunk, inlineChunk, substituted);
1036
+
1017
1037
  // Throttled onChunk: coalesce chunks arriving inside the throttle window.
1018
1038
  // A timer flushes quiet tails at the throttle boundary; dump() catches a
1019
1039
  // final pending chunk when the process exits before that timer fires.
@@ -1028,9 +1048,15 @@ export class OutputSink {
1028
1048
  this.#schedulePendingChunkFlush();
1029
1049
  }
1030
1050
  }
1051
+ }
1031
1052
 
1053
+ /** Count, cap, mirror, and retain one sanitized chunk. */
1054
+ #store(chunk: string, inlineChunk: string, substituted: boolean): void {
1032
1055
  const rawBytes = Buffer.byteLength(chunk, "utf-8");
1033
1056
  this.#totalBytes += rawBytes;
1057
+ // Line the chunk starts on, as numbered in the artifact; 0 when the capped
1058
+ // inline text is a substitute whose lines do not map onto the artifact.
1059
+ const firstLine = substituted ? 0 : this.#totalLines + 1;
1034
1060
 
1035
1061
  if (chunk.length > 0) {
1036
1062
  this.#sawData = true;
@@ -1041,7 +1067,7 @@ export class OutputSink {
1041
1067
  // Per-line column cap. State persists across chunks so a mid-line split
1042
1068
  // still respects the budget. Operates on the inline chunk; the complete
1043
1069
  // chunk is mirrored to the artifact before any cap is applied.
1044
- const capped = this.#maxColumns > 0 ? this.#applyColumnCap(inlineChunk) : inlineChunk;
1070
+ const capped = this.#maxColumns > 0 ? this.#applyColumnCap(inlineChunk, firstLine) : inlineChunk;
1045
1071
  const cappedBytes = capped === inlineChunk ? inlineBytes : Buffer.byteLength(capped, "utf-8");
1046
1072
  const cappedThisChunk = cappedBytes < inlineBytes;
1047
1073
  if (substituted) this.#truncated = true;
@@ -1089,11 +1115,13 @@ export class OutputSink {
1089
1115
  * cap; subsequent bytes are skipped until the next `\n`. State persists
1090
1116
  * across calls so a long line split across chunks still produces one marker.
1091
1117
  */
1092
- #applyColumnCap(chunk: string): string {
1118
+ #applyColumnCap(chunk: string, firstLine: number): string {
1093
1119
  if (chunk.length === 0) return chunk;
1120
+ if (!this.#columnEllipsisAdded && this.#fitsColumnCap(chunk)) return chunk;
1094
1121
  const max = this.#maxColumns;
1095
1122
  const parts: string[] = [];
1096
1123
  let cursor = 0;
1124
+ let line = firstLine;
1097
1125
  while (cursor < chunk.length) {
1098
1126
  const nlIdx = chunk.indexOf(NL, cursor);
1099
1127
  const segEnd = nlIdx === -1 ? chunk.length : nlIdx;
@@ -1124,6 +1152,12 @@ export class OutputSink {
1124
1152
  parts.push(ELLIPSIS);
1125
1153
  this.#columnDroppedBytes += segBytes - keptBytes;
1126
1154
  this.#columnTruncatedLines++;
1155
+ if (line > 0) {
1156
+ if (this.#columnFirstCutLine === 0) this.#columnFirstCutLine = line;
1157
+ this.#columnLastCutLine = line;
1158
+ } else {
1159
+ this.#columnCutLinesUnmapped = true;
1160
+ }
1127
1161
  this.#currentLineBytes += keptBytes + ellipsisBytes;
1128
1162
  this.#columnEllipsisAdded = true;
1129
1163
  }
@@ -1134,10 +1168,37 @@ export class OutputSink {
1134
1168
  this.#currentLineBytes = 0;
1135
1169
  this.#columnEllipsisAdded = false;
1136
1170
  cursor = nlIdx + 1;
1171
+ if (line > 0) line++;
1137
1172
  }
1138
1173
  return parts.join("");
1139
1174
  }
1140
1175
 
1176
+ /**
1177
+ * Fast path for {@link #applyColumnCap}: when every line segment fits the
1178
+ * remaining cap even at the 3-bytes-per-code-unit UTF-8 worst case, the
1179
+ * chunk passes through unchanged and only the trailing line width is
1180
+ * measured. Returns false (state untouched) when any line might trip the cap.
1181
+ */
1182
+ #fitsColumnCap(chunk: string): boolean {
1183
+ const max = this.#maxColumns;
1184
+ let room = max - this.#currentLineBytes;
1185
+ let cursor = 0;
1186
+ for (;;) {
1187
+ const nlIdx = chunk.indexOf(NL, cursor);
1188
+ const segEnd = nlIdx === -1 ? chunk.length : nlIdx;
1189
+ if ((segEnd - cursor) * 3 > room) return false;
1190
+ if (nlIdx === -1) break;
1191
+ cursor = nlIdx + 1;
1192
+ room = max;
1193
+ }
1194
+ if (cursor === 0) {
1195
+ this.#currentLineBytes += Buffer.byteLength(chunk, "utf-8");
1196
+ } else {
1197
+ this.#currentLineBytes = cursor === chunk.length ? 0 : Buffer.byteLength(chunk.substring(cursor), "utf-8");
1198
+ }
1199
+ return true;
1200
+ }
1201
+
1141
1202
  // The rolling tail budget is whatever the head window has not consumed of
1142
1203
  // the inline budget: `spillThreshold - #headBytes`. While the head window
1143
1204
  // fills it shrinks toward `spillThreshold - headLimit`; after `replace()`
@@ -1171,15 +1232,27 @@ export class OutputSink {
1171
1232
  const { text, bytes } = truncateTailBytes(chunk, threshold);
1172
1233
  this.#buffer = text;
1173
1234
  this.#bufferBytes = bytes;
1174
- } else {
1175
- // Intermediate size is bounded (<= threshold + dataBytes), safe to concat.
1176
- this.#buffer += chunk;
1177
- this.#bufferBytes += dataBytes;
1178
-
1179
- const { text, bytes } = truncateTailBytes(this.#buffer, threshold);
1180
- this.#buffer = text;
1181
- this.#bufferBytes = bytes;
1235
+ this.#tailUntrimmed = false;
1236
+ return;
1182
1237
  }
1238
+ // Amortize the trim: let the window grow to 2× the budget before cutting it
1239
+ // back, so steady-state chunks cost an append instead of a window copy.
1240
+ // `#trimTail()` restores the exact budget before the buffer is read.
1241
+ this.#buffer += chunk;
1242
+ this.#bufferBytes += dataBytes;
1243
+ this.#tailUntrimmed = true;
1244
+ if (this.#bufferBytes > threshold * 2) this.#trimTail();
1245
+ }
1246
+
1247
+ /** Cut an overflowed tail window back to the current tail budget. */
1248
+ #trimTail(): void {
1249
+ if (!this.#tailUntrimmed) return;
1250
+ this.#tailUntrimmed = false;
1251
+ const threshold = Math.max(0, this.#spillThreshold - this.#headBytes);
1252
+ if (this.#bufferBytes <= threshold) return;
1253
+ const { text, bytes } = truncateTailBytes(this.#buffer, threshold);
1254
+ this.#buffer = text;
1255
+ this.#bufferBytes = bytes;
1183
1256
  }
1184
1257
 
1185
1258
  /**
@@ -1309,6 +1382,10 @@ export class OutputSink {
1309
1382
  async #createFileSink(): Promise<void> {
1310
1383
  if (!this.#artifactPath || this.#fileReady || this.#artifactError) return;
1311
1384
  try {
1385
+ // Bun's Windows FileSink defers the open: an unopenable target (e.g. a
1386
+ // directory) only fails on the first write, misreported as a write
1387
+ // failure. Probe the open eagerly so it stays classified — and terminal.
1388
+ if (process.platform === "win32") fs.closeSync(fs.openSync(this.#artifactPath, "w"));
1312
1389
  const sink = Bun.file(this.#artifactPath).writer();
1313
1390
  this.#file = { path: this.#artifactPath, artifactId: this.#artifactId, sink };
1314
1391
  this.#fileReady = true;
@@ -1367,6 +1444,7 @@ export class OutputSink {
1367
1444
  this.#clearPendingChunkTimer();
1368
1445
  this.#buffer = text;
1369
1446
  this.#bufferBytes = Buffer.byteLength(text, "utf-8");
1447
+ this.#tailUntrimmed = false;
1370
1448
  this.#head = "";
1371
1449
  this.#headBytes = 0;
1372
1450
  this.#headLines = 0;
@@ -1379,6 +1457,8 @@ export class OutputSink {
1379
1457
  this.#columnEllipsisAdded = false;
1380
1458
  this.#columnDroppedBytes = 0;
1381
1459
  this.#columnTruncatedLines = 0;
1460
+ // The artifact keeps the replaced stream, so later line numbers no longer match it.
1461
+ this.#columnCutLinesUnmapped = true;
1382
1462
  this.#pendingChunk = "";
1383
1463
  this.#pendingCarriageReturn = false;
1384
1464
  }
@@ -1453,22 +1533,31 @@ export class OutputSink {
1453
1533
  }
1454
1534
  }
1455
1535
 
1456
- async dump(notice?: string): Promise<OutputSummary> {
1457
- if (this.#pendingCarriageReturn) {
1458
- this.#pendingCarriageReturn = false;
1459
- this.push(NL);
1460
- }
1461
- const noticeLine = notice ? `[${notice}]\n` : "";
1536
+ /**
1537
+ * Current inline view without finalizing: the body {@link dump} would
1538
+ * return right now (head + elision marker + rolling tail), minus any notice
1539
+ * and minus the newline `dump()` appends after output that ends in a bare
1540
+ * carriage return. Each call trims the rolling tail to its budget (a copy
1541
+ * of the tail window once it overflowed), so call it from a throttled
1542
+ * onChunk (`chunkThrottleMs`), not once per raw chunk.
1543
+ */
1544
+ preview(): string {
1545
+ return this.#composeBody().body;
1546
+ }
1462
1547
 
1463
- // Flush any chunk still held back by the throttle so the live preview
1464
- // ends with the complete stream.
1465
- this.#flushPendingChunk();
1548
+ /**
1549
+ * Compose the visible output. With head retention, splice head + marker +
1550
+ * tail when content was elided. Otherwise return the rolling buffer.
1551
+ */
1552
+ #composeBody(): {
1553
+ body: string;
1554
+ outputBytes: number;
1555
+ outputLines: number;
1556
+ elidedBytes?: number;
1557
+ elidedLines?: number;
1558
+ } {
1559
+ this.#trimTail();
1466
1560
  const totalLines = this.#sawData ? this.#totalLines + 1 : 0;
1467
-
1468
- await this.#finalizeFile();
1469
-
1470
- // Compose the visible output. With head retention, splice head + marker
1471
- // + tail when content was elided. Otherwise return the rolling buffer.
1472
1561
  const headBytes = this.#headBytes;
1473
1562
  const tailBuf = this.#buffer;
1474
1563
  const tailBytes = this.#bufferBytes;
@@ -1479,39 +1568,50 @@ export class OutputSink {
1479
1568
  // so column-dropped bytes don't inflate the "elided from middle" count.
1480
1569
  const effectiveTotalBytes = Math.max(0, this.#totalBytes - this.#columnDroppedBytes);
1481
1570
 
1482
- let body: string;
1483
- let outputBytes: number;
1484
- let outputLines: number;
1485
- let elidedBytes: number | undefined;
1486
- let elidedLines: number | undefined;
1487
-
1488
1571
  if (headBytes > 0 && effectiveTotalBytes > headBytes + tailBytes) {
1489
1572
  // Middle was elided. Emit head + marker + tail.
1490
- elidedBytes = Math.max(0, effectiveTotalBytes - headBytes - tailBytes);
1491
- elidedLines = Math.max(0, totalLines - headLines - tailLines);
1573
+ const elidedBytes = Math.max(0, effectiveTotalBytes - headBytes - tailBytes);
1574
+ const elidedLines = Math.max(0, totalLines - headLines - tailLines);
1492
1575
  const marker = formatMiddleElisionMarker(elidedLines, elidedBytes);
1493
1576
  const markerBytes = Buffer.byteLength(marker, "utf-8");
1494
1577
  const headSep = this.#head.endsWith("\n") ? "" : "\n";
1495
1578
  const tailSep = tailBuf.startsWith("\n") ? "" : "\n";
1496
- body = `${this.#head}${headSep}${marker}${tailSep}${tailBuf}`;
1497
- outputBytes =
1498
- headBytes +
1499
- markerBytes +
1500
- tailBytes +
1501
- Buffer.byteLength(headSep, "utf-8") +
1502
- Buffer.byteLength(tailSep, "utf-8");
1503
- outputLines = headLines + 1 + tailLines;
1504
- this.#truncated = true;
1505
- } else if (headBytes > 0) {
1579
+ return {
1580
+ body: `${this.#head}${headSep}${marker}${tailSep}${tailBuf}`,
1581
+ outputBytes: headBytes + markerBytes + tailBytes + headSep.length + tailSep.length,
1582
+ outputLines: headLines + 1 + tailLines,
1583
+ elidedBytes,
1584
+ elidedLines,
1585
+ };
1586
+ }
1587
+ if (headBytes > 0) {
1506
1588
  // Head + tail combine into the full buffered output (no overlap or elision).
1507
- body = `${this.#head}${tailBuf}`;
1508
- outputBytes = headBytes + tailBytes;
1509
- outputLines = body.length > 0 ? countNewlines(body) + 1 : 0;
1510
- } else {
1511
- body = tailBuf;
1512
- outputBytes = tailBytes;
1513
- outputLines = tailLines;
1589
+ const body = `${this.#head}${tailBuf}`;
1590
+ return {
1591
+ body,
1592
+ outputBytes: headBytes + tailBytes,
1593
+ outputLines: body.length > 0 ? countNewlines(body) + 1 : 0,
1594
+ };
1514
1595
  }
1596
+ return { body: tailBuf, outputBytes: tailBytes, outputLines: tailLines };
1597
+ }
1598
+
1599
+ async dump(notice?: string): Promise<OutputSummary> {
1600
+ if (this.#pendingCarriageReturn) {
1601
+ this.#pendingCarriageReturn = false;
1602
+ this.push(NL);
1603
+ }
1604
+ const noticeLine = notice ? `[${notice}]\n` : "";
1605
+
1606
+ // Flush any chunk still held back by the throttle so the live preview
1607
+ // ends with the complete stream.
1608
+ this.#flushPendingChunk();
1609
+ const totalLines = this.#sawData ? this.#totalLines + 1 : 0;
1610
+
1611
+ await this.#finalizeFile();
1612
+
1613
+ const { body, outputBytes, outputLines, elidedBytes, elidedLines } = this.#composeBody();
1614
+ if (elidedBytes !== undefined) this.#truncated = true;
1515
1615
 
1516
1616
  return {
1517
1617
  output: `${noticeLine}${body}`,
@@ -1525,6 +1625,10 @@ export class OutputSink {
1525
1625
  columnDroppedBytes: this.#columnDroppedBytes > 0 ? this.#columnDroppedBytes : undefined,
1526
1626
  columnTruncatedLines: this.#columnTruncatedLines > 0 ? this.#columnTruncatedLines : undefined,
1527
1627
  columnMax: this.#columnTruncatedLines > 0 ? this.#maxColumns : undefined,
1628
+ columnTruncatedRange:
1629
+ this.#columnFirstCutLine > 0 && !this.#columnCutLinesUnmapped
1630
+ ? { first: this.#columnFirstCutLine, last: this.#columnLastCutLine }
1631
+ : undefined,
1528
1632
  artifactId: this.#artifactError ? undefined : this.#file?.artifactId,
1529
1633
  artifactElidedBytes:
1530
1634
  this.#artifactError || !this.#file?.artifactId || this.#artifactElidedBytes === 0
@@ -1,10 +1,9 @@
1
1
  import type { Usage } from "@linxiraos/pi-ai";
2
2
  import type { ThemeColor } from "../theme/theme";
3
3
  import type { ConfiguredThinkingLevel } from "../render/render-utils";
4
+ import type { RenderResultOptions, NativeToolView, ToolRenderResult } from "./renderer";
4
5
  import { type Component } from "../tui";
5
- import type { RenderResultOptions } from "./renderer";
6
6
  import { type Theme } from "../theme/theme";
7
- import type { NativeToolView, ToolRenderResult } from "./renderer";
8
7
  /** Render context threaded in from `ToolExecutionComponent.#buildRenderContext`. */
9
8
  interface TaskRenderContext {
10
9
  hasResult?: boolean;
@@ -255,7 +254,7 @@ export interface AgentProgress {
255
254
  resolvedModelRoute?: string;
256
255
  /** True when a live advisor was attached to this run's session, not merely enabled in settings. */
257
256
  advisor?: boolean;
258
- /** The agent's latest self-estimate of task completion (0–100), from the periodic `task.completionProbeMs` side request. */
257
+ /** The agent's latest self-estimate of task completion (0–100), from the periodic `task.completionProbe` side request. */
259
258
  completionPercent?: number;
260
259
  /** Data extracted by registered subprocess tool handlers (keyed by tool name) */
261
260
  extractedToolData?: Record<string, unknown[]>;