@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
@@ -108,13 +108,16 @@ export async function compactMessagesWithLLM(messages, options) {
108
108
  * `oldMessages`. Shared by the non-streaming overflow path (`generateSummary`)
109
109
  * and the streaming manual `/compact` path (`Agent.summarizeForCompaction`).
110
110
  */
111
- export function buildCompactionPromptMessages(oldMessages) {
111
+ export function buildCompactionPromptMessages(oldMessages, userContext) {
112
112
  const transcript = serializeTranscript(oldMessages);
113
+ const preservationNote = userContext?.trim()
114
+ ? `\n\nUser-provided context for this compaction:\n${userContext.trim()}\n\nIncorporate this context prominently in the relevant sections.`
115
+ : "";
113
116
  return [
114
117
  { role: "system", content: COMPACT_SYSTEM_PROMPT },
115
118
  {
116
119
  role: "user",
117
- content: `Conversation to summarize:\n\n${transcript}\n\n---\n\n${COMPACT_INSTRUCTIONS}`,
120
+ content: `Conversation to summarize:\n\n${transcript}\n\n---\n\n${COMPACT_INSTRUCTIONS}${preservationNote}`,
118
121
  },
119
122
  ];
120
123
  }
@@ -10,6 +10,8 @@ const OVERFLOW_PATTERNS = [
10
10
  /exceeds the context window/i,
11
11
  /exceeds the limit of\s+\d+/i,
12
12
  /prompt is too long/i,
13
+ /prompt exceeds max(?:imum)? length/i,
14
+ /maximum prompt length/i,
13
15
  /maximum context length/i,
14
16
  /too many tokens/i,
15
17
  // Gemini: "The input token count (N) exceeds the maximum number of tokens allowed (M)."
@@ -5,8 +5,16 @@ export interface ProjectionOptions {
5
5
  modelId?: string;
6
6
  usageAnchorTokens?: number;
7
7
  anchorMessageCount?: number;
8
+ /** Request tokens not represented by messages, such as active tool schemas. */
9
+ additionalInputTokens?: number;
8
10
  }
9
11
  export declare function projectMessages(messages: Message[], options?: ProjectionOptions): ProviderMessage[];
12
+ /**
13
+ * Re-bound restored tool messages and divide a hard aggregate budget fairly
14
+ * across sibling calls. A historical 6MB JSONL entry therefore becomes safe
15
+ * at projection time even if it predates live-result normalization.
16
+ */
17
+ export declare function boundToolOutputBatches(messages: ProviderMessage[], providerId: string, modelId: string): ProviderMessage[];
10
18
  /**
11
19
  * Ensures every assistant `tool_calls` is followed (in order) by tool messages
12
20
  * responding to each tool_call_id, with no foreign messages interleaved.
@@ -2,6 +2,7 @@ import { getContextBudget } from "./budget.js";
2
2
  import { compactCurrentTurnToolGroups, compactMessages } from "./compact.js";
3
3
  import { pruneMessages } from "./prune.js";
4
4
  import { formatInternalContextBlock, formatInternalReminderBlock } from "../agent/internal-reminder-sanitizer.js";
5
+ import { DEFAULT_TOOL_OUTPUT_BYTE_LIMIT, TOOL_OUTPUT_BATCH_BYTE_LIMIT, truncateToolOutputForModel, } from "./tool-output-truncate.js";
5
6
  // Prefix-cache invariant: only the leading static system prompt is promoted to
6
7
  // the first provider message. Runtime meta reminders stay in the conversational
7
8
  // body at their original relative position, so a new per-turn reminder does not
@@ -49,11 +50,14 @@ export function projectMessages(messages, options = {}) {
49
50
  ...projectedBody,
50
51
  ];
51
52
  const repaired = repairToolCallChains(projected);
53
+ const bounded = options.providerId && options.modelId
54
+ ? boundToolOutputBatches(repaired, options.providerId, options.modelId)
55
+ : repaired;
52
56
  if (mode === "pruned") {
53
- return pruneMessages(repaired);
57
+ return pruneMessages(bounded);
54
58
  }
55
59
  if (mode === "budgeted") {
56
- const pruned = pruneMessages(repaired);
60
+ const pruned = pruneMessages(bounded);
57
61
  if (!options.providerId || !options.modelId) {
58
62
  return pruned;
59
63
  }
@@ -61,8 +65,9 @@ export function projectMessages(messages, options = {}) {
61
65
  ? {
62
66
  usageAnchorTokens: options.usageAnchorTokens,
63
67
  tailMessages: pruned.slice(Math.min(options.anchorMessageCount, pruned.length)),
68
+ additionalInputTokens: options.additionalInputTokens,
64
69
  }
65
- : undefined);
70
+ : { additionalInputTokens: options.additionalInputTokens });
66
71
  if (!budget.shouldCompact) {
67
72
  return pruned;
68
73
  }
@@ -81,7 +86,9 @@ export function projectMessages(messages, options = {}) {
81
86
  const next = pass();
82
87
  if (next)
83
88
  working = next;
84
- const after = getContextBudget(options.providerId, options.modelId, working);
89
+ const after = getContextBudget(options.providerId, options.modelId, working, {
90
+ additionalInputTokens: options.additionalInputTokens,
91
+ });
85
92
  if (!after.shouldCompact)
86
93
  break;
87
94
  }
@@ -91,9 +98,51 @@ export function projectMessages(messages, options = {}) {
91
98
  const providerSafe = working.map((message) => message.role === "meta"
92
99
  ? { role: "user", content: formatMetaMessage(message) }
93
100
  : message);
94
- return repairToolCallChains(providerSafe);
101
+ return boundToolOutputBatches(repairToolCallChains(providerSafe), options.providerId, options.modelId);
102
+ }
103
+ return bounded;
104
+ }
105
+ /**
106
+ * Re-bound restored tool messages and divide a hard aggregate budget fairly
107
+ * across sibling calls. A historical 6MB JSONL entry therefore becomes safe
108
+ * at projection time even if it predates live-result normalization.
109
+ */
110
+ export function boundToolOutputBatches(messages, providerId, modelId) {
111
+ const bounded = [];
112
+ for (let index = 0; index < messages.length; index++) {
113
+ const message = messages[index];
114
+ bounded.push(message);
115
+ if (message.role !== "assistant" || !message.toolCalls?.length)
116
+ continue;
117
+ const siblingCount = message.toolCalls.length;
118
+ const perResultByteLimit = Math.min(DEFAULT_TOOL_OUTPUT_BYTE_LIMIT, Math.floor(TOOL_OUTPUT_BATCH_BYTE_LIMIT / siblingCount));
119
+ for (let sibling = 0; sibling < siblingCount; sibling++) {
120
+ const toolMessage = messages[index + 1 + sibling];
121
+ if (!toolMessage || toolMessage.role !== "tool")
122
+ break;
123
+ const result = truncateToolOutputForModel(toolMessage.content, providerId, modelId, { hardByteLimit: perResultByteLimit });
124
+ bounded.push(result.truncated
125
+ ? {
126
+ ...toolMessage,
127
+ content: result.content,
128
+ metadata: {
129
+ ...toolMessage.metadata,
130
+ truncated: true,
131
+ toolOutputTruncation: {
132
+ originalBytes: result.originalBytes,
133
+ finalBytes: result.finalBytes,
134
+ originalTokens: result.originalTokens,
135
+ finalTokens: result.finalTokens,
136
+ hardByteLimit: result.hardByteLimit,
137
+ ...(result.limit ? { modelTokenLimit: result.limit } : {}),
138
+ },
139
+ },
140
+ }
141
+ : toolMessage);
142
+ }
143
+ index += siblingCount;
95
144
  }
96
- return repaired;
145
+ return bounded;
97
146
  }
98
147
  /**
99
148
  * Ensures every assistant `tool_calls` is followed (in order) by tool messages
@@ -1,8 +1,24 @@
1
+ import type { ToolResult } from "../types.js";
2
+ export declare const DEFAULT_TOOL_OUTPUT_BYTE_LIMIT: number;
3
+ export declare const TOOL_OUTPUT_BATCH_BYTE_LIMIT: number;
4
+ export interface ToolTruncationOptions {
5
+ /** Override used by a sibling tool batch to divide its aggregate budget. */
6
+ hardByteLimit?: number;
7
+ }
1
8
  export interface ToolTruncationResult {
2
9
  content: string;
3
10
  truncated: boolean;
4
11
  originalTokens: number;
5
12
  finalTokens: number;
13
+ originalBytes: number;
14
+ finalBytes: number;
15
+ /** Provider/model-declared token cap, when one exists. */
6
16
  limit: number | undefined;
17
+ hardByteLimit: number;
7
18
  }
8
- export declare function truncateToolOutputForModel(content: string, providerId: string, modelId: string): ToolTruncationResult;
19
+ export declare function truncateToolOutputForModel(content: string, providerId: string, modelId: string, options?: ToolTruncationOptions): ToolTruncationResult;
20
+ export declare function normalizeToolResultForModel(result: ToolResult, providerId: string, modelId: string, options?: ToolTruncationOptions): ToolResult;
21
+ /** Return the longest prefix that fits without splitting a Unicode code point. */
22
+ export declare function utf8Prefix(content: string, maxBytes: number): string;
23
+ /** Return the longest suffix that fits without splitting a Unicode code point. */
24
+ export declare function utf8Suffix(content: string, maxBytes: number): string;
@@ -1,59 +1,181 @@
1
- // Tool-output truncation honoring the model's server-declared limit.
1
+ // Tool-output bounding for both live results and restored session history.
2
2
  //
3
- // Codex backend's /models endpoint reports per-model `truncation_policy.limit`
4
- // (e.g. 10000 tokens for gpt-5.5). The expectation is that the CLIENT truncates
5
- // each tool result to that budget before adding it to history; sending raw
6
- // 50-100k tool dumps will blow through the input window after a handful of
7
- // calls. Codex CLI does this via TruncationPolicy::Tokens; mirror it here.
8
- //
9
- // Strategy: middle-truncate (preserve head + tail with an explicit marker in
10
- // between). Heads usually carry structure/headers; tails often carry totals,
11
- // errors, or conclusions — losing either is worse than losing the middle.
3
+ // A provider-declared token cap is useful when present, but it cannot be the
4
+ // only guard: several providers (including GLM coding-plan models) declare no
5
+ // per-tool limit at all. Every model-visible tool result therefore has a hard
6
+ // byte ceiling as well. The stricter of the two policies wins.
12
7
  import { getToolOutputTokenLimit } from "../model-catalog.js";
13
8
  import { estimateTextTokens } from "./budget.js";
14
- export function truncateToolOutputForModel(content, providerId, modelId) {
9
+ export const DEFAULT_TOOL_OUTPUT_BYTE_LIMIT = 64 * 1024;
10
+ export const TOOL_OUTPUT_BATCH_BYTE_LIMIT = 160 * 1024;
11
+ export function truncateToolOutputForModel(content, providerId, modelId, options = {}) {
15
12
  const limit = getToolOutputTokenLimit(providerId, modelId);
13
+ const hardByteLimit = Math.max(0, Math.floor(options.hardByteLimit ?? DEFAULT_TOOL_OUTPUT_BYTE_LIMIT));
16
14
  const originalTokens = estimateTextTokens(content, providerId);
17
- if (!limit || originalTokens <= limit) {
18
- return { content, truncated: false, originalTokens, finalTokens: originalTokens, limit };
15
+ const originalBytes = Buffer.byteLength(content, "utf8");
16
+ if (originalBytes <= hardByteLimit && (!limit || originalTokens <= limit)) {
17
+ return {
18
+ content,
19
+ truncated: false,
20
+ originalTokens,
21
+ finalTokens: originalTokens,
22
+ originalBytes,
23
+ finalBytes: originalBytes,
24
+ limit,
25
+ hardByteLimit,
26
+ };
27
+ }
28
+ if (hardByteLimit === 0) {
29
+ return {
30
+ content: "",
31
+ truncated: content.length > 0,
32
+ originalTokens,
33
+ finalTokens: 0,
34
+ originalBytes,
35
+ finalBytes: 0,
36
+ limit,
37
+ hardByteLimit,
38
+ };
39
+ }
40
+ // Start with the byte ceiling. If a token policy is tighter, use the
41
+ // observed token/byte ratio to choose a smaller first candidate.
42
+ let candidateByteBudget = hardByteLimit;
43
+ if (limit && originalTokens > limit) {
44
+ candidateByteBudget = Math.min(candidateByteBudget, Math.max(1, Math.floor(originalBytes * (limit / originalTokens) * 0.9)));
45
+ }
46
+ let truncated = middleTruncateToByteBudget(content, candidateByteBudget, buildMarker(originalBytes, hardByteLimit, limit));
47
+ // Token estimation varies across providers and scripts. Tighten until both
48
+ // invariants hold; byte truncation itself is UTF-8 safe on every pass.
49
+ for (let pass = 0; pass < 8 && limit && estimateTextTokens(truncated, providerId) > limit; pass++) {
50
+ const tokens = estimateTextTokens(truncated, providerId);
51
+ candidateByteBudget = Math.max(1, Math.floor(candidateByteBudget * (limit / Math.max(1, tokens)) * 0.9));
52
+ truncated = middleTruncateToByteBudget(content, candidateByteBudget, buildMarker(originalBytes, hardByteLimit, limit));
53
+ }
54
+ // Extremely small model caps may not even fit the descriptive marker.
55
+ // Continue shrinking deterministically rather than violating the contract.
56
+ while (limit && estimateTextTokens(truncated, providerId) > limit && truncated.length > 0) {
57
+ candidateByteBudget = Math.max(0, Math.floor(candidateByteBudget * 0.75));
58
+ truncated = middleTruncateToByteBudget(content, candidateByteBudget, buildMarker(originalBytes, hardByteLimit, limit));
19
59
  }
20
- const truncated = middleTruncateToTokenBudget(content, limit, providerId);
21
60
  const finalTokens = estimateTextTokens(truncated, providerId);
22
- return { content: truncated, truncated: true, originalTokens, finalTokens, limit };
61
+ const finalBytes = Buffer.byteLength(truncated, "utf8");
62
+ return {
63
+ content: truncated,
64
+ truncated: true,
65
+ originalTokens,
66
+ finalTokens,
67
+ originalBytes,
68
+ finalBytes,
69
+ limit,
70
+ hardByteLimit,
71
+ };
72
+ }
73
+ export function normalizeToolResultForModel(result, providerId, modelId, options = {}) {
74
+ const bounded = truncateToolOutputForModel(result.content, providerId, modelId, options);
75
+ if (!bounded.truncated)
76
+ return result;
77
+ return {
78
+ ...result,
79
+ content: bounded.content,
80
+ metadata: {
81
+ ...result.metadata,
82
+ truncated: true,
83
+ toolOutputTruncation: {
84
+ originalBytes: bounded.originalBytes,
85
+ finalBytes: bounded.finalBytes,
86
+ originalTokens: bounded.originalTokens,
87
+ finalTokens: bounded.finalTokens,
88
+ hardByteLimit: bounded.hardByteLimit,
89
+ ...(bounded.limit ? { modelTokenLimit: bounded.limit } : {}),
90
+ },
91
+ },
92
+ };
93
+ }
94
+ function buildMarker(originalBytes, hardByteLimit, tokenLimit) {
95
+ const policy = tokenLimit
96
+ ? `${formatBytes(hardByteLimit)} hard cap; ${tokenLimit}-token model cap`
97
+ : `${formatBytes(hardByteLimit)} hard cap`;
98
+ return `\n\n[... middle of ${formatBytes(originalBytes)} output truncated by model policy (${policy}) ...]\n\n`;
99
+ }
100
+ function middleTruncateToByteBudget(content, byteBudget, marker) {
101
+ if (byteBudget <= 0)
102
+ return "";
103
+ if (Buffer.byteLength(content, "utf8") <= byteBudget)
104
+ return content;
105
+ let safeMarker = marker;
106
+ if (Buffer.byteLength(safeMarker, "utf8") > byteBudget) {
107
+ safeMarker = utf8Prefix(safeMarker, byteBudget);
108
+ }
109
+ const markerBytes = Buffer.byteLength(safeMarker, "utf8");
110
+ const payloadBytes = Math.max(0, byteBudget - markerBytes);
111
+ const headBudget = Math.floor(payloadBytes / 2);
112
+ const tailBudget = payloadBytes - headBudget;
113
+ const head = utf8Prefix(content, headBudget);
114
+ const tail = utf8Suffix(content, tailBudget);
115
+ return `${head}${safeMarker}${tail}`;
116
+ }
117
+ /** Return the longest prefix that fits without splitting a Unicode code point. */
118
+ export function utf8Prefix(content, maxBytes) {
119
+ if (maxBytes <= 0 || content.length === 0)
120
+ return "";
121
+ if (Buffer.byteLength(content, "utf8") <= maxBytes)
122
+ return content;
123
+ let low = 0;
124
+ let high = content.length;
125
+ while (low < high) {
126
+ const mid = Math.ceil((low + high) / 2);
127
+ const safeMid = isLowSurrogateAt(content, mid) ? mid - 1 : mid;
128
+ if (Buffer.byteLength(content.slice(0, safeMid), "utf8") <= maxBytes)
129
+ low = mid;
130
+ else
131
+ high = mid - 1;
132
+ }
133
+ let end = Math.min(low, content.length);
134
+ if (isLowSurrogateAt(content, end))
135
+ end -= 1;
136
+ while (end > 0 && Buffer.byteLength(content.slice(0, end), "utf8") > maxBytes)
137
+ end -= 1;
138
+ if (isLowSurrogateAt(content, end))
139
+ end -= 1;
140
+ return content.slice(0, Math.max(0, end));
23
141
  }
24
- function middleTruncateToTokenBudget(content, tokenBudget, providerId) {
25
- // Convert token budget to a char budget via the estimator's effective ratio.
26
- // The estimator may under/overcount, so we iterate one round if needed.
27
- const tokensAll = estimateTextTokens(content, providerId);
28
- if (tokensAll <= tokenBudget)
142
+ /** Return the longest suffix that fits without splitting a Unicode code point. */
143
+ export function utf8Suffix(content, maxBytes) {
144
+ if (maxBytes <= 0 || content.length === 0)
145
+ return "";
146
+ if (Buffer.byteLength(content, "utf8") <= maxBytes)
29
147
  return content;
30
- const charsPerToken = content.length / Math.max(1, tokensAll);
31
- let charBudget = Math.floor(tokenBudget * charsPerToken);
32
- const marker = (dropped) => `\n\n[... middle ${formatChars(dropped)} truncated by model policy (${tokenBudget}-token cap) ...]\n\n`;
33
- // Reserve some room for the marker itself.
34
- const reserveForMarker = 200;
35
- charBudget = Math.max(200, charBudget - reserveForMarker);
36
- const half = Math.floor(charBudget / 2);
37
- const head = content.slice(0, half);
38
- const tail = content.slice(content.length - (charBudget - half));
39
- const droppedChars = content.length - head.length - tail.length;
40
- let truncated = `${head}${marker(droppedChars)}${tail}`;
41
- // Tighten if our estimate of charsPerToken undercounts and we're still over.
42
- let safety = 3;
43
- while (estimateTextTokens(truncated, providerId) > tokenBudget && safety-- > 0) {
44
- const newHalf = Math.floor(head.length * 0.8);
45
- const newTailLen = Math.floor(tail.length * 0.8);
46
- const newHead = content.slice(0, newHalf);
47
- const newTail = content.slice(content.length - newTailLen);
48
- const newDropped = content.length - newHead.length - newTail.length;
49
- truncated = `${newHead}${marker(newDropped)}${newTail}`;
50
- }
51
- return truncated;
52
- }
53
- function formatChars(count) {
54
- if (count < 1000)
55
- return `${count} chars`;
56
- if (count < 1_000_000)
57
- return `${(count / 1000).toFixed(1)}K chars`;
58
- return `${(count / 1_000_000).toFixed(2)}M chars`;
148
+ let low = 0;
149
+ let high = content.length;
150
+ while (low < high) {
151
+ const length = Math.ceil((low + high) / 2);
152
+ let start = content.length - length;
153
+ if (isLowSurrogateAt(content, start))
154
+ start += 1;
155
+ if (Buffer.byteLength(content.slice(start), "utf8") <= maxBytes)
156
+ low = length;
157
+ else
158
+ high = length - 1;
159
+ }
160
+ let start = Math.max(0, content.length - low);
161
+ if (isLowSurrogateAt(content, start))
162
+ start += 1;
163
+ while (start < content.length && Buffer.byteLength(content.slice(start), "utf8") > maxBytes)
164
+ start += 1;
165
+ if (isLowSurrogateAt(content, start))
166
+ start += 1;
167
+ return content.slice(Math.min(start, content.length));
168
+ }
169
+ function isLowSurrogateAt(content, index) {
170
+ if (index <= 0 || index >= content.length)
171
+ return false;
172
+ const code = content.charCodeAt(index);
173
+ return code >= 0xdc00 && code <= 0xdfff;
174
+ }
175
+ function formatBytes(count) {
176
+ if (count < 1024)
177
+ return `${count}B`;
178
+ if (count < 1024 * 1024)
179
+ return `${(count / 1024).toFixed(1)}KiB`;
180
+ return `${(count / (1024 * 1024)).toFixed(2)}MiB`;
59
181
  }
@@ -31,6 +31,7 @@ import { applyCardBudget } from "../card/budget.js";
31
31
  import { renderCard } from "../card/renderer.js";
32
32
  import { createInitialRunState } from "../card/run-state-types.js";
33
33
  import { hasInFlightTool, markError, markInterrupted, markIdleTimeout, reduceRunState } from "../card/run-state.js";
34
+ import { assertProviderModelAllowed } from "../../provider-model-policy.js";
34
35
  export class RunDriver {
35
36
  opts;
36
37
  constructor(opts) {
@@ -311,6 +312,8 @@ export class RunDriver {
311
312
  ? decodeModel(normalizedConfigured)
312
313
  : { providerId: undefined, modelId: "" };
313
314
  const activeProviderId = effectiveProviderId || fallbackProviderId;
315
+ if (effectiveModelId)
316
+ assertProviderModelAllowed(activeProviderId, effectiveModelId);
314
317
  if (registry.supportsOAuth(activeProviderId) && registry.getAuthStorage().has(activeProviderId)) {
315
318
  await registry.prepareProvider(activeProviderId);
316
319
  }
@@ -85,6 +85,8 @@ export async function serveFeishu(opts = {}) {
85
85
  const skillRegistry = new SkillRegistry({
86
86
  cwd: rootCwd,
87
87
  skillPaths: userConfig.getSkillPaths(),
88
+ disabledSkills: userConfig.getDisabledSkills(),
89
+ onDisabledSkillsChange: (disabledSkills) => userConfig.setDisabledSkills(disabledSkills),
88
90
  });
89
91
  const mcpLoaded = loadMcpConfig({ cwd: rootCwd });
90
92
  const mcpManager = new McpManager({ servers: mcpLoaded.servers });
@@ -4,7 +4,7 @@
4
4
  * Forms:
5
5
  * /goal -> show summary
6
6
  * /goal <objective> [--budget N] -> set a new goal
7
- * /goal clear | pause | resume
7
+ * /goal status | clear | pause | resume
8
8
  * /goal edit <new objective>
9
9
  *
10
10
  * --budget accepts plain integers and k/m suffixes: 200000, 200k, 1.5m.
@@ -4,12 +4,12 @@
4
4
  * Forms:
5
5
  * /goal -> show summary
6
6
  * /goal <objective> [--budget N] -> set a new goal
7
- * /goal clear | pause | resume
7
+ * /goal status | clear | pause | resume
8
8
  * /goal edit <new objective>
9
9
  *
10
10
  * --budget accepts plain integers and k/m suffixes: 200000, 200k, 1.5m.
11
11
  */
12
- const SUBCOMMANDS = new Set(["clear", "pause", "resume", "edit"]);
12
+ const SUBCOMMANDS = new Set(["status", "clear", "pause", "resume", "edit"]);
13
13
  export function parseGoalCommand(input) {
14
14
  const body = input.trim().replace(/^\/goal\b/, "").trim();
15
15
  if (!body)
@@ -17,6 +17,11 @@ export function parseGoalCommand(input) {
17
17
  const firstToken = body.split(/\s+/, 1)[0].toLowerCase();
18
18
  const rest = body.slice(firstToken.length).trim();
19
19
  if (SUBCOMMANDS.has(firstToken)) {
20
+ if (firstToken === "status") {
21
+ if (rest)
22
+ return { kind: "show", error: "/goal status takes no arguments" };
23
+ return { kind: "show" };
24
+ }
20
25
  if (firstToken === "edit") {
21
26
  if (!rest)
22
27
  return { kind: "edit", error: "Usage: /goal edit <new objective>" };
package/dist/main.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- #!/usr/bin/env bun
1
+ #!/usr/bin/env node
2
2
  /**
3
3
  * Main entry point - assembles all layers and runs the agent.
4
4
  */
package/dist/main.js CHANGED
@@ -1,4 +1,4 @@
1
- #!/usr/bin/env bun
1
+ #!/usr/bin/env node
2
2
  /**
3
3
  * Main entry point - assembles all layers and runs the agent.
4
4
  */
@@ -38,6 +38,8 @@ import { normalizeSingleLine, truncateVisual } from "./text-display.js";
38
38
  import { BUBBLE_WORDMARK } from "./tui/wordmark.js";
39
39
  import { configureDebugTrace, summarizeAgentEventForTrace, summarizeTraceMessage, traceEvent, } from "./debug-trace.js";
40
40
  import { shouldRejectGrokSessionInPrintMode } from "./external-runtime/session-policy.js";
41
+ import { rmSync } from "node:fs";
42
+ import { splitLeadingContext } from "./context/compact.js";
41
43
  async function main() {
42
44
  const args = parseArgs(process.argv.slice(2));
43
45
  if (process.argv.includes("-h") || process.argv.includes("--help")) {
@@ -72,6 +74,8 @@ async function main() {
72
74
  const skillRegistry = new SkillRegistry({
73
75
  cwd: args.cwd,
74
76
  skillPaths: userConfig.getSkillPaths(),
77
+ disabledSkills: userConfig.getDisabledSkills(),
78
+ onDisabledSkillsChange: (disabledSkills) => userConfig.setDisabledSkills(disabledSkills),
75
79
  });
76
80
  const printMode = args.print || !!args.prompt;
77
81
  // Resolve configured providers only; do not auto-inject OpenRouter as a startup default.
@@ -187,6 +191,7 @@ async function main() {
187
191
  processManager,
188
192
  allowBackgroundTasks,
189
193
  promotionChannel,
194
+ autoBackgroundAfterMs: userConfig.getTasksAutoBackgroundAfterMs(),
190
195
  // Lazy: sessionManager is resolved after tools are created.
191
196
  checkpoints: () => sessionManager?.getCheckpoints(),
192
197
  });
@@ -263,8 +268,8 @@ async function main() {
263
268
  }
264
269
  const pickerThemeMode = effectiveThemeModeForTerminal(themeConfig, preResolvedTheme);
265
270
  const pickerResolvedTheme = pickerThemeMode === "auto" ? preResolvedTheme : pickerThemeMode;
266
- const { runSessionPicker } = await import("./tui-ink/run-session-picker.js");
267
- const { canvasBackgroundFor } = await import("./tui-ink/theme.js");
271
+ const { runSessionPicker } = await import("./tui/run-session-picker.js");
272
+ const { canvasBackgroundFor } = await import("./tui/model/theme.js");
268
273
  // Same rule as the main TUI: a forced theme mismatching the terminal
269
274
  // paints its canvas so its foregrounds stay readable.
270
275
  const pickerCanvas = themeConfig.overrides?.background
@@ -367,7 +372,7 @@ async function main() {
367
372
  sessionFile: sessionManager?.getSessionFile(),
368
373
  provider: activeProviderId || "none",
369
374
  model: activeModel || "none",
370
- renderer: printMode ? "print" : "ink",
375
+ renderer: printMode ? "print" : "pi-tui",
371
376
  });
372
377
  if (traceInfo.enabled) {
373
378
  traceEvent("run_start", {
@@ -451,6 +456,8 @@ async function main() {
451
456
  list: () => processManager.listTasks(agent.getSessionID()),
452
457
  version: () => processManager.getTaskStateVersion(),
453
458
  outputTail: (id) => processManager.taskOutputTail(id, 2000),
459
+ kill: (id) => processManager.killTask(id),
460
+ subscribe: (listener) => processManager.onChange(() => listener()),
454
461
  };
455
462
  }
456
463
  if (sessionManager) {
@@ -674,9 +681,8 @@ async function main() {
674
681
  // that persists to the session (onMessageAppend, markers, title updater)
675
682
  // by reassigning the outer `sessionManager`, then replace the agent's
676
683
  // history the same way startup resume does.
677
- const switchSession = (sessionFile) => {
684
+ const activateSession = (next) => {
678
685
  try {
679
- const next = new SessionManager(sessionFile);
680
686
  const history = next.getMessages();
681
687
  const nextPromptCacheKey = next.getOrCreatePromptCacheKey();
682
688
  const nextTitleUpdater = createSessionTitleUpdater({
@@ -691,7 +697,7 @@ async function main() {
691
697
  });
692
698
  // Keep the live system/meta head (mode reminders survive the switch),
693
699
  // mirroring the /rewind history-replacement pattern.
694
- const head = agent.messages.filter((m) => m.role === "system" || m.role === "meta");
700
+ const head = splitLeadingContext(agent.messages).leading;
695
701
  const nextMessages = [...head, ...history];
696
702
  // Commit only after every file read/write and reconstruction step has
697
703
  // succeeded. Callers can safely prepare candidate sessions without a
@@ -713,9 +719,33 @@ async function main() {
713
719
  return { error: error instanceof Error ? error.message : String(error) };
714
720
  }
715
721
  };
722
+ const switchSession = (sessionFile) => {
723
+ try {
724
+ return activateSession(new SessionManager(sessionFile));
725
+ }
726
+ catch (error) {
727
+ return { error: error instanceof Error ? error.message : String(error) };
728
+ }
729
+ };
730
+ const createFreshSession = (cwd) => {
731
+ let fresh;
732
+ try {
733
+ fresh = SessionManager.createFresh(cwd);
734
+ const result = activateSession(fresh);
735
+ if ("error" in result)
736
+ rmSync(fresh.getSessionFile(), { force: true });
737
+ return result;
738
+ }
739
+ catch (error) {
740
+ if (fresh)
741
+ rmSync(fresh.getSessionFile(), { force: true });
742
+ return { error: error instanceof Error ? error.message : String(error) };
743
+ }
744
+ };
716
745
  const commonOptions = {
717
746
  sessionManager,
718
747
  switchSession,
748
+ createFreshSession,
719
749
  createProvider,
720
750
  registry,
721
751
  skillRegistry,
@@ -749,7 +779,7 @@ async function main() {
749
779
  const { startStartupUpdateCheck } = await import("./update/index.js");
750
780
  const updateCheck = await startStartupUpdateCheck();
751
781
  const updateNotice = updateCheck.notice;
752
- const { runTui } = await import("./tui-ink/run.js");
782
+ const { runTui } = await import("./tui/run.js");
753
783
  const summary = await runTui(agent, args, {
754
784
  ...commonOptions,
755
785
  themeMode: effectiveThemeMode,
package/dist/memory/db.js CHANGED
@@ -304,10 +304,6 @@ function unixNow() {
304
304
  return Math.floor(Date.now() / 1000);
305
305
  }
306
306
  function createDatabase(path) {
307
- if (isBunRuntime()) {
308
- const bunSqlite = require("bun:sqlite");
309
- return new bunSqlite.Database(path);
310
- }
311
307
  const Database = require("better-sqlite3");
312
308
  return new Database(path);
313
309
  }
@@ -318,6 +314,3 @@ function setWalMode(db) {
318
314
  }
319
315
  db.prepare("PRAGMA journal_mode = WAL").get();
320
316
  }
321
- function isBunRuntime() {
322
- return typeof globalThis.Bun !== "undefined";
323
- }