@theowlops/boombot 0.0.0-stage → 1.1.1

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 (544) hide show
  1. package/README.md +69 -3
  2. package/dist/LICENSE +21 -0
  3. package/dist/bin/boombot.js +16 -0
  4. package/dist/cli/api-key.js +123 -0
  5. package/dist/cli/bin-bun.js +17 -0
  6. package/dist/cli/bin.js +34 -0
  7. package/dist/cli/cli/cli-error.js +61 -0
  8. package/dist/cli/cli/dispatch.js +138 -0
  9. package/dist/cli/cli/help.js +83 -0
  10. package/dist/cli/cli/parser.js +89 -0
  11. package/dist/cli/cli/registry.js +185 -0
  12. package/dist/cli/cli/spec.js +41 -0
  13. package/dist/cli/cli/suggest.js +125 -0
  14. package/dist/cli/cli/version.js +30 -0
  15. package/dist/cli/cli/vocabulary.js +87 -0
  16. package/dist/cli/commands/doctor.js +365 -0
  17. package/dist/cli/commands/gateway.js +290 -0
  18. package/dist/cli/commands/migrate.js +270 -0
  19. package/dist/cli/commands/plugin.js +97 -0
  20. package/dist/cli/commands/setup.js +244 -0
  21. package/dist/cli/config-file.js +133 -0
  22. package/dist/cli/master-key.js +78 -0
  23. package/dist/cli/open-browser.js +59 -0
  24. package/dist/cli/web-assets.js +58 -0
  25. package/dist/gateway/auth.js +46 -0
  26. package/dist/gateway/config-format.js +202 -0
  27. package/dist/gateway/config.js +427 -0
  28. package/dist/gateway/context.js +1 -0
  29. package/dist/gateway/env-file.js +129 -0
  30. package/dist/gateway/events.js +172 -0
  31. package/dist/gateway/guard/tagging.js +505 -0
  32. package/dist/gateway/handlers/index.js +66 -0
  33. package/dist/gateway/handlers/memory.js +54 -0
  34. package/dist/gateway/handlers/providers.js +73 -0
  35. package/dist/gateway/handlers/registry.js +39 -0
  36. package/dist/gateway/handlers/sessions.js +188 -0
  37. package/dist/gateway/handlers/system.js +12 -0
  38. package/dist/gateway/handlers/tasks.js +191 -0
  39. package/dist/gateway/handlers/turn.js +100 -0
  40. package/dist/gateway/index.js +126 -0
  41. package/dist/gateway/main.js +23 -0
  42. package/dist/gateway/server.js +354 -0
  43. package/dist/gateway/services/context-limits.js +75 -0
  44. package/dist/gateway/services/history-normalizer.js +42 -0
  45. package/dist/gateway/services/image-pipeline.js +56 -0
  46. package/dist/gateway/services/key-roulette-client.js +43 -0
  47. package/dist/gateway/services/llm-client.js +593 -0
  48. package/dist/gateway/services/llm-decoder.js +200 -0
  49. package/dist/gateway/services/local-fallback.js +135 -0
  50. package/dist/gateway/services/memory.js +511 -0
  51. package/dist/gateway/services/persistent-memory.js +196 -0
  52. package/dist/gateway/services/providers.js +44 -0
  53. package/dist/gateway/services/tasks.js +237 -0
  54. package/dist/gateway/services/verification.js +124 -0
  55. package/dist/gateway/services/vision-payload.js +48 -0
  56. package/dist/gateway/services.js +257 -0
  57. package/dist/gateway/session-snapshot.js +19 -0
  58. package/dist/gateway/sessions.js +701 -0
  59. package/dist/gateway/static.js +239 -0
  60. package/dist/gateway/turns/clarify-tool.js +57 -0
  61. package/dist/gateway/turns/cronjob-tool.js +96 -0
  62. package/dist/gateway/turns/deferred-tools.js +154 -0
  63. package/dist/gateway/turns/execute-code-tool.js +84 -0
  64. package/dist/gateway/turns/file-tool-defs.js +178 -0
  65. package/dist/gateway/turns/file-tool-ops.js +178 -0
  66. package/dist/gateway/turns/file-tool-scan.js +182 -0
  67. package/dist/gateway/turns/file-tool.js +302 -0
  68. package/dist/gateway/turns/index.js +416 -0
  69. package/dist/gateway/turns/jev-middleware.js +91 -0
  70. package/dist/gateway/turns/local-reply.js +156 -0
  71. package/dist/gateway/turns/mcp-client.js +643 -0
  72. package/dist/gateway/turns/memory-tool.js +171 -0
  73. package/dist/gateway/turns/middleware.js +96 -0
  74. package/dist/gateway/turns/python-core.js +397 -0
  75. package/dist/gateway/turns/routing/index.js +3 -0
  76. package/dist/gateway/turns/routing/intent-classifier.js +60 -0
  77. package/dist/gateway/turns/routing/planner-adapter.js +91 -0
  78. package/dist/gateway/turns/routing/types.js +1 -0
  79. package/dist/gateway/turns/runtime-deps.js +228 -0
  80. package/dist/gateway/turns/self-config-tool.js +277 -0
  81. package/dist/gateway/turns/service-types.js +11 -0
  82. package/dist/gateway/turns/service.js +820 -0
  83. package/dist/gateway/turns/session-adapter.js +158 -0
  84. package/dist/gateway/turns/session-tool.js +49 -0
  85. package/dist/gateway/turns/shell-tool.js +190 -0
  86. package/dist/gateway/turns/skill-tool.js +239 -0
  87. package/dist/gateway/turns/spillover.js +201 -0
  88. package/dist/gateway/turns/subagent-tool.js +140 -0
  89. package/dist/gateway/turns/system-prompt.js +121 -0
  90. package/dist/gateway/turns/tool-schema.js +90 -0
  91. package/dist/gateway/turns/turn-utils.js +58 -0
  92. package/dist/gateway/turns/vision-tool.js +120 -0
  93. package/dist/gateway/types.js +1 -0
  94. package/dist/native/win32-x64/boombot-native-host.exe +0 -0
  95. package/dist/node_modules/@boombot/channels/handlers.d.ts +9 -0
  96. package/dist/node_modules/@boombot/channels/handlers.js +109 -0
  97. package/dist/node_modules/@boombot/channels/index.d.ts +12 -0
  98. package/dist/node_modules/@boombot/channels/index.js +12 -0
  99. package/dist/node_modules/@boombot/channels/package.json +9 -0
  100. package/dist/node_modules/@boombot/channels/service.d.ts +62 -0
  101. package/dist/node_modules/@boombot/channels/service.js +608 -0
  102. package/dist/node_modules/@boombot/channels/tool.d.ts +10 -0
  103. package/dist/node_modules/@boombot/channels/tool.js +46 -0
  104. package/dist/node_modules/@boombot/channels/transports/common/dedup.d.ts +17 -0
  105. package/dist/node_modules/@boombot/channels/transports/common/dedup.js +42 -0
  106. package/dist/node_modules/@boombot/channels/transports/common/handoff.d.ts +19 -0
  107. package/dist/node_modules/@boombot/channels/transports/common/handoff.js +32 -0
  108. package/dist/node_modules/@boombot/channels/transports/common/index.d.ts +3 -0
  109. package/dist/node_modules/@boombot/channels/transports/common/index.js +3 -0
  110. package/dist/node_modules/@boombot/channels/transports/common/types.d.ts +99 -0
  111. package/dist/node_modules/@boombot/channels/transports/common/types.js +54 -0
  112. package/dist/node_modules/@boombot/channels/transports/common.d.ts +2 -0
  113. package/dist/node_modules/@boombot/channels/transports/common.js +2 -0
  114. package/dist/node_modules/@boombot/channels/transports/dedup/index.d.ts +1 -0
  115. package/dist/node_modules/@boombot/channels/transports/dedup/index.js +1 -0
  116. package/dist/node_modules/@boombot/channels/transports/dedup.d.ts +2 -0
  117. package/dist/node_modules/@boombot/channels/transports/dedup.js +2 -0
  118. package/dist/node_modules/@boombot/channels/transports/discord/index.d.ts +1 -0
  119. package/dist/node_modules/@boombot/channels/transports/discord/index.js +1 -0
  120. package/dist/node_modules/@boombot/channels/transports/discord/transport.d.ts +36 -0
  121. package/dist/node_modules/@boombot/channels/transports/discord/transport.js +199 -0
  122. package/dist/node_modules/@boombot/channels/transports/discord.d.ts +2 -0
  123. package/dist/node_modules/@boombot/channels/transports/discord.js +2 -0
  124. package/dist/node_modules/@boombot/channels/transports/handoff.d.ts +2 -0
  125. package/dist/node_modules/@boombot/channels/transports/handoff.js +2 -0
  126. package/dist/node_modules/@boombot/channels/transports/messenger/index.d.ts +1 -0
  127. package/dist/node_modules/@boombot/channels/transports/messenger/index.js +1 -0
  128. package/dist/node_modules/@boombot/channels/transports/messenger/transport.d.ts +34 -0
  129. package/dist/node_modules/@boombot/channels/transports/messenger/transport.js +180 -0
  130. package/dist/node_modules/@boombot/channels/transports/messenger.d.ts +2 -0
  131. package/dist/node_modules/@boombot/channels/transports/messenger.js +2 -0
  132. package/dist/node_modules/@boombot/channels/transports/slack/index.d.ts +1 -0
  133. package/dist/node_modules/@boombot/channels/transports/slack/index.js +1 -0
  134. package/dist/node_modules/@boombot/channels/transports/slack/transport.d.ts +35 -0
  135. package/dist/node_modules/@boombot/channels/transports/slack/transport.js +183 -0
  136. package/dist/node_modules/@boombot/channels/transports/slack.d.ts +2 -0
  137. package/dist/node_modules/@boombot/channels/transports/slack.js +2 -0
  138. package/dist/node_modules/@boombot/channels/transports/streamer/index.d.ts +1 -0
  139. package/dist/node_modules/@boombot/channels/transports/streamer/index.js +1 -0
  140. package/dist/node_modules/@boombot/channels/transports/streamer/streamer.d.ts +31 -0
  141. package/dist/node_modules/@boombot/channels/transports/streamer/streamer.js +141 -0
  142. package/dist/node_modules/@boombot/channels/transports/streamer.d.ts +2 -0
  143. package/dist/node_modules/@boombot/channels/transports/streamer.js +2 -0
  144. package/dist/node_modules/@boombot/channels/transports/telegram/index.d.ts +1 -0
  145. package/dist/node_modules/@boombot/channels/transports/telegram/index.js +1 -0
  146. package/dist/node_modules/@boombot/channels/transports/telegram/transport.d.ts +75 -0
  147. package/dist/node_modules/@boombot/channels/transports/telegram/transport.js +395 -0
  148. package/dist/node_modules/@boombot/channels/transports/telegram.d.ts +2 -0
  149. package/dist/node_modules/@boombot/channels/transports/telegram.js +2 -0
  150. package/dist/node_modules/@boombot/channels/transports/tiktok/index.d.ts +1 -0
  151. package/dist/node_modules/@boombot/channels/transports/tiktok/index.js +1 -0
  152. package/dist/node_modules/@boombot/channels/transports/tiktok/transport.d.ts +27 -0
  153. package/dist/node_modules/@boombot/channels/transports/tiktok/transport.js +97 -0
  154. package/dist/node_modules/@boombot/channels/transports/tiktok.d.ts +2 -0
  155. package/dist/node_modules/@boombot/channels/transports/tiktok.js +2 -0
  156. package/dist/node_modules/@boombot/channels/transports/whatsapp/index.d.ts +1 -0
  157. package/dist/node_modules/@boombot/channels/transports/whatsapp/index.js +1 -0
  158. package/dist/node_modules/@boombot/channels/transports/whatsapp/transport.d.ts +38 -0
  159. package/dist/node_modules/@boombot/channels/transports/whatsapp/transport.js +189 -0
  160. package/dist/node_modules/@boombot/channels/transports/whatsapp.d.ts +2 -0
  161. package/dist/node_modules/@boombot/channels/transports/whatsapp.js +2 -0
  162. package/dist/node_modules/@boombot/channels/transports/zalo/index.d.ts +2 -0
  163. package/dist/node_modules/@boombot/channels/transports/zalo/index.js +2 -0
  164. package/dist/node_modules/@boombot/channels/transports/zalo/oa.d.ts +28 -0
  165. package/dist/node_modules/@boombot/channels/transports/zalo/oa.js +94 -0
  166. package/dist/node_modules/@boombot/channels/transports/zalo/personal.d.ts +106 -0
  167. package/dist/node_modules/@boombot/channels/transports/zalo/personal.js +171 -0
  168. package/dist/node_modules/@boombot/channels/transports/zalo-personal.d.ts +2 -0
  169. package/dist/node_modules/@boombot/channels/transports/zalo-personal.js +2 -0
  170. package/dist/node_modules/@boombot/channels/transports/zalo.d.ts +2 -0
  171. package/dist/node_modules/@boombot/channels/transports/zalo.js +2 -0
  172. package/dist/node_modules/@boombot/core/agent-core/index.d.ts +12 -0
  173. package/dist/node_modules/@boombot/core/agent-core/index.js +12 -0
  174. package/dist/node_modules/@boombot/core/agent-core/middleware.d.ts +60 -0
  175. package/dist/node_modules/@boombot/core/agent-core/middleware.js +152 -0
  176. package/dist/node_modules/@boombot/core/agent-core/routing.d.ts +128 -0
  177. package/dist/node_modules/@boombot/core/agent-core/routing.js +437 -0
  178. package/dist/node_modules/@boombot/core/agent-core/runtime-deps.d.ts +88 -0
  179. package/dist/node_modules/@boombot/core/agent-core/runtime-deps.js +8 -0
  180. package/dist/node_modules/@boombot/core/agent-core/tool-errors.d.ts +44 -0
  181. package/dist/node_modules/@boombot/core/agent-core/tool-errors.js +60 -0
  182. package/dist/node_modules/@boombot/core/agent-core/turn-loop.d.ts +21 -0
  183. package/dist/node_modules/@boombot/core/agent-core/turn-loop.js +561 -0
  184. package/dist/node_modules/@boombot/core/agent-core/types.d.ts +189 -0
  185. package/dist/node_modules/@boombot/core/agent-core/types.js +7 -0
  186. package/dist/node_modules/@boombot/core/compaction/compactor.d.ts +19 -0
  187. package/dist/node_modules/@boombot/core/compaction/compactor.js +127 -0
  188. package/dist/node_modules/@boombot/core/compaction/estimator.d.ts +10 -0
  189. package/dist/node_modules/@boombot/core/compaction/estimator.js +48 -0
  190. package/dist/node_modules/@boombot/core/compaction/index.d.ts +3 -0
  191. package/dist/node_modules/@boombot/core/compaction/index.js +3 -0
  192. package/dist/node_modules/@boombot/core/compaction/types.d.ts +31 -0
  193. package/dist/node_modules/@boombot/core/compaction/types.js +7 -0
  194. package/dist/node_modules/@boombot/core/index.d.ts +9 -0
  195. package/dist/node_modules/@boombot/core/index.js +9 -0
  196. package/dist/node_modules/@boombot/core/jev/index.d.ts +2 -0
  197. package/dist/node_modules/@boombot/core/jev/index.js +2 -0
  198. package/dist/node_modules/@boombot/core/jev/jev.d.ts +30 -0
  199. package/dist/node_modules/@boombot/core/jev/jev.js +164 -0
  200. package/dist/node_modules/@boombot/core/jev/types.d.ts +22 -0
  201. package/dist/node_modules/@boombot/core/jev/types.js +1 -0
  202. package/dist/node_modules/@boombot/core/memory/consolidation/budget.d.ts +63 -0
  203. package/dist/node_modules/@boombot/core/memory/consolidation/budget.js +94 -0
  204. package/dist/node_modules/@boombot/core/memory/consolidation/consolidator.d.ts +152 -0
  205. package/dist/node_modules/@boombot/core/memory/consolidation/consolidator.js +318 -0
  206. package/dist/node_modules/@boombot/core/memory/consolidation/index.d.ts +12 -0
  207. package/dist/node_modules/@boombot/core/memory/consolidation/index.js +12 -0
  208. package/dist/node_modules/@boombot/core/memory/curation.d.ts +86 -0
  209. package/dist/node_modules/@boombot/core/memory/curation.js +120 -0
  210. package/dist/node_modules/@boombot/core/memory/errors.d.ts +12 -0
  211. package/dist/node_modules/@boombot/core/memory/errors.js +20 -0
  212. package/dist/node_modules/@boombot/core/memory/hybrid-search.d.ts +29 -0
  213. package/dist/node_modules/@boombot/core/memory/hybrid-search.js +52 -0
  214. package/dist/node_modules/@boombot/core/memory/index.d.ts +23 -0
  215. package/dist/node_modules/@boombot/core/memory/index.js +23 -0
  216. package/dist/node_modules/@boombot/core/memory/indexer.d.ts +47 -0
  217. package/dist/node_modules/@boombot/core/memory/indexer.js +138 -0
  218. package/dist/node_modules/@boombot/core/memory/lifecycle.d.ts +12 -0
  219. package/dist/node_modules/@boombot/core/memory/lifecycle.js +66 -0
  220. package/dist/node_modules/@boombot/core/memory/provider.d.ts +84 -0
  221. package/dist/node_modules/@boombot/core/memory/provider.js +117 -0
  222. package/dist/node_modules/@boombot/core/memory/recall.d.ts +7 -0
  223. package/dist/node_modules/@boombot/core/memory/recall.js +111 -0
  224. package/dist/node_modules/@boombot/core/memory/scope-resolver.d.ts +27 -0
  225. package/dist/node_modules/@boombot/core/memory/scope-resolver.js +60 -0
  226. package/dist/node_modules/@boombot/core/memory/search.d.ts +37 -0
  227. package/dist/node_modules/@boombot/core/memory/search.js +158 -0
  228. package/dist/node_modules/@boombot/core/memory/store.d.ts +60 -0
  229. package/dist/node_modules/@boombot/core/memory/store.js +289 -0
  230. package/dist/node_modules/@boombot/core/memory/types.d.ts +121 -0
  231. package/dist/node_modules/@boombot/core/memory/types.js +21 -0
  232. package/dist/node_modules/@boombot/core/memory/vector-index.d.ts +34 -0
  233. package/dist/node_modules/@boombot/core/memory/vector-index.js +65 -0
  234. package/dist/node_modules/@boombot/core/package.json +9 -0
  235. package/dist/node_modules/@boombot/core/reflection/classifier.d.ts +13 -0
  236. package/dist/node_modules/@boombot/core/reflection/classifier.js +77 -0
  237. package/dist/node_modules/@boombot/core/reflection/index.d.ts +2 -0
  238. package/dist/node_modules/@boombot/core/reflection/index.js +2 -0
  239. package/dist/node_modules/@boombot/core/reflection/types.d.ts +13 -0
  240. package/dist/node_modules/@boombot/core/reflection/types.js +4 -0
  241. package/dist/node_modules/@boombot/core/research/config.d.ts +89 -0
  242. package/dist/node_modules/@boombot/core/research/config.js +206 -0
  243. package/dist/node_modules/@boombot/core/research/crawl.d.ts +36 -0
  244. package/dist/node_modules/@boombot/core/research/crawl.js +179 -0
  245. package/dist/node_modules/@boombot/core/research/factory.d.ts +26 -0
  246. package/dist/node_modules/@boombot/core/research/factory.js +46 -0
  247. package/dist/node_modules/@boombot/core/research/http.d.ts +87 -0
  248. package/dist/node_modules/@boombot/core/research/http.js +250 -0
  249. package/dist/node_modules/@boombot/core/research/index.d.ts +17 -0
  250. package/dist/node_modules/@boombot/core/research/index.js +10 -0
  251. package/dist/node_modules/@boombot/core/research/orchestrator.d.ts +113 -0
  252. package/dist/node_modules/@boombot/core/research/orchestrator.js +252 -0
  253. package/dist/node_modules/@boombot/core/research/parse/docx.d.ts +24 -0
  254. package/dist/node_modules/@boombot/core/research/parse/docx.js +183 -0
  255. package/dist/node_modules/@boombot/core/research/parse/guards.d.ts +89 -0
  256. package/dist/node_modules/@boombot/core/research/parse/guards.js +171 -0
  257. package/dist/node_modules/@boombot/core/research/parse/index.d.ts +68 -0
  258. package/dist/node_modules/@boombot/core/research/parse/index.js +219 -0
  259. package/dist/node_modules/@boombot/core/research/parse/pdf.d.ts +38 -0
  260. package/dist/node_modules/@boombot/core/research/parse/pdf.js +567 -0
  261. package/dist/node_modules/@boombot/core/research/providers/arxiv.d.ts +9 -0
  262. package/dist/node_modules/@boombot/core/research/providers/arxiv.js +72 -0
  263. package/dist/node_modules/@boombot/core/research/providers/brave.d.ts +11 -0
  264. package/dist/node_modules/@boombot/core/research/providers/brave.js +36 -0
  265. package/dist/node_modules/@boombot/core/research/providers/duckduckgo.d.ts +9 -0
  266. package/dist/node_modules/@boombot/core/research/providers/duckduckgo.js +78 -0
  267. package/dist/node_modules/@boombot/core/research/providers/exa.d.ts +11 -0
  268. package/dist/node_modules/@boombot/core/research/providers/exa.js +34 -0
  269. package/dist/node_modules/@boombot/core/research/providers/firecrawl.d.ts +16 -0
  270. package/dist/node_modules/@boombot/core/research/providers/firecrawl.js +47 -0
  271. package/dist/node_modules/@boombot/core/research/providers/index.d.ts +17 -0
  272. package/dist/node_modules/@boombot/core/research/providers/index.js +11 -0
  273. package/dist/node_modules/@boombot/core/research/providers/jina.d.ts +13 -0
  274. package/dist/node_modules/@boombot/core/research/providers/jina.js +114 -0
  275. package/dist/node_modules/@boombot/core/research/providers/openalex.d.ts +14 -0
  276. package/dist/node_modules/@boombot/core/research/providers/openalex.js +66 -0
  277. package/dist/node_modules/@boombot/core/research/providers/semantic-scholar.d.ts +9 -0
  278. package/dist/node_modules/@boombot/core/research/providers/semantic-scholar.js +56 -0
  279. package/dist/node_modules/@boombot/core/research/providers/tavily.d.ts +11 -0
  280. package/dist/node_modules/@boombot/core/research/providers/tavily.js +35 -0
  281. package/dist/node_modules/@boombot/core/research/providers/wikipedia.d.ts +12 -0
  282. package/dist/node_modules/@boombot/core/research/providers/wikipedia.js +47 -0
  283. package/dist/node_modules/@boombot/core/research/tools.d.ts +27 -0
  284. package/dist/node_modules/@boombot/core/research/tools.js +251 -0
  285. package/dist/node_modules/@boombot/core/research/types.d.ts +133 -0
  286. package/dist/node_modules/@boombot/core/research/types.js +8 -0
  287. package/dist/node_modules/@boombot/core/research/wiring.d.ts +25 -0
  288. package/dist/node_modules/@boombot/core/research/wiring.js +51 -0
  289. package/dist/node_modules/@boombot/core/scheduler/cron.d.ts +34 -0
  290. package/dist/node_modules/@boombot/core/scheduler/cron.js +147 -0
  291. package/dist/node_modules/@boombot/core/scheduler/evaluator.d.ts +42 -0
  292. package/dist/node_modules/@boombot/core/scheduler/evaluator.js +148 -0
  293. package/dist/node_modules/@boombot/core/scheduler/index.d.ts +15 -0
  294. package/dist/node_modules/@boombot/core/scheduler/index.js +15 -0
  295. package/dist/node_modules/@boombot/core/scheduler/registry.d.ts +81 -0
  296. package/dist/node_modules/@boombot/core/scheduler/registry.js +263 -0
  297. package/dist/node_modules/@boombot/core/scheduler/runner.d.ts +59 -0
  298. package/dist/node_modules/@boombot/core/scheduler/runner.js +257 -0
  299. package/dist/node_modules/@boombot/core/scheduler/store.d.ts +150 -0
  300. package/dist/node_modules/@boombot/core/scheduler/store.js +526 -0
  301. package/dist/node_modules/@boombot/core/scheduler/timezone.d.ts +35 -0
  302. package/dist/node_modules/@boombot/core/scheduler/timezone.js +96 -0
  303. package/dist/node_modules/@boombot/core/scheduler/types.d.ts +157 -0
  304. package/dist/node_modules/@boombot/core/scheduler/types.js +89 -0
  305. package/dist/node_modules/@boombot/core/task-runner/index.d.ts +7 -0
  306. package/dist/node_modules/@boombot/core/task-runner/index.js +5 -0
  307. package/dist/node_modules/@boombot/core/task-runner/planner.d.ts +37 -0
  308. package/dist/node_modules/@boombot/core/task-runner/planner.js +154 -0
  309. package/dist/node_modules/@boombot/core/task-runner/runner.d.ts +8 -0
  310. package/dist/node_modules/@boombot/core/task-runner/runner.js +564 -0
  311. package/dist/node_modules/@boombot/core/task-runner/store.d.ts +28 -0
  312. package/dist/node_modules/@boombot/core/task-runner/store.js +126 -0
  313. package/dist/node_modules/@boombot/core/task-runner/types.d.ts +138 -0
  314. package/dist/node_modules/@boombot/core/task-runner/types.js +11 -0
  315. package/dist/node_modules/@boombot/core/workflow/dag.d.ts +16 -0
  316. package/dist/node_modules/@boombot/core/workflow/dag.js +109 -0
  317. package/dist/node_modules/@boombot/core/workflow/engine.d.ts +34 -0
  318. package/dist/node_modules/@boombot/core/workflow/engine.js +304 -0
  319. package/dist/node_modules/@boombot/core/workflow/index.d.ts +3 -0
  320. package/dist/node_modules/@boombot/core/workflow/index.js +3 -0
  321. package/dist/node_modules/@boombot/core/workflow/types.d.ts +98 -0
  322. package/dist/node_modules/@boombot/core/workflow/types.js +21 -0
  323. package/dist/node_modules/@boombot/cronjobs/handlers.d.ts +11 -0
  324. package/dist/node_modules/@boombot/cronjobs/handlers.js +174 -0
  325. package/dist/node_modules/@boombot/cronjobs/index.d.ts +2 -0
  326. package/dist/node_modules/@boombot/cronjobs/index.js +2 -0
  327. package/dist/node_modules/@boombot/cronjobs/package.json +9 -0
  328. package/dist/node_modules/@boombot/cronjobs/service.d.ts +53 -0
  329. package/dist/node_modules/@boombot/cronjobs/service.js +200 -0
  330. package/dist/node_modules/@boombot/plugins/index.d.ts +2 -0
  331. package/dist/node_modules/@boombot/plugins/index.js +2 -0
  332. package/dist/node_modules/@boombot/plugins/installer.d.ts +45 -0
  333. package/dist/node_modules/@boombot/plugins/installer.js +487 -0
  334. package/dist/node_modules/@boombot/plugins/manager.d.ts +23 -0
  335. package/dist/node_modules/@boombot/plugins/manager.js +243 -0
  336. package/dist/node_modules/@boombot/plugins/package.json +9 -0
  337. package/dist/node_modules/@boombot/protocol/gateway-protocol/commands-channels.d.ts +125 -0
  338. package/dist/node_modules/@boombot/protocol/gateway-protocol/commands-channels.js +76 -0
  339. package/dist/node_modules/@boombot/protocol/gateway-protocol/commands-plugins.d.ts +220 -0
  340. package/dist/node_modules/@boombot/protocol/gateway-protocol/commands-plugins.js +60 -0
  341. package/dist/node_modules/@boombot/protocol/gateway-protocol/commands-scheduler.d.ts +33 -0
  342. package/dist/node_modules/@boombot/protocol/gateway-protocol/commands-scheduler.js +25 -0
  343. package/dist/node_modules/@boombot/protocol/gateway-protocol/commands.d.ts +4349 -0
  344. package/dist/node_modules/@boombot/protocol/gateway-protocol/commands.js +563 -0
  345. package/dist/node_modules/@boombot/protocol/gateway-protocol/envelope.d.ts +32 -0
  346. package/dist/node_modules/@boombot/protocol/gateway-protocol/envelope.js +61 -0
  347. package/dist/node_modules/@boombot/protocol/gateway-protocol/errors.d.ts +13 -0
  348. package/dist/node_modules/@boombot/protocol/gateway-protocol/errors.js +16 -0
  349. package/dist/node_modules/@boombot/protocol/gateway-protocol/events.d.ts +567 -0
  350. package/dist/node_modules/@boombot/protocol/gateway-protocol/events.js +395 -0
  351. package/dist/node_modules/@boombot/protocol/gateway-protocol/index.d.ts +20 -0
  352. package/dist/node_modules/@boombot/protocol/gateway-protocol/index.js +13 -0
  353. package/dist/node_modules/@boombot/protocol/gateway-protocol/types.d.ts +91 -0
  354. package/dist/node_modules/@boombot/protocol/gateway-protocol/types.js +7 -0
  355. package/dist/node_modules/@boombot/protocol/index.d.ts +4 -0
  356. package/dist/node_modules/@boombot/protocol/index.js +3 -0
  357. package/dist/node_modules/@boombot/protocol/package.json +9 -0
  358. package/dist/node_modules/@boombot/protocol/plugin-sdk/channel.d.ts +41 -0
  359. package/dist/node_modules/@boombot/protocol/plugin-sdk/channel.js +17 -0
  360. package/dist/node_modules/@boombot/protocol/plugin-sdk/index.d.ts +10 -0
  361. package/dist/node_modules/@boombot/protocol/plugin-sdk/index.js +10 -0
  362. package/dist/node_modules/@boombot/protocol/plugin-sdk/manifest.d.ts +58 -0
  363. package/dist/node_modules/@boombot/protocol/plugin-sdk/manifest.js +116 -0
  364. package/dist/node_modules/@boombot/protocol/plugin-sdk/plugin.d.ts +25 -0
  365. package/dist/node_modules/@boombot/protocol/plugin-sdk/plugin.js +1 -0
  366. package/dist/node_modules/@boombot/protocol/providers/cipher.d.ts +7 -0
  367. package/dist/node_modules/@boombot/protocol/providers/cipher.js +52 -0
  368. package/dist/node_modules/@boombot/protocol/providers/index.d.ts +19 -0
  369. package/dist/node_modules/@boombot/protocol/providers/index.js +19 -0
  370. package/dist/node_modules/@boombot/protocol/providers/key-roulette.d.ts +79 -0
  371. package/dist/node_modules/@boombot/protocol/providers/key-roulette.js +81 -0
  372. package/dist/node_modules/@boombot/protocol/providers/probe.d.ts +29 -0
  373. package/dist/node_modules/@boombot/protocol/providers/probe.js +96 -0
  374. package/dist/node_modules/@boombot/protocol/providers/profiles/anthropic.d.ts +11 -0
  375. package/dist/node_modules/@boombot/protocol/providers/profiles/anthropic.js +11 -0
  376. package/dist/node_modules/@boombot/protocol/providers/profiles/custom.d.ts +22 -0
  377. package/dist/node_modules/@boombot/protocol/providers/profiles/custom.js +222 -0
  378. package/dist/node_modules/@boombot/protocol/providers/profiles/deepseek.d.ts +7 -0
  379. package/dist/node_modules/@boombot/protocol/providers/profiles/deepseek.js +9 -0
  380. package/dist/node_modules/@boombot/protocol/providers/profiles/google.d.ts +10 -0
  381. package/dist/node_modules/@boombot/protocol/providers/profiles/google.js +10 -0
  382. package/dist/node_modules/@boombot/protocol/providers/profiles/index.d.ts +31 -0
  383. package/dist/node_modules/@boombot/protocol/providers/profiles/index.js +56 -0
  384. package/dist/node_modules/@boombot/protocol/providers/profiles/local.d.ts +10 -0
  385. package/dist/node_modules/@boombot/protocol/providers/profiles/local.js +11 -0
  386. package/dist/node_modules/@boombot/protocol/providers/profiles/mistral.d.ts +7 -0
  387. package/dist/node_modules/@boombot/protocol/providers/profiles/mistral.js +9 -0
  388. package/dist/node_modules/@boombot/protocol/providers/profiles/openai-compatible.d.ts +10 -0
  389. package/dist/node_modules/@boombot/protocol/providers/profiles/openai-compatible.js +10 -0
  390. package/dist/node_modules/@boombot/protocol/providers/profiles/openai.d.ts +7 -0
  391. package/dist/node_modules/@boombot/protocol/providers/profiles/openai.js +11 -0
  392. package/dist/node_modules/@boombot/protocol/providers/profiles/types.d.ts +58 -0
  393. package/dist/node_modules/@boombot/protocol/providers/profiles/types.js +1 -0
  394. package/dist/node_modules/@boombot/protocol/providers/profiles/xai.d.ts +7 -0
  395. package/dist/node_modules/@boombot/protocol/providers/profiles/xai.js +10 -0
  396. package/dist/node_modules/@boombot/protocol/providers/request-profile.d.ts +102 -0
  397. package/dist/node_modules/@boombot/protocol/providers/request-profile.js +118 -0
  398. package/dist/node_modules/@boombot/protocol/providers/service.d.ts +2 -0
  399. package/dist/node_modules/@boombot/protocol/providers/service.js +418 -0
  400. package/dist/node_modules/@boombot/protocol/providers/types.d.ts +141 -0
  401. package/dist/node_modules/@boombot/protocol/providers/types.js +16 -0
  402. package/dist/node_modules/@boombot/sandbox/fs-path.d.ts +13 -0
  403. package/dist/node_modules/@boombot/sandbox/fs-path.js +79 -0
  404. package/dist/node_modules/@boombot/sandbox/index.d.ts +13 -0
  405. package/dist/node_modules/@boombot/sandbox/index.js +13 -0
  406. package/dist/node_modules/@boombot/sandbox/native.d.ts +39 -0
  407. package/dist/node_modules/@boombot/sandbox/native.js +224 -0
  408. package/dist/node_modules/@boombot/sandbox/package.json +9 -0
  409. package/dist/node_modules/@boombot/sandbox/sandbox.d.ts +92 -0
  410. package/dist/node_modules/@boombot/sandbox/sandbox.js +229 -0
  411. package/dist/node_modules/@boombot/security/harness-guard/boundary.d.ts +22 -0
  412. package/dist/node_modules/@boombot/security/harness-guard/boundary.js +105 -0
  413. package/dist/node_modules/@boombot/security/harness-guard/gates.d.ts +90 -0
  414. package/dist/node_modules/@boombot/security/harness-guard/gates.js +791 -0
  415. package/dist/node_modules/@boombot/security/harness-guard/index.d.ts +23 -0
  416. package/dist/node_modules/@boombot/security/harness-guard/index.js +23 -0
  417. package/dist/node_modules/@boombot/security/harness-guard/policy.d.ts +20 -0
  418. package/dist/node_modules/@boombot/security/harness-guard/policy.js +70 -0
  419. package/dist/node_modules/@boombot/security/harness-guard/sanitizer.d.ts +53 -0
  420. package/dist/node_modules/@boombot/security/harness-guard/sanitizer.js +145 -0
  421. package/dist/node_modules/@boombot/security/harness-guard/types.d.ts +71 -0
  422. package/dist/node_modules/@boombot/security/harness-guard/types.js +10 -0
  423. package/dist/node_modules/@boombot/security/harness-guard/verifier.d.ts +59 -0
  424. package/dist/node_modules/@boombot/security/harness-guard/verifier.js +169 -0
  425. package/dist/node_modules/@boombot/security/index.d.ts +5 -0
  426. package/dist/node_modules/@boombot/security/index.js +9 -0
  427. package/dist/node_modules/@boombot/security/package.json +9 -0
  428. package/dist/node_modules/@boombot/security/policy/approval.d.ts +117 -0
  429. package/dist/node_modules/@boombot/security/policy/approval.js +223 -0
  430. package/dist/node_modules/@boombot/security/reasoning-guard/claim-extractor.d.ts +10 -0
  431. package/dist/node_modules/@boombot/security/reasoning-guard/claim-extractor.js +124 -0
  432. package/dist/node_modules/@boombot/security/reasoning-guard/evidence-ledger.d.ts +25 -0
  433. package/dist/node_modules/@boombot/security/reasoning-guard/evidence-ledger.js +70 -0
  434. package/dist/node_modules/@boombot/security/reasoning-guard/gate.d.ts +38 -0
  435. package/dist/node_modules/@boombot/security/reasoning-guard/gate.js +61 -0
  436. package/dist/node_modules/@boombot/security/reasoning-guard/grounding-check.d.ts +12 -0
  437. package/dist/node_modules/@boombot/security/reasoning-guard/grounding-check.js +234 -0
  438. package/dist/node_modules/@boombot/security/reasoning-guard/index.d.ts +17 -0
  439. package/dist/node_modules/@boombot/security/reasoning-guard/index.js +13 -0
  440. package/dist/node_modules/@boombot/security/reasoning-guard/policy.d.ts +15 -0
  441. package/dist/node_modules/@boombot/security/reasoning-guard/policy.js +39 -0
  442. package/dist/node_modules/@boombot/security/reasoning-guard/types.d.ts +46 -0
  443. package/dist/node_modules/@boombot/security/reasoning-guard/types.js +7 -0
  444. package/dist/node_modules/@boombot/security/security/approval.d.ts +63 -0
  445. package/dist/node_modules/@boombot/security/security/approval.js +140 -0
  446. package/dist/node_modules/@boombot/security/security/audit.d.ts +39 -0
  447. package/dist/node_modules/@boombot/security/security/audit.js +70 -0
  448. package/dist/node_modules/@boombot/security/security/index.d.ts +12 -0
  449. package/dist/node_modules/@boombot/security/security/index.js +12 -0
  450. package/dist/node_modules/@boombot/security/security/trust.d.ts +79 -0
  451. package/dist/node_modules/@boombot/security/security/trust.js +87 -0
  452. package/dist/package.json +5 -0
  453. package/dist/proto/agent_core.proto +56 -0
  454. package/dist/python/agent-core-python/pyproject.toml +40 -0
  455. package/dist/python/agent-core-python/src/boombot_agent/__init__.py +5 -0
  456. package/dist/python/agent-core-python/src/boombot_agent/generated/__init__.py +0 -0
  457. package/dist/python/agent-core-python/src/boombot_agent/generated/agent_core_pb2.py +54 -0
  458. package/dist/python/agent-core-python/src/boombot_agent/generated/agent_core_pb2_grpc.py +140 -0
  459. package/dist/python/agent-core-python/src/boombot_agent/rpc.py +265 -0
  460. package/dist/python/agent-core-python/src/boombot_agent/turn.py +577 -0
  461. package/dist/python/agent-core-python/src/boombot_ml/__init__.py +12 -0
  462. package/dist/python/agent-core-python/src/boombot_ml/embeddings.py +58 -0
  463. package/dist/python/agent-core-python/src/boombot_ml/training.py +156 -0
  464. package/dist/python/agent-core-python/uv.lock +2856 -0
  465. package/dist/web/assets/ChatView-BZrSD-64.js +262 -0
  466. package/dist/web/assets/ChatView-Cahbjez6.css +1 -0
  467. package/dist/web/assets/KaTeX_AMS-Regular-BQhdFMY1.woff2 +0 -0
  468. package/dist/web/assets/KaTeX_AMS-Regular-DMm9YOAa.woff +0 -0
  469. package/dist/web/assets/KaTeX_AMS-Regular-DRggAlZN.ttf +0 -0
  470. package/dist/web/assets/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf +0 -0
  471. package/dist/web/assets/KaTeX_Caligraphic-Bold-BEiXGLvX.woff +0 -0
  472. package/dist/web/assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 +0 -0
  473. package/dist/web/assets/KaTeX_Caligraphic-Regular-CTRA-rTL.woff +0 -0
  474. package/dist/web/assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 +0 -0
  475. package/dist/web/assets/KaTeX_Caligraphic-Regular-wX97UBjC.ttf +0 -0
  476. package/dist/web/assets/KaTeX_Fraktur-Bold-BdnERNNW.ttf +0 -0
  477. package/dist/web/assets/KaTeX_Fraktur-Bold-BsDP51OF.woff +0 -0
  478. package/dist/web/assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 +0 -0
  479. package/dist/web/assets/KaTeX_Fraktur-Regular-CB_wures.ttf +0 -0
  480. package/dist/web/assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 +0 -0
  481. package/dist/web/assets/KaTeX_Fraktur-Regular-Dxdc4cR9.woff +0 -0
  482. package/dist/web/assets/KaTeX_Main-Bold-Cx986IdX.woff2 +0 -0
  483. package/dist/web/assets/KaTeX_Main-Bold-Jm3AIy58.woff +0 -0
  484. package/dist/web/assets/KaTeX_Main-Bold-waoOVXN0.ttf +0 -0
  485. package/dist/web/assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 +0 -0
  486. package/dist/web/assets/KaTeX_Main-BoldItalic-DzxPMmG6.ttf +0 -0
  487. package/dist/web/assets/KaTeX_Main-BoldItalic-SpSLRI95.woff +0 -0
  488. package/dist/web/assets/KaTeX_Main-Italic-3WenGoN9.ttf +0 -0
  489. package/dist/web/assets/KaTeX_Main-Italic-BMLOBm91.woff +0 -0
  490. package/dist/web/assets/KaTeX_Main-Italic-NWA7e6Wa.woff2 +0 -0
  491. package/dist/web/assets/KaTeX_Main-Regular-B22Nviop.woff2 +0 -0
  492. package/dist/web/assets/KaTeX_Main-Regular-Dr94JaBh.woff +0 -0
  493. package/dist/web/assets/KaTeX_Main-Regular-ypZvNtVU.ttf +0 -0
  494. package/dist/web/assets/KaTeX_Math-BoldItalic-B3XSjfu4.ttf +0 -0
  495. package/dist/web/assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 +0 -0
  496. package/dist/web/assets/KaTeX_Math-BoldItalic-iY-2wyZ7.woff +0 -0
  497. package/dist/web/assets/KaTeX_Math-Italic-DA0__PXp.woff +0 -0
  498. package/dist/web/assets/KaTeX_Math-Italic-flOr_0UB.ttf +0 -0
  499. package/dist/web/assets/KaTeX_Math-Italic-t53AETM-.woff2 +0 -0
  500. package/dist/web/assets/KaTeX_SansSerif-Bold-CFMepnvq.ttf +0 -0
  501. package/dist/web/assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 +0 -0
  502. package/dist/web/assets/KaTeX_SansSerif-Bold-DbIhKOiC.woff +0 -0
  503. package/dist/web/assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 +0 -0
  504. package/dist/web/assets/KaTeX_SansSerif-Italic-DN2j7dab.woff +0 -0
  505. package/dist/web/assets/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf +0 -0
  506. package/dist/web/assets/KaTeX_SansSerif-Regular-BNo7hRIc.ttf +0 -0
  507. package/dist/web/assets/KaTeX_SansSerif-Regular-CS6fqUqJ.woff +0 -0
  508. package/dist/web/assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 +0 -0
  509. package/dist/web/assets/KaTeX_Script-Regular-C5JkGWo-.ttf +0 -0
  510. package/dist/web/assets/KaTeX_Script-Regular-D3wIWfF6.woff2 +0 -0
  511. package/dist/web/assets/KaTeX_Script-Regular-D5yQViql.woff +0 -0
  512. package/dist/web/assets/KaTeX_Size1-Regular-C195tn64.woff +0 -0
  513. package/dist/web/assets/KaTeX_Size1-Regular-Dbsnue_I.ttf +0 -0
  514. package/dist/web/assets/KaTeX_Size1-Regular-mCD8mA8B.woff2 +0 -0
  515. package/dist/web/assets/KaTeX_Size2-Regular-B7gKUWhC.ttf +0 -0
  516. package/dist/web/assets/KaTeX_Size2-Regular-Dy4dx90m.woff2 +0 -0
  517. package/dist/web/assets/KaTeX_Size2-Regular-oD1tc_U0.woff +0 -0
  518. package/dist/web/assets/KaTeX_Size3-Regular-CTq5MqoE.woff +0 -0
  519. package/dist/web/assets/KaTeX_Size3-Regular-DgpXs0kz.ttf +0 -0
  520. package/dist/web/assets/KaTeX_Size4-Regular-BF-4gkZK.woff +0 -0
  521. package/dist/web/assets/KaTeX_Size4-Regular-DWFBv043.ttf +0 -0
  522. package/dist/web/assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2 +0 -0
  523. package/dist/web/assets/KaTeX_Typewriter-Regular-C0xS9mPB.woff +0 -0
  524. package/dist/web/assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 +0 -0
  525. package/dist/web/assets/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf +0 -0
  526. package/dist/web/assets/MemoryView-BJbXqqs7.css +1 -0
  527. package/dist/web/assets/MemoryView-BfMq_6CD.js +1 -0
  528. package/dist/web/assets/SchedulesView-B22QmPR-.js +1 -0
  529. package/dist/web/assets/SchedulesView-C6XK7A8a.css +1 -0
  530. package/dist/web/assets/SessionsView-C1dqdhxI.css +1 -0
  531. package/dist/web/assets/SessionsView-DS0-aH2a.js +1 -0
  532. package/dist/web/assets/TasksView-Dtasg4hd.css +1 -0
  533. package/dist/web/assets/TasksView-ey0FLsW8.js +2 -0
  534. package/dist/web/assets/Textarea-DN3Zybl1.js +1 -0
  535. package/dist/web/assets/Tooltip-Bn2cqFPz.css +1 -0
  536. package/dist/web/assets/Tooltip-MzV2Gqnc.js +1 -0
  537. package/dist/web/assets/browser-Bnt73-Ub.js +8 -0
  538. package/dist/web/assets/index-BL8bi7Yt.css +1 -0
  539. package/dist/web/assets/index-CuPR73Tn.js +73 -0
  540. package/dist/web/favicon.svg +4 -0
  541. package/dist/web/index.html +26 -0
  542. package/dist/web/logo.jpg +0 -0
  543. package/dist/web/logo.png +0 -0
  544. package/package.json +51 -4
