@bubblebrain-ai/bubble 0.0.63 → 0.0.64

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 (912) hide show
  1. package/README.md +437 -11
  2. package/dist/agent/abort-errors.d.ts +18 -0
  3. package/dist/agent/abort-errors.js +51 -0
  4. package/dist/agent/budget-ledger.d.ts +20 -0
  5. package/dist/agent/budget-ledger.js +45 -0
  6. package/dist/agent/categories.d.ts +100 -0
  7. package/dist/agent/categories.js +203 -0
  8. package/dist/agent/change-tracker.d.ts +40 -0
  9. package/dist/agent/change-tracker.js +89 -0
  10. package/dist/agent/child-runner.d.ts +64 -0
  11. package/dist/agent/child-runner.js +405 -0
  12. package/dist/agent/input-controller.d.ts +14 -0
  13. package/dist/agent/input-controller.js +43 -0
  14. package/dist/agent/internal-reminder-sanitizer.d.ts +25 -0
  15. package/dist/agent/internal-reminder-sanitizer.js +297 -0
  16. package/dist/agent/profiles.d.ts +76 -0
  17. package/dist/agent/profiles.js +526 -0
  18. package/dist/agent/provider-fingerprint.d.ts +6 -0
  19. package/dist/agent/provider-fingerprint.js +89 -0
  20. package/dist/agent/resident-history.d.ts +7 -0
  21. package/dist/agent/resident-history.js +61 -0
  22. package/dist/agent/result-integrator.d.ts +22 -0
  23. package/dist/agent/result-integrator.js +50 -0
  24. package/dist/agent/routing-catalog.d.ts +131 -0
  25. package/dist/agent/routing-catalog.js +260 -0
  26. package/dist/agent/structured-output.d.ts +37 -0
  27. package/dist/agent/structured-output.js +193 -0
  28. package/dist/agent/subagent/router.d.ts +65 -0
  29. package/dist/agent/subagent/router.js +203 -0
  30. package/dist/agent/subagent/runtime.d.ts +235 -0
  31. package/dist/agent/subagent/runtime.js +835 -0
  32. package/dist/agent/subagent-control.d.ts +100 -0
  33. package/dist/agent/subagent-control.js +70 -0
  34. package/dist/agent/subagent-lifecycle-reminder.d.ts +3 -0
  35. package/dist/agent/subagent-lifecycle-reminder.js +112 -0
  36. package/dist/agent/subagent-route-format.d.ts +8 -0
  37. package/dist/agent/subagent-route-format.js +18 -0
  38. package/dist/agent/subagent-scheduler.d.ts +105 -0
  39. package/dist/agent/subagent-scheduler.js +287 -0
  40. package/dist/agent/subagent-store.d.ts +57 -0
  41. package/dist/agent/subagent-store.js +180 -0
  42. package/dist/agent/subagent-summary.d.ts +30 -0
  43. package/dist/agent/subagent-summary.js +74 -0
  44. package/dist/agent/subagent-wait-guidance.d.ts +2 -0
  45. package/dist/agent/subagent-wait-guidance.js +8 -0
  46. package/dist/agent/subtask-policy.d.ts +13 -0
  47. package/dist/agent/subtask-policy.js +56 -0
  48. package/dist/agent/task-lifecycle-reminder.d.ts +26 -0
  49. package/dist/agent/task-lifecycle-reminder.js +59 -0
  50. package/dist/agent/tool-intent.d.ts +45 -0
  51. package/dist/agent/tool-intent.js +318 -0
  52. package/dist/agent/tool-visibility.d.ts +10 -0
  53. package/dist/agent/tool-visibility.js +6 -0
  54. package/dist/agent/transcript-helpers.d.ts +20 -0
  55. package/dist/agent/transcript-helpers.js +63 -0
  56. package/dist/agent/update-queue.d.ts +13 -0
  57. package/dist/agent/update-queue.js +69 -0
  58. package/dist/agent/workflow/control.d.ts +60 -0
  59. package/dist/agent/workflow/control.js +62 -0
  60. package/dist/agent/workflow/errors.d.ts +16 -0
  61. package/dist/agent/workflow/errors.js +24 -0
  62. package/dist/agent/workflow/runs.d.ts +73 -0
  63. package/dist/agent/workflow/runs.js +160 -0
  64. package/dist/agent/workflow/runtime.d.ts +88 -0
  65. package/dist/agent/workflow/runtime.js +319 -0
  66. package/dist/agent/worktree.d.ts +29 -0
  67. package/dist/agent/worktree.js +73 -0
  68. package/dist/agent.d.ts +460 -0
  69. package/dist/agent.js +2210 -0
  70. package/dist/anthropic-thinking.d.ts +4 -0
  71. package/dist/anthropic-thinking.js +11 -0
  72. package/dist/approval/controller.d.ts +71 -0
  73. package/dist/approval/controller.js +286 -0
  74. package/dist/approval/danger.d.ts +13 -0
  75. package/dist/approval/danger.js +55 -0
  76. package/dist/approval/diff-hunks.d.ts +12 -0
  77. package/dist/approval/diff-hunks.js +32 -0
  78. package/dist/approval/protected-paths.d.ts +1 -0
  79. package/dist/approval/protected-paths.js +35 -0
  80. package/dist/approval/session-cache.d.ts +21 -0
  81. package/dist/approval/session-cache.js +38 -0
  82. package/dist/approval/tool-helper.d.ts +14 -0
  83. package/dist/approval/tool-helper.js +47 -0
  84. package/dist/approval/types.d.ts +146 -0
  85. package/dist/approval/types.js +8 -0
  86. package/dist/bin.d.ts +2 -0
  87. package/dist/bin.js +3 -0
  88. package/dist/bubble-home.d.ts +8 -0
  89. package/dist/bubble-home.js +19 -0
  90. package/dist/checkpoints.d.ts +57 -0
  91. package/dist/checkpoints.js +0 -0
  92. package/dist/cli.d.ts +37 -0
  93. package/dist/cli.js +175 -0
  94. package/dist/clipboard.d.ts +14 -0
  95. package/dist/clipboard.js +132 -0
  96. package/dist/config.d.ts +96 -0
  97. package/dist/config.js +287 -0
  98. package/dist/context/budget.d.ts +28 -0
  99. package/dist/context/budget.js +130 -0
  100. package/dist/context/checkpoint.d.ts +18 -0
  101. package/dist/context/checkpoint.js +117 -0
  102. package/dist/context/compact-llm.d.ts +25 -0
  103. package/dist/context/compact-llm.js +175 -0
  104. package/dist/context/compact.d.ts +124 -0
  105. package/dist/context/compact.js +635 -0
  106. package/dist/context/compaction-files.d.ts +44 -0
  107. package/dist/context/compaction-files.js +148 -0
  108. package/dist/context/llm-compactor.d.ts +53 -0
  109. package/dist/context/llm-compactor.js +424 -0
  110. package/dist/context/overflow.d.ts +9 -0
  111. package/dist/context/overflow.js +50 -0
  112. package/dist/context/projector.d.ts +34 -0
  113. package/dist/context/projector.js +251 -0
  114. package/dist/context/prune.d.ts +26 -0
  115. package/dist/context/prune.js +171 -0
  116. package/dist/context/session-write-lock.d.ts +20 -0
  117. package/dist/context/session-write-lock.js +162 -0
  118. package/dist/context/token-estimator.d.ts +14 -0
  119. package/dist/context/token-estimator.js +106 -0
  120. package/dist/context/tool-images.d.ts +3 -0
  121. package/dist/context/tool-images.js +35 -0
  122. package/dist/context/tool-output-truncate.d.ts +24 -0
  123. package/dist/context/tool-output-truncate.js +181 -0
  124. package/dist/context/usage.d.ts +34 -0
  125. package/dist/context/usage.js +230 -0
  126. package/dist/debug-trace.d.ts +27 -0
  127. package/dist/debug-trace.js +401 -0
  128. package/dist/diff-stats.d.ts +5 -0
  129. package/dist/diff-stats.js +21 -0
  130. package/dist/external-runtime/grok-acp.d.ts +56 -0
  131. package/dist/external-runtime/grok-acp.js +386 -0
  132. package/dist/external-runtime/grok-binary.d.ts +25 -0
  133. package/dist/external-runtime/grok-binary.js +108 -0
  134. package/dist/external-runtime/grok-errors.d.ts +7 -0
  135. package/dist/external-runtime/grok-errors.js +15 -0
  136. package/dist/external-runtime/grok-input-policy.d.ts +58 -0
  137. package/dist/external-runtime/grok-input-policy.js +52 -0
  138. package/dist/external-runtime/grok-ndjson.d.ts +14 -0
  139. package/dist/external-runtime/grok-ndjson.js +193 -0
  140. package/dist/external-runtime/grok-network.d.ts +15 -0
  141. package/dist/external-runtime/grok-network.js +81 -0
  142. package/dist/external-runtime/grok-preflight.d.ts +28 -0
  143. package/dist/external-runtime/grok-preflight.js +194 -0
  144. package/dist/external-runtime/grok-process.d.ts +26 -0
  145. package/dist/external-runtime/grok-process.js +184 -0
  146. package/dist/external-runtime/grok-profile.d.ts +32 -0
  147. package/dist/external-runtime/grok-profile.js +419 -0
  148. package/dist/external-runtime/grok-provider.d.ts +31 -0
  149. package/dist/external-runtime/grok-provider.js +41 -0
  150. package/dist/external-runtime/grok-runtime.d.ts +91 -0
  151. package/dist/external-runtime/grok-runtime.js +882 -0
  152. package/dist/external-runtime/index.d.ts +13 -0
  153. package/dist/external-runtime/index.js +13 -0
  154. package/dist/external-runtime/session-policy.d.ts +11 -0
  155. package/dist/external-runtime/session-policy.js +30 -0
  156. package/dist/external-runtime/types.d.ts +65 -0
  157. package/dist/external-runtime/types.js +1 -0
  158. package/dist/feedback/collect.d.ts +7 -0
  159. package/dist/feedback/collect.js +119 -0
  160. package/dist/feedback/config.d.ts +14 -0
  161. package/dist/feedback/config.js +16 -0
  162. package/dist/feedback/redact.d.ts +1 -0
  163. package/dist/feedback/redact.js +25 -0
  164. package/dist/feedback/submit.d.ts +6 -0
  165. package/dist/feedback/submit.js +43 -0
  166. package/dist/feedback/types.d.ts +22 -0
  167. package/dist/feedback/types.js +1 -0
  168. package/dist/feishu/agent-host/approval-card.d.ts +11 -0
  169. package/dist/feishu/agent-host/approval-card.js +85 -0
  170. package/dist/feishu/agent-host/approval-ui.d.ts +59 -0
  171. package/dist/feishu/agent-host/approval-ui.js +214 -0
  172. package/dist/feishu/agent-host/run-driver.d.ts +51 -0
  173. package/dist/feishu/agent-host/run-driver.js +397 -0
  174. package/dist/feishu/agent-host/runtime-deps.d.ts +33 -0
  175. package/dist/feishu/agent-host/runtime-deps.js +8 -0
  176. package/dist/feishu/card/budget.d.ts +40 -0
  177. package/dist/feishu/card/budget.js +134 -0
  178. package/dist/feishu/card/renderer.d.ts +29 -0
  179. package/dist/feishu/card/renderer.js +245 -0
  180. package/dist/feishu/card/run-state-types.d.ts +49 -0
  181. package/dist/feishu/card/run-state-types.js +15 -0
  182. package/dist/feishu/card/run-state.d.ts +21 -0
  183. package/dist/feishu/card/run-state.js +223 -0
  184. package/dist/feishu/channel/channel.d.ts +52 -0
  185. package/dist/feishu/channel/channel.js +74 -0
  186. package/dist/feishu/config.d.ts +24 -0
  187. package/dist/feishu/config.js +97 -0
  188. package/dist/feishu/format.d.ts +6 -0
  189. package/dist/feishu/format.js +14 -0
  190. package/dist/feishu/index.d.ts +4 -0
  191. package/dist/feishu/index.js +4 -0
  192. package/dist/feishu/logger.d.ts +31 -0
  193. package/dist/feishu/logger.js +62 -0
  194. package/dist/feishu/paths.d.ts +12 -0
  195. package/dist/feishu/paths.js +38 -0
  196. package/dist/feishu/process-registry.d.ts +29 -0
  197. package/dist/feishu/process-registry.js +90 -0
  198. package/dist/feishu/router/commands.d.ts +38 -0
  199. package/dist/feishu/router/commands.js +286 -0
  200. package/dist/feishu/router/event-router.d.ts +40 -0
  201. package/dist/feishu/router/event-router.js +208 -0
  202. package/dist/feishu/router/whitelist.d.ts +23 -0
  203. package/dist/feishu/router/whitelist.js +20 -0
  204. package/dist/feishu/runtime/active-runs.d.ts +32 -0
  205. package/dist/feishu/runtime/active-runs.js +84 -0
  206. package/dist/feishu/runtime/pending-queue.d.ts +36 -0
  207. package/dist/feishu/runtime/pending-queue.js +98 -0
  208. package/dist/feishu/runtime/process-pool.d.ts +29 -0
  209. package/dist/feishu/runtime/process-pool.js +49 -0
  210. package/dist/feishu/schema.d.ts +17 -0
  211. package/dist/feishu/schema.js +252 -0
  212. package/dist/feishu/scope/scope-registry.d.ts +39 -0
  213. package/dist/feishu/scope/scope-registry.js +148 -0
  214. package/dist/feishu/scope/session-binder.d.ts +44 -0
  215. package/dist/feishu/scope/session-binder.js +100 -0
  216. package/dist/feishu/scope/session-store.d.ts +24 -0
  217. package/dist/feishu/scope/session-store.js +73 -0
  218. package/dist/feishu/secrets.d.ts +37 -0
  219. package/dist/feishu/secrets.js +129 -0
  220. package/dist/feishu/serve.d.ts +12 -0
  221. package/dist/feishu/serve.js +302 -0
  222. package/dist/feishu/types.d.ts +75 -0
  223. package/dist/feishu/types.js +23 -0
  224. package/dist/feishu/wizard.d.ts +24 -0
  225. package/dist/feishu/wizard.js +121 -0
  226. package/dist/goal/command.d.ts +20 -0
  227. package/dist/goal/command.js +76 -0
  228. package/dist/goal/engine.d.ts +33 -0
  229. package/dist/goal/engine.js +65 -0
  230. package/dist/goal/format.d.ts +18 -0
  231. package/dist/goal/format.js +112 -0
  232. package/dist/goal/prompts.d.ts +13 -0
  233. package/dist/goal/prompts.js +84 -0
  234. package/dist/goal/store.d.ts +64 -0
  235. package/dist/goal/store.js +174 -0
  236. package/dist/goal/tools.d.ts +13 -0
  237. package/dist/goal/tools.js +67 -0
  238. package/dist/goal/usage.d.ts +2 -0
  239. package/dist/goal/usage.js +3 -0
  240. package/dist/hooks/config.d.ts +9 -0
  241. package/dist/hooks/config.js +278 -0
  242. package/dist/hooks/controller.d.ts +24 -0
  243. package/dist/hooks/controller.js +254 -0
  244. package/dist/hooks/index.d.ts +6 -0
  245. package/dist/hooks/index.js +4 -0
  246. package/dist/hooks/log.d.ts +14 -0
  247. package/dist/hooks/log.js +54 -0
  248. package/dist/hooks/runner.d.ts +5 -0
  249. package/dist/hooks/runner.js +225 -0
  250. package/dist/hooks/trust.d.ts +37 -0
  251. package/dist/hooks/trust.js +143 -0
  252. package/dist/hooks/types.d.ts +173 -0
  253. package/dist/hooks/types.js +46 -0
  254. package/dist/loop/engine.d.ts +29 -0
  255. package/dist/loop/engine.js +63 -0
  256. package/dist/lsp/config.d.ts +18 -0
  257. package/dist/lsp/config.js +58 -0
  258. package/dist/lsp/diagnostics.d.ts +24 -0
  259. package/dist/lsp/diagnostics.js +103 -0
  260. package/dist/lsp/index.d.ts +3 -0
  261. package/dist/lsp/index.js +3 -0
  262. package/dist/lsp/service.d.ts +97 -0
  263. package/dist/lsp/service.js +815 -0
  264. package/dist/main.d.ts +5 -0
  265. package/dist/main.js +984 -0
  266. package/dist/mcp/client.d.ts +68 -0
  267. package/dist/mcp/client.js +177 -0
  268. package/dist/mcp/config.d.ts +30 -0
  269. package/dist/mcp/config.js +144 -0
  270. package/dist/mcp/manager.d.ts +67 -0
  271. package/dist/mcp/manager.js +328 -0
  272. package/dist/mcp/name.d.ts +26 -0
  273. package/dist/mcp/name.js +40 -0
  274. package/dist/mcp/transports.d.ts +54 -0
  275. package/dist/mcp/transports.js +267 -0
  276. package/dist/mcp/types.d.ts +111 -0
  277. package/dist/mcp/types.js +14 -0
  278. package/dist/memory/db.d.ts +65 -0
  279. package/dist/memory/db.js +332 -0
  280. package/dist/memory/index.d.ts +10 -0
  281. package/dist/memory/index.js +10 -0
  282. package/dist/memory/paths.d.ts +18 -0
  283. package/dist/memory/paths.js +38 -0
  284. package/dist/memory/phase1.d.ts +23 -0
  285. package/dist/memory/phase1.js +292 -0
  286. package/dist/memory/phase2.d.ts +19 -0
  287. package/dist/memory/phase2.js +119 -0
  288. package/dist/memory/prompts.d.ts +19 -0
  289. package/dist/memory/prompts.js +104 -0
  290. package/dist/memory/reset.d.ts +1 -0
  291. package/dist/memory/reset.js +13 -0
  292. package/dist/memory/session-policy.d.ts +25 -0
  293. package/dist/memory/session-policy.js +55 -0
  294. package/dist/memory/start.d.ts +24 -0
  295. package/dist/memory/start.js +50 -0
  296. package/dist/memory/storage.d.ts +11 -0
  297. package/dist/memory/storage.js +95 -0
  298. package/dist/memory/store.d.ts +43 -0
  299. package/dist/memory/store.js +193 -0
  300. package/dist/memory/usage.d.ts +1 -0
  301. package/dist/memory/usage.js +38 -0
  302. package/dist/model-catalog.d.ts +65 -0
  303. package/dist/model-catalog.js +387 -0
  304. package/dist/model-config.d.ts +40 -0
  305. package/dist/model-config.js +74 -0
  306. package/dist/model-data.generated.d.ts +16 -0
  307. package/dist/model-data.generated.js +275 -0
  308. package/dist/model-pricing.d.ts +54 -0
  309. package/dist/model-pricing.js +244 -0
  310. package/dist/model-selection.d.ts +7 -0
  311. package/dist/model-selection.js +18 -0
  312. package/dist/network/chatgpt-transport.d.ts +16 -0
  313. package/dist/network/chatgpt-transport.js +232 -0
  314. package/dist/network/errors.d.ts +47 -0
  315. package/dist/network/errors.js +48 -0
  316. package/dist/network/provider-transport-log.d.ts +12 -0
  317. package/dist/network/provider-transport-log.js +32 -0
  318. package/dist/network/provider-transport.d.ts +37 -0
  319. package/dist/network/provider-transport.js +256 -0
  320. package/dist/network/retry.d.ts +34 -0
  321. package/dist/network/retry.js +97 -0
  322. package/dist/network/system-proxy.d.ts +18 -0
  323. package/dist/network/system-proxy.js +175 -0
  324. package/dist/oauth/grok.d.ts +26 -0
  325. package/dist/oauth/grok.js +251 -0
  326. package/dist/oauth/index.d.ts +4 -0
  327. package/dist/oauth/index.js +3 -0
  328. package/dist/oauth/openai-codex.d.ts +15 -0
  329. package/dist/oauth/openai-codex.js +193 -0
  330. package/dist/oauth/refresh-control.d.ts +12 -0
  331. package/dist/oauth/refresh-control.js +42 -0
  332. package/dist/oauth/storage.d.ts +88 -0
  333. package/dist/oauth/storage.js +357 -0
  334. package/dist/oauth/types.d.ts +15 -0
  335. package/dist/oauth/types.js +1 -0
  336. package/dist/orchestrator/default-hooks.d.ts +22 -0
  337. package/dist/orchestrator/default-hooks.js +127 -0
  338. package/dist/orchestrator/hooks.d.ts +69 -0
  339. package/dist/orchestrator/hooks.js +52 -0
  340. package/dist/permission/mode.d.ts +19 -0
  341. package/dist/permission/mode.js +16 -0
  342. package/dist/permissions/rule.d.ts +42 -0
  343. package/dist/permissions/rule.js +293 -0
  344. package/dist/permissions/settings.d.ts +97 -0
  345. package/dist/permissions/settings.js +289 -0
  346. package/dist/permissions/shell-command.d.ts +36 -0
  347. package/dist/permissions/shell-command.js +226 -0
  348. package/dist/permissions/trust-prompt.d.ts +10 -0
  349. package/dist/permissions/trust-prompt.js +34 -0
  350. package/dist/permissions/trust.d.ts +26 -0
  351. package/dist/permissions/trust.js +113 -0
  352. package/dist/permissions/types.d.ts +61 -0
  353. package/dist/permissions/types.js +14 -0
  354. package/dist/print-output.d.ts +98 -0
  355. package/dist/print-output.js +117 -0
  356. package/dist/prompt/compose.d.ts +19 -0
  357. package/dist/prompt/compose.js +110 -0
  358. package/dist/prompt/delegation.d.ts +14 -0
  359. package/dist/prompt/delegation.js +100 -0
  360. package/dist/prompt/environment.d.ts +12 -0
  361. package/dist/prompt/environment.js +55 -0
  362. package/dist/prompt/provider-prompts/anthropic.d.ts +1 -0
  363. package/dist/prompt/provider-prompts/anthropic.js +5 -0
  364. package/dist/prompt/provider-prompts/codex.d.ts +1 -0
  365. package/dist/prompt/provider-prompts/codex.js +5 -0
  366. package/dist/prompt/provider-prompts/deepseek.d.ts +1 -0
  367. package/dist/prompt/provider-prompts/deepseek.js +7 -0
  368. package/dist/prompt/provider-prompts/default.d.ts +1 -0
  369. package/dist/prompt/provider-prompts/default.js +6 -0
  370. package/dist/prompt/provider-prompts/gemini.d.ts +1 -0
  371. package/dist/prompt/provider-prompts/gemini.js +5 -0
  372. package/dist/prompt/provider-prompts/glm.d.ts +1 -0
  373. package/dist/prompt/provider-prompts/glm.js +7 -0
  374. package/dist/prompt/provider-prompts/gpt.d.ts +1 -0
  375. package/dist/prompt/provider-prompts/gpt.js +5 -0
  376. package/dist/prompt/provider-prompts/kimi.d.ts +1 -0
  377. package/dist/prompt/provider-prompts/kimi.js +8 -0
  378. package/dist/prompt/reminders.d.ts +33 -0
  379. package/dist/prompt/reminders.js +135 -0
  380. package/dist/prompt/routing.d.ts +14 -0
  381. package/dist/prompt/routing.js +71 -0
  382. package/dist/prompt/runtime.d.ts +12 -0
  383. package/dist/prompt/runtime.js +40 -0
  384. package/dist/prompt/task-reminders.d.ts +12 -0
  385. package/dist/prompt/task-reminders.js +64 -0
  386. package/dist/provider-ai-sdk.d.ts +59 -0
  387. package/dist/provider-ai-sdk.js +541 -0
  388. package/dist/provider-anthropic.d.ts +126 -0
  389. package/dist/provider-anthropic.js +940 -0
  390. package/dist/provider-ark-responses.d.ts +29 -0
  391. package/dist/provider-ark-responses.js +518 -0
  392. package/dist/provider-artifacts.d.ts +7 -0
  393. package/dist/provider-artifacts.js +60 -0
  394. package/dist/provider-error-record.d.ts +43 -0
  395. package/dist/provider-error-record.js +213 -0
  396. package/dist/provider-grok.d.ts +50 -0
  397. package/dist/provider-grok.js +110 -0
  398. package/dist/provider-model-policy.d.ts +16 -0
  399. package/dist/provider-model-policy.js +33 -0
  400. package/dist/provider-openai-codex.d.ts +66 -0
  401. package/dist/provider-openai-codex.js +781 -0
  402. package/dist/provider-registry.d.ts +197 -0
  403. package/dist/provider-registry.js +1194 -0
  404. package/dist/provider-transform.d.ts +12 -0
  405. package/dist/provider-transform.js +293 -0
  406. package/dist/provider-zen-errors.d.ts +9 -0
  407. package/dist/provider-zen-errors.js +36 -0
  408. package/dist/provider.d.ts +85 -0
  409. package/dist/provider.js +925 -0
  410. package/dist/question/controller.d.ts +22 -0
  411. package/dist/question/controller.js +98 -0
  412. package/dist/question/index.d.ts +2 -0
  413. package/dist/question/index.js +2 -0
  414. package/dist/question/normalize.d.ts +6 -0
  415. package/dist/question/normalize.js +11 -0
  416. package/dist/question/types.d.ts +42 -0
  417. package/dist/question/types.js +6 -0
  418. package/dist/reasoning-debug.d.ts +7 -0
  419. package/dist/reasoning-debug.js +33 -0
  420. package/dist/rewind.d.ts +20 -0
  421. package/dist/rewind.js +29 -0
  422. package/dist/sdk/index.d.ts +319 -0
  423. package/dist/sdk/index.js +1068 -0
  424. package/dist/sdk/replay-event-log.d.ts +26 -0
  425. package/dist/sdk/replay-event-log.js +122 -0
  426. package/dist/sdk/session-turn-coordinator.d.ts +45 -0
  427. package/dist/sdk/session-turn-coordinator.js +227 -0
  428. package/dist/session-context-fence.d.ts +16 -0
  429. package/dist/session-context-fence.js +26 -0
  430. package/dist/session-log.d.ts +25 -0
  431. package/dist/session-log.js +444 -0
  432. package/dist/session-title.d.ts +16 -0
  433. package/dist/session-title.js +131 -0
  434. package/dist/session-types.d.ts +86 -0
  435. package/dist/session-types.js +1 -0
  436. package/dist/session.d.ts +135 -0
  437. package/dist/session.js +664 -0
  438. package/dist/skills/discovery.d.ts +12 -0
  439. package/dist/skills/discovery.js +166 -0
  440. package/dist/skills/format.d.ts +32 -0
  441. package/dist/skills/format.js +68 -0
  442. package/dist/skills/frontmatter.d.ts +5 -0
  443. package/dist/skills/frontmatter.js +60 -0
  444. package/dist/skills/invocation.d.ts +8 -0
  445. package/dist/skills/invocation.js +33 -0
  446. package/dist/skills/registry.d.ts +28 -0
  447. package/dist/skills/registry.js +79 -0
  448. package/dist/skills/types.d.ts +34 -0
  449. package/dist/skills/types.js +1 -0
  450. package/dist/slash-commands/commands.d.ts +10 -0
  451. package/dist/slash-commands/commands.js +1251 -0
  452. package/dist/slash-commands/feishu.d.ts +17 -0
  453. package/dist/slash-commands/feishu.js +400 -0
  454. package/dist/slash-commands/index.d.ts +4 -0
  455. package/dist/slash-commands/index.js +8 -0
  456. package/dist/slash-commands/registry.d.ts +32 -0
  457. package/dist/slash-commands/registry.js +73 -0
  458. package/dist/slash-commands/types.d.ts +109 -0
  459. package/dist/slash-commands/types.js +1 -0
  460. package/dist/slash-commands/unified.d.ts +38 -0
  461. package/dist/slash-commands/unified.js +38 -0
  462. package/dist/stats/usage.d.ts +59 -0
  463. package/dist/stats/usage.js +485 -0
  464. package/dist/stream-json.d.ts +13 -0
  465. package/dist/stream-json.js +74 -0
  466. package/dist/system-prompt.d.ts +40 -0
  467. package/dist/system-prompt.js +7 -0
  468. package/dist/tasks/manager.d.ts +145 -0
  469. package/dist/tasks/manager.js +634 -0
  470. package/dist/tasks/process-utils.d.ts +10 -0
  471. package/dist/tasks/process-utils.js +49 -0
  472. package/dist/tasks/promotion.d.ts +17 -0
  473. package/dist/tasks/promotion.js +30 -0
  474. package/dist/tasks/wake.d.ts +53 -0
  475. package/dist/tasks/wake.js +125 -0
  476. package/dist/text-display.d.ts +3 -0
  477. package/dist/text-display.js +25 -0
  478. package/dist/tools/agent-lifecycle.d.ts +30 -0
  479. package/dist/tools/agent-lifecycle.js +790 -0
  480. package/dist/tools/bash.d.ts +23 -0
  481. package/dist/tools/bash.js +443 -0
  482. package/dist/tools/child-tools.d.ts +41 -0
  483. package/dist/tools/child-tools.js +122 -0
  484. package/dist/tools/edit-apply.d.ts +25 -0
  485. package/dist/tools/edit-apply.js +274 -0
  486. package/dist/tools/edit.d.ts +18 -0
  487. package/dist/tools/edit.js +200 -0
  488. package/dist/tools/exa-mcp.d.ts +3 -0
  489. package/dist/tools/exa-mcp.js +74 -0
  490. package/dist/tools/exit-plan-mode.d.ts +22 -0
  491. package/dist/tools/exit-plan-mode.js +79 -0
  492. package/dist/tools/file-mutation-queue.d.ts +2 -0
  493. package/dist/tools/file-mutation-queue.js +43 -0
  494. package/dist/tools/file-state.d.ts +48 -0
  495. package/dist/tools/file-state.js +76 -0
  496. package/dist/tools/grep.d.ts +9 -0
  497. package/dist/tools/grep.js +387 -0
  498. package/dist/tools/index.d.ts +63 -0
  499. package/dist/tools/index.js +76 -0
  500. package/dist/tools/ls.d.ts +3 -0
  501. package/dist/tools/ls.js +85 -0
  502. package/dist/tools/lsp.d.ts +4 -0
  503. package/dist/tools/lsp.js +95 -0
  504. package/dist/tools/memory.d.ts +8 -0
  505. package/dist/tools/memory.js +77 -0
  506. package/dist/tools/path-utils.d.ts +8 -0
  507. package/dist/tools/path-utils.js +53 -0
  508. package/dist/tools/prompt-metadata.d.ts +3 -0
  509. package/dist/tools/prompt-metadata.js +17 -0
  510. package/dist/tools/question.d.ts +3 -0
  511. package/dist/tools/question.js +177 -0
  512. package/dist/tools/read.d.ts +8 -0
  513. package/dist/tools/read.js +309 -0
  514. package/dist/tools/sensitive-paths.d.ts +11 -0
  515. package/dist/tools/sensitive-paths.js +106 -0
  516. package/dist/tools/server-manager.d.ts +6 -0
  517. package/dist/tools/server-manager.js +6 -0
  518. package/dist/tools/server.d.ts +6 -0
  519. package/dist/tools/server.js +249 -0
  520. package/dist/tools/skill-search.d.ts +10 -0
  521. package/dist/tools/skill-search.js +134 -0
  522. package/dist/tools/skill.d.ts +7 -0
  523. package/dist/tools/skill.js +81 -0
  524. package/dist/tools/task-tools.d.ts +10 -0
  525. package/dist/tools/task-tools.js +133 -0
  526. package/dist/tools/tool-search.d.ts +23 -0
  527. package/dist/tools/tool-search.js +145 -0
  528. package/dist/tools/web-fetch.d.ts +6 -0
  529. package/dist/tools/web-fetch.js +76 -0
  530. package/dist/tools/web-search.d.ts +5 -0
  531. package/dist/tools/web-search.js +50 -0
  532. package/dist/tools/write.d.ts +10 -0
  533. package/dist/tools/write.js +155 -0
  534. package/dist/tui/animation-clock.d.ts +14 -0
  535. package/dist/tui/animation-clock.js +34 -0
  536. package/dist/tui/app.d.ts +176 -0
  537. package/dist/tui/app.js +1659 -0
  538. package/dist/tui/components/approval-dialog.d.ts +43 -0
  539. package/dist/tui/components/approval-dialog.js +212 -0
  540. package/dist/tui/components/bottom-sheet.d.ts +9 -0
  541. package/dist/tui/components/bottom-sheet.js +32 -0
  542. package/dist/tui/components/context-info.d.ts +54 -0
  543. package/dist/tui/components/context-info.js +388 -0
  544. package/dist/tui/components/feedback-dialog.d.ts +56 -0
  545. package/dist/tui/components/feedback-dialog.js +262 -0
  546. package/dist/tui/components/feishu-setup-dialog.d.ts +65 -0
  547. package/dist/tui/components/feishu-setup-dialog.js +332 -0
  548. package/dist/tui/components/image-preview.d.ts +32 -0
  549. package/dist/tui/components/image-preview.js +130 -0
  550. package/dist/tui/components/plan-dialog.d.ts +34 -0
  551. package/dist/tui/components/plan-dialog.js +196 -0
  552. package/dist/tui/components/provider-key-input.d.ts +18 -0
  553. package/dist/tui/components/provider-key-input.js +49 -0
  554. package/dist/tui/components/question-dialog.d.ts +25 -0
  555. package/dist/tui/components/question-dialog.js +263 -0
  556. package/dist/tui/components/responsive-transcript.d.ts +31 -0
  557. package/dist/tui/components/responsive-transcript.js +77 -0
  558. package/dist/tui/components/rewind-picker.d.ts +62 -0
  559. package/dist/tui/components/rewind-picker.js +317 -0
  560. package/dist/tui/components/session-picker.d.ts +49 -0
  561. package/dist/tui/components/session-picker.js +303 -0
  562. package/dist/tui/components/skills-panel.d.ts +63 -0
  563. package/dist/tui/components/skills-panel.js +582 -0
  564. package/dist/tui/components/stats-panel.d.ts +40 -0
  565. package/dist/tui/components/stats-panel.js +301 -0
  566. package/dist/tui/components/streaming-message.d.ts +69 -0
  567. package/dist/tui/components/streaming-message.js +398 -0
  568. package/dist/tui/components/subagent-inspector.d.ts +28 -0
  569. package/dist/tui/components/subagent-inspector.js +127 -0
  570. package/dist/tui/components/task-inspector.d.ts +26 -0
  571. package/dist/tui/components/task-inspector.js +70 -0
  572. package/dist/tui/components/tasks-pane.d.ts +126 -0
  573. package/dist/tui/components/tasks-pane.js +566 -0
  574. package/dist/tui/components/transcript.d.ts +103 -0
  575. package/dist/tui/components/transcript.js +858 -0
  576. package/dist/tui/components/welcome.d.ts +20 -0
  577. package/dist/tui/components/welcome.js +133 -0
  578. package/dist/tui/components/workflow-inspector.d.ts +30 -0
  579. package/dist/tui/components/workflow-inspector.js +136 -0
  580. package/dist/tui/composer-autocomplete.d.ts +76 -0
  581. package/dist/tui/composer-autocomplete.js +465 -0
  582. package/dist/tui/composer-style.d.ts +7 -0
  583. package/dist/tui/composer-style.js +29 -0
  584. package/dist/tui/controller/agent-event-reducer.d.ts +75 -0
  585. package/dist/tui/controller/agent-event-reducer.js +239 -0
  586. package/dist/tui/controller/composer-controller.d.ts +95 -0
  587. package/dist/tui/controller/composer-controller.js +502 -0
  588. package/dist/tui/controller/controller.d.ts +199 -0
  589. package/dist/tui/controller/controller.js +1034 -0
  590. package/dist/tui/controller/effects.d.ts +71 -0
  591. package/dist/tui/controller/effects.js +1 -0
  592. package/dist/tui/controller/goal-runtime-controller.d.ts +47 -0
  593. package/dist/tui/controller/goal-runtime-controller.js +202 -0
  594. package/dist/tui/controller/input-queue-machine.d.ts +71 -0
  595. package/dist/tui/controller/input-queue-machine.js +121 -0
  596. package/dist/tui/controller/intents.d.ts +56 -0
  597. package/dist/tui/controller/intents.js +6 -0
  598. package/dist/tui/controller/overlay-controller.d.ts +64 -0
  599. package/dist/tui/controller/overlay-controller.js +129 -0
  600. package/dist/tui/controller/ports.d.ts +57 -0
  601. package/dist/tui/controller/ports.js +9 -0
  602. package/dist/tui/controller/session-transition.d.ts +54 -0
  603. package/dist/tui/controller/session-transition.js +68 -0
  604. package/dist/tui/controller/state.d.ts +14 -0
  605. package/dist/tui/controller/state.js +36 -0
  606. package/dist/tui/controller/task-runtime-controller.d.ts +66 -0
  607. package/dist/tui/controller/task-runtime-controller.js +158 -0
  608. package/dist/tui/detect-theme.d.ts +4 -0
  609. package/dist/tui/detect-theme.js +116 -0
  610. package/dist/tui/display-history.d.ts +64 -0
  611. package/dist/tui/display-history.js +283 -0
  612. package/dist/tui/display-sanitizer.d.ts +3 -0
  613. package/dist/tui/display-sanitizer.js +38 -0
  614. package/dist/tui/edit-diff.d.ts +11 -0
  615. package/dist/tui/edit-diff.js +57 -0
  616. package/dist/tui/file-mentions.d.ts +29 -0
  617. package/dist/tui/file-mentions.js +174 -0
  618. package/dist/tui/footer.d.ts +37 -0
  619. package/dist/tui/footer.js +80 -0
  620. package/dist/tui/formatting/edit-diff.d.ts +11 -0
  621. package/dist/tui/formatting/edit-diff.js +52 -0
  622. package/dist/tui/formatting/summary.d.ts +43 -0
  623. package/dist/tui/formatting/summary.js +150 -0
  624. package/dist/tui/fullscreen.d.ts +48 -0
  625. package/dist/tui/fullscreen.js +256 -0
  626. package/dist/tui/image-display.d.ts +23 -0
  627. package/dist/tui/image-display.js +92 -0
  628. package/dist/tui/image-paste.d.ts +113 -0
  629. package/dist/tui/image-paste.js +565 -0
  630. package/dist/tui/input-history.d.ts +47 -0
  631. package/dist/tui/input-history.js +250 -0
  632. package/dist/tui/markdown-style.d.ts +5 -0
  633. package/dist/tui/markdown-style.js +23 -0
  634. package/dist/tui/model/composer-buffer.d.ts +55 -0
  635. package/dist/tui/model/composer-buffer.js +317 -0
  636. package/dist/tui/model/composer-types.d.ts +17 -0
  637. package/dist/tui/model/composer-types.js +1 -0
  638. package/dist/tui/model/display-history.d.ts +78 -0
  639. package/dist/tui/model/display-history.js +124 -0
  640. package/dist/tui/model/display-reconstruct.d.ts +3 -0
  641. package/dist/tui/model/display-reconstruct.js +130 -0
  642. package/dist/tui/model/file-mentions.d.ts +31 -0
  643. package/dist/tui/model/file-mentions.js +178 -0
  644. package/dist/tui/model/image-attachment.d.ts +15 -0
  645. package/dist/tui/model/image-attachment.js +1 -0
  646. package/dist/tui/model/image-paste.d.ts +119 -0
  647. package/dist/tui/model/image-paste.js +610 -0
  648. package/dist/tui/model/input-history.d.ts +1 -0
  649. package/dist/tui/model/input-history.js +1 -0
  650. package/dist/tui/model/input-queue.d.ts +12 -0
  651. package/dist/tui/model/input-queue.js +17 -0
  652. package/dist/tui/model/key-events.d.ts +9 -0
  653. package/dist/tui/model/key-events.js +8 -0
  654. package/dist/tui/model/paste-operation-tracker.d.ts +13 -0
  655. package/dist/tui/model/paste-operation-tracker.js +25 -0
  656. package/dist/tui/model/recent-activity.d.ts +8 -0
  657. package/dist/tui/model/recent-activity.js +71 -0
  658. package/dist/tui/model/subagent-view.d.ts +87 -0
  659. package/dist/tui/model/subagent-view.js +336 -0
  660. package/dist/tui/model/submit-dedupe.d.ts +5 -0
  661. package/dist/tui/model/submit-dedupe.js +25 -0
  662. package/dist/tui/model/sync-output.d.ts +17 -0
  663. package/dist/tui/model/sync-output.js +35 -0
  664. package/dist/tui/model/task-lifecycle.d.ts +57 -0
  665. package/dist/tui/model/task-lifecycle.js +124 -0
  666. package/dist/tui/model/terminal-env.d.ts +15 -0
  667. package/dist/tui/model/terminal-env.js +22 -0
  668. package/dist/tui/model/terminal-mouse.d.ts +28 -0
  669. package/dist/tui/model/terminal-mouse.js +82 -0
  670. package/dist/tui/model/theme-style.d.ts +10 -0
  671. package/dist/tui/model/theme-style.js +79 -0
  672. package/dist/tui/model/theme.d.ts +72 -0
  673. package/dist/tui/model/theme.js +121 -0
  674. package/dist/tui/model/trace-groups.d.ts +45 -0
  675. package/dist/tui/model/trace-groups.js +558 -0
  676. package/dist/tui/model/trace-interaction.d.ts +63 -0
  677. package/dist/tui/model/trace-interaction.js +87 -0
  678. package/dist/tui/model/width.d.ts +18 -0
  679. package/dist/tui/model/width.js +130 -0
  680. package/dist/tui/model-picker-data.d.ts +9 -0
  681. package/dist/tui/model-picker-data.js +39 -0
  682. package/dist/tui/model-switch.d.ts +49 -0
  683. package/dist/tui/model-switch.js +67 -0
  684. package/dist/tui/paste-placeholder.d.ts +11 -0
  685. package/dist/tui/paste-placeholder.js +52 -0
  686. package/dist/tui/recent-activity.d.ts +8 -0
  687. package/dist/tui/recent-activity.js +71 -0
  688. package/dist/tui/run-session-picker.d.ts +9 -0
  689. package/dist/tui/run-session-picker.js +64 -0
  690. package/dist/tui/run.d.ts +72 -0
  691. package/dist/tui/run.js +139 -0
  692. package/dist/tui/session-display.d.ts +6 -0
  693. package/dist/tui/session-display.js +12 -0
  694. package/dist/tui/session-picker-data.d.ts +18 -0
  695. package/dist/tui/session-picker-data.js +21 -0
  696. package/dist/tui/terminal/multiplexer.d.ts +5 -0
  697. package/dist/tui/terminal/multiplexer.js +14 -0
  698. package/dist/tui/testing/fake-agent.d.ts +24 -0
  699. package/dist/tui/testing/fake-agent.js +22 -0
  700. package/dist/tui/testing/spy-host.d.ts +21 -0
  701. package/dist/tui/testing/spy-host.js +55 -0
  702. package/dist/tui/trace-groups.d.ts +43 -0
  703. package/dist/tui/trace-groups.js +554 -0
  704. package/dist/tui/wordmark.d.ts +18 -0
  705. package/dist/tui/wordmark.js +208 -0
  706. package/dist/types.d.ts +503 -0
  707. package/dist/types.js +4 -0
  708. package/dist/update/index.d.ts +61 -0
  709. package/dist/update/index.js +267 -0
  710. package/dist/variant/thinking-level.d.ts +5 -0
  711. package/dist/variant/thinking-level.js +26 -0
  712. package/dist/variant/variant-resolver.d.ts +28 -0
  713. package/dist/variant/variant-resolver.js +62 -0
  714. package/node_modules/@bubblebrain-ai/pi-tui/LICENSE +21 -0
  715. package/node_modules/@bubblebrain-ai/pi-tui/README.md +854 -0
  716. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/alt-screen-search.d.ts +26 -0
  717. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/alt-screen-search.d.ts.map +1 -0
  718. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/alt-screen-search.js +121 -0
  719. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/alt-screen-search.js.map +1 -0
  720. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/autocomplete.d.ts +86 -0
  721. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/autocomplete.d.ts.map +1 -0
  722. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/autocomplete.js +649 -0
  723. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/autocomplete.js.map +1 -0
  724. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/alt-screen-flash.d.ts +13 -0
  725. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/alt-screen-flash.d.ts.map +1 -0
  726. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/alt-screen-flash.js +36 -0
  727. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/alt-screen-flash.js.map +1 -0
  728. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/box.d.ts +22 -0
  729. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/box.d.ts.map +1 -0
  730. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/box.js +99 -0
  731. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/box.js.map +1 -0
  732. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/cancellable-loader.d.ts +22 -0
  733. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/cancellable-loader.d.ts.map +1 -0
  734. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/cancellable-loader.js +36 -0
  735. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/cancellable-loader.js.map +1 -0
  736. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/editor.d.ts +330 -0
  737. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/editor.d.ts.map +1 -0
  738. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/editor.js +2344 -0
  739. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/editor.js.map +1 -0
  740. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/h-stack.d.ts +7 -0
  741. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/h-stack.d.ts.map +1 -0
  742. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/h-stack.js +43 -0
  743. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/h-stack.js.map +1 -0
  744. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/image.d.ts +28 -0
  745. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/image.d.ts.map +1 -0
  746. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/image.js +82 -0
  747. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/image.js.map +1 -0
  748. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/input.d.ts +48 -0
  749. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/input.d.ts.map +1 -0
  750. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/input.js +390 -0
  751. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/input.js.map +1 -0
  752. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/loader.d.ts +31 -0
  753. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/loader.d.ts.map +1 -0
  754. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/loader.js +67 -0
  755. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/loader.js.map +1 -0
  756. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/markdown.d.ts +103 -0
  757. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/markdown.d.ts.map +1 -0
  758. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/markdown.js +797 -0
  759. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/markdown.js.map +1 -0
  760. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/scroll-view.d.ts +56 -0
  761. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/scroll-view.d.ts.map +1 -0
  762. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/scroll-view.js +179 -0
  763. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/scroll-view.js.map +1 -0
  764. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/select-list.d.ts +53 -0
  765. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/select-list.d.ts.map +1 -0
  766. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/select-list.js +175 -0
  767. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/select-list.js.map +1 -0
  768. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/settings-list.d.ts +50 -0
  769. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/settings-list.d.ts.map +1 -0
  770. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/settings-list.js +174 -0
  771. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/settings-list.js.map +1 -0
  772. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/spacer.d.ts +12 -0
  773. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/spacer.d.ts.map +1 -0
  774. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/spacer.js +22 -0
  775. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/spacer.js.map +1 -0
  776. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/stack.d.ts +32 -0
  777. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/stack.d.ts.map +1 -0
  778. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/stack.js +109 -0
  779. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/stack.js.map +1 -0
  780. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/text.d.ts +19 -0
  781. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/text.d.ts.map +1 -0
  782. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/text.js +81 -0
  783. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/text.js.map +1 -0
  784. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/truncated-text.d.ts +13 -0
  785. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/truncated-text.d.ts.map +1 -0
  786. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/truncated-text.js +48 -0
  787. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/truncated-text.js.map +1 -0
  788. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/v-stack.d.ts +8 -0
  789. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/v-stack.d.ts.map +1 -0
  790. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/v-stack.js +26 -0
  791. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/v-stack.js.map +1 -0
  792. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/editor-component.d.ts +39 -0
  793. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/editor-component.d.ts.map +1 -0
  794. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/editor-component.js +2 -0
  795. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/editor-component.js.map +1 -0
  796. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/fuzzy.d.ts +16 -0
  797. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/fuzzy.d.ts.map +1 -0
  798. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/fuzzy.js +110 -0
  799. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/fuzzy.js.map +1 -0
  800. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/index.d.ts +31 -0
  801. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/index.d.ts.map +1 -0
  802. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/index.js +42 -0
  803. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/index.js.map +1 -0
  804. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/keybindings.d.ts +273 -0
  805. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/keybindings.d.ts.map +1 -0
  806. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/keybindings.js +231 -0
  807. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/keybindings.js.map +1 -0
  808. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/keys.d.ts +184 -0
  809. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/keys.d.ts.map +1 -0
  810. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/keys.js +1174 -0
  811. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/keys.js.map +1 -0
  812. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/kill-ring.d.ts +28 -0
  813. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/kill-ring.d.ts.map +1 -0
  814. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/kill-ring.js +46 -0
  815. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/kill-ring.js.map +1 -0
  816. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/latex.d.ts +10 -0
  817. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/latex.d.ts.map +1 -0
  818. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/latex.js +1268 -0
  819. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/latex.js.map +1 -0
  820. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/layout-node.d.ts +40 -0
  821. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/layout-node.d.ts.map +1 -0
  822. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/layout-node.js +6 -0
  823. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/layout-node.js.map +1 -0
  824. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/layout.d.ts +42 -0
  825. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/layout.d.ts.map +1 -0
  826. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/layout.js +335 -0
  827. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/layout.js.map +1 -0
  828. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/native-modifiers.d.ts +3 -0
  829. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/native-modifiers.d.ts.map +1 -0
  830. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/native-modifiers.js +60 -0
  831. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/native-modifiers.js.map +1 -0
  832. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/stdin-buffer.d.ts +56 -0
  833. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/stdin-buffer.d.ts.map +1 -0
  834. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/stdin-buffer.js +363 -0
  835. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/stdin-buffer.js.map +1 -0
  836. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/terminal-colors.d.ts +10 -0
  837. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/terminal-colors.d.ts.map +1 -0
  838. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/terminal-colors.js +59 -0
  839. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/terminal-colors.js.map +1 -0
  840. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/terminal-image.d.ts +116 -0
  841. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/terminal-image.d.ts.map +1 -0
  842. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/terminal-image.js +518 -0
  843. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/terminal-image.js.map +1 -0
  844. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/terminal.d.ts +142 -0
  845. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/terminal.d.ts.map +1 -0
  846. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/terminal.js +544 -0
  847. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/terminal.js.map +1 -0
  848. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/testing.d.ts +11 -0
  849. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/testing.d.ts.map +1 -0
  850. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/testing.js +11 -0
  851. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/testing.js.map +1 -0
  852. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/tui-alt-screen.d.ts +141 -0
  853. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/tui-alt-screen.d.ts.map +1 -0
  854. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/tui-alt-screen.js +1340 -0
  855. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/tui-alt-screen.js.map +1 -0
  856. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/tui-main-screen.d.ts +39 -0
  857. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/tui-main-screen.d.ts.map +1 -0
  858. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/tui-main-screen.js +536 -0
  859. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/tui-main-screen.js.map +1 -0
  860. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/tui.d.ts +340 -0
  861. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/tui.d.ts.map +1 -0
  862. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/tui.js +1020 -0
  863. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/tui.js.map +1 -0
  864. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/undo-stack.d.ts +17 -0
  865. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/undo-stack.d.ts.map +1 -0
  866. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/undo-stack.js +27 -0
  867. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/undo-stack.js.map +1 -0
  868. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/utils.d.ts +96 -0
  869. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/utils.d.ts.map +1 -0
  870. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/utils.js +1193 -0
  871. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/utils.js.map +1 -0
  872. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/word-navigation.d.ts +25 -0
  873. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/word-navigation.d.ts.map +1 -0
  874. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/word-navigation.js +96 -0
  875. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/word-navigation.js.map +1 -0
  876. package/node_modules/@bubblebrain-ai/pi-tui/dist/test/virtual-terminal.d.ts +73 -0
  877. package/node_modules/@bubblebrain-ai/pi-tui/dist/test/virtual-terminal.d.ts.map +1 -0
  878. package/node_modules/@bubblebrain-ai/pi-tui/dist/test/virtual-terminal.js +188 -0
  879. package/node_modules/@bubblebrain-ai/pi-tui/dist/test/virtual-terminal.js.map +1 -0
  880. package/node_modules/@bubblebrain-ai/pi-tui/native/darwin/README.md +20 -0
  881. package/node_modules/@bubblebrain-ai/pi-tui/native/darwin/build.sh +62 -0
  882. package/node_modules/@bubblebrain-ai/pi-tui/native/darwin/prebuilds/darwin-arm64/darwin-modifiers.node +0 -0
  883. package/node_modules/@bubblebrain-ai/pi-tui/native/darwin/prebuilds/darwin-x64/darwin-modifiers.node +0 -0
  884. package/node_modules/@bubblebrain-ai/pi-tui/native/darwin/src/darwin-modifiers.c +70 -0
  885. package/node_modules/@bubblebrain-ai/pi-tui/native/win32/README.md +22 -0
  886. package/node_modules/@bubblebrain-ai/pi-tui/native/win32/build.mjs +229 -0
  887. package/node_modules/@bubblebrain-ai/pi-tui/native/win32/prebuilds/win32-arm64/win32-console-mode.node +0 -0
  888. package/node_modules/@bubblebrain-ai/pi-tui/native/win32/prebuilds/win32-x64/win32-console-mode.node +0 -0
  889. package/node_modules/@bubblebrain-ai/pi-tui/native/win32/src/win32-console-mode.c +119 -0
  890. package/node_modules/@bubblebrain-ai/pi-tui/package.json +66 -0
  891. package/node_modules/get-east-asian-width/index.d.ts +60 -0
  892. package/node_modules/get-east-asian-width/index.js +30 -0
  893. package/node_modules/get-east-asian-width/license +9 -0
  894. package/node_modules/get-east-asian-width/lookup-data.js +21 -0
  895. package/node_modules/get-east-asian-width/lookup.js +138 -0
  896. package/node_modules/get-east-asian-width/package.json +71 -0
  897. package/node_modules/get-east-asian-width/readme.md +65 -0
  898. package/node_modules/get-east-asian-width/utilities.js +24 -0
  899. package/node_modules/marked/LICENSE +44 -0
  900. package/node_modules/marked/README.md +115 -0
  901. package/node_modules/marked/bin/main.js +284 -0
  902. package/node_modules/marked/bin/marked.js +16 -0
  903. package/node_modules/marked/lib/marked.d.ts +760 -0
  904. package/node_modules/marked/lib/marked.esm.js +77 -0
  905. package/node_modules/marked/lib/marked.esm.js.map +7 -0
  906. package/node_modules/marked/lib/marked.umd.js +79 -0
  907. package/node_modules/marked/lib/marked.umd.js.map +7 -0
  908. package/node_modules/marked/man/marked.1 +113 -0
  909. package/node_modules/marked/man/marked.1.md +93 -0
  910. package/node_modules/marked/package.json +103 -0
  911. package/package.json +96 -17
  912. package/bin/bubble.js +0 -39
