@bubblebrain-ai/bubble 0.0.51 → 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 +80 -11
  49. package/dist/provider-transform.js +32 -4
  50. package/dist/provider.d.ts +6 -2
  51. package/dist/provider.js +100 -11
  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
@@ -16,6 +16,11 @@ const KIMI_K3_FAMILY = new Set(["k3", "k3-256k", "kimi-k3"]);
16
16
  const KIMI_TOGGLE_THINKING_FAMILY = new Set(["kimi-k2.5", "kimi-k2.6"]);
17
17
  const KIMI_K26_DEFAULT_MAX_TOKENS = 32768;
18
18
  const MINIMAX_M3_FAMILY = new Set(["MiniMax-M3"]);
19
+ const DEEPSEEK_V4_FAMILY = new Set([
20
+ "deepseek-v4-flash",
21
+ "deepseek-v4-flash-vision-exp",
22
+ "deepseek-v4-pro",
23
+ ]);
19
24
  function isFireworksKimi(providerId, modelId) {
20
25
  const model = modelId.toLowerCase();
21
26
  return providerId === "fireworks" && (model.includes("kimi")
@@ -52,6 +57,21 @@ export function resolveProviderRequestConfig(providerId, modelId, requestedLevel
52
57
  : { reasoning_effort: effectiveThinkingLevel },
53
58
  };
54
59
  }
60
+ // Ox Alpha exposes mandatory low/high/max reasoning. Treat unsupported state
61
+ // restored from an older session as inherited state and fall back to the
62
+ // model's declared default (max), never OpenRouter's disabling "none" value.
63
+ if (providerId === "openrouter") {
64
+ const openRouterThinkingLevel = normalizeInheritedThinkingLevel(providerId, modelId, requestedLevel);
65
+ return {
66
+ effectiveThinkingLevel: openRouterThinkingLevel,
67
+ reasoningContentEcho: "tool_calls",
68
+ extraBody: {
69
+ reasoning: {
70
+ effort: openRouterThinkingLevel,
71
+ },
72
+ },
73
+ };
74
+ }
55
75
  if (isFireworksKimi(providerId, modelId)) {
56
76
  return {
57
77
  effectiveThinkingLevel,
@@ -60,7 +80,16 @@ export function resolveProviderRequestConfig(providerId, modelId, requestedLevel
60
80
  maxTokens: KIMI_K26_DEFAULT_MAX_TOKENS,
61
81
  };
62
82
  }
63
- if (providerId === "deepseek" && (modelId === "deepseek-v4-flash" || modelId === "deepseek-v4-pro")) {
83
+ if (providerId === "deepseek" && DEEPSEEK_V4_FAMILY.has(modelId)) {
84
+ if (effectiveThinkingLevel === "off") {
85
+ return {
86
+ effectiveThinkingLevel,
87
+ // Non-thinking requests do not need prior reasoning replayed. Omitting
88
+ // reasoning_content also keeps the history valid when switching modes.
89
+ reasoningContentEcho: "none",
90
+ extraBody: { thinking: { type: "disabled" } },
91
+ };
92
+ }
64
93
  return {
65
94
  effectiveThinkingLevel,
66
95
  reasoningContentEcho: "all",
@@ -115,11 +144,11 @@ export function resolveProviderRequestConfig(providerId, modelId, requestedLevel
115
144
  // `thinking` block rather than OpenAI's `reasoning_effort` shape.
116
145
  if (["zhipuai", "zhipuai-coding-plan", "zai", "zai-coding-plan"].includes(providerId)) {
117
146
  // GLM-5.2+ also accept `reasoning_effort`. GLM-5.2 can disable thinking;
118
- // GLM-5.3 requires thinking and Coding Plan normalizes its effort into
147
+ // the GLM-5.3 family requires thinking and normalizes its effort into
119
148
  // low/high/max. The catalog clamps 5.3 choices before this serialization
120
149
  // boundary. The effort field rides inside the body alongside `thinking`,
121
150
  // so it goes in extraBody, not the OpenRouter-style config field.
122
- if (modelId === "glm-5.2" || modelId === "glm-5.3") {
151
+ if (modelId === "glm-5.2" || modelId === "glm-5.3" || modelId === "glm-5.3-flash") {
123
152
  return {
124
153
  effectiveThinkingLevel,
125
154
  extraBody: modelId === "glm-5.2" && effectiveThinkingLevel === "off"
@@ -185,7 +214,6 @@ export function resolveProviderRequestConfig(providerId, modelId, requestedLevel
185
214
  return { effectiveThinkingLevel };
186
215
  }
187
216
  if (providerId === "openai"
188
- || providerId === "openrouter"
189
217
  || providerId === "google"
190
218
  || providerId === "azure"
191
219
  || providerId === "openai-compatible") {
@@ -64,8 +64,12 @@ export declare function translateOpenAIFullResponse(response: any): AsyncIterabl
64
64
  * in index order to keep multi-call turns deterministic.
65
65
  */
66
66
  export declare function translateOpenAIStream(stream: AsyncIterable<any>, options?: TranslateOpenAIStreamOptions): AsyncIterable<StreamChunk>;
67
- /** Largest value Node's 32-bit timers accept; ~24.8 days. */
68
- export declare const MAX_TIMER_MS = 2147483647;
67
+ /**
68
+ * Largest value that survives the OpenAI SDK's internal `timeout + 1000`
69
+ * agent-grace (core.js minAgentTimeout) without overflowing Node's 32-bit
70
+ * timers; ~24.8 days.
71
+ */
72
+ export declare const MAX_TIMER_MS = 2147482647;
69
73
  /**
70
74
  * Resolve the provider request timeout (ms) from the operator override.
71
75
  *
package/dist/provider.js CHANGED
@@ -14,8 +14,9 @@ import { getChatGptFetch } from "./network/chatgpt-transport.js";
14
14
  import { createProviderProtocolArtifactFilter } from "./provider-artifacts.js";
15
15
  import { resolveProviderRequestConfig } from "./provider-transform.js";
16
16
  import { debugReasoningStream, summarizeDebugText } from "./reasoning-debug.js";
17
- import { RateLimitError } from "./network/errors.js";
18
- import { ProviderStreamInterruptedError } from "./network/retry.js";
17
+ import { isProviderResponseError, ProviderResponseError, RateLimitError, } from "./network/errors.js";
18
+ import { isRetryableHttpStatus, ProviderStreamInterruptedError } from "./network/retry.js";
19
+ import { assertProviderModelAllowed } from "./provider-model-policy.js";
19
20
  // Diagnostic logger for tool-args byte-loss investigation. Activate with
20
21
  // BUBBLE_DEBUG_TOOL_ARGS=/path/to/log.jsonl (any writable path)
21
22
  // Each line is a JSON record describing a transition. When debugging is off,
@@ -123,6 +124,7 @@ export function createProviderInstance(options) {
123
124
  });
124
125
  const fallbackModel = "gpt-4o";
125
126
  async function* streamChat(messages, chatOptions) {
127
+ assertProviderModelAllowed(options.providerId || "", chatOptions.model);
126
128
  const requestConfig = resolveProviderRequestConfig(options.providerId || "", chatOptions.model, chatOptions.thinkingLevel ?? options.thinkingLevel ?? "off");
127
129
  const tools = chatOptions.tools?.map((t) => ({
128
130
  type: "function",
@@ -201,9 +203,9 @@ export function createProviderInstance(options) {
201
203
  // paths already wrap — this generic chat-completions path did not).
202
204
  try {
203
205
  yield* translateOpenAIStream(stream, {
204
- toolArgsMergeMode: resolveToolArgsMergeMode(options.providerId || "", options.baseURL),
205
- reasoningMergeMode: resolveReasoningMergeMode(options.providerId || "", options.baseURL),
206
- textMergeMode: resolveTextMergeMode(options.providerId || "", options.baseURL),
206
+ toolArgsMergeMode: resolveToolArgsMergeMode(options.providerId || "", options.baseURL || ""),
207
+ reasoningMergeMode: resolveReasoningMergeMode(options.providerId || "", options.baseURL || ""),
208
+ textMergeMode: resolveTextMergeMode(options.providerId || "", options.baseURL || ""),
207
209
  debugProviderId: options.providerId || "",
208
210
  debugModelId: chatOptions.model,
209
211
  });
@@ -211,14 +213,38 @@ export function createProviderInstance(options) {
211
213
  catch (error) {
212
214
  if (chatOptions.abortSignal?.aborted)
213
215
  throw error;
216
+ if (isProviderResponseError(error)) {
217
+ const rateLimited = error.status === 429 || error.errorType === "rate_limit_exceeded";
218
+ if (rateLimited && chatOptions.rateLimitPolicy === "defer") {
219
+ throw new RateLimitError(error.message, {
220
+ status: error.status ?? 429,
221
+ retryAfterMs: error.retryAfterMs,
222
+ cause: error,
223
+ });
224
+ }
225
+ if (isRetryableProviderResponseError(error)) {
226
+ // OpenRouter has already exhausted any pre-stream fallback before it
227
+ // emits a terminal SSE error. One client retry is useful for a fresh
228
+ // route; repeating the previous two-retry socket budget turns a
229
+ // five-minute upstream timeout into a fifteen-minute apparent hang.
230
+ throw new ProviderStreamInterruptedError(error.message, {
231
+ cause: error,
232
+ retryAfterMs: error.retryAfterMs,
233
+ maxRetries: 1,
234
+ });
235
+ }
236
+ throw error;
237
+ }
214
238
  throw new ProviderStreamInterruptedError(`Provider stream interrupted: ${error instanceof Error ? error.message : String(error)}`, { cause: error });
215
239
  }
216
240
  yield { type: "done" };
217
241
  }
218
242
  async function complete(messages, chatOptions) {
219
- const requestConfig = resolveProviderRequestConfig(options.providerId || "", chatOptions?.model ?? fallbackModel, chatOptions?.thinkingLevel ?? options.thinkingLevel ?? "off");
243
+ const model = chatOptions?.model ?? fallbackModel;
244
+ assertProviderModelAllowed(options.providerId || "", model);
245
+ const requestConfig = resolveProviderRequestConfig(options.providerId || "", model, chatOptions?.thinkingLevel ?? options.thinkingLevel ?? "off");
220
246
  const body = {
221
- model: chatOptions?.model ?? fallbackModel,
247
+ model,
222
248
  messages: messages.map((message) => toChatCompletionsMessage(message, {
223
249
  reasoningContentEcho: requestConfig.reasoningContentEcho ?? "tool_calls",
224
250
  })),
@@ -246,7 +272,7 @@ function resolveProviderProtocol(options) {
246
272
  if (options.protocol)
247
273
  return options.protocol;
248
274
  const providerId = (options.providerId || "").toLowerCase();
249
- const baseURL = options.baseURL.toLowerCase();
275
+ const baseURL = (options.baseURL || "").toLowerCase();
250
276
  if (providerId === "doubao"
251
277
  && baseURL.replace(/\/+$/, "") === "https://ark.cn-beijing.volces.com/api/v3") {
252
278
  return "ark-responses";
@@ -260,7 +286,7 @@ function resolveProviderProtocol(options) {
260
286
  }
261
287
  function isMiniMaxOpenAICompatible(options) {
262
288
  const providerId = (options.providerId || "").toLowerCase();
263
- const baseURL = options.baseURL.toLowerCase();
289
+ const baseURL = (options.baseURL || "").toLowerCase();
264
290
  return providerId === "minimax-openai"
265
291
  || (providerId === "minimax" && !baseURL.includes("/anthropic"))
266
292
  || baseURL.includes("api.minimaxi.com/v1")
@@ -488,6 +514,62 @@ function usageToStreamChunk(usage) {
488
514
  },
489
515
  };
490
516
  }
517
+ const RETRYABLE_PROVIDER_ERROR_TYPES = new Set([
518
+ "capacity_exhausted",
519
+ "provider_timeout",
520
+ "rate_limit_exceeded",
521
+ "server",
522
+ "temporarily_unavailable",
523
+ ]);
524
+ function isRetryableProviderResponseError(error) {
525
+ return (error.status !== undefined && isRetryableHttpStatus(error.status))
526
+ || (error.errorType !== undefined && RETRYABLE_PROVIDER_ERROR_TYPES.has(error.errorType));
527
+ }
528
+ function positiveSecondsToMs(value) {
529
+ const seconds = typeof value === "number" ? value : Number(value);
530
+ return Number.isFinite(seconds) && seconds >= 0 ? Math.round(seconds * 1000) : undefined;
531
+ }
532
+ /** Parse HTTP-200 in-band provider errors such as OpenRouter's SSE format. */
533
+ function providerResponseErrorFromChunk(chunk, providerId) {
534
+ const finishReason = chunk?.choices?.[0]?.finish_reason;
535
+ const rawError = chunk?.error;
536
+ if ((!rawError || typeof rawError !== "object") && finishReason !== "error")
537
+ return undefined;
538
+ const metadata = rawError && typeof rawError.metadata === "object" && rawError.metadata !== null
539
+ ? rawError.metadata
540
+ : undefined;
541
+ const availability = metadata && typeof metadata.availability === "object" && metadata.availability !== null
542
+ ? metadata.availability
543
+ : undefined;
544
+ const status = typeof rawError?.code === "number"
545
+ ? rawError.code
546
+ : typeof rawError?.status === "number"
547
+ ? rawError.status
548
+ : undefined;
549
+ const errorType = typeof metadata?.error_type === "string"
550
+ ? metadata.error_type
551
+ : typeof rawError?.type === "string"
552
+ ? rawError.type
553
+ : undefined;
554
+ const retryAfterMs = positiveSecondsToMs(availability?.retry_after ?? metadata?.retry_after ?? rawError?.retry_after);
555
+ const provider = typeof chunk?.provider === "string" && chunk.provider.trim()
556
+ ? chunk.provider.trim()
557
+ : providerId?.trim() || "Provider";
558
+ const details = [
559
+ status !== undefined ? String(status) : undefined,
560
+ errorType,
561
+ ].filter(Boolean).join(", ");
562
+ const rawMessage = typeof rawError?.message === "string" && rawError.message.trim()
563
+ ? rawError.message.trim()
564
+ : "Generation ended with finish_reason=error.";
565
+ const message = `${provider} stream error${details ? ` (${details})` : ""}: ${rawMessage}`;
566
+ return new ProviderResponseError(message, {
567
+ status,
568
+ errorType,
569
+ retryAfterMs,
570
+ cause: rawError,
571
+ });
572
+ }
491
573
  /**
492
574
  * Convert an OpenAI-compatible chat-completions stream into our internal StreamChunk events.
493
575
  *
@@ -557,6 +639,9 @@ export async function* translateOpenAIStream(stream, options = {}) {
557
639
  const delta = choice?.delta;
558
640
  const usage = chunk.usage ?? choice?.usage;
559
641
  const finishReason = choice?.finish_reason;
642
+ const providerError = providerResponseErrorFromChunk(chunk, options.debugProviderId);
643
+ if (providerError)
644
+ throw providerError;
560
645
  if (typeof chunk?.system_fingerprint === "string"
561
646
  && chunk.system_fingerprint
562
647
  && chunk.system_fingerprint !== systemFingerprint) {
@@ -764,8 +849,12 @@ function parsePositiveInt(raw) {
764
849
  const value = Number(raw);
765
850
  return Number.isInteger(value) && value > 0 ? value : undefined;
766
851
  }
767
- /** Largest value Node's 32-bit timers accept; ~24.8 days. */
768
- export const MAX_TIMER_MS = 2_147_483_647; // 2**31 - 1
852
+ /**
853
+ * Largest value that survives the OpenAI SDK's internal `timeout + 1000`
854
+ * agent-grace (core.js minAgentTimeout) without overflowing Node's 32-bit
855
+ * timers; ~24.8 days.
856
+ */
857
+ export const MAX_TIMER_MS = 2_147_482_647; // 2**31 - 1 - 1000
769
858
  /**
770
859
  * Resolve the provider request timeout (ms) from the operator override.
771
860
  *
@@ -1,4 +1,5 @@
1
1
  import { QuestionRejectedError } from "./types.js";
2
+ import { normalizeQuestionInlineText } from "./normalize.js";
2
3
  export class QuestionController {
3
4
  pending = new Map();
4
5
  listeners = new Set();
@@ -74,12 +75,12 @@ export class QuestionController {
74
75
  }
75
76
  function normalizePrompt(input) {
76
77
  return {
77
- header: String(input.header ?? "").trim(),
78
- question: String(input.question ?? "").trim(),
78
+ header: normalizeQuestionInlineText(input.header),
79
+ question: normalizeQuestionInlineText(input.question),
79
80
  options: Array.isArray(input.options)
80
81
  ? input.options.map((option) => ({
81
- label: String(option?.label ?? "").trim(),
82
- description: String(option?.description ?? "").trim(),
82
+ label: normalizeQuestionInlineText(option?.label),
83
+ description: normalizeQuestionInlineText(option?.description),
83
84
  }))
84
85
  : [],
85
86
  multiple: input.multiple === true,
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Structured-question fields are rendered as single terminal rows. Models can
3
+ * still return embedded CR/LF/tab whitespace, so collapse it at the question
4
+ * boundary instead of letting terminal control characters reach a renderer.
5
+ */
6
+ export declare function normalizeQuestionInlineText(value: unknown): string;
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Structured-question fields are rendered as single terminal rows. Models can
3
+ * still return embedded CR/LF/tab whitespace, so collapse it at the question
4
+ * boundary instead of letting terminal control characters reach a renderer.
5
+ */
6
+ export function normalizeQuestionInlineText(value) {
7
+ return String(value ?? "")
8
+ .replace(/\s+/gu, " ")
9
+ .replace(/\s+([,.;:!?,。;:!?、))\]}])/gu, "$1")
10
+ .trim();
11
+ }
@@ -0,0 +1,20 @@
1
+ import type { CheckpointRestoreResult } from "./checkpoints.js";
2
+ import type { SessionManager, UserTurn } from "./session.js";
3
+ import type { Message } from "./types.js";
4
+ export type RewindScope = "all" | "chat" | "code";
5
+ export interface RewindAgentState {
6
+ messages: Message[];
7
+ resetContextUsageAnchor(): void;
8
+ }
9
+ export interface RewindExecutionResult {
10
+ target: UserTurn;
11
+ scope: RewindScope;
12
+ files: CheckpointRestoreResult;
13
+ removedEntries: number;
14
+ }
15
+ /**
16
+ * Apply the persistent rewind exactly once. Renderers layer their own visual
17
+ * transaction around this function, but the session log and Agent transcript
18
+ * always move together here.
19
+ */
20
+ export declare function executeRewind(session: SessionManager, agent: RewindAgentState, targetId: string, scope: RewindScope): Promise<RewindExecutionResult>;
package/dist/rewind.js ADDED
@@ -0,0 +1,29 @@
1
+ const EMPTY_FILE_RESULT = {
2
+ restored: [],
3
+ deleted: [],
4
+ failed: [],
5
+ };
6
+ /**
7
+ * Apply the persistent rewind exactly once. Renderers layer their own visual
8
+ * transaction around this function, but the session log and Agent transcript
9
+ * always move together here.
10
+ */
11
+ export async function executeRewind(session, agent, targetId, scope) {
12
+ const target = session.listUserTurns().find((turn) => turn.id === targetId);
13
+ if (!target)
14
+ throw new Error("The selected rewind point is no longer available.");
15
+ const files = scope === "chat"
16
+ ? { ...EMPTY_FILE_RESULT, restored: [], deleted: [], failed: [] }
17
+ : await session.getCheckpoints().restoreTo(target.id);
18
+ let removedEntries = 0;
19
+ if (scope !== "code") {
20
+ const rewound = session.rewindToEntry(target.id);
21
+ if (!rewound)
22
+ throw new Error("The selected rewind point is no longer available.");
23
+ removedEntries = rewound.removedEntries;
24
+ const head = agent.messages.filter((message) => message.role === "system" || message.role === "meta");
25
+ agent.messages = [...head, ...session.getMessages()];
26
+ agent.resetContextUsageAnchor();
27
+ }
28
+ return { target, scope, files, removedEntries };
29
+ }
@@ -133,7 +133,7 @@ export declare class BubbleSdk {
133
133
  * turn_end events; each cost covers only that step's usage, so hosts sum them.
134
134
  * Events for unpriced models (or without usage) pass through untouched.
135
135
  */
136
- export declare function attachTurnCost(event: AgentEvent, providerId: string, modelId: string): AgentEvent;
136
+ export declare function attachTurnCost(event: AgentEvent, providerId: string, modelId: string, at?: Date): AgentEvent;
137
137
  /**
138
138
  * If the prompt (or its first text part) is a "/<skill-name> <task>" skill
139
139
  * invocation, rewrite it into the same explicit execution prompt the TUI
package/dist/sdk/index.js CHANGED
@@ -29,6 +29,7 @@ import { ProviderRegistry, encodeModel, decodeModel, displayModel } from "../pro
29
29
  import { createProviderInstance } from "../provider.js";
30
30
  import { getDefaultThinkingLevel } from "../variant/variant-resolver.js";
31
31
  import { QuestionController } from "../question/controller.js";
32
+ import { assertProviderModelAllowed } from "../provider-model-policy.js";
32
33
  import { SkillRegistry } from "../skills/registry.js";
33
34
  import { parseSkillInvocation } from "../skills/invocation.js";
34
35
  import { GoalStore } from "../goal/store.js";
@@ -88,6 +89,7 @@ export class BubbleSdk {
88
89
  const registry = new SkillRegistry({
89
90
  cwd: cwd || this.defaultCwd,
90
91
  skillPaths: this.userConfig.getSkillPaths(),
92
+ disabledSkills: this.userConfig.getDisabledSkills(),
91
93
  });
92
94
  return registry.summaries();
93
95
  }
@@ -166,7 +168,11 @@ export class BubbleSdk {
166
168
  });
167
169
  abort.signal.addEventListener("abort", () => questionController.rejectAll(), { once: true });
168
170
  try {
169
- const skillRegistry = new SkillRegistry({ cwd, skillPaths: this.userConfig.getSkillPaths() });
171
+ const skillRegistry = new SkillRegistry({
172
+ cwd,
173
+ skillPaths: this.userConfig.getSkillPaths(),
174
+ disabledSkills: this.userConfig.getDisabledSkills(),
175
+ });
170
176
  const tools = createAllTools(cwd, skillRegistry, {
171
177
  approvalController,
172
178
  fileStateTracker,
@@ -355,6 +361,8 @@ export class BubbleSdk {
355
361
  ? decodeModel(normalized)
356
362
  : { providerId: undefined, modelId: "" };
357
363
  const activeProviderId = effId || fallbackProviderId;
364
+ if (effModelId)
365
+ assertProviderModelAllowed(activeProviderId, effModelId);
358
366
  const target = this.registry.getConfigured().find((p) => p.id === activeProviderId) || defaultProvider;
359
367
  if (!target?.apiKey) {
360
368
  throw new Error("No provider with an API key configured — run the Bubble CLI once to set one up");
@@ -381,10 +389,10 @@ function sessionFileName(sessionId) {
381
389
  * turn_end events; each cost covers only that step's usage, so hosts sum them.
382
390
  * Events for unpriced models (or without usage) pass through untouched.
383
391
  */
384
- export function attachTurnCost(event, providerId, modelId) {
392
+ export function attachTurnCost(event, providerId, modelId, at = new Date()) {
385
393
  if (event.type !== "turn_end" || !event.usage)
386
394
  return event;
387
- const cost = calculateUsageCost(providerId, modelId, event.usage);
395
+ const cost = calculateUsageCost(providerId, modelId, event.usage, at);
388
396
  return cost ? { ...event, cost } : event;
389
397
  }
390
398
  /**
package/dist/session.d.ts CHANGED
@@ -36,6 +36,7 @@ export declare class SessionManager {
36
36
  private sessionFile;
37
37
  private log;
38
38
  private checkpoints?;
39
+ private readonly metadataListeners;
39
40
  constructor(sessionFile: string);
40
41
  static create(cwd: string, sessionName?: string): SessionManager;
41
42
  static resume(cwd: string, sessionName?: string): SessionManager | undefined;
@@ -47,6 +48,12 @@ export declare class SessionManager {
47
48
  private persist;
48
49
  private rewrite;
49
50
  getMetadata(): SessionMetadata;
51
+ /**
52
+ * Subscribe to committed metadata changes (title, model, goal, runtime, ...).
53
+ * Renderers use this instead of polling the session file, so async title
54
+ * generation and runtime switches update fixed UI surfaces immediately.
55
+ */
56
+ subscribeMetadata(listener: (metadata: SessionMetadata) => void): () => void;
50
57
  getOrCreatePromptCacheKey(): string;
51
58
  setMetadata(metadata: SessionMetadata): void;
52
59
  updateMetadata(patch: Partial<SessionMetadata>): void;
package/dist/session.js CHANGED
@@ -17,6 +17,7 @@ export class SessionManager {
17
17
  sessionFile;
18
18
  log = new SessionLog();
19
19
  checkpoints;
20
+ metadataListeners = new Set();
20
21
  constructor(sessionFile) {
21
22
  this.sessionFile = sessionFile;
22
23
  if (existsSync(sessionFile)) {
@@ -113,6 +114,15 @@ export class SessionManager {
113
114
  getMetadata() {
114
115
  return this.log.getMetadata();
115
116
  }
117
+ /**
118
+ * Subscribe to committed metadata changes (title, model, goal, runtime, ...).
119
+ * Renderers use this instead of polling the session file, so async title
120
+ * generation and runtime switches update fixed UI surfaces immediately.
121
+ */
122
+ subscribeMetadata(listener) {
123
+ this.metadataListeners.add(listener);
124
+ return () => this.metadataListeners.delete(listener);
125
+ }
116
126
  getOrCreatePromptCacheKey() {
117
127
  const existing = this.log.getMetadata().promptCacheKey;
118
128
  if (existing)
@@ -124,6 +134,16 @@ export class SessionManager {
124
134
  setMetadata(metadata) {
125
135
  const nextEntries = this.log.setMetadata(metadata);
126
136
  this.rewrite(nextEntries);
137
+ const committed = this.log.getMetadata();
138
+ for (const listener of this.metadataListeners) {
139
+ try {
140
+ listener(committed);
141
+ }
142
+ catch {
143
+ // Persistence already committed. A UI observer must never turn a
144
+ // successful metadata write into an application-level failure.
145
+ }
146
+ }
127
147
  }
128
148
  updateMetadata(patch) {
129
149
  this.setMetadata({
@@ -112,14 +112,32 @@ function normalizeMeta(attributes, fallbackName, filePath, diagnostics) {
112
112
  const tags = Array.isArray(attributes.tags)
113
113
  ? attributes.tags.filter((item) => typeof item === "string" && !!item.trim()).map((item) => item.trim())
114
114
  : undefined;
115
+ const author = typeof attributes.author === "string" && attributes.author.trim()
116
+ ? attributes.author.trim()
117
+ : undefined;
118
+ const allowedTools = normalizeStringList(attributes["allowed-tools"] ?? attributes.allowedTools);
115
119
  return {
116
120
  name,
117
121
  description,
118
122
  disableModelInvocation: attributes["disable-model-invocation"] === true,
119
123
  version: typeof attributes.version === "number" ? attributes.version : undefined,
120
124
  tags: tags && tags.length > 0 ? tags : undefined,
125
+ author,
126
+ allowedTools,
121
127
  };
122
128
  }
129
+ function normalizeStringList(value) {
130
+ const raw = Array.isArray(value)
131
+ ? value
132
+ : typeof value === "string"
133
+ ? value.trim().replace(/^\[(.*)\]$/, "$1").split(",")
134
+ : [];
135
+ const items = raw
136
+ .filter((item) => typeof item === "string")
137
+ .map((item) => item.trim())
138
+ .filter(Boolean);
139
+ return items.length > 0 ? [...new Set(items)] : undefined;
140
+ }
123
141
  function indexResources(rootDir) {
124
142
  return {
125
143
  references: listRelativeFiles(join(rootDir, "references"), rootDir),
@@ -5,14 +5,24 @@ export interface SkillRegistryOptions {
5
5
  agentsHome?: string;
6
6
  claudeHome?: string;
7
7
  skillPaths?: string[];
8
+ disabledSkills?: string[];
9
+ onDisabledSkillsChange?: (disabledSkills: string[]) => void;
8
10
  }
9
11
  export declare class SkillRegistry {
10
- private readonly skills;
11
- private readonly diagnostics;
12
+ private skills;
13
+ private diagnostics;
14
+ private readonly roots;
15
+ private readonly disabledSkills;
16
+ private readonly onDisabledSkillsChange?;
12
17
  constructor(options?: SkillRegistryOptions);
18
+ reload(): void;
13
19
  all(): SkillRecord[];
14
20
  promptVisible(): SkillRecord[];
15
21
  summaries(): SkillSummary[];
16
22
  get(name: string): SkillRecord | undefined;
23
+ getAny(name: string): SkillRecord | undefined;
24
+ isEnabled(name: string): boolean;
25
+ setEnabled(name: string, enabled: boolean): boolean;
26
+ getDisabledSkillNames(): string[];
17
27
  getDiagnostics(): SkillDiagnostic[];
18
28
  }
@@ -3,21 +3,29 @@ import { homedir } from "node:os";
3
3
  import { getBubbleHome } from "../bubble-home.js";
4
4
  import { discoverSkills } from "./discovery.js";
5
5
  export class SkillRegistry {
6
- skills;
7
- diagnostics;
6
+ skills = [];
7
+ diagnostics = [];
8
+ roots;
9
+ disabledSkills;
10
+ onDisabledSkillsChange;
8
11
  constructor(options = {}) {
9
12
  const cwd = options.cwd ?? process.cwd();
10
13
  const bubbleHome = options.bubbleHome ?? getBubbleHome();
11
14
  const agentsHome = options.agentsHome ?? join(homedir(), ".agents");
12
15
  const claudeHome = options.claudeHome ?? join(homedir(), ".claude");
13
- const roots = [
16
+ this.roots = [
14
17
  { path: join(bubbleHome, "skills"), source: "user" },
15
18
  { path: join(agentsHome, "skills"), source: "user" },
16
19
  { path: join(claudeHome, "skills"), source: "user" },
17
20
  { path: join(cwd, ".bubble", "skills"), source: "project" },
18
21
  ...(options.skillPaths ?? []).map((path) => ({ path, source: "configured" })),
19
22
  ];
20
- const result = discoverSkills({ roots });
23
+ this.disabledSkills = new Set(options.disabledSkills ?? []);
24
+ this.onDisabledSkillsChange = options.onDisabledSkillsChange;
25
+ this.reload();
26
+ }
27
+ reload() {
28
+ const result = discoverSkills({ roots: this.roots });
21
29
  this.skills = result.skills;
22
30
  this.diagnostics = result.diagnostics;
23
31
  }
@@ -25,7 +33,7 @@ export class SkillRegistry {
25
33
  return this.skills.slice();
26
34
  }
27
35
  promptVisible() {
28
- return this.skills.filter((skill) => !skill.meta.disableModelInvocation);
36
+ return this.skills.filter((skill) => (this.isEnabled(skill.meta.name) && !skill.meta.disableModelInvocation));
29
37
  }
30
38
  summaries() {
31
39
  return this.promptVisible().map((skill) => ({
@@ -36,8 +44,35 @@ export class SkillRegistry {
36
44
  }));
37
45
  }
38
46
  get(name) {
47
+ if (!this.isEnabled(name))
48
+ return undefined;
49
+ return this.getAny(name);
50
+ }
51
+ getAny(name) {
39
52
  return this.skills.find((skill) => skill.meta.name === name);
40
53
  }
54
+ isEnabled(name) {
55
+ return !this.disabledSkills.has(name);
56
+ }
57
+ setEnabled(name, enabled) {
58
+ if (!this.getAny(name))
59
+ return false;
60
+ let changed = false;
61
+ if (enabled) {
62
+ changed = this.disabledSkills.delete(name);
63
+ }
64
+ else if (!this.disabledSkills.has(name)) {
65
+ this.disabledSkills.add(name);
66
+ changed = true;
67
+ }
68
+ if (!changed)
69
+ return false;
70
+ this.onDisabledSkillsChange?.([...this.disabledSkills].sort((a, b) => a.localeCompare(b)));
71
+ return true;
72
+ }
73
+ getDisabledSkillNames() {
74
+ return [...this.disabledSkills].sort((a, b) => a.localeCompare(b));
75
+ }
41
76
  getDiagnostics() {
42
77
  return this.diagnostics.slice();
43
78
  }
@@ -4,6 +4,8 @@ export interface SkillMeta {
4
4
  disableModelInvocation: boolean;
5
5
  version?: number;
6
6
  tags?: string[];
7
+ author?: string;
8
+ allowedTools?: string[];
7
9
  }
8
10
  export interface SkillResourceIndex {
9
11
  references: string[];