@bubblebrain-ai/bubble 0.0.52 → 0.0.53

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 (481) hide show
  1. package/README.md +4 -12
  2. package/dist/agent/routing-catalog.js +3 -2
  3. package/dist/agent/subagent/router.js +5 -0
  4. package/dist/agent/subagent/runtime.d.ts +1 -0
  5. package/dist/agent/subagent/runtime.js +13 -1
  6. package/dist/agent/subagent-control.d.ts +4 -0
  7. package/dist/agent/subagent-control.js +1 -0
  8. package/dist/agent/subagent-store.js +2 -0
  9. package/dist/agent/workflow/control.d.ts +2 -0
  10. package/dist/agent/workflow/runs.d.ts +1 -0
  11. package/dist/agent/workflow/runs.js +3 -0
  12. package/dist/agent.d.ts +11 -1
  13. package/dist/agent.js +158 -57
  14. package/dist/bin.js +2 -44
  15. package/dist/config.d.ts +14 -1
  16. package/dist/config.js +45 -4
  17. package/dist/context/budget.d.ts +7 -1
  18. package/dist/context/budget.js +25 -2
  19. package/dist/context/compact-llm.d.ts +1 -1
  20. package/dist/context/compact-llm.js +5 -2
  21. package/dist/context/overflow.js +2 -0
  22. package/dist/context/projector.d.ts +8 -0
  23. package/dist/context/projector.js +55 -6
  24. package/dist/context/tool-output-truncate.d.ts +17 -1
  25. package/dist/context/tool-output-truncate.js +171 -49
  26. package/dist/feishu/agent-host/run-driver.js +3 -0
  27. package/dist/feishu/serve.js +2 -0
  28. package/dist/goal/command.d.ts +1 -1
  29. package/dist/goal/command.js +7 -2
  30. package/dist/main.d.ts +1 -1
  31. package/dist/main.js +38 -8
  32. package/dist/memory/db.js +0 -7
  33. package/dist/model-catalog.js +25 -6
  34. package/dist/model-config.js +3 -2
  35. package/dist/model-pricing.d.ts +24 -5
  36. package/dist/model-pricing.js +0 -0
  37. package/dist/model-selection.js +13 -4
  38. package/dist/network/chatgpt-transport.js +0 -34
  39. package/dist/network/errors.d.ts +19 -0
  40. package/dist/network/errors.js +24 -0
  41. package/dist/network/provider-transport.d.ts +0 -4
  42. package/dist/network/provider-transport.js +3 -35
  43. package/dist/network/retry.d.ts +6 -1
  44. package/dist/network/retry.js +9 -0
  45. package/dist/provider-model-policy.d.ts +16 -0
  46. package/dist/provider-model-policy.js +33 -0
  47. package/dist/provider-registry.d.ts +1 -1
  48. package/dist/provider-registry.js +73 -10
  49. package/dist/provider-transform.js +32 -4
  50. package/dist/provider.d.ts +6 -2
  51. package/dist/provider.js +95 -6
  52. package/dist/question/controller.js +5 -4
  53. package/dist/question/normalize.d.ts +6 -0
  54. package/dist/question/normalize.js +11 -0
  55. package/dist/rewind.d.ts +20 -0
  56. package/dist/rewind.js +29 -0
  57. package/dist/sdk/index.d.ts +1 -1
  58. package/dist/sdk/index.js +11 -3
  59. package/dist/session.d.ts +7 -0
  60. package/dist/session.js +20 -0
  61. package/dist/skills/discovery.js +18 -0
  62. package/dist/skills/registry.d.ts +12 -2
  63. package/dist/skills/registry.js +40 -5
  64. package/dist/skills/types.d.ts +2 -0
  65. package/dist/slash-commands/commands.js +120 -81
  66. package/dist/slash-commands/registry.d.ts +2 -1
  67. package/dist/slash-commands/registry.js +3 -0
  68. package/dist/slash-commands/types.d.ts +22 -4
  69. package/dist/stats/usage.d.ts +3 -1
  70. package/dist/stats/usage.js +22 -13
  71. package/dist/tasks/manager.d.ts +4 -2
  72. package/dist/tasks/manager.js +34 -9
  73. package/dist/tasks/promotion.d.ts +2 -2
  74. package/dist/tasks/promotion.js +2 -2
  75. package/dist/tools/agent-lifecycle.js +4 -0
  76. package/dist/tools/bash.d.ts +3 -1
  77. package/dist/tools/bash.js +13 -2
  78. package/dist/tools/grep.d.ts +5 -1
  79. package/dist/tools/grep.js +318 -69
  80. package/dist/tools/index.d.ts +3 -1
  81. package/dist/tools/index.js +1 -0
  82. package/dist/tools/question.js +5 -4
  83. package/dist/tools/read.js +40 -21
  84. package/dist/tui/animation-clock.d.ts +14 -0
  85. package/dist/tui/animation-clock.js +34 -0
  86. package/dist/tui/app.d.ts +176 -0
  87. package/dist/tui/app.js +1647 -0
  88. package/dist/tui/components/approval-dialog.d.ts +43 -0
  89. package/dist/tui/components/approval-dialog.js +247 -0
  90. package/dist/tui/components/bottom-sheet.d.ts +9 -0
  91. package/dist/tui/components/bottom-sheet.js +32 -0
  92. package/dist/tui/components/context-info.d.ts +54 -0
  93. package/dist/tui/components/context-info.js +388 -0
  94. package/dist/tui/components/feedback-dialog.d.ts +56 -0
  95. package/dist/tui/components/feedback-dialog.js +262 -0
  96. package/dist/tui/components/feishu-setup-dialog.d.ts +65 -0
  97. package/dist/tui/components/feishu-setup-dialog.js +332 -0
  98. package/dist/tui/components/image-preview.d.ts +32 -0
  99. package/dist/tui/components/image-preview.js +130 -0
  100. package/dist/tui/components/plan-dialog.d.ts +34 -0
  101. package/dist/tui/components/plan-dialog.js +196 -0
  102. package/dist/tui/components/provider-key-input.d.ts +18 -0
  103. package/dist/tui/components/provider-key-input.js +49 -0
  104. package/dist/tui/components/question-dialog.d.ts +25 -0
  105. package/dist/tui/components/question-dialog.js +263 -0
  106. package/dist/tui/components/responsive-transcript.d.ts +31 -0
  107. package/dist/tui/components/responsive-transcript.js +77 -0
  108. package/dist/tui/components/rewind-picker.d.ts +62 -0
  109. package/dist/tui/components/rewind-picker.js +317 -0
  110. package/dist/tui/components/session-picker.d.ts +49 -0
  111. package/dist/tui/components/session-picker.js +303 -0
  112. package/dist/tui/components/skills-panel.d.ts +59 -0
  113. package/dist/tui/components/skills-panel.js +568 -0
  114. package/dist/tui/components/stats-panel.d.ts +40 -0
  115. package/dist/tui/components/stats-panel.js +301 -0
  116. package/dist/tui/components/streaming-message.d.ts +69 -0
  117. package/dist/tui/components/streaming-message.js +393 -0
  118. package/dist/tui/components/subagent-inspector.d.ts +28 -0
  119. package/dist/tui/components/subagent-inspector.js +127 -0
  120. package/dist/tui/components/task-inspector.d.ts +26 -0
  121. package/dist/tui/components/task-inspector.js +70 -0
  122. package/dist/tui/components/tasks-pane.d.ts +88 -0
  123. package/dist/tui/components/tasks-pane.js +416 -0
  124. package/dist/tui/components/transcript.d.ts +96 -0
  125. package/dist/tui/components/transcript.js +771 -0
  126. package/dist/tui/components/welcome.d.ts +20 -0
  127. package/dist/tui/components/welcome.js +133 -0
  128. package/dist/tui/components/workflow-inspector.d.ts +30 -0
  129. package/dist/tui/components/workflow-inspector.js +136 -0
  130. package/dist/tui/composer-autocomplete.d.ts +61 -0
  131. package/dist/tui/composer-autocomplete.js +383 -0
  132. package/dist/tui/composer-style.d.ts +7 -0
  133. package/dist/tui/composer-style.js +29 -0
  134. package/dist/tui/controller/agent-event-reducer.d.ts +75 -0
  135. package/dist/tui/controller/agent-event-reducer.js +238 -0
  136. package/dist/tui/controller/composer-controller.d.ts +95 -0
  137. package/dist/tui/controller/composer-controller.js +502 -0
  138. package/dist/tui/controller/controller.d.ts +194 -0
  139. package/dist/tui/controller/controller.js +1035 -0
  140. package/dist/tui/controller/effects.d.ts +71 -0
  141. package/dist/tui/controller/effects.js +1 -0
  142. package/dist/tui/controller/goal-runtime-controller.d.ts +47 -0
  143. package/dist/tui/controller/goal-runtime-controller.js +202 -0
  144. package/dist/tui/controller/input-queue-machine.d.ts +71 -0
  145. package/dist/tui/controller/input-queue-machine.js +121 -0
  146. package/dist/tui/controller/intents.d.ts +56 -0
  147. package/dist/tui/controller/intents.js +6 -0
  148. package/dist/tui/controller/overlay-controller.d.ts +64 -0
  149. package/dist/tui/controller/overlay-controller.js +129 -0
  150. package/dist/tui/controller/ports.d.ts +57 -0
  151. package/dist/tui/controller/ports.js +9 -0
  152. package/dist/tui/controller/session-transition.d.ts +54 -0
  153. package/dist/tui/controller/session-transition.js +68 -0
  154. package/dist/tui/controller/state.d.ts +14 -0
  155. package/dist/tui/controller/state.js +36 -0
  156. package/dist/tui/controller/task-runtime-controller.d.ts +66 -0
  157. package/dist/tui/controller/task-runtime-controller.js +158 -0
  158. package/dist/tui/footer.d.ts +37 -0
  159. package/dist/tui/footer.js +80 -0
  160. package/dist/{tui-ink → tui/formatting}/edit-diff.d.ts +1 -1
  161. package/dist/{tui-ink → tui/formatting}/edit-diff.js +1 -1
  162. package/dist/{tui-ink/app-helpers.d.ts → tui/formatting/summary.d.ts} +4 -4
  163. package/dist/{tui-ink/app-helpers.js → tui/formatting/summary.js} +2 -2
  164. package/dist/tui/fullscreen.d.ts +48 -0
  165. package/dist/tui/fullscreen.js +255 -0
  166. package/dist/tui/image-display.d.ts +4 -0
  167. package/dist/tui/image-display.js +30 -12
  168. package/dist/tui/markdown-style.d.ts +5 -0
  169. package/dist/tui/markdown-style.js +23 -0
  170. package/dist/{tui-ink → tui/model}/composer-buffer.js +1 -1
  171. package/dist/tui/model/composer-types.d.ts +17 -0
  172. package/dist/tui/model/composer-types.js +1 -0
  173. package/dist/{tui-ink → tui/model}/display-history.d.ts +7 -1
  174. package/dist/{tui-ink → tui/model}/display-reconstruct.d.ts +1 -1
  175. package/dist/{tui-ink → tui/model}/display-reconstruct.js +54 -6
  176. package/dist/{tui-ink → tui/model}/file-mentions.d.ts +2 -0
  177. package/dist/{tui-ink → tui/model}/file-mentions.js +4 -0
  178. package/dist/tui/model/image-attachment.d.ts +15 -0
  179. package/dist/tui/model/image-attachment.js +1 -0
  180. package/dist/{tui-ink → tui/model}/image-paste.d.ts +7 -1
  181. package/dist/{tui-ink → tui/model}/image-paste.js +46 -0
  182. package/dist/tui/model/input-history.d.ts +1 -0
  183. package/dist/tui/model/input-history.js +1 -0
  184. package/dist/{tui-ink → tui/model}/input-queue.d.ts +1 -1
  185. package/dist/{tui-ink → tui/model}/recent-activity.js +1 -1
  186. package/dist/{tui-ink → tui/model}/subagent-view.d.ts +17 -2
  187. package/dist/{tui-ink → tui/model}/subagent-view.js +125 -4
  188. package/dist/{tui-ink → tui/model}/submit-dedupe.d.ts +1 -1
  189. package/dist/tui/model/theme-style.d.ts +10 -0
  190. package/dist/tui/model/theme-style.js +79 -0
  191. package/dist/{tui-ink → tui/model}/theme.d.ts +11 -23
  192. package/dist/{tui-ink → tui/model}/theme.js +23 -38
  193. package/dist/{tui-ink → tui/model}/trace-groups.d.ts +2 -0
  194. package/dist/{tui-ink → tui/model}/trace-groups.js +91 -30
  195. package/dist/tui/model/trace-interaction.d.ts +63 -0
  196. package/dist/tui/model/trace-interaction.js +87 -0
  197. package/dist/tui/model-picker-data.d.ts +1 -2
  198. package/dist/tui/model-picker-data.js +8 -1
  199. package/dist/tui/model-switch.js +2 -0
  200. package/dist/{tui-ink → tui}/run-session-picker.d.ts +2 -3
  201. package/dist/tui/run-session-picker.js +64 -0
  202. package/dist/tui/run.d.ts +72 -0
  203. package/dist/tui/run.js +139 -0
  204. package/dist/tui/terminal/multiplexer.d.ts +5 -0
  205. package/dist/tui/terminal/multiplexer.js +14 -0
  206. package/dist/tui/testing/fake-agent.d.ts +24 -0
  207. package/dist/tui/testing/fake-agent.js +22 -0
  208. package/dist/tui/testing/spy-host.d.ts +21 -0
  209. package/dist/tui/testing/spy-host.js +55 -0
  210. package/dist/tui/trace-groups.js +27 -6
  211. package/dist/types.d.ts +7 -0
  212. package/node_modules/@bubblebrain-ai/pi-tui/LICENSE +21 -0
  213. package/node_modules/@bubblebrain-ai/pi-tui/README.md +854 -0
  214. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/alt-screen-search.d.ts +26 -0
  215. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/alt-screen-search.d.ts.map +1 -0
  216. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/alt-screen-search.js +121 -0
  217. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/alt-screen-search.js.map +1 -0
  218. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/autocomplete.d.ts +86 -0
  219. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/autocomplete.d.ts.map +1 -0
  220. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/autocomplete.js +649 -0
  221. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/autocomplete.js.map +1 -0
  222. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/alt-screen-flash.d.ts +13 -0
  223. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/alt-screen-flash.d.ts.map +1 -0
  224. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/alt-screen-flash.js +36 -0
  225. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/alt-screen-flash.js.map +1 -0
  226. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/box.d.ts +22 -0
  227. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/box.d.ts.map +1 -0
  228. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/box.js +99 -0
  229. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/box.js.map +1 -0
  230. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/cancellable-loader.d.ts +22 -0
  231. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/cancellable-loader.d.ts.map +1 -0
  232. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/cancellable-loader.js +36 -0
  233. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/cancellable-loader.js.map +1 -0
  234. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/editor.d.ts +330 -0
  235. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/editor.d.ts.map +1 -0
  236. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/editor.js +2344 -0
  237. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/editor.js.map +1 -0
  238. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/h-stack.d.ts +7 -0
  239. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/h-stack.d.ts.map +1 -0
  240. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/h-stack.js +43 -0
  241. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/h-stack.js.map +1 -0
  242. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/image.d.ts +28 -0
  243. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/image.d.ts.map +1 -0
  244. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/image.js +82 -0
  245. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/image.js.map +1 -0
  246. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/input.d.ts +48 -0
  247. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/input.d.ts.map +1 -0
  248. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/input.js +390 -0
  249. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/input.js.map +1 -0
  250. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/loader.d.ts +31 -0
  251. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/loader.d.ts.map +1 -0
  252. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/loader.js +67 -0
  253. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/loader.js.map +1 -0
  254. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/markdown.d.ts +103 -0
  255. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/markdown.d.ts.map +1 -0
  256. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/markdown.js +797 -0
  257. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/markdown.js.map +1 -0
  258. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/scroll-view.d.ts +56 -0
  259. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/scroll-view.d.ts.map +1 -0
  260. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/scroll-view.js +179 -0
  261. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/scroll-view.js.map +1 -0
  262. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/select-list.d.ts +53 -0
  263. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/select-list.d.ts.map +1 -0
  264. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/select-list.js +175 -0
  265. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/select-list.js.map +1 -0
  266. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/settings-list.d.ts +50 -0
  267. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/settings-list.d.ts.map +1 -0
  268. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/settings-list.js +174 -0
  269. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/settings-list.js.map +1 -0
  270. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/spacer.d.ts +12 -0
  271. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/spacer.d.ts.map +1 -0
  272. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/spacer.js +22 -0
  273. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/spacer.js.map +1 -0
  274. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/stack.d.ts +32 -0
  275. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/stack.d.ts.map +1 -0
  276. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/stack.js +109 -0
  277. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/stack.js.map +1 -0
  278. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/text.d.ts +19 -0
  279. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/text.d.ts.map +1 -0
  280. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/text.js +81 -0
  281. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/text.js.map +1 -0
  282. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/truncated-text.d.ts +13 -0
  283. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/truncated-text.d.ts.map +1 -0
  284. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/truncated-text.js +48 -0
  285. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/truncated-text.js.map +1 -0
  286. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/v-stack.d.ts +8 -0
  287. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/v-stack.d.ts.map +1 -0
  288. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/v-stack.js +26 -0
  289. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/v-stack.js.map +1 -0
  290. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/editor-component.d.ts +39 -0
  291. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/editor-component.d.ts.map +1 -0
  292. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/editor-component.js +2 -0
  293. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/editor-component.js.map +1 -0
  294. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/fuzzy.d.ts +16 -0
  295. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/fuzzy.d.ts.map +1 -0
  296. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/fuzzy.js +110 -0
  297. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/fuzzy.js.map +1 -0
  298. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/index.d.ts +31 -0
  299. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/index.d.ts.map +1 -0
  300. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/index.js +42 -0
  301. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/index.js.map +1 -0
  302. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/keybindings.d.ts +273 -0
  303. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/keybindings.d.ts.map +1 -0
  304. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/keybindings.js +231 -0
  305. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/keybindings.js.map +1 -0
  306. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/keys.d.ts +184 -0
  307. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/keys.d.ts.map +1 -0
  308. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/keys.js +1174 -0
  309. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/keys.js.map +1 -0
  310. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/kill-ring.d.ts +28 -0
  311. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/kill-ring.d.ts.map +1 -0
  312. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/kill-ring.js +46 -0
  313. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/kill-ring.js.map +1 -0
  314. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/latex.d.ts +10 -0
  315. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/latex.d.ts.map +1 -0
  316. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/latex.js +1268 -0
  317. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/latex.js.map +1 -0
  318. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/layout-node.d.ts +40 -0
  319. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/layout-node.d.ts.map +1 -0
  320. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/layout-node.js +6 -0
  321. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/layout-node.js.map +1 -0
  322. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/layout.d.ts +42 -0
  323. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/layout.d.ts.map +1 -0
  324. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/layout.js +335 -0
  325. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/layout.js.map +1 -0
  326. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/native-modifiers.d.ts +3 -0
  327. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/native-modifiers.d.ts.map +1 -0
  328. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/native-modifiers.js +60 -0
  329. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/native-modifiers.js.map +1 -0
  330. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/stdin-buffer.d.ts +56 -0
  331. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/stdin-buffer.d.ts.map +1 -0
  332. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/stdin-buffer.js +363 -0
  333. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/stdin-buffer.js.map +1 -0
  334. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/terminal-colors.d.ts +10 -0
  335. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/terminal-colors.d.ts.map +1 -0
  336. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/terminal-colors.js +59 -0
  337. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/terminal-colors.js.map +1 -0
  338. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/terminal-image.d.ts +116 -0
  339. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/terminal-image.d.ts.map +1 -0
  340. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/terminal-image.js +518 -0
  341. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/terminal-image.js.map +1 -0
  342. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/terminal.d.ts +142 -0
  343. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/terminal.d.ts.map +1 -0
  344. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/terminal.js +544 -0
  345. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/terminal.js.map +1 -0
  346. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/testing.d.ts +11 -0
  347. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/testing.d.ts.map +1 -0
  348. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/testing.js +11 -0
  349. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/testing.js.map +1 -0
  350. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/tui-alt-screen.d.ts +140 -0
  351. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/tui-alt-screen.d.ts.map +1 -0
  352. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/tui-alt-screen.js +1334 -0
  353. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/tui-alt-screen.js.map +1 -0
  354. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/tui-main-screen.d.ts +39 -0
  355. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/tui-main-screen.d.ts.map +1 -0
  356. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/tui-main-screen.js +536 -0
  357. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/tui-main-screen.js.map +1 -0
  358. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/tui.d.ts +338 -0
  359. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/tui.d.ts.map +1 -0
  360. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/tui.js +1016 -0
  361. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/tui.js.map +1 -0
  362. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/undo-stack.d.ts +17 -0
  363. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/undo-stack.d.ts.map +1 -0
  364. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/undo-stack.js +27 -0
  365. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/undo-stack.js.map +1 -0
  366. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/utils.d.ts +96 -0
  367. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/utils.d.ts.map +1 -0
  368. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/utils.js +1193 -0
  369. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/utils.js.map +1 -0
  370. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/word-navigation.d.ts +25 -0
  371. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/word-navigation.d.ts.map +1 -0
  372. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/word-navigation.js +96 -0
  373. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/word-navigation.js.map +1 -0
  374. package/node_modules/@bubblebrain-ai/pi-tui/dist/test/virtual-terminal.d.ts +73 -0
  375. package/node_modules/@bubblebrain-ai/pi-tui/dist/test/virtual-terminal.d.ts.map +1 -0
  376. package/node_modules/@bubblebrain-ai/pi-tui/dist/test/virtual-terminal.js +188 -0
  377. package/node_modules/@bubblebrain-ai/pi-tui/dist/test/virtual-terminal.js.map +1 -0
  378. package/node_modules/@bubblebrain-ai/pi-tui/native/darwin/README.md +20 -0
  379. package/node_modules/@bubblebrain-ai/pi-tui/native/darwin/build.sh +62 -0
  380. package/node_modules/@bubblebrain-ai/pi-tui/native/darwin/prebuilds/darwin-arm64/darwin-modifiers.node +0 -0
  381. package/node_modules/@bubblebrain-ai/pi-tui/native/darwin/prebuilds/darwin-x64/darwin-modifiers.node +0 -0
  382. package/node_modules/@bubblebrain-ai/pi-tui/native/darwin/src/darwin-modifiers.c +70 -0
  383. package/node_modules/@bubblebrain-ai/pi-tui/native/win32/README.md +22 -0
  384. package/node_modules/@bubblebrain-ai/pi-tui/native/win32/build.mjs +229 -0
  385. package/node_modules/@bubblebrain-ai/pi-tui/native/win32/prebuilds/win32-arm64/win32-console-mode.node +0 -0
  386. package/node_modules/@bubblebrain-ai/pi-tui/native/win32/prebuilds/win32-x64/win32-console-mode.node +0 -0
  387. package/node_modules/@bubblebrain-ai/pi-tui/native/win32/src/win32-console-mode.c +119 -0
  388. package/node_modules/@bubblebrain-ai/pi-tui/package.json +66 -0
  389. package/node_modules/get-east-asian-width/index.d.ts +60 -0
  390. package/node_modules/get-east-asian-width/index.js +30 -0
  391. package/node_modules/get-east-asian-width/license +9 -0
  392. package/node_modules/get-east-asian-width/lookup-data.js +21 -0
  393. package/node_modules/get-east-asian-width/lookup.js +138 -0
  394. package/node_modules/get-east-asian-width/package.json +71 -0
  395. package/node_modules/get-east-asian-width/readme.md +65 -0
  396. package/node_modules/get-east-asian-width/utilities.js +24 -0
  397. package/package.json +23 -10
  398. package/packages/pi-tui/node_modules/marked/LICENSE +44 -0
  399. package/packages/pi-tui/node_modules/marked/README.md +115 -0
  400. package/packages/pi-tui/node_modules/marked/bin/main.js +284 -0
  401. package/packages/pi-tui/node_modules/marked/bin/marked.js +16 -0
  402. package/packages/pi-tui/node_modules/marked/lib/marked.d.ts +760 -0
  403. package/packages/pi-tui/node_modules/marked/lib/marked.esm.js +77 -0
  404. package/packages/pi-tui/node_modules/marked/lib/marked.esm.js.map +7 -0
  405. package/packages/pi-tui/node_modules/marked/lib/marked.umd.js +79 -0
  406. package/packages/pi-tui/node_modules/marked/lib/marked.umd.js.map +7 -0
  407. package/packages/pi-tui/node_modules/marked/man/marked.1 +113 -0
  408. package/packages/pi-tui/node_modules/marked/man/marked.1.md +93 -0
  409. package/packages/pi-tui/node_modules/marked/package.json +103 -0
  410. package/dist/tui-ink/app.d.ts +0 -76
  411. package/dist/tui-ink/app.js +0 -2377
  412. package/dist/tui-ink/approval/approval-dialog.d.ts +0 -13
  413. package/dist/tui-ink/approval/approval-dialog.js +0 -184
  414. package/dist/tui-ink/approval/diff-view.d.ts +0 -7
  415. package/dist/tui-ink/approval/diff-view.js +0 -44
  416. package/dist/tui-ink/approval/select.d.ts +0 -35
  417. package/dist/tui-ink/approval/select.js +0 -98
  418. package/dist/tui-ink/code-highlight.d.ts +0 -8
  419. package/dist/tui-ink/code-highlight.js +0 -121
  420. package/dist/tui-ink/command-palette.d.ts +0 -32
  421. package/dist/tui-ink/command-palette.js +0 -158
  422. package/dist/tui-ink/compaction-progress.d.ts +0 -19
  423. package/dist/tui-ink/compaction-progress.js +0 -74
  424. package/dist/tui-ink/detect-theme.d.ts +0 -1
  425. package/dist/tui-ink/detect-theme.js +0 -1
  426. package/dist/tui-ink/feedback-dialog.d.ts +0 -19
  427. package/dist/tui-ink/feedback-dialog.js +0 -133
  428. package/dist/tui-ink/feishu-setup-picker.d.ts +0 -5
  429. package/dist/tui-ink/feishu-setup-picker.js +0 -271
  430. package/dist/tui-ink/footer.d.ts +0 -26
  431. package/dist/tui-ink/footer.js +0 -51
  432. package/dist/tui-ink/input-box.d.ts +0 -189
  433. package/dist/tui-ink/input-box.js +0 -1279
  434. package/dist/tui-ink/input-history.d.ts +0 -1
  435. package/dist/tui-ink/input-history.js +0 -1
  436. package/dist/tui-ink/markdown.d.ts +0 -103
  437. package/dist/tui-ink/markdown.js +0 -747
  438. package/dist/tui-ink/message-list.d.ts +0 -49
  439. package/dist/tui-ink/message-list.js +0 -841
  440. package/dist/tui-ink/model-picker.d.ts +0 -143
  441. package/dist/tui-ink/model-picker.js +0 -966
  442. package/dist/tui-ink/plan-confirm.d.ts +0 -7
  443. package/dist/tui-ink/plan-confirm.js +0 -115
  444. package/dist/tui-ink/question-dialog.d.ts +0 -8
  445. package/dist/tui-ink/question-dialog.js +0 -135
  446. package/dist/tui-ink/rewind-picker.d.ts +0 -8
  447. package/dist/tui-ink/rewind-picker.js +0 -102
  448. package/dist/tui-ink/run-session-picker.js +0 -22
  449. package/dist/tui-ink/run.d.ts +0 -62
  450. package/dist/tui-ink/run.js +0 -103
  451. package/dist/tui-ink/session-picker.d.ts +0 -10
  452. package/dist/tui-ink/session-picker.js +0 -113
  453. package/dist/tui-ink/stats-panel.d.ts +0 -11
  454. package/dist/tui-ink/stats-panel.js +0 -65
  455. package/dist/tui-ink/subagent-inspector.d.ts +0 -21
  456. package/dist/tui-ink/subagent-inspector.js +0 -205
  457. package/dist/tui-ink/use-terminal-size.d.ts +0 -4
  458. package/dist/tui-ink/use-terminal-size.js +0 -48
  459. package/dist/tui-ink/waiting-indicator.d.ts +0 -12
  460. package/dist/tui-ink/waiting-indicator.js +0 -129
  461. package/dist/tui-ink/welcome.d.ts +0 -25
  462. package/dist/tui-ink/welcome.js +0 -88
  463. package/dist/tui-ink/wordmark.d.ts +0 -8
  464. package/dist/tui-ink/wordmark.js +0 -103
  465. /package/dist/{tui-ink → tui/model}/composer-buffer.d.ts +0 -0
  466. /package/dist/{tui-ink → tui/model}/display-history.js +0 -0
  467. /package/dist/{tui-ink → tui/model}/input-queue.js +0 -0
  468. /package/dist/{tui-ink → tui/model}/key-events.d.ts +0 -0
  469. /package/dist/{tui-ink → tui/model}/key-events.js +0 -0
  470. /package/dist/{tui-ink → tui/model}/paste-operation-tracker.d.ts +0 -0
  471. /package/dist/{tui-ink → tui/model}/paste-operation-tracker.js +0 -0
  472. /package/dist/{tui-ink → tui/model}/recent-activity.d.ts +0 -0
  473. /package/dist/{tui-ink → tui/model}/submit-dedupe.js +0 -0
  474. /package/dist/{tui-ink → tui/model}/sync-output.d.ts +0 -0
  475. /package/dist/{tui-ink → tui/model}/sync-output.js +0 -0
  476. /package/dist/{tui-ink → tui/model}/terminal-env.d.ts +0 -0
  477. /package/dist/{tui-ink → tui/model}/terminal-env.js +0 -0
  478. /package/dist/{tui-ink → tui/model}/terminal-mouse.d.ts +0 -0
  479. /package/dist/{tui-ink → tui/model}/terminal-mouse.js +0 -0
  480. /package/dist/{tui-ink → tui/model}/width.d.ts +0 -0
  481. /package/dist/{tui-ink → tui/model}/width.js +0 -0