@@ -0,0 +1,835 @@
1
+ import { AgentRunInputQueue } from "../input-controller.js";
2
+ import { randomUUID } from "node:crypto";
3
+ import { buildSystemPrompt } from "../../system-prompt.js";
4
+ import { buildToolPromptOptions } from "../../tools/index.js";
5
+ import { appendOutputSchemaInstructions, buildSchemaCorrectionPrompt, validateStructuredSummary } from "../structured-output.js";
6
+ import { runWorkflow, WorkflowConcurrencyGate } from "../workflow/runtime.js";
7
+ import { assignAgentNickname, discoverAgentProfiles, findAgentProfile, validateAgentProfileTools } from "../profiles.js";
8
+ import { snapshotSubagentThread, subagentResultFromThread } from "../subagent-control.js";
9
+ import { SubagentStore } from "../subagent-store.js";
10
+ import { SubagentScheduler } from "../subagent-scheduler.js";
11
+ import { ChildRunner, classifySubagentAbortReason, SafeSubagentConfigurationError, } from "../child-runner.js";
12
+ import { ResultIntegrator } from "../result-integrator.js";
13
+ import { SubagentAbortError } from "../abort-errors.js";
14
+ import { createSubagentWorktree, finalizeSubagentWorktree } from "../worktree.js";
15
+ import { createWorktreeChildTools, isolateReadonlyChildFileTools } from "../../tools/child-tools.js";
16
+ import { mergeAgentCategories, parseThinkingLevel } from "../categories.js";
17
+ import { composeAbortSignals } from "../budget-ledger.js";
18
+ export class SubagentRuntime {
19
+ parent;
20
+ router;
21
+ categories;
22
+ subagentsConfig;
23
+ /** Public so Agent can expose the same private-field access tests rely on. */
24
+ store;
25
+ scheduler;
26
+ childRunner;
27
+ resultIntegrator = new ResultIntegrator();
28
+ pendingUpdates = [];
29
+ updateWakers = new Set();
30
+ constructor(deps) {
31
+ this.parent = deps.parent;
32
+ this.router = deps.router;
33
+ this.categories = deps.categories;
34
+ this.subagentsConfig = deps.config;
35
+ // Eager, with loadPersisted() in the constructor: list_agents must return
36
+ // persisted children before any spawn happens this process.
37
+ this.store = new SubagentStore(deps.persistDir);
38
+ this.store.loadPersisted();
39
+ this.scheduler = new SubagentScheduler({
40
+ maxActiveSubagents: this.subagentsConfig.maxActiveSubagents,
41
+ launchBurst: this.subagentsConfig.launchBurst,
42
+ launchIntervalMs: this.subagentsConfig.launchIntervalMs,
43
+ rateLimitMaxAttempts: this.subagentsConfig.rateLimitMaxAttempts,
44
+ rateLimitBackoffMs: this.subagentsConfig.rateLimitBackoffMs,
45
+ transportRetryMaxAttempts: this.subagentsConfig.transportRetryMaxAttempts,
46
+ transportRetryBackoffMs: this.subagentsConfig.transportRetryBackoffMs,
47
+ getCategoryLimit: (category) => mergeAgentCategories(this.categories)[category]?.maxConcurrent,
48
+ });
49
+ this.childRunner = new ChildRunner({
50
+ allTools: () => this.parent.allTools(),
51
+ emit: (record, options, status, event, message) => this.emitSubagentLifecycle(record, options, status, event, message),
52
+ runLifecycleHook: (record, cwd, eventName, status, error, abortSignal) => this.runSubagentLifecycleHookFor(record, cwd, eventName, status, error, abortSignal),
53
+ finalizeBlocked: (record, error, options) => this.finalizeSubagentBlocked(record, error, options),
54
+ createInstance: (record, tools, cwd, forkContext) => this.createSubAgentInstance(record, tools, cwd, forkContext),
55
+ recordProviderError: (record, error, request) => this.recordSubagentProviderError(record, error, request),
56
+ notifyWaiters: (record) => this.store.notifyWaiters(record),
57
+ onFinal: (record, options) => {
58
+ if ((record.inputQueue?.pendingInputCount() ?? 0) > 0) {
59
+ record.inputQueue?.closePendingInputs();
60
+ record.inputDelivery = "rejected";
61
+ record.toolNotes.push("Pending supplementary input was not delivered because the run ended.");
62
+ this.emitSubagentLifecycle(record, options, record.status === "closed" ? "cancelled" : record.status);
63
+ }
64
+ this.reclaimWorktree(record);
65
+ // Workflow-internal agents are not persisted (they never re-import into
66
+ // the store on restart) and never ingest into parent context (option C).
67
+ if (!record.workflowInternal) {
68
+ this.store.persist(record);
69
+ this.maybeEnqueueIngestion(record, options);
70
+ }
71
+ },
72
+ });
73
+ }
74
+ // ---- parent-facing view: everything Agent.run() pulls ----
75
+ /** True when a background child has queued an update the loop should drain. */
76
+ hasPendingUpdates() {
77
+ return this.pendingUpdates.length > 0;
78
+ }
79
+ /** Follows a session switch: evicts the old session's final children and loads the new one's. */
80
+ repointPersistDir(persistDir) {
81
+ this.store.repoint(persistDir);
82
+ }
83
+ /**
84
+ * Inspects and cleans up a child's worktree at ANY terminal outcome:
85
+ * unchanged → removed; changed → kept for the parent to review, with a
86
+ * diff stat in the handoff (§8). Called from ChildRunner's onFinal and
87
+ * from all three scheduler-terminal callbacks — the scheduler paths used
88
+ * to skip reclamation entirely, leaking the directory and its git
89
+ * registration whenever a write child exhausted its retries
90
+ * (known-defects #1).
91
+ *
92
+ * When the directory was removed (= the child left no changes, so there
93
+ * is no file state to lose), the record's worktree reference is cleared:
94
+ * a kept reference would send a later resume into a deleted directory —
95
+ * clearing it makes the resume path rebuild a fresh worktree instead
96
+ * (see ChildRunner's reuse guard).
97
+ */
98
+ reclaimWorktree(record) {
99
+ if (!record.worktree)
100
+ return;
101
+ // finalizeSubagentWorktree is idempotent (already-finalized worktrees
102
+ // return unchanged); only the call that actually performed finalization
103
+ // may push the handoff note, or re-finalization would duplicate it.
104
+ const alreadyFinalized = record.worktree.changed !== undefined;
105
+ finalizeSubagentWorktree(record.worktree);
106
+ if (!alreadyFinalized && record.worktree.changed) {
107
+ record.toolNotes.push(`worktree: changes left in ${record.worktree.path} — review the diff before applying`);
108
+ }
109
+ if (record.worktree.removed)
110
+ record.worktree = undefined;
111
+ }
112
+ /** Registers a waker so a blocked tool-execution loop learns about updates. */
113
+ subscribe(wake) {
114
+ this.updateWakers.add(wake);
115
+ return () => this.updateWakers.delete(wake);
116
+ }
117
+ /**
118
+ * Completed background children whose summaries should reach parent context
119
+ * before the next inference turn (design §5). Pulled, not injected.
120
+ */
121
+ drainIngestionNotices() {
122
+ if (!this.resultIntegrator.hasPending())
123
+ return [];
124
+ return this.resultIntegrator.drainNotices(this.store);
125
+ }
126
+ async runSubAgent(input, cwd, options) {
127
+ const record = this.createSubagentThreadRecord({
128
+ profile: options.profile,
129
+ task: typeof input === "string" ? input : "(multimodal task)",
130
+ runId: options.runId,
131
+ agentId: options.subAgentId,
132
+ parentToolCallId: options.parentToolCallId,
133
+ parentToolName: "subagent",
134
+ nickname: options.nickname,
135
+ route: options.route ?? this.router.resolve(options.profile, options.category),
136
+ });
137
+ this.store.set(record);
138
+ const approval = options.approval ?? options.profile.approval;
139
+ const admissionError = this.admitSubagentProfile(record, approval);
140
+ if (admissionError) {
141
+ this.finalizeSubagentBlocked(record, admissionError, { directEmit: options.emitUpdate });
142
+ return subagentResultFromThread(record);
143
+ }
144
+ record.promise = this.dispatchSubagentRun(record, input, cwd, {
145
+ approval,
146
+ abortSignal: options.abortSignal,
147
+ forkContext: options.forkContext,
148
+ directEmit: options.emitUpdate,
149
+ });
150
+ await record.promise;
151
+ return subagentResultFromThread(record);
152
+ }
153
+ async spawnSubAgent(input, cwd, options) {
154
+ const route = options.route
155
+ ?? this.router.resolve(options.profile, options.category, { model: options.model, effort: options.effort });
156
+ // Early validation (design §7): throws reach the model as a tool error it
157
+ // can correct this turn, instead of a late provider-factory failure.
158
+ const routeNote = this.router.validateForDispatch(route);
159
+ const record = this.createSubagentThreadRecord({
160
+ profile: options.profile,
161
+ task: typeof input === "string" ? input : "(multimodal task)",
162
+ parentToolCallId: options.parentToolCallId,
163
+ parentToolName: "spawn_agent",
164
+ route,
165
+ });
166
+ if (routeNote)
167
+ record.toolNotes.push(routeNote);
168
+ this.store.set(record);
169
+ const approval = options.approval ?? record.profile.approval;
170
+ // Admission validation runs before queueing (design §4.2): a request that
171
+ // would block never consumes a queue slot.
172
+ const admissionError = this.admitSubagentProfile(record, approval);
173
+ if (admissionError) {
174
+ this.finalizeSubagentBlocked(record, admissionError, { queueUpdates: true });
175
+ return this.snapshotSubagent(record);
176
+ }
177
+ this.queueSubagentUpdate(record, "queued", undefined, `Queued ${record.nickname} (${record.profile.name})`);
178
+ record.promise = this.dispatchSubagentRun(record, input, cwd, {
179
+ approval,
180
+ abortSignal: options.abortSignal,
181
+ forkContext: options.forkContext,
182
+ queueUpdates: true,
183
+ });
184
+ void record.promise.finally(() => this.store.notifyWaiters(record));
185
+ return this.snapshotSubagent(record);
186
+ }
187
+ async waitSubAgents(options = {}) {
188
+ const targets = this.resolveSubagentTargets(options.agentIds);
189
+ if (targets.length === 0)
190
+ return [];
191
+ const completed = targets.filter((record) => isFinalSubagentStatus(record.status));
192
+ if (completed.length > 0) {
193
+ for (const record of completed)
194
+ this.store.markDelivered(record.agentId);
195
+ return completed.map((record) => this.snapshotSubagent(record));
196
+ }
197
+ const timeoutMs = normalizeWaitTimeout(options.timeoutMs);
198
+ let waiter;
199
+ await Promise.race([
200
+ new Promise((resolve) => {
201
+ waiter = resolve;
202
+ for (const record of targets) {
203
+ record.waiters.add(resolve);
204
+ }
205
+ }).finally(() => {
206
+ if (waiter) {
207
+ for (const record of targets) {
208
+ record.waiters.delete(waiter);
209
+ }
210
+ }
211
+ }),
212
+ new Promise((resolve) => setTimeout(resolve, timeoutMs)),
213
+ ]);
214
+ const finished = targets.filter((record) => isFinalSubagentStatus(record.status));
215
+ for (const record of finished)
216
+ this.store.markDelivered(record.agentId);
217
+ return (finished.length > 0 ? finished : targets).map((record) => this.snapshotSubagent(record));
218
+ }
219
+ async sendSubAgentInput(agentId, input, cwd, options = {}) {
220
+ const record = this.store.get(agentId);
221
+ if (!record) {
222
+ throw new Error(`Unknown subagent: ${agentId}`);
223
+ }
224
+ if (record.status === "running" || record.status === "queued") {
225
+ if (!options.interrupt) {
226
+ if (typeof input !== "string")
227
+ throw new Error("Running subagents currently accept text follow-ups only.");
228
+ record.inputQueue ??= new AgentRunInputQueue(`child-${agentId}`);
229
+ if (record.inputQueue.tryEnqueue(input)) {
230
+ record.inputDelivery = "queued";
231
+ record.updatedAt = Date.now();
232
+ this.queueSubagentUpdate(record, record.status, undefined, "Supplementary input queued for the next safe boundary.");
233
+ return this.snapshotSubagent(record);
234
+ }
235
+ // Admission closed at the final boundary. Resume only after the old
236
+ // run has fully settled; never run the same child concurrently.
237
+ await record.promise?.catch(() => undefined);
238
+ }
239
+ if (options.interrupt) {
240
+ record.abortController.abort(new SubagentAbortError(`Subagent ${agentId} interrupted.`, "interrupt"));
241
+ await record.promise?.catch(() => undefined);
242
+ }
243
+ }
244
+ if (record.status === "closed") {
245
+ throw new Error(`Subagent ${agentId} is closed.`);
246
+ }
247
+ // Identity and trace anchor belong to the child, not a follow-up tool call.
248
+ record.abortController = new AbortController();
249
+ record.inputQueue = new AgentRunInputQueue(`child-${agentId}-${Date.now()}`);
250
+ record.inputDelivery = undefined;
251
+ record.task = typeof input === "string" ? input : "(multimodal task)";
252
+ record.summary = "";
253
+ record.toolNotes = [];
254
+ record.usage = undefined;
255
+ record.error = undefined;
256
+ record.finalReason = undefined;
257
+ record.deliveredAt = undefined;
258
+ record.updatedAt = Date.now();
259
+ if (record.worktree) {
260
+ // A kept (changed) worktree carries changed/diffStat frozen at the
261
+ // previous terminal outcome; reset them so the finalize after THIS
262
+ // run recomputes instead of reporting stale state.
263
+ record.worktree.changed = undefined;
264
+ record.worktree.diffStat = undefined;
265
+ }
266
+ // A send_input restart is a launch like any other: it goes through the
267
+ // scheduler's dispatch point and is subject to the same admission limits
268
+ // (design §4.1) — batch-resuming team members cannot bypass concurrency caps.
269
+ record.promise = this.dispatchSubagentRun(record, input, cwd, {
270
+ approval: record.profile.approval,
271
+ abortSignal: options.abortSignal,
272
+ queueUpdates: true,
273
+ reuseAgent: true,
274
+ });
275
+ void record.promise.finally(() => this.store.notifyWaiters(record));
276
+ return this.snapshotSubagent(record);
277
+ }
278
+ async closeSubAgent(agentId) {
279
+ const record = this.store.get(agentId);
280
+ if (!record) {
281
+ throw new Error(`Unknown subagent: ${agentId}`);
282
+ }
283
+ if (!isFinalSubagentStatus(record.status)) {
284
+ record.abortController.abort(new SubagentAbortError(`Subagent ${agentId} closed.`, "user_close"));
285
+ await record.promise?.catch(() => undefined);
286
+ }
287
+ record.status = "closed";
288
+ record.finalReason = record.finalReason ?? "cancelled_user";
289
+ record.updatedAt = Date.now();
290
+ this.queueSubagentUpdate(record, "cancelled", undefined, `${record.nickname} closed`);
291
+ this.store.persist(record);
292
+ this.store.notifyWaiters(record);
293
+ return this.snapshotSubagent(record);
294
+ }
295
+ /**
296
+ * Live (non-final) children only — the delegation-nudge gate
297
+ * (large-task-delegation design §2). listSubAgents() is a grows-only
298
+ * session history (finished + resumed children stay forever), so it must
299
+ * never be used to answer "am I currently delegating?".
300
+ */
301
+ activeSubAgentCount() {
302
+ return this.store.activeCount();
303
+ }
304
+ listSubAgents() {
305
+ return this.store.values()
306
+ .filter((record) => !record.workflowInternal)
307
+ .map((record) => this.snapshotSubagent(record));
308
+ }
309
+ async executeWorkflow(cwd, options) {
310
+ const profiles = discoverAgentProfiles(cwd, "both").profiles;
311
+ const runRecords = [];
312
+ const logs = [];
313
+ let currentWorkflowPhase;
314
+ // Per-run isolation (option C review): a concurrency sub-cap below the
315
+ // global limit so a workflow can't starve interactive subagents.
316
+ const interactiveReserve = 2;
317
+ const globalCap = Math.max(1, this.subagentsConfig.maxActiveSubagents ?? 8);
318
+ const workflowConcurrency = Math.max(1, globalCap - interactiveReserve);
319
+ const gate = new WorkflowConcurrencyGate(workflowConcurrency);
320
+ const dispatchAgent = async (spec) => {
321
+ const baseProfile = findAgentProfile(profiles, spec.opts.agentType ?? "default")
322
+ ?? findAgentProfile(profiles, "default");
323
+ if (!baseProfile)
324
+ return { ok: false, error: "no default subagent profile available" };
325
+ // Workflow agents are readonly-by-default; mode upgrades come only from the
326
+ // profile, never from the script (security invariant).
327
+ const unsupported = baseProfile.mode !== "readonly" && baseProfile.mode !== "write_worktree";
328
+ if (unsupported)
329
+ return { ok: false, error: `profile "${baseProfile.name}" mode ${baseProfile.mode} not supported` };
330
+ // Default-no-network: unattended orchestration of net-capable agents is new
331
+ // authority in aggregate (option C review), so strip web tools unless the
332
+ // script opts in with agentType pointing at a profile that includes them.
333
+ const profile = {
334
+ ...baseProfile,
335
+ tools: { ...baseProfile.tools, exclude: [...(baseProfile.tools.exclude ?? []), "web_fetch", "web_search"] },
336
+ };
337
+ let route;
338
+ let routeNote;
339
+ try {
340
+ route = this.router.resolve(profile, spec.opts.category, {
341
+ model: spec.opts.model,
342
+ effort: parseThinkingLevel(spec.opts.effort),
343
+ });
344
+ // Dispatch-time validation (§7): resolved routes, never script source text.
345
+ routeNote = this.router.validateForDispatch(route);
346
+ }
347
+ catch (error) {
348
+ return { ok: false, error: error?.message || String(error) };
349
+ }
350
+ const baseTask = spec.opts.schema !== undefined
351
+ ? appendOutputSchemaInstructions(spec.prompt, spec.opts.schema)
352
+ : spec.prompt;
353
+ const record = this.createSubagentThreadRecord({
354
+ profile,
355
+ task: baseTask,
356
+ parentToolCallId: options.parentToolCallId,
357
+ parentToolName: "run_workflow",
358
+ runId: options.workflowRunId,
359
+ phase: currentWorkflowPhase,
360
+ route,
361
+ workflowInternal: true,
362
+ });
363
+ record.expectsStructuredOutput = spec.opts.schema !== undefined;
364
+ if (routeNote)
365
+ record.toolNotes.push(routeNote);
366
+ const memberLabel = typeof spec.opts.label === "string" ? spec.opts.label.trim().slice(0, 40) : "";
367
+ if (memberLabel)
368
+ record.nickname = memberLabel;
369
+ runRecords.push(record);
370
+ this.store.set(record);
371
+ // Project-local profiles pass the same first-use trust gate as
372
+ // spawn_agent: a .bubble/agents profile must never gain a side door
373
+ // into execution just because a script named it (Codex review on #58).
374
+ // Checked AFTER the record exists so a rejected member still shows up
375
+ // in the run's counts/snapshots as blocked instead of vanishing.
376
+ if (options.ensureProfileTrusted) {
377
+ const blocked = await options.ensureProfileTrusted(baseProfile);
378
+ if (blocked) {
379
+ const message = typeof blocked.content === "string" ? blocked.content : `profile "${baseProfile.name}" requires user approval`;
380
+ this.finalizeSubagentBlocked(record, message, { directEmit: options.directEmit, queueUpdates: options.queueUpdates });
381
+ return { ok: false, error: message };
382
+ }
383
+ }
384
+ const admissionError = this.admitSubagentProfile(record, profile.approval);
385
+ if (admissionError) {
386
+ this.finalizeSubagentBlocked(record, admissionError, { directEmit: options.directEmit, queueUpdates: options.queueUpdates });
387
+ return { ok: false, error: admissionError };
388
+ }
389
+ // Leaf-only concurrency permit (option C review M5): held ONLY around this
390
+ // agent's dispatch, never across parallel/pipeline composition.
391
+ await gate.acquire();
392
+ try {
393
+ record.promise = this.dispatchSubagentRun(record, baseTask, cwd, {
394
+ approval: profile.approval,
395
+ abortSignal: options.abortSignal,
396
+ directEmit: options.directEmit,
397
+ queueUpdates: options.queueUpdates,
398
+ });
399
+ await record.promise;
400
+ }
401
+ finally {
402
+ gate.release();
403
+ }
404
+ this.store.markDelivered(record.agentId);
405
+ if (record.status !== "completed") {
406
+ return { ok: false, error: record.error || `agent ${record.nickname} ended: ${record.finalReason ?? record.status}` };
407
+ }
408
+ if (spec.opts.schema === undefined) {
409
+ return { ok: true, value: record.summary };
410
+ }
411
+ // Structured output: validate, one corrective retry, then fall back to raw.
412
+ // The schema: log lines are the telemetry that decides whether the
413
+ // deferred terminate-style structured-output tool ever gets reopened.
414
+ let validated = validateStructuredSummary(record.summary, spec.opts.schema);
415
+ if (!validated.ok) {
416
+ logs.push(`schema: ${record.nickname} first output failed validation; sending one corrective retry`);
417
+ try {
418
+ await this.sendSubAgentInput(record.agentId, buildSchemaCorrectionPrompt(spec.opts.schema, record.summary), cwd, { abortSignal: options.abortSignal });
419
+ await record.promise?.catch(() => undefined);
420
+ validated = validateStructuredSummary(record.summary, spec.opts.schema);
421
+ }
422
+ catch {
423
+ // resume failed; fall through to raw summary
424
+ }
425
+ logs.push(validated.ok
426
+ ? `schema: ${record.nickname} corrective retry produced valid output`
427
+ : `schema: ${record.nickname} corrective retry still invalid; returning raw summary`);
428
+ }
429
+ return { ok: true, value: validated.ok ? validated.value : record.summary };
430
+ };
431
+ const result = await runWorkflow({
432
+ script: options.script,
433
+ args: options.args,
434
+ dispatchAgent,
435
+ onLog: (message) => logs.push(message),
436
+ onPhase: (title) => {
437
+ currentWorkflowPhase = title;
438
+ logs.push(`— phase: ${title} —`);
439
+ },
440
+ budget: {
441
+ // The ledger is pure accounting (no pool limit); scripts see an
442
+ // unlimited budget unless a future host contract reintroduces one.
443
+ total: null,
444
+ spent: () => runRecords.reduce((sum, r) => sum + (r.usage ? r.usage.promptTokens + r.usage.completionTokens : 0), 0),
445
+ remaining: () => Number.POSITIVE_INFINITY,
446
+ },
447
+ signal: options.abortSignal,
448
+ });
449
+ return {
450
+ result,
451
+ agentCount: runRecords.length,
452
+ logs,
453
+ snapshots: runRecords.map((record) => this.snapshotSubagent(record)),
454
+ };
455
+ }
456
+ markSubagentDelivered(agentId) {
457
+ this.store.markDelivered(agentId);
458
+ }
459
+ snapshotSubagent(record) {
460
+ const snapshot = snapshotSubagentThread(record);
461
+ if (record.status === "queued") {
462
+ const queuePosition = this.scheduler.queuePosition(record.agentId);
463
+ if (queuePosition !== undefined)
464
+ return { ...snapshot, queuePosition };
465
+ }
466
+ return snapshot;
467
+ }
468
+ /** Returns the blocking diagnostic message when the profile cannot run, else undefined. */
469
+ admitSubagentProfile(record, approval) {
470
+ const diagnostics = validateAgentProfileTools(this.parent.allTools(), record.profile, approval);
471
+ const blocking = diagnostics.filter((diagnostic) => diagnostic.severity === "error");
472
+ if (blocking.length === 0)
473
+ return undefined;
474
+ return blocking.map((diagnostic) => diagnostic.message).join("\n");
475
+ }
476
+ /**
477
+ * Background children (queueUpdates) get their results ingested before the
478
+ * parent's next inference turn (design §5); foreground children (team,
479
+ * legacy task) deliver through their tool result instead.
480
+ */
481
+ maybeEnqueueIngestion(record, options) {
482
+ if (options.queueUpdates) {
483
+ this.resultIntegrator.enqueue(record.agentId);
484
+ }
485
+ }
486
+ finalizeSubagentBlocked(record, error, emitOptions) {
487
+ record.status = "blocked";
488
+ record.finalReason = "blocked";
489
+ record.error = error;
490
+ record.updatedAt = Date.now();
491
+ this.emitSubagentLifecycle(record, emitOptions, "blocked", undefined, error);
492
+ this.store.persist(record);
493
+ this.store.notifyWaiters(record);
494
+ }
495
+ dispatchSubagentRun(record, input, cwd, options) {
496
+ record.status = "queued";
497
+ record.updatedAt = Date.now();
498
+ const queueSignal = composeAbortSignals([options.abortSignal, record.abortController.signal]);
499
+ return this.scheduler.dispatch({
500
+ agentId: record.agentId,
501
+ category: record.category,
502
+ signal: queueSignal,
503
+ run: (ctx) => this.runSubagentThread(record, input, cwd, { ...options, attempt: ctx.attempt }),
504
+ onCancelledWhileQueued: (reason) => {
505
+ record.status = "cancelled";
506
+ record.finalReason = classifySubagentAbortReason(reason, options.abortSignal);
507
+ record.error = "Subagent was cancelled.";
508
+ record.updatedAt = Date.now();
509
+ // This path is NOT only "run never started" — a 429/transport
510
+ // failure re-queues the entry with the abort listener re-armed, so
511
+ // an abort during backoff lands here AFTER attempt 1 already ran
512
+ // (worktree created, SubagentStart fired). Reclaim is therefore a
513
+ // real leak fix here, and an open Start pair must be closed too
514
+ // (design §9): only when no Start ever fired is skipping Stop right.
515
+ if (record.hookStopPending) {
516
+ void this.runSubagentLifecycleHookFor(record, cwd, "SubagentStop", record.status, record.error);
517
+ }
518
+ this.reclaimWorktree(record);
519
+ this.emitSubagentLifecycle(record, options, "cancelled", undefined, record.error);
520
+ this.store.persist(record);
521
+ this.store.notifyWaiters(record);
522
+ this.maybeEnqueueIngestion(record, options);
523
+ },
524
+ onRateLimitExhausted: (attempts) => {
525
+ record.status = "failed";
526
+ record.finalReason = "rate_limited_exhausted";
527
+ record.error = `Provider rate limit persisted after ${attempts} attempts.`;
528
+ this.recordSubagentProviderError(record, Object.assign(new Error(record.error), { status: 429, code: "rate_limit_exhausted" }), { messageCount: record.agent?.messages.length ?? 0, toolCount: 0 });
529
+ record.updatedAt = Date.now();
530
+ // Reclaim before persist so the handoff note lands in the
531
+ // persisted toolNotes.
532
+ this.reclaimWorktree(record);
533
+ void this.runSubagentLifecycleHookFor(record, cwd, "SubagentStop", record.status, record.error);
534
+ this.emitSubagentLifecycle(record, options, "failed", undefined, record.error);
535
+ this.store.persist(record);
536
+ this.store.notifyWaiters(record);
537
+ this.maybeEnqueueIngestion(record, options);
538
+ },
539
+ onTransportRetryExhausted: (attempts) => {
540
+ record.status = "failed";
541
+ // failed_transient stays resumable, so the parent can still send_input
542
+ // to recover the child with its context intact.
543
+ record.finalReason = "failed_transient";
544
+ record.error = `Provider transport error persisted after ${attempts} attempts.`;
545
+ this.recordSubagentProviderError(record, new Error(record.error), {
546
+ messageCount: record.agent?.messages.length ?? 0,
547
+ toolCount: 0,
548
+ });
549
+ record.updatedAt = Date.now();
550
+ this.reclaimWorktree(record);
551
+ void this.runSubagentLifecycleHookFor(record, cwd, "SubagentStop", record.status, record.error);
552
+ this.emitSubagentLifecycle(record, options, "failed", undefined, record.error);
553
+ this.store.persist(record);
554
+ this.store.notifyWaiters(record);
555
+ this.maybeEnqueueIngestion(record, options);
556
+ },
557
+ });
558
+ }
559
+ recordSubagentProviderError(record, error, request) {
560
+ const route = record.route ?? {
561
+ providerId: this.parent.providerId,
562
+ model: this.parent.apiModel,
563
+ thinkingLevel: this.parent.thinkingLevel,
564
+ inherited: true,
565
+ };
566
+ this.parent.recordProviderError(error, {
567
+ providerId: route.providerId,
568
+ modelId: route.model,
569
+ model: route.providerId ? `${route.providerId}:${route.model}` : route.model,
570
+ thinkingLevel: route.thinkingLevel,
571
+ messageCount: request.messageCount,
572
+ toolCount: request.toolCount,
573
+ });
574
+ }
575
+ emitSubagentLifecycle(record, options, status, event, message) {
576
+ const update = this.buildSubagentUpdate(record, status, event, message);
577
+ options.directEmit?.(update);
578
+ if (options.queueUpdates) {
579
+ this.pendingUpdates.push({ id: record.parentToolCallId, name: record.parentToolName, update });
580
+ this.wakeSubagentUpdateWaiters();
581
+ }
582
+ }
583
+ /** Lets a blocked tool-execution loop drain freshly queued subagent updates. */
584
+ wakeSubagentUpdateWaiters() {
585
+ for (const wake of this.updateWakers)
586
+ wake();
587
+ }
588
+ async runSubagentLifecycleHookFor(record, cwd, eventName, status, error, abortSignal) {
589
+ // Pairing state (design §9), tracked at this single choke point —
590
+ // every Start/Stop passes through here, so no call site can desync it.
591
+ // Set synchronously, before the await, to stay ordered with callers.
592
+ record.hookStopPending = eventName === "SubagentStart";
593
+ try {
594
+ await this.parent.runExternalHook({
595
+ eventName,
596
+ cwd,
597
+ runId: record.runId,
598
+ target: record.profile.name,
599
+ payload: {
600
+ agentId: record.agentId,
601
+ nickname: record.nickname,
602
+ profile: record.profile.name,
603
+ status,
604
+ error,
605
+ },
606
+ }, abortSignal);
607
+ }
608
+ catch {
609
+ // Subagent lifecycle hooks are observe-only; never fail the subagent.
610
+ // Observe-only extends to the RESULT, not just errors: the returned
611
+ // events and modelContext are dropped ON PURPOSE, matching every other
612
+ // terminal/lifecycle event (Stop, StopFailure, SessionStart/End).
613
+ // Injecting them would push each child's start/stop hook output into
614
+ // the parent transcript, once per child in a fan-out. Do not "fix"
615
+ // this by wiring the result into injectHookModelContext.
616
+ }
617
+ }
618
+ createSubagentThreadRecord(options) {
619
+ const now = Date.now();
620
+ const nickname = options.nickname ?? assignAgentNickname(options.profile, this.activeSubagentNicknames());
621
+ return {
622
+ agentId: options.agentId ?? randomUUID(),
623
+ runId: options.runId ?? randomUUID(),
624
+ nickname,
625
+ profile: options.profile,
626
+ category: options.route?.category,
627
+ phase: options.phase,
628
+ route: options.route,
629
+ workflowInternal: options.workflowInternal,
630
+ parentToolCallId: options.parentToolCallId,
631
+ parentToolName: options.parentToolName,
632
+ status: "queued",
633
+ task: options.task,
634
+ summary: "",
635
+ toolNotes: [],
636
+ createdAt: now,
637
+ updatedAt: now,
638
+ inputQueue: new AgentRunInputQueue(`child-input-${randomUUID()}`),
639
+ abortController: new AbortController(),
640
+ waiters: new Set(),
641
+ };
642
+ }
643
+ runSubagentThread(record, input, cwd, options) {
644
+ return this.childRunner.run(record, input, cwd, options);
645
+ }
646
+ async createSubAgentInstance(record, tools, cwd, forkContext) {
647
+ let childCwd = cwd;
648
+ let childMode = "plan";
649
+ if (record.profile.mode === "write_worktree") {
650
+ // Write children work in a runtime-allocated worktree with fresh tool
651
+ // instances bound to it (design §8): the parent tree is never touched,
652
+ // and the tools' own workspace fence enforces containment in code.
653
+ // NOTE: record.worktree must be assigned before anything below can
654
+ // throw — ChildRunner's failure path reclaims it off the record.
655
+ if (!record.worktree) {
656
+ try {
657
+ record.worktree = createSubagentWorktree(cwd, record.agentId);
658
+ }
659
+ catch (error) {
660
+ const message = error instanceof Error && error.message.includes("need a git repository")
661
+ ? "write_worktree subagents need a git repository: the working directory is not inside one."
662
+ : "Failed to create subagent worktree.";
663
+ throw new SafeSubagentConfigurationError(message);
664
+ }
665
+ }
666
+ childCwd = record.worktree.path;
667
+ childMode = "default";
668
+ tools = createWorktreeChildTools(childCwd, record.profile.tools.include);
669
+ }
670
+ else {
671
+ // Readonly children share the parent's tool instances; isolate the only
672
+ // one with mutable file state (read → its FileStateTracker) so concurrent
673
+ // fan-out members never race shared tool state (design v2 §2).
674
+ tools = isolateReadonlyChildFileTools(tools);
675
+ }
676
+ const childToolNames = tools.map((tool) => tool.name);
677
+ const route = record.route ?? {
678
+ providerId: this.parent.providerId,
679
+ model: this.parent.apiModel,
680
+ thinkingLevel: this.parent.thinkingLevel,
681
+ inherited: true,
682
+ };
683
+ const provider = await this.resolveProviderForRoute(route);
684
+ const childSystemPrompt = buildSystemPrompt({
685
+ agentName: "Bubble",
686
+ configuredProvider: route.providerId || "none",
687
+ configuredModel: route.model || "none",
688
+ configuredModelId: route.providerId && route.model ? `${route.providerId}:${route.model}` : route.model || "none",
689
+ thinkingLevel: route.thinkingLevel,
690
+ mode: childMode,
691
+ workingDir: childCwd,
692
+ ...buildToolPromptOptions(tools),
693
+ // A child that can load skills sees the same catalog as its parent.
694
+ ...(childToolNames.includes("skill")
695
+ ? { skills: this.parent.getSkillSummaries?.(), skillCatalogChars: this.parent.getSkillCatalogChars?.() }
696
+ : {}),
697
+ memoryPrompt: childToolNames.some((name) => name === "memory")
698
+ ? this.parent.memoryPrompt
699
+ : undefined,
700
+ agentProfilePrompt: [
701
+ `You are subagent ${record.nickname}. Your agent profile is ${record.profile.name}.`,
702
+ record.profile.mode === "write_worktree"
703
+ ? [
704
+ "You work inside an isolated git worktree; the parent reviews your diff after you finish.",
705
+ "Make your changes, verify them (run tests where possible), and end with a handoff that lists the files you changed and how you verified them.",
706
+ "Do not commit, push, or touch anything outside this worktree.",
707
+ ].join(" ")
708
+ : "",
709
+ record.profile.prompt,
710
+ ].filter(Boolean).join("\n\n"),
711
+ });
712
+ // Cross-restart resume (design §7): rebuild the child from its persisted
713
+ // history — including its original system prompt — so send_input continues
714
+ // with context intact. Consumed here so a later run does not re-seed it.
715
+ const resumeMessages = record.messages && record.messages.length > 0
716
+ ? record.messages.map((message) => ({ ...message }))
717
+ : undefined;
718
+ if (resumeMessages)
719
+ record.messages = undefined;
720
+ return this.parent.createChild({
721
+ provider,
722
+ providerId: route.providerId,
723
+ model: route.model,
724
+ tools,
725
+ thinkingLevel: route.thinkingLevel,
726
+ mode: childMode,
727
+ maxTurns: record.profile.maxTurns,
728
+ budgetSource: { runId: record.runId, subAgentId: record.agentId },
729
+ systemPrompt: childSystemPrompt,
730
+ subAgentId: record.agentId,
731
+ resumeMessages,
732
+ forkContext,
733
+ });
734
+ }
735
+ async resolveProviderForRoute(route) {
736
+ if (!route.providerId || route.providerId === this.parent.providerId) {
737
+ return this.parent.provider;
738
+ }
739
+ if (!this.parent.providerFactory) {
740
+ throw new SafeSubagentConfigurationError([
741
+ `Subagent route requires provider "${route.providerId}" for model "${route.model}",`,
742
+ `but the parent agent only has provider "${this.parent.providerId || "none"}" and no provider factory is configured.`,
743
+ ].join(" "));
744
+ }
745
+ return this.parent.providerFactory(route);
746
+ }
747
+ buildSubagentUpdate(record, status, event, message) {
748
+ return {
749
+ type: "subagent_update",
750
+ parentToolCallId: record.parentToolCallId,
751
+ runId: record.runId,
752
+ subAgentId: record.agentId,
753
+ agentName: record.profile.name,
754
+ nickname: record.nickname,
755
+ category: record.category,
756
+ route: record.route,
757
+ status,
758
+ childEvent: event,
759
+ summaryDelta: event?.type === "text_delta" ? event.content : undefined,
760
+ toolName: "name" in (event ?? {}) ? event.name : undefined,
761
+ toolCallId: "id" in (event ?? {}) ? event.id : undefined,
762
+ message,
763
+ metadata: {
764
+ kind: "subagent",
765
+ runId: record.runId,
766
+ mode: record.parentToolName === "run_workflow" ? "workflow" : "single",
767
+ subagents: [{
768
+ subAgentId: record.agentId,
769
+ runId: record.runId,
770
+ agentName: record.profile.name,
771
+ nickname: record.nickname,
772
+ category: record.category,
773
+ phase: record.phase,
774
+ route: record.route,
775
+ status,
776
+ profileSource: record.profile.source,
777
+ task: record.task,
778
+ summary: record.summary,
779
+ toolNotes: record.toolNotes,
780
+ usage: record.usage,
781
+ error: record.error,
782
+ createdAt: record.createdAt,
783
+ updatedAt: record.updatedAt,
784
+ pendingInputCount: record.inputQueue?.pendingInputCount() ?? 0,
785
+ inputDelivery: record.inputDelivery,
786
+ }],
787
+ },
788
+ };
789
+ }
790
+ queueSubagentUpdate(record, status, event, message) {
791
+ this.pendingUpdates.push({
792
+ id: record.parentToolCallId,
793
+ name: record.parentToolName,
794
+ update: this.buildSubagentUpdate(record, status, event, message),
795
+ });
796
+ this.wakeSubagentUpdateWaiters();
797
+ }
798
+ /** Queued background-child updates for Agent.run() to emit. */
799
+ drainToolUpdates() {
800
+ return this.pendingUpdates.splice(0, this.pendingUpdates.length)
801
+ .map((pending) => ({
802
+ type: "tool_update",
803
+ id: pending.id,
804
+ name: pending.name,
805
+ update: pending.update,
806
+ }));
807
+ }
808
+ activeSubagentNicknames() {
809
+ return this.store.active().map((record) => record.nickname);
810
+ }
811
+ resolveSubagentTargets(agentIds) {
812
+ if (!agentIds || agentIds.length === 0) {
813
+ return this.store.values().filter((record) => record.status !== "closed" && !record.workflowInternal);
814
+ }
815
+ return agentIds.map((id) => {
816
+ const record = this.store.get(id);
817
+ if (!record) {
818
+ throw new Error(`Unknown subagent: ${id}`);
819
+ }
820
+ return record;
821
+ });
822
+ }
823
+ }
824
+ export function isFinalSubagentStatus(status) {
825
+ return status === "completed"
826
+ || status === "failed"
827
+ || status === "blocked"
828
+ || status === "cancelled"
829
+ || status === "closed";
830
+ }
831
+ export function normalizeWaitTimeout(value) {
832
+ if (typeof value !== "number" || !Number.isFinite(value))
833
+ return 30_000;
834
+ return Math.max(100, Math.min(3_600_000, Math.floor(value)));
835
+ }