@@ -0,0 +1,365 @@
1
+ /**
2
+ * `boombot doctor` — environment health checks.
3
+ *
4
+ * Every check is pure/async-testable via `runDoctor()`; printing and the
5
+ * process exit code live in `printDoctorReport()` / the bin entrypoint.
6
+ * No secret values are ever printed — only their presence.
7
+ */
8
+ import { spawnSync } from 'node:child_process';
9
+ import { accessSync, constants, existsSync, mkdirSync, readFileSync } from 'node:fs';
10
+ import { createServer } from 'node:net';
11
+ import path from 'node:path';
12
+ import { fileURLToPath } from 'node:url';
13
+ import { ConfigError, configHasSecrets, expandTilde, fileModeBits, loadConfig, resolveConfigPath, validateConfig, } from "../config-file.js";
14
+ import { resolveMasterKeyPath } from "../master-key.js";
15
+ import { resolveWebAssets } from "../web-assets.js";
16
+ const HEALTH_TIMEOUT_MS = 5000;
17
+ /** SQLite is unflagged from Node 22.13; newer supported runtime line starts at 24. */
18
+ export const MIN_NODE_MAJOR = 22;
19
+ /** Real provider store written by `boombot setup` (keys encrypted at rest). */
20
+ export function providerStorePath(dataDir) {
21
+ return path.join(expandTilde(dataDir), 'providers.json');
22
+ }
23
+ function healthzUrl(config) {
24
+ return `http://${config.host}:${config.port}/healthz`;
25
+ }
26
+ function checkNodeVersion() {
27
+ const raw = process.versions.node;
28
+ const [major = 0, minor = 0] = raw.split('.').map(Number);
29
+ if ((major === MIN_NODE_MAJOR && minor >= 13) || major >= 24) {
30
+ return { name: 'node version', status: 'pass', detail: `node v${raw} (22.13+ or 24+)` };
31
+ }
32
+ return {
33
+ name: 'node version',
34
+ status: 'fail',
35
+ detail: `node v${raw} is unsupported — BoomBot needs 22.13+ (22.x) or 24+`,
36
+ fix: 'install a supported Node.js version: https://nodejs.org/en/download',
37
+ };
38
+ }
39
+ function checkPythonRuntime() {
40
+ const sourceVenv = fileURLToPath(new URL(process.platform === 'win32'
41
+ ? '../../../../agent-core-python/.venv/Scripts/python.exe'
42
+ : '../../../../agent-core-python/.venv/bin/python', import.meta.url));
43
+ const python = process.env['BOOMBOT_PYTHON']
44
+ ?? (existsSync(sourceVenv) ? sourceVenv : process.platform === 'win32' ? 'python' : 'python3');
45
+ const probe = spawnSync(python, ['-c', 'import grpc, google.protobuf, sys; print(f"{sys.version_info.major}.{sys.version_info.minor}")'], { encoding: 'utf8', timeout: 5_000, windowsHide: true });
46
+ const version = probe.stdout?.trim() ?? '';
47
+ if (probe.status === 0 && /^(?:3\.(?:1[1-9]|[2-9]\d)|[4-9]\d)\b/u.test(version)) {
48
+ return { name: 'python agent core', status: 'pass', detail: `python ${version} with gRPC` };
49
+ }
50
+ return {
51
+ name: 'python agent core',
52
+ status: 'fail',
53
+ detail: probe.error?.message ?? (probe.stderr?.trim() || 'Python 3.11+ with grpcio is unavailable'),
54
+ fix: 'install Python 3.11+ with grpcio/protobuf; source checkouts run `pnpm python:sync`, or set BOOMBOT_PYTHON',
55
+ };
56
+ }
57
+ function checkMasterKey(configPath) {
58
+ const fromEnv = process.env['BOOMBOT_MASTER_KEY'];
59
+ if (fromEnv !== undefined && fromEnv !== '') {
60
+ return { name: 'master key', status: 'pass', detail: 'provided via BOOMBOT_MASTER_KEY' };
61
+ }
62
+ const keyPath = resolveMasterKeyPath(configPath);
63
+ if (existsSync(keyPath)) {
64
+ return { name: 'master key', status: 'pass', detail: `found at ${keyPath}` };
65
+ }
66
+ return {
67
+ name: 'master key',
68
+ status: 'fail',
69
+ detail: `no master key at ${keyPath} — provider API keys are stored encrypted and need one`,
70
+ fix: 'run `boombot setup` to generate one, or set BOOMBOT_MASTER_KEY',
71
+ };
72
+ }
73
+ /** Try to bind `host:port` briefly. Resolves when the port is free. */
74
+ function tryBind(host, port) {
75
+ return new Promise((resolve, reject) => {
76
+ const srv = createServer();
77
+ srv.once('error', (err) => {
78
+ srv.close(() => reject(err));
79
+ });
80
+ srv.listen(port, host, () => {
81
+ srv.close((err) => {
82
+ if (err)
83
+ reject(err);
84
+ else
85
+ resolve();
86
+ });
87
+ });
88
+ });
89
+ }
90
+ async function checkPort(host, port) {
91
+ try {
92
+ await tryBind(host, port);
93
+ return { name: 'port', status: 'pass', detail: `port ${port} on ${host} is free` };
94
+ }
95
+ catch (err) {
96
+ const code = err.code;
97
+ if (code === 'EADDRINUSE') {
98
+ return {
99
+ name: 'port',
100
+ status: 'fail',
101
+ detail: `port ${port} on ${host} is already in use (and it is not our gateway)`,
102
+ fix: 'stop the other process, or pick another port in `boombot setup`',
103
+ };
104
+ }
105
+ return {
106
+ name: 'port',
107
+ status: 'fail',
108
+ detail: `cannot bind ${host}:${port}: ${err.message}`,
109
+ fix: 'check the host/port in your config',
110
+ };
111
+ }
112
+ }
113
+ /** Read `<dataDir>/providers.json`; `null` when absent/unreadable/invalid. */
114
+ function readProviderStore(dataDir) {
115
+ let raw;
116
+ try {
117
+ raw = readFileSync(providerStorePath(dataDir), 'utf8');
118
+ }
119
+ catch {
120
+ return null;
121
+ }
122
+ try {
123
+ const parsed = JSON.parse(raw);
124
+ if (!Array.isArray(parsed.providers))
125
+ return { count: 0, active: 0 };
126
+ const providers = parsed.providers;
127
+ return {
128
+ count: providers.length,
129
+ active: providers.filter((p) => p.active === true).length,
130
+ };
131
+ }
132
+ catch {
133
+ return null;
134
+ }
135
+ }
136
+ function checkWebAssets() {
137
+ const web = resolveWebAssets();
138
+ if (web.found) {
139
+ return { name: 'web assets', status: 'pass', detail: `web UI found at ${web.path}` };
140
+ }
141
+ if (web.isDistLayout) {
142
+ // A global `npm i -g` install must ship dist/web — its absence is a broken install.
143
+ return {
144
+ name: 'web assets',
145
+ status: 'fail',
146
+ detail: 'bundled web UI is missing from this install (the gateway would run API-only)',
147
+ fix: 'reinstall: npm i -g @boombot/cli',
148
+ };
149
+ }
150
+ return {
151
+ name: 'web assets',
152
+ status: 'warn',
153
+ detail: 'web UI not built — the gateway will run API-only',
154
+ fix: 'build it with `pnpm --filter @boombot/web build` (or run the web dev server)',
155
+ };
156
+ }
157
+ export async function runDoctor(options = {}) {
158
+ const checks = [];
159
+ const configPath = options.configPath ?? resolveConfigPath();
160
+ const fetchImpl = options.fetchImpl ?? fetch;
161
+ const timeoutMs = options.healthTimeoutMs ?? HEALTH_TIMEOUT_MS;
162
+ // 0. Node.js version.
163
+ checks.push(checkNodeVersion());
164
+ checks.push(checkPythonRuntime());
165
+ // 1. Config file exists and is valid.
166
+ let config = null;
167
+ try {
168
+ config = loadConfig(configPath);
169
+ }
170
+ catch (err) {
171
+ checks.push({
172
+ name: 'config file',
173
+ status: 'fail',
174
+ detail: err instanceof ConfigError ? err.message : `unexpected error: ${err.message}`,
175
+ fix: 'run `boombot setup` to create a fresh config, or fix the JSON by hand',
176
+ });
177
+ }
178
+ if (config === null) {
179
+ checks.push({
180
+ name: 'config file',
181
+ status: 'fail',
182
+ detail: `not found at ${configPath}`,
183
+ fix: 'run `boombot setup` to create it',
184
+ });
185
+ }
186
+ else {
187
+ const problems = validateConfig(config);
188
+ checks.push(problems.length === 0
189
+ ? { name: 'config file', status: 'pass', detail: `${configPath} is valid` }
190
+ : {
191
+ name: 'config file',
192
+ status: 'fail',
193
+ detail: problems.join('; '),
194
+ fix: 'run `boombot setup` again or edit the file',
195
+ });
196
+ // 2. File permissions when secrets are present.
197
+ const bits = fileModeBits(configPath);
198
+ if (configHasSecrets(config)) {
199
+ if (process.platform === 'win32') {
200
+ // chmod 0600 is a no-op on Windows (no POSIX permission bits), so
201
+ // a PASS here would lie. Report WARN: secrets are NOT OS-protected.
202
+ checks.push({
203
+ name: 'config permissions',
204
+ status: 'warn',
205
+ detail: `${configPath} holds secrets but permission bits are not enforced on Windows ` +
206
+ `(chmod is a no-op there) — restrict the file via Windows ACLs`,
207
+ fix: 'use `icacls` to remove access for other users, or keep the machine single-user (see SECURITY.md §5)',
208
+ });
209
+ }
210
+ else if (bits === 0o600) {
211
+ checks.push({
212
+ name: 'config permissions',
213
+ status: 'pass',
214
+ detail: `${configPath} is 0600 (secrets protected)`,
215
+ });
216
+ }
217
+ else {
218
+ checks.push({
219
+ name: 'config permissions',
220
+ status: 'fail',
221
+ detail: `config contains secrets but ${configPath} has mode ${bits === null ? 'unknown' : '0o' + bits.toString(8)}`,
222
+ fix: `run \`chmod 600 ${configPath}\``,
223
+ });
224
+ }
225
+ }
226
+ else {
227
+ checks.push({
228
+ name: 'config permissions',
229
+ status: 'pass',
230
+ detail: 'no secrets in config file — permissions not critical',
231
+ });
232
+ }
233
+ // 3. dataDir writable.
234
+ const dataDir = expandTilde(config.dataDir);
235
+ try {
236
+ mkdirSync(dataDir, { recursive: true });
237
+ accessSync(dataDir, constants.W_OK);
238
+ checks.push({ name: 'data dir', status: 'pass', detail: `${dataDir} is writable` });
239
+ }
240
+ catch (err) {
241
+ checks.push({
242
+ name: 'data dir',
243
+ status: 'fail',
244
+ detail: `${dataDir}: ${err.message}`,
245
+ fix: 'check directory ownership and permissions',
246
+ });
247
+ }
248
+ // 4. Master key for provider-key encryption.
249
+ checks.push(checkMasterKey(configPath));
250
+ // 5. Gateway reachable.
251
+ const url = healthzUrl(config);
252
+ let gatewayOk = false;
253
+ try {
254
+ const res = await fetchImpl(url, { signal: AbortSignal.timeout(timeoutMs) });
255
+ if (res.ok) {
256
+ gatewayOk = true;
257
+ checks.push({ name: 'gateway', status: 'pass', detail: `GET ${url} → ${res.status}` });
258
+ }
259
+ else {
260
+ checks.push({
261
+ name: 'gateway',
262
+ status: 'fail',
263
+ detail: `GET ${url} → ${res.status} (expected 2xx)`,
264
+ fix: 'start it with `boombot gateway`',
265
+ });
266
+ }
267
+ }
268
+ catch (err) {
269
+ checks.push({
270
+ name: 'gateway',
271
+ status: 'fail',
272
+ detail: `GET ${url} failed: ${err.message}`,
273
+ fix: 'start it with `boombot gateway`',
274
+ });
275
+ }
276
+ // 6. Port bindable — only when the gateway is NOT already answering
277
+ // (a running gateway legitimately holds the port).
278
+ if (!gatewayOk) {
279
+ checks.push(await checkPort(config.host, config.port));
280
+ }
281
+ // 7. Provider configured in the real encrypted store.
282
+ const store = readProviderStore(config.dataDir);
283
+ if (store !== null && store.count > 0) {
284
+ checks.push({
285
+ name: 'provider',
286
+ status: 'pass',
287
+ detail: `${store.count} provider(s) in ${providerStorePath(config.dataDir)} (${store.active} active)`,
288
+ });
289
+ }
290
+ else {
291
+ checks.push({
292
+ name: 'provider',
293
+ status: 'fail',
294
+ detail: 'no default provider configured',
295
+ fix: 'run `boombot setup` and choose a provider',
296
+ });
297
+ }
298
+ // 8. Web UI assets the gateway would serve.
299
+ checks.push(checkWebAssets());
300
+ // 9. Channel tokens present (names only — never the token values).
301
+ const present = [];
302
+ const empty = [];
303
+ const sections = [
304
+ ['telegram', config.telegram?.botToken],
305
+ ['discord', config.discord?.botToken],
306
+ ['slack', config.slack?.botToken],
307
+ ['whatsapp', config.whatsapp?.accessToken],
308
+ ];
309
+ for (const [name, token] of sections) {
310
+ if (token !== undefined && token !== '')
311
+ present.push(name);
312
+ else
313
+ empty.push(name);
314
+ }
315
+ if (present.length > 0) {
316
+ checks.push({
317
+ name: 'channels',
318
+ status: 'pass',
319
+ detail: `configured: ${present.join(', ')}; not configured: ${empty.length > 0 ? empty.join(', ') : 'none'}`,
320
+ });
321
+ }
322
+ else if (empty.some((name) => hasChannelSection(config, name))) {
323
+ checks.push({
324
+ name: 'channels',
325
+ status: 'fail',
326
+ detail: 'channel section exists but its token is empty',
327
+ fix: 'run `boombot setup` again and paste the token, or remove the empty section',
328
+ });
329
+ }
330
+ else {
331
+ checks.push({
332
+ name: 'channels',
333
+ status: 'pass',
334
+ detail: 'no channels configured (optional — chat via web UI still works)',
335
+ });
336
+ }
337
+ }
338
+ return { checks, ok: checks.every((c) => c.status !== 'fail') };
339
+ }
340
+ function hasChannelSection(config, name) {
341
+ switch (name) {
342
+ case 'telegram':
343
+ return config.telegram !== undefined;
344
+ case 'discord':
345
+ return config.discord !== undefined;
346
+ case 'slack':
347
+ return config.slack !== undefined;
348
+ case 'whatsapp':
349
+ return config.whatsapp !== undefined;
350
+ default:
351
+ return false;
352
+ }
353
+ }
354
+ /** Print a report in `PASS`/`WARN`/`FAIL` lines. Returns the exit code (0 when nothing failed). */
355
+ export function printDoctorReport(report) {
356
+ for (const check of report.checks) {
357
+ const tag = check.status === 'pass' ? 'PASS' : check.status === 'warn' ? 'WARN' : 'FAIL';
358
+ console.log(`${tag} ${check.name}: ${check.detail}`);
359
+ if (check.status !== 'pass' && check.fix !== undefined) {
360
+ console.log(` fix: ${check.fix}`);
361
+ }
362
+ }
363
+ console.log(report.ok ? '\nAll checks passed.' : '\nSome checks failed — see fixes above.');
364
+ return report.ok ? 0 : 1;
365
+ }
@@ -0,0 +1,290 @@
1
+ var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExtension) || function (path, preserveJsx) {
2
+ if (typeof path === "string" && /^\.\.?\//.test(path)) {
3
+ return path.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function (m, tsx, d, ext, cm) {
4
+ return tsx ? preserveJsx ? ".jsx" : ".js" : d && (!ext || !cm) ? m : (d + ext + "." + cm.toLowerCase() + "js");
5
+ });
6
+ }
7
+ return path;
8
+ };
9
+ /**
10
+ * `boombot gateway` — boot the gateway in-process.
11
+ *
12
+ * The gateway entry is owned by the coordinator: `agent-worker/src/index.ts`
13
+ * MUST export `startGateway(): Promise<void>`. This launcher resolves that
14
+ * entry relative to THIS file (override with `BOOMBOT_GATEWAY_ENTRY`),
15
+ * dynamic-imports it, and hands over control.
16
+ *
17
+ * Layouts handled (first existing file wins):
18
+ * - npm dist, bundled CLI: `dist/bin/boombot.js` → `dist/gateway/index.js`
19
+ * - npm dist, per-file tsc: `dist/bin/commands/*.js` → `dist/gateway/index.js`
20
+ * - monorepo build: `apps/cli/…` → `agent-worker/dist/index.js`
21
+ *
22
+ * Only the npm-dist bundle is runnable by plain `node`: its workspace deps are
23
+ * vendored as compiled JS under `dist/node_modules/@boombot/*`. The monorepo
24
+ * candidate is a last resort — it resolves `@boombot/*` through the
25
+ * workspace symlink to TypeScript sources whose relative `./x.js` specifiers
26
+ * do not resolve outside vitest, so it is listed last and never preferred.
27
+ * Source-tree runs must use `BOOMBOT_GATEWAY_ENTRY`.
28
+ *
29
+ * Before booting, the provider master key is loaded into
30
+ * `BOOMBOT_MASTER_KEY` (the gateway refuses to boot without it). After the
31
+ * server is listening, the UI URL is printed and opened in the browser
32
+ * (best-effort; `BOOMBOT_NO_BROWSER=1` or `--no-browser` skips it).
33
+ *
34
+ * The browser is handed the stored gateway API key in the URL fragment
35
+ * (`#k=…`, see `withApiKey`) — that is what lets the web UI connect on its own
36
+ * instead of opening on a form asking for a secret the user has no way to look
37
+ * up. The URL that gets PRINTED never carries the key: it must not reach a
38
+ * terminal, a log, or a pasted bug report.
39
+ *
40
+ * NOTE for the coordinator: please make sure `startGateway` exists and
41
+ * resolves when the gateway is up (it should keep the process alive via its
42
+ * server/scheduler, like `src/main.ts` does today once wired).
43
+ */
44
+ import { existsSync } from 'node:fs';
45
+ import { isIP } from 'node:net';
46
+ import path from 'node:path';
47
+ import { fileURLToPath, pathToFileURL } from 'node:url';
48
+ import { apiKeyMatchesHash, effectiveApiKey, ensureApiKey, resolveApiKeyPath } from "../api-key.js";
49
+ import { loadConfig, resolveConfigPath, saveConfig } from "../config-file.js";
50
+ import { ensureMasterKey, ensureMasterKeyEnv, hasMasterKey, resolveMasterKeyPath } from "../master-key.js";
51
+ import { openBrowser } from "../open-browser.js";
52
+ /**
53
+ * The `apps/cli` package root, derived from this file's own location.
54
+ * Exported for tests.
55
+ *
56
+ * Uses `fileURLToPath` — NOT `new URL(import.meta.url).pathname`: on
57
+ * Windows a file URL looks like `file:///C:/...` and `.pathname` keeps the
58
+ * bogus leading `/C:/`, which `path.resolve` then mangles into `\C:\...`.
59
+ */
60
+ export function cliPackageRoot() {
61
+ // src/commands/gateway.ts → apps/cli/
62
+ return path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..', '..');
63
+ }
64
+ /** Directory containing this module file (`dist/bin[/commands]` in the npm layout). */
65
+ function moduleDir() {
66
+ return path.dirname(fileURLToPath(import.meta.url));
67
+ }
68
+ function resolveGatewayEntry() {
69
+ const override = process.env['BOOMBOT_GATEWAY_ENTRY'];
70
+ if (override !== undefined && override !== '')
71
+ return override;
72
+ const dir = moduleDir();
73
+ // Order matters: the npm-dist bundle is the ONLY candidate plain `node` can
74
+ // load (see the header note). The monorepo paths point at TS sources whose
75
+ // `.js` specifiers never resolve outside vitest, so they must never shadow a
76
+ // real bundle — listing them first is what made a working install crash.
77
+ const candidates = [
78
+ // npm dist layout (bundled CLI): dist/bin/boombot.js → dist/gateway/index.js
79
+ path.join(dir, '..', 'gateway', 'index.js'),
80
+ path.join(dir, '..', 'gateway', 'main.js'),
81
+ // npm dist layout (per-file tsc): dist/bin/commands/gateway.js → dist/gateway/index.js
82
+ path.join(dir, '..', '..', 'gateway', 'index.js'),
83
+ // Monorepo build layout — last resort only (not runnable under plain node).
84
+ path.join(cliPackageRoot(), '..', '..', 'agent-worker', 'dist', 'index.js'),
85
+ ];
86
+ for (const candidate of candidates) {
87
+ if (existsSync(candidate))
88
+ return candidate;
89
+ }
90
+ throw new Error('gateway entry not found — expected dist/gateway/index.js next to the CLI ' +
91
+ '(npm layout) or agent-worker/dist/index.js (monorepo layout, which plain ' +
92
+ 'node cannot load). Reinstall so dist/gateway/ ships, or point ' +
93
+ 'BOOMBOT_GATEWAY_ENTRY=<path> at a runnable bundle.');
94
+ }
95
+ /** Gateway host/port from the CLI config (safe defaults when unreadable). */
96
+ function gatewayHostPort() {
97
+ try {
98
+ const config = loadConfig(resolveConfigPath());
99
+ const host = process.env['BOOMBOT_HOST']?.trim() || config?.host || '127.0.0.1';
100
+ const port = Number.parseInt(process.env['BOOMBOT_PORT']?.trim() || String(config?.port ?? 8787), 10);
101
+ return { host, port: Number.isInteger(port) && port > 0 && port <= 65535 ? port : 8787 };
102
+ }
103
+ catch {
104
+ return { host: '127.0.0.1', port: 8787 };
105
+ }
106
+ }
107
+ /** Public URL for the browser: 0.0.0.0/:: mean "this machine". Exported for tests. */
108
+ export function gatewayPublicUrl() {
109
+ const { host, port } = gatewayHostPort();
110
+ const browserHost = host === '0.0.0.0' || host === '::' ? '127.0.0.1' : host;
111
+ return `http://${isIP(browserHost) === 6 ? `[${browserHost}]` : browserHost}:${port}`;
112
+ }
113
+ /**
114
+ * The URL to hand the browser, with the stored API key in the fragment.
115
+ *
116
+ * The fragment is deliberate: browsers never transmit it to the server, so the
117
+ * key cannot land in an access log or a `Referer` header, and it is never baked
118
+ * into the served HTML — where any script on the origin could read it.
119
+ *
120
+ * Returns `url` unchanged when no key is stored. A gateway on another machine is
121
+ * not this CLI's to vouch for, and the UI's manual form is the right path there.
122
+ * Exported for tests.
123
+ */
124
+ export function withApiKey(url, keyPath = resolveApiKeyPath()) {
125
+ const key = effectiveApiKey(keyPath);
126
+ if (key === null)
127
+ return url;
128
+ const target = new URL(url);
129
+ target.hash = `k=${encodeURIComponent(key)}`;
130
+ return target.href;
131
+ }
132
+ /** First launch only: local defaults and recoverable keys, never reset an existing install. */
133
+ export function initializeGateway(configPath = resolveConfigPath()) {
134
+ if (loadConfig(configPath) !== null)
135
+ return false;
136
+ const dataDir = path.resolve(process.env['BOOMBOT_DATA_DIR']?.trim() || path.join(path.dirname(path.resolve(configPath)), 'data'));
137
+ const masterKeyPath = resolveMasterKeyPath(configPath);
138
+ if (!hasMasterKey(masterKeyPath)) {
139
+ if (existsSync(path.join(dataDir, 'providers.json'))) {
140
+ throw new Error('Existing provider data has no master key. Restore master.key before starting; no keys were changed.');
141
+ }
142
+ ensureMasterKey(masterKeyPath);
143
+ }
144
+ const { apiKeyHash } = ensureApiKey(resolveApiKeyPath(configPath));
145
+ saveConfig({ host: '127.0.0.1', port: 8787, dataDir, apiKeyHash }, configPath, 'wx');
146
+ return true;
147
+ }
148
+ /**
149
+ * Say so when the stored key cannot authenticate, instead of letting the UI open
150
+ * on a silent UNAUTHORIZED that reads like a broken gateway.
151
+ *
152
+ * Three ways to end up there, in the order they are checked: no hash in
153
+ * `config.json` at all (the gateway fails closed on every request), no key left
154
+ * to hand over, or a key that no longer hashes to the stored one — an old
155
+ * `api.key` beside a config rewritten by a later `boombot setup`.
156
+ */
157
+ function warnOnApiKeyDrift() {
158
+ let hash;
159
+ try {
160
+ hash = loadConfig(resolveConfigPath())?.apiKeyHash;
161
+ }
162
+ catch {
163
+ return; // unreadable config — the gateway's own error is clearer than ours
164
+ }
165
+ if (hash === undefined) {
166
+ console.log('⚠ config.json has no apiKeyHash — the gateway rejects every request.\n' +
167
+ ' Run `boombot setup` to generate one.');
168
+ return;
169
+ }
170
+ if (effectiveApiKey() === null) {
171
+ // The state every install predating `api.key` is in: config.json keeps the
172
+ // hash, the plaintext is gone, and no arithmetic brings it back. Say so —
173
+ // the UI otherwise just shows a form asking for a secret that does not exist.
174
+ console.log(`⚠ config.json has an apiKeyHash but ${resolveApiKeyPath()} is missing, so there is\n` +
175
+ ' no key left to sign the browser in with — a hash cannot be turned back into\n' +
176
+ ' the key it came from. Re-run `boombot setup` to rotate it (the old key stops\n' +
177
+ ' working), or restore that file if you still have the key.');
178
+ return;
179
+ }
180
+ if (apiKeyMatchesHash(hash) === false) {
181
+ console.log(`⚠ ${resolveApiKeyPath()} does not match config.json's apiKeyHash — the browser\n` +
182
+ ' would be signed in with a key the gateway rejects. Delete that file and\n' +
183
+ ' re-run `boombot setup` to rotate the key.');
184
+ }
185
+ }
186
+ /**
187
+ * Run the gateway from a statically-bundled module (Bun `--compile` binary).
188
+ * Mirrors the tail of `runGateway()` below: starts the gateway, wires up
189
+ * the shutdown IPC handshake, prints the URL.
190
+ */
191
+ async function runBundledGateway(mod, options) {
192
+ const firstRun = initializeGateway();
193
+ ensureMasterKeyEnv();
194
+ const start = mod.startGatewayManaged ?? mod.startGateway;
195
+ if (typeof start !== 'function') {
196
+ throw new Error('bundled gateway does not export startGateway(): Promise<void>.');
197
+ }
198
+ try {
199
+ const stop = await start();
200
+ if (typeof stop === 'function' && typeof process.send === 'function') {
201
+ process.on('message', (message) => {
202
+ if (typeof message === 'object' &&
203
+ message !== null &&
204
+ message.type === 'shutdown') {
205
+ void stop().finally(() => process.exit(0));
206
+ }
207
+ });
208
+ }
209
+ }
210
+ catch (err) {
211
+ if (err.code === 'EADDRINUSE') {
212
+ const { port } = gatewayHostPort();
213
+ throw new Error(`port ${port} is already in use — is another gateway running? ` +
214
+ `Stop it, or pick another port in ${resolveConfigPath()}.`);
215
+ }
216
+ throw err;
217
+ }
218
+ const url = gatewayPublicUrl();
219
+ console.log(`\n🦉 BoomBot is running — open ${url} in your browser\n`);
220
+ warnOnApiKeyDrift();
221
+ if (firstRun) {
222
+ console.log('Local setup complete. Choose your AI provider in Settings → Connection. Keep this terminal open; Ctrl+C stops BoomBot.');
223
+ }
224
+ if (!options.noBrowser && process.env['BOOMBOT_NO_BROWSER'] !== '1') {
225
+ await openBrowser(url);
226
+ }
227
+ }
228
+ export async function runGateway(options = {}) {
229
+ // Bun-compiled standalone binary: the gateway is bundled via a static import
230
+ // (see src/bin-bun.ts). Check for it before the dynamic-import path below.
231
+ const bundled = globalThis.__BOOMBOT_BUNDLED_GATEWAY__;
232
+ if (bundled && (typeof bundled.startGatewayManaged === 'function' || typeof bundled.startGateway === 'function')) {
233
+ await runBundledGateway(bundled, options);
234
+ return;
235
+ }
236
+ const entry = resolveGatewayEntry();
237
+ const firstRun = initializeGateway();
238
+ // The gateway needs BOOMBOT_MASTER_KEY to decrypt provider keys; load the
239
+ // key `boombot setup` generated so a fresh install just works.
240
+ ensureMasterKeyEnv();
241
+ let mod;
242
+ try {
243
+ mod = (await import(__rewriteRelativeImportExtension(pathToFileURL(entry).href)));
244
+ }
245
+ catch (err) {
246
+ throw new Error(`failed to import gateway entry ${entry}: ${err.message}`);
247
+ }
248
+ const start = mod.startGatewayManaged ?? mod.startGateway;
249
+ if (typeof start !== 'function') {
250
+ throw new Error(`gateway entry ${entry} does not export startGateway(): Promise<void> ` +
251
+ '(coordinator: please add this export).');
252
+ }
253
+ try {
254
+ const stop = await start();
255
+ if (typeof stop === 'function' && typeof process.send === 'function') {
256
+ process.on('message', (message) => {
257
+ if (typeof message === 'object' &&
258
+ message !== null &&
259
+ message.type === 'shutdown') {
260
+ void stop().finally(() => process.exit(0));
261
+ }
262
+ });
263
+ }
264
+ }
265
+ catch (err) {
266
+ if (err.code === 'EADDRINUSE') {
267
+ const { port } = gatewayHostPort();
268
+ throw new Error(`port ${port} is already in use — is another gateway running? ` +
269
+ `Stop it, or pick another port in ${resolveConfigPath()}.`);
270
+ }
271
+ throw err;
272
+ }
273
+ // startGateway resolves once the server is listening.
274
+ const url = gatewayPublicUrl();
275
+ console.log(`\n🦉 BoomBot is running — open ${url} in your browser\n`);
276
+ warnOnApiKeyDrift();
277
+ if (firstRun) {
278
+ console.log('Local setup complete. Choose your AI provider in Settings → Connection. Keep this terminal open; Ctrl+C stops BoomBot.');
279
+ }
280
+ if (options.noBrowser !== true) {
281
+ // The fragment carries the API key to the browser. Browsers never send a
282
+ // fragment to the server, so the key reaches neither the static file server
283
+ // nor any access log, and it is not baked into the served HTML. The web app
284
+ // persists it and rewrites the URL to drop it again.
285
+ const opened = await openBrowser(withApiKey(firstRun ? `${url}/settings/connection` : url));
286
+ if (!opened) {
287
+ console.log('(could not open a browser automatically — headless? open the URL above yourself)');
288
+ }
289
+ }
290
+ }