@@ -0,0 +1,393 @@
1
+ /**
2
+ * Streaming assistant message component.
3
+ *
4
+ * Rendering contract (verified against the vendored TuiMainScreen with
5
+ * VirtualTerminal): rebuilding component children every frame makes the
6
+ * renderer treat old rows as deleted and commits every intermediate frame
7
+ * to scrollback (the duplicated-prefix bug). A pool of PERSISTENT Text
8
+ * components updated via setText() is rewritten in place and never leaks —
9
+ * and Text("") renders zero rows, so empty pool slots vanish from the
10
+ * document naturally.
11
+ *
12
+ * Lifecycle: keep one instance as the transcript container's LAST child,
13
+ * update() per flush, and clearToNothing() in the same frame the controller
14
+ * commits the settled message. The scrollable row pool collapses to zero;
15
+ * the separate activityLane stays one row tall and merely clears its text.
16
+ */
17
+ import chalk from "chalk";
18
+ import { Spacer, Text, truncateToWidth, VStack, } from "@bubblebrain-ai/pi-tui";
19
+ import { themeDim, themeForeground } from "../model/theme-style.js";
20
+ import { projectAssistantRows, projectReasoningRows, joinTranscriptProjections, MINIMAL_REASONING_BODY_ROWS, projectToolTraceGroups, } from "./transcript.js";
21
+ const SPINNER_FRAMES = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
22
+ const GENERIC_PHRASES = [
23
+ "mapping the workspace",
24
+ "reading the room",
25
+ "following the threads",
26
+ "connecting the pieces",
27
+ "sorting the context",
28
+ "scanning the structure",
29
+ "shaping the next step",
30
+ "gathering signal",
31
+ "checking the edges",
32
+ "lining up the answer",
33
+ "tracing the flow",
34
+ "building the picture",
35
+ "walking the graph",
36
+ "collecting the clues",
37
+ "framing the problem",
38
+ "locating the source",
39
+ "resolving the shape",
40
+ "untangling the state",
41
+ "comparing the paths",
42
+ "narrowing the target",
43
+ "tracking the changes",
44
+ "reading the patterns",
45
+ "weighing the options",
46
+ "assembling the context",
47
+ "following the signal",
48
+ "checking the assumptions",
49
+ "aligning the details",
50
+ "testing the shape",
51
+ "pulling the thread",
52
+ "cleaning the edges",
53
+ "refining the draft",
54
+ "verifying the route",
55
+ "making sense of it",
56
+ "looking for leverage",
57
+ "stitching the answer",
58
+ "holding the thread",
59
+ "distilling the noise",
60
+ "finding the seam",
61
+ "reading between the lines",
62
+ "preparing the response",
63
+ ];
64
+ const TOOL_TARGET_PHRASES = {
65
+ read: "reading files",
66
+ write: "writing changes",
67
+ edit: "patching files",
68
+ grep: "searching the codebase",
69
+ glob: "scanning paths",
70
+ ls: "listing directories",
71
+ bash: "running command",
72
+ web_search: "searching the web",
73
+ web_fetch: "fetching a page",
74
+ task: "spawning subagent",
75
+ spawn_agent: "spawning subagent",
76
+ run_workflow: "running workflow",
77
+ wait_agent: "waiting for subagent",
78
+ wait_workflow: "waiting for workflow",
79
+ };
80
+ function approximateTokenLabel(chars) {
81
+ const tokens = Math.max(0, Math.round(chars / 4));
82
+ if (tokens < 1_000)
83
+ return `${tokens}`;
84
+ if (tokens < 10_000)
85
+ return `${(tokens / 1_000).toFixed(1)}k`;
86
+ return `${Math.round(tokens / 1_000)}k`;
87
+ }
88
+ /**
89
+ * A permanent one-row boundary between the scrolling transcript and composer.
90
+ * Running turns paint the spinner into this lane; idle turns leave it blank.
91
+ * The row never collapses, so completing a turn cannot change the document /
92
+ * composer geometry.
93
+ */
94
+ export class AgentActivityLaneComponent {
95
+ text = "";
96
+ setText(text) {
97
+ this.text = text;
98
+ }
99
+ render(width) {
100
+ return [truncateToWidth(this.text, Math.max(1, Math.floor(width)))];
101
+ }
102
+ invalidate() {
103
+ // No cache: the owner mutates `text` and requests the enclosing TUI render.
104
+ }
105
+ }
106
+ /**
107
+ * A pooled projected row needs three states: unused (zero rows), semantic
108
+ * blank (one empty row), and visible text. `Text` collapses both unused and
109
+ * whitespace-only values, so it cannot preserve that distinction.
110
+ */
111
+ class ProjectedRowComponent {
112
+ onActivate;
113
+ row = null;
114
+ target;
115
+ interaction;
116
+ constructor(onActivate) {
117
+ this.onActivate = onActivate;
118
+ }
119
+ setRow(row, target, interaction) {
120
+ this.row = row;
121
+ this.target = target;
122
+ this.interaction = interaction;
123
+ }
124
+ clear() {
125
+ this.row = null;
126
+ this.target = undefined;
127
+ this.interaction = undefined;
128
+ }
129
+ render(width) {
130
+ if (this.row === null)
131
+ return [];
132
+ if (this.row === "")
133
+ return [""];
134
+ return [truncateToWidth(this.row, Math.max(1, Math.floor(width)))];
135
+ }
136
+ invalidate() {
137
+ // No cache; rows are already projected to terminal lines.
138
+ }
139
+ handleMouse(event) {
140
+ if (!this.interaction)
141
+ return false;
142
+ if (event.kind === "leave") {
143
+ const changed = this.interaction.clearHover();
144
+ if (changed)
145
+ this.onActivate?.();
146
+ return changed;
147
+ }
148
+ if (event.kind === "move") {
149
+ const changed = this.interaction.hover(this.target);
150
+ if (changed)
151
+ this.onActivate?.();
152
+ return changed;
153
+ }
154
+ if (event.release || (event.button & 3) !== 0 || !this.target)
155
+ return false;
156
+ const action = this.interaction.activate(this.target, event.clickCount);
157
+ this.onActivate?.(action);
158
+ return true;
159
+ }
160
+ }
161
+ export class StreamingMessageComponent extends VStack {
162
+ onTraceAction;
163
+ getTheme;
164
+ tail = null;
165
+ commandActivity = null;
166
+ frame = 0;
167
+ spinnerActive = false;
168
+ idlePhraseElapsedMs = 0;
169
+ onFrame;
170
+ // Persistent row pool — NEVER re-created, only setText.
171
+ activityLane;
172
+ thinkingHeaderRow;
173
+ thinkingEllipsisRow;
174
+ reasoningGapRow;
175
+ timelineEllipsisRow;
176
+ liveGapRow;
177
+ reasoningRows;
178
+ timelineRows;
179
+ idlePhraseIndex = 0;
180
+ projectionOptions = {};
181
+ constructor(maxPreviewRows = 8, onFrame, onTraceAction, getTheme) {
182
+ super([]);
183
+ this.onTraceAction = onTraceAction;
184
+ this.getTheme = getTheme;
185
+ this.onFrame = onFrame;
186
+ this.activityLane = new AgentActivityLaneComponent();
187
+ this.thinkingHeaderRow = new Text("", 0, 0);
188
+ this.thinkingEllipsisRow = new Text("", 0, 0);
189
+ this.reasoningGapRow = new Spacer(0);
190
+ this.timelineEllipsisRow = new Text("", 0, 0);
191
+ this.liveGapRow = new Spacer(0);
192
+ this.reasoningRows = Array.from({ length: MINIMAL_REASONING_BODY_ROWS }, () => new Text("", 0, 0));
193
+ // One ordered pool mirrors Ink's DisplayMessagePart timeline. Reserve
194
+ // enough rows for a useful grouped tool trace plus an answer tail.
195
+ this.timelineRows = Array.from({ length: maxPreviewRows + 16 }, () => new ProjectedRowComponent((action) => {
196
+ if (action)
197
+ this.onTraceAction?.(action);
198
+ if (this.tail)
199
+ this.update(this.tail, this.lastColumns ?? 80, this.projectionOptions);
200
+ this.onFrame?.();
201
+ }));
202
+ // The live tail remains scrollable. Its spinner lives in the permanent
203
+ // activity lane mounted by the app immediately above the composer.
204
+ this.addChild(this.thinkingHeaderRow);
205
+ for (const row of this.reasoningRows)
206
+ this.addChild(row);
207
+ this.addChild(this.thinkingEllipsisRow);
208
+ this.addChild(this.reasoningGapRow);
209
+ this.addChild(this.timelineEllipsisRow);
210
+ for (const row of this.timelineRows)
211
+ this.addChild(row);
212
+ this.addChild(this.liveGapRow);
213
+ }
214
+ /** Live update while streaming. */
215
+ update(tail, columns, projectionOptions = {}) {
216
+ this.tail = tail;
217
+ this.commandActivity = null;
218
+ this.lastColumns = columns;
219
+ this.projectionOptions = projectionOptions;
220
+ const width = Math.max(1, Math.floor(columns));
221
+ const theme = this.getTheme?.();
222
+ this.updateActivityLane();
223
+ let hasLiveRows = false;
224
+ this.thinkingHeaderRow.setText("");
225
+ this.thinkingEllipsisRow.setText("");
226
+ this.reasoningGapRow.setLines(0);
227
+ this.timelineEllipsisRow.setText("");
228
+ for (const row of this.reasoningRows)
229
+ row.setText("");
230
+ for (const row of this.timelineRows)
231
+ row.clear();
232
+ // Reasoning models get a dedicated rolling window instead of burying
233
+ // their work inside the spinner status line. It is an independent region:
234
+ // answer/tool bytes must not make Thinking disappear mid-frame.
235
+ if (tail.reasoning) {
236
+ hasLiveRows = true;
237
+ const projected = projectReasoningRows(tail.reasoning, { ...projectionOptions, columns: width }, { running: true, maxBodyRows: MINIMAL_REASONING_BODY_ROWS, fromEnd: true });
238
+ this.thinkingHeaderRow.setText(projected[0] ?? "");
239
+ const body = projected.slice(1);
240
+ const visible = body.slice(0, this.reasoningRows.length);
241
+ for (let index = 0; index < visible.length; index += 1) {
242
+ this.reasoningRows[index].setText(visible[index] ?? "");
243
+ }
244
+ if (body.length > visible.length)
245
+ this.thinkingEllipsisRow.setText(body.at(-1) ?? "");
246
+ }
247
+ const parts = tail.parts.length > 0
248
+ ? tail.parts
249
+ : [
250
+ ...(tail.tools.length > 0 ? [{ type: "tools", toolCalls: [...tail.tools] }] : []),
251
+ ...(tail.content ? [{ type: "text", content: tail.content }] : []),
252
+ ];
253
+ let lastToolsPart = -1;
254
+ for (let index = parts.length - 1; index >= 0; index -= 1) {
255
+ if (parts[index]?.type === "tools") {
256
+ lastToolsPart = index;
257
+ break;
258
+ }
259
+ }
260
+ const timelineBlocks = [];
261
+ for (let partIndex = 0; partIndex < parts.length; partIndex += 1) {
262
+ const part = parts[partIndex];
263
+ if (part.type === "tools") {
264
+ timelineBlocks.push(projectToolTraceGroups(part.toolCalls, { ...projectionOptions, columns: width }, { showActivity: partIndex === lastToolsPart }));
265
+ continue;
266
+ }
267
+ const rows = projectAssistantRows(part.content, { ...projectionOptions, columns: width });
268
+ timelineBlocks.push({ rows, traceTargets: rows.map(() => undefined) });
269
+ }
270
+ const timeline = joinTranscriptProjections(timelineBlocks);
271
+ this.reasoningGapRow.setLines(tail.reasoning && timeline.rows.length > 0 ? 1 : 0);
272
+ if (timeline.rows.length > 0) {
273
+ hasLiveRows = true;
274
+ const start = Math.max(0, timeline.rows.length - this.timelineRows.length);
275
+ const visible = timeline.rows.slice(start);
276
+ const visibleTargets = timeline.traceTargets.slice(start);
277
+ this.timelineEllipsisRow.setText(timeline.rows.length > visible.length
278
+ ? theme ? themeDim(theme.dim, " …") : chalk.dim(" …")
279
+ : "");
280
+ for (let index = 0; index < visible.length; index += 1) {
281
+ this.timelineRows[index].setRow(visible[index], visibleTargets[index], projectionOptions.traceInteraction);
282
+ }
283
+ }
284
+ this.liveGapRow.setLines(hasLiveRows ? 1 : 0);
285
+ }
286
+ /** Paint a non-turn command into the same permanent activity lane Grok uses
287
+ * for Thinking, tools and manual compaction. No transcript preview rows are
288
+ * created, so completion only replaces the spinner with its event line. */
289
+ updateCommandActivity(label, cancelling, columns) {
290
+ this.tail = null;
291
+ this.commandActivity = { label, cancelling };
292
+ this.lastColumns = columns;
293
+ this.clearProjectedRows();
294
+ this.updateActivityLane();
295
+ }
296
+ /**
297
+ * Turn ended: collapse every scrollable slot and clear (but do not collapse)
298
+ * the permanent activity lane. Same-frame with the controller's settled
299
+ * append, the full answer replaces the preview without changing the
300
+ * transcript/composer boundary height.
301
+ */
302
+ clearToNothing() {
303
+ this.stopSpinner();
304
+ this.tail = null;
305
+ this.commandActivity = null;
306
+ this.clearProjectedRows();
307
+ this.activityLane.setText("");
308
+ }
309
+ clearProjectedRows() {
310
+ this.thinkingHeaderRow.setText("");
311
+ this.thinkingEllipsisRow.setText("");
312
+ this.reasoningGapRow.setLines(0);
313
+ this.timelineEllipsisRow.setText("");
314
+ this.liveGapRow.setLines(0);
315
+ for (const row of this.reasoningRows)
316
+ row.setText("");
317
+ for (const row of this.timelineRows)
318
+ row.clear();
319
+ }
320
+ startSpinner() {
321
+ if (this.spinnerActive)
322
+ return;
323
+ this.spinnerActive = true;
324
+ this.idlePhraseElapsedMs = 0;
325
+ }
326
+ lastColumns;
327
+ stopSpinner() {
328
+ this.spinnerActive = false;
329
+ this.idlePhraseElapsedMs = 0;
330
+ }
331
+ isAnimationActive() {
332
+ return this.spinnerActive;
333
+ }
334
+ /** Advance decorative state only; trace/Markdown projection never runs here. */
335
+ advanceAnimationFrame(elapsedMs = 100) {
336
+ if (!this.spinnerActive)
337
+ return false;
338
+ this.frame = (this.frame + 1) % SPINNER_FRAMES.length;
339
+ if (this.tail && !this.tail.content && !this.tail.reasoning && this.tail.tools.length === 0) {
340
+ this.idlePhraseElapsedMs += Math.max(0, elapsedMs);
341
+ while (this.idlePhraseElapsedMs >= 1_500) {
342
+ this.idlePhraseElapsedMs -= 1_500;
343
+ this.idlePhraseIndex = (this.idlePhraseIndex + 1) % GENERIC_PHRASES.length;
344
+ }
345
+ }
346
+ else {
347
+ this.idlePhraseElapsedMs = 0;
348
+ }
349
+ this.updateActivityLane();
350
+ return true;
351
+ }
352
+ dispose() {
353
+ this.stopSpinner();
354
+ }
355
+ /** Remember the width for spinner-driven rebuilds between flushes. */
356
+ noteWidth(columns) {
357
+ this.lastColumns = columns;
358
+ }
359
+ updateActivityLane() {
360
+ const width = Math.max(1, Math.floor(this.lastColumns ?? 80));
361
+ const theme = this.getTheme?.();
362
+ const spinner = theme
363
+ ? themeForeground(theme.accent, SPINNER_FRAMES[this.frame])
364
+ : chalk.cyan(SPINNER_FRAMES[this.frame]);
365
+ let text = "";
366
+ if (this.tail) {
367
+ const idlePhrase = GENERIC_PHRASES[this.idlePhraseIndex % GENERIC_PHRASES.length];
368
+ const activeTool = [...this.tail.tools].reverse().find((tool) => (tool.status === "queued"
369
+ || tool.status === "pending"
370
+ || tool.status === "running"
371
+ || (tool.status === undefined && tool.result === undefined)));
372
+ const phrase = activeTool
373
+ ? TOOL_TARGET_PHRASES[activeTool.name] ?? `running ${activeTool.name}`
374
+ : this.tail.content
375
+ ? "writing the response"
376
+ : this.tail.reasoning
377
+ ? "working through the request"
378
+ : idlePhrase;
379
+ const streamedChars = this.tail.content.length + this.tail.reasoning.length;
380
+ const tokenText = streamedChars > 0 ? ` (↓${approximateTokenLabel(streamedChars)} tok)` : "";
381
+ text = `${phrase}${tokenText}`;
382
+ }
383
+ else if (this.commandActivity) {
384
+ text = this.commandActivity.cancelling ? "Cancelling…" : `${this.commandActivity.label}…`;
385
+ }
386
+ if (!text) {
387
+ this.activityLane.setText("");
388
+ return;
389
+ }
390
+ const status = theme ? themeDim(theme.dim, text) : chalk.dim(text);
391
+ this.activityLane.setText(truncateToWidth(` ${spinner} ${status}`, width));
392
+ }
393
+ }
@@ -0,0 +1,28 @@
1
+ import { type Component } from "@bubblebrain-ai/pi-tui";
2
+ import type { BubbleTuiController } from "../controller/controller.js";
3
+ import type { TranscriptRenderOptions } from "./transcript.js";
4
+ import type { SubagentDisplay } from "../model/subagent-view.js";
5
+ import { type Theme } from "../model/theme.js";
6
+ export interface SubagentInspectorOptions {
7
+ agentId: string;
8
+ controller: BubbleTuiController;
9
+ getMember(): SubagentDisplay | undefined;
10
+ getTerminalRows(): number;
11
+ renderOptions(): Omit<TranscriptRenderOptions, "columns">;
12
+ onClose(): void;
13
+ onNavigate?(direction: -1 | 1): void;
14
+ onRender(): void;
15
+ theme?: Theme;
16
+ }
17
+ export declare class SubagentInspectorComponent implements Component {
18
+ private readonly options;
19
+ focused: boolean;
20
+ private scrollOffset;
21
+ private followEnd;
22
+ private lastBodyRows;
23
+ private lastContentRows;
24
+ constructor(options: SubagentInspectorOptions);
25
+ render(width: number): string[];
26
+ handleInput(data: string): void;
27
+ invalidate(): void;
28
+ }
@@ -0,0 +1,127 @@
1
+ import { matchesKey, truncateToWidth, visibleWidth, } from "@bubblebrain-ai/pi-tui";
2
+ import { joinTranscriptBlocks, projectAssistantRows, projectReasoningRows, projectToolTraceGroups, projectTranscript, } from "./transcript.js";
3
+ import { darkTheme } from "../model/theme.js";
4
+ import { themeDim, themeForeground } from "../model/theme-style.js";
5
+ function pad(line, width) {
6
+ const clipped = truncateToWidth(line, Math.max(1, width), "");
7
+ return clipped + " ".repeat(Math.max(0, width - visibleWidth(clipped)));
8
+ }
9
+ function tokens(member) {
10
+ if (!member?.usage)
11
+ return "";
12
+ const total = member.usage.promptTokens + member.usage.completionTokens;
13
+ return total >= 1000 ? `${(total / 1000).toFixed(total < 10_000 ? 1 : 0)}k tok` : `${total} tok`;
14
+ }
15
+ function elapsed(member) {
16
+ if (!member?.createdAt)
17
+ return "";
18
+ const final = new Set(["completed", "failed", "blocked", "cancelled", "closed"]).has(member.status ?? "");
19
+ const seconds = Math.floor((((final ? member.updatedAt : Date.now()) ?? Date.now()) - member.createdAt) / 1000);
20
+ return seconds < 60 ? `${seconds}s` : `${Math.floor(seconds / 60)}m`;
21
+ }
22
+ export class SubagentInspectorComponent {
23
+ options;
24
+ focused = false;
25
+ scrollOffset = 0;
26
+ followEnd = true;
27
+ lastBodyRows = 0;
28
+ lastContentRows = 0;
29
+ constructor(options) {
30
+ this.options = options;
31
+ }
32
+ render(width) {
33
+ const theme = this.options.theme ?? darkTheme;
34
+ const frameWidth = Math.max(1, Math.floor(width));
35
+ const bodyWidth = Math.max(1, frameWidth - 4);
36
+ const member = this.options.getMember();
37
+ const transcript = projectTranscript(this.options.controller.getChildTranscript(this.options.agentId), {
38
+ ...this.options.renderOptions(),
39
+ columns: bodyWidth,
40
+ trailingSpacer: false,
41
+ }).rows;
42
+ const tail = this.options.controller.getChildStreamingTail(this.options.agentId);
43
+ const liveRows = tail
44
+ ? joinTranscriptBlocks([
45
+ tail.reasoning ? projectReasoningRows(tail.reasoning, { ...this.options.renderOptions(), columns: bodyWidth }, { running: true }) : [],
46
+ tail.tools.length > 0 ? projectToolTraceGroups(tail.tools, { ...this.options.renderOptions(), columns: bodyWidth }, { showActivity: true }).rows : [],
47
+ tail.content ? projectAssistantRows(tail.content, { ...this.options.renderOptions(), columns: bodyWidth }) : [],
48
+ ])
49
+ : [];
50
+ const content = joinTranscriptBlocks([transcript, liveRows]);
51
+ const terminalRows = Math.max(8, this.options.getTerminalRows());
52
+ const bodyRows = Math.max(3, terminalRows - 6);
53
+ this.lastBodyRows = bodyRows;
54
+ this.lastContentRows = content.length;
55
+ const maxOffset = Math.max(0, content.length - bodyRows);
56
+ if (this.followEnd)
57
+ this.scrollOffset = maxOffset;
58
+ this.scrollOffset = Math.max(0, Math.min(this.scrollOffset, maxOffset));
59
+ const visible = content.slice(this.scrollOffset, this.scrollOffset + bodyRows);
60
+ while (visible.length < bodyRows)
61
+ visible.push("");
62
+ const status = member?.status ?? "running";
63
+ const route = member?.route?.model ?? member?.agentName ?? "subagent";
64
+ const meta = [status, route, tokens(member), elapsed(member)].filter(Boolean).join(" · ");
65
+ const title = `${member?.nickname ?? member?.agentName ?? "Subagent"} — read only`;
66
+ if (frameWidth < 6) {
67
+ return [title, meta, ...visible]
68
+ .slice(0, Math.max(1, this.options.getTerminalRows()))
69
+ .map((row) => truncateToWidth(row, frameWidth, ""));
70
+ }
71
+ const border = (text) => themeForeground(theme.border, text);
72
+ const top = border(`┌─ ${truncateToWidth(title, Math.max(1, frameWidth - 6), "")} ${"─".repeat(Math.max(0, frameWidth - visibleWidth(title) - 5))}┐`);
73
+ const header = `${border("│")} ${pad(themeDim(theme.dim, meta), bodyWidth)} ${border("│")}`;
74
+ const separator = border(`├${"─".repeat(frameWidth - 2)}┤`);
75
+ const body = visible.map((row) => `${border("│")} ${pad(row, bodyWidth)} ${border("│")}`);
76
+ const hint = pad(themeDim(theme.dim, "↑↓ scroll · [ ] previous/next · x stop · Esc close"), bodyWidth);
77
+ const bottom = border(`└${"─".repeat(frameWidth - 2)}┘`);
78
+ return [top, header, separator, ...body, `${border("│")} ${hint} ${border("│")}`, bottom];
79
+ }
80
+ handleInput(data) {
81
+ if (matchesKey(data, "escape")) {
82
+ this.options.onClose();
83
+ return;
84
+ }
85
+ if (data === "x") {
86
+ const status = this.options.getMember()?.status ?? "running";
87
+ if (!new Set(["completed", "failed", "blocked", "cancelled", "closed"]).has(status)) {
88
+ this.options.controller.stopSubagent(this.options.agentId);
89
+ }
90
+ return;
91
+ }
92
+ if (data === "[") {
93
+ this.options.onNavigate?.(-1);
94
+ return;
95
+ }
96
+ if (data === "]") {
97
+ this.options.onNavigate?.(1);
98
+ return;
99
+ }
100
+ const maxOffset = Math.max(0, this.lastContentRows - this.lastBodyRows);
101
+ if (matchesKey(data, "up") || data === "k") {
102
+ this.followEnd = false;
103
+ this.scrollOffset = Math.max(0, this.scrollOffset - 1);
104
+ }
105
+ else if (matchesKey(data, "down") || data === "j") {
106
+ this.scrollOffset = Math.min(maxOffset, this.scrollOffset + 1);
107
+ this.followEnd = this.scrollOffset >= maxOffset;
108
+ }
109
+ else if (matchesKey(data, "pageUp")) {
110
+ this.followEnd = false;
111
+ this.scrollOffset = Math.max(0, this.scrollOffset - this.lastBodyRows);
112
+ }
113
+ else if (matchesKey(data, "pageDown")) {
114
+ this.scrollOffset = Math.min(maxOffset, this.scrollOffset + this.lastBodyRows);
115
+ this.followEnd = this.scrollOffset >= maxOffset;
116
+ }
117
+ else if (matchesKey(data, "end")) {
118
+ this.followEnd = true;
119
+ this.scrollOffset = maxOffset;
120
+ }
121
+ else {
122
+ return;
123
+ }
124
+ this.options.onRender();
125
+ }
126
+ invalidate() { }
127
+ }
@@ -0,0 +1,26 @@
1
+ import { type Component } from "@bubblebrain-ai/pi-tui";
2
+ import { type Theme } from "../model/theme.js";
3
+ export interface TaskInspectorOptions {
4
+ id: string;
5
+ title: string;
6
+ getStatus(): string;
7
+ getOutput(): string;
8
+ getTerminalRows(): number;
9
+ onClose(): void;
10
+ onStop(): void;
11
+ onCopy(): void | Promise<void>;
12
+ onRender(): void;
13
+ theme?: Theme;
14
+ }
15
+ export declare class TaskInspectorComponent implements Component {
16
+ private readonly options;
17
+ focused: boolean;
18
+ private offset;
19
+ private follow;
20
+ private bodyRows;
21
+ private contentRows;
22
+ constructor(options: TaskInspectorOptions);
23
+ render(width: number): string[];
24
+ handleInput(data: string): void;
25
+ invalidate(): void;
26
+ }
@@ -0,0 +1,70 @@
1
+ import { matchesKey, truncateToWidth, visibleWidth } from "@bubblebrain-ai/pi-tui";
2
+ import { safeSheetText } from "./bottom-sheet.js";
3
+ import { darkTheme } from "../model/theme.js";
4
+ import { themeDim, themeForeground } from "../model/theme-style.js";
5
+ function pad(line, width) {
6
+ const clipped = truncateToWidth(line, width, "");
7
+ return clipped + " ".repeat(Math.max(0, width - visibleWidth(clipped)));
8
+ }
9
+ export class TaskInspectorComponent {
10
+ options;
11
+ focused = false;
12
+ offset = 0;
13
+ follow = true;
14
+ bodyRows = 0;
15
+ contentRows = 0;
16
+ constructor(options) {
17
+ this.options = options;
18
+ }
19
+ render(width) {
20
+ const theme = this.options.theme ?? darkTheme;
21
+ const frameWidth = Math.max(1, Math.floor(width));
22
+ const inside = Math.max(1, frameWidth - 4);
23
+ const bodyRows = Math.max(3, this.options.getTerminalRows() - 6);
24
+ const output = safeSheetText(this.options.getOutput()).split("\n");
25
+ this.bodyRows = bodyRows;
26
+ this.contentRows = output.length;
27
+ const maxOffset = Math.max(0, output.length - bodyRows);
28
+ if (this.follow)
29
+ this.offset = maxOffset;
30
+ const visible = output.slice(this.offset, this.offset + bodyRows);
31
+ while (visible.length < bodyRows)
32
+ visible.push("");
33
+ const rawTitle = `${this.options.title} — ${this.options.getStatus()}`;
34
+ if (frameWidth < 6) {
35
+ return [rawTitle, ...visible]
36
+ .slice(0, Math.max(1, this.options.getTerminalRows()))
37
+ .map((line) => truncateToWidth(line, frameWidth, ""));
38
+ }
39
+ const title = truncateToWidth(rawTitle, frameWidth - 6, "");
40
+ return [
41
+ themeForeground(theme.border, `┌─ ${title} ${"─".repeat(Math.max(0, frameWidth - visibleWidth(title) - 5))}┐`),
42
+ ...visible.map((line) => `${themeForeground(theme.border, "│")} ${pad(line, inside)} ${themeForeground(theme.border, "│")}`),
43
+ `${themeForeground(theme.border, "│")} ${pad(themeDim(theme.dim, "↑↓ scroll · y copy · x stop · Esc close"), inside)} ${themeForeground(theme.border, "│")}`,
44
+ themeForeground(theme.border, `└${"─".repeat(frameWidth - 2)}┘`),
45
+ ];
46
+ }
47
+ handleInput(data) {
48
+ if (matchesKey(data, "escape"))
49
+ return this.options.onClose();
50
+ if (data === "x" && this.options.getStatus() === "running")
51
+ return this.options.onStop();
52
+ if (data === "y") {
53
+ void this.options.onCopy();
54
+ return;
55
+ }
56
+ const maxOffset = Math.max(0, this.contentRows - this.bodyRows);
57
+ if (matchesKey(data, "up") || data === "k") {
58
+ this.follow = false;
59
+ this.offset = Math.max(0, this.offset - 1);
60
+ }
61
+ else if (matchesKey(data, "down") || data === "j") {
62
+ this.offset = Math.min(maxOffset, this.offset + 1);
63
+ this.follow = this.offset >= maxOffset;
64
+ }
65
+ else
66
+ return;
67
+ this.options.onRender();
68
+ }
69
+ invalidate() { }
70
+ }