@hailer/mcp 1.2.1 → 1.3.9

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 (774) hide show
  1. package/.claude/agents/agent-hailer-helper.md +118 -0
  2. package/.claude/commands/debug-squad.md +13 -290
  3. package/.claude/commands/publish.md +2 -2
  4. package/.claude/commands/review-squad.md +17 -139
  5. package/.claude/skills/create-and-publish-app/SKILL.md +133 -143
  6. package/.claude/skills/hailer-app-builder/SKILL.md +29 -2
  7. package/.claude/skills/hailer-ui-guide/SKILL.md +265 -0
  8. package/.env.example +50 -1
  9. package/CLAUDE.md +141 -10
  10. package/dist/app-prep.d.ts +27 -0
  11. package/dist/app-prep.d.ts.map +1 -0
  12. package/dist/app-prep.js +94 -0
  13. package/dist/app-prep.js.map +1 -0
  14. package/dist/app.d.ts.map +1 -1
  15. package/dist/app.js +3 -0
  16. package/dist/app.js.map +1 -1
  17. package/dist/bot/bot-manager.d.ts +9 -6
  18. package/dist/bot/bot-manager.d.ts.map +1 -1
  19. package/dist/bot/bot-manager.js +142 -31
  20. package/dist/bot/bot-manager.js.map +1 -1
  21. package/dist/bot/bot.d.ts +61 -16
  22. package/dist/bot/bot.d.ts.map +1 -1
  23. package/dist/bot/bot.js +927 -151
  24. package/dist/bot/bot.js.map +1 -1
  25. package/dist/bot/operation-logger.d.ts.map +1 -1
  26. package/dist/bot/operation-logger.js +24 -12
  27. package/dist/bot/operation-logger.js.map +1 -1
  28. package/dist/bot/services/bot-permissions.d.ts +37 -5
  29. package/dist/bot/services/bot-permissions.d.ts.map +1 -1
  30. package/dist/bot/services/bot-permissions.js +159 -35
  31. package/dist/bot/services/bot-permissions.js.map +1 -1
  32. package/dist/bot/services/conversation-manager.d.ts +23 -23
  33. package/dist/bot/services/conversation-manager.d.ts.map +1 -1
  34. package/dist/bot/services/conversation-manager.js +52 -49
  35. package/dist/bot/services/conversation-manager.js.map +1 -1
  36. package/dist/bot/services/helper-prompt.d.ts +8 -0
  37. package/dist/bot/services/helper-prompt.d.ts.map +1 -0
  38. package/dist/bot/services/helper-prompt.js +177 -0
  39. package/dist/bot/services/helper-prompt.js.map +1 -0
  40. package/dist/bot/services/message-classifier.d.ts +16 -16
  41. package/dist/bot/services/message-classifier.d.ts.map +1 -1
  42. package/dist/bot/services/message-classifier.js +55 -49
  43. package/dist/bot/services/message-classifier.js.map +1 -1
  44. package/dist/bot/services/message-formatter.d.ts +47 -38
  45. package/dist/bot/services/message-formatter.d.ts.map +1 -1
  46. package/dist/bot/services/message-formatter.js +99 -80
  47. package/dist/bot/services/message-formatter.js.map +1 -1
  48. package/dist/bot/services/permission-guard.d.ts.map +1 -1
  49. package/dist/bot/services/permission-guard.js +20 -10
  50. package/dist/bot/services/permission-guard.js.map +1 -1
  51. package/dist/bot/services/signal-router.d.ts.map +1 -1
  52. package/dist/bot/services/signal-router.js +11 -6
  53. package/dist/bot/services/signal-router.js.map +1 -1
  54. package/dist/bot/services/system-prompt.d.ts +14 -0
  55. package/dist/bot/services/system-prompt.d.ts.map +1 -1
  56. package/dist/bot/services/system-prompt.js +181 -4
  57. package/dist/bot/services/system-prompt.js.map +1 -1
  58. package/dist/bot/services/token-billing.d.ts +23 -23
  59. package/dist/bot/services/token-billing.d.ts.map +1 -1
  60. package/dist/bot/services/token-billing.js +51 -36
  61. package/dist/bot/services/token-billing.js.map +1 -1
  62. package/dist/bot/services/types.d.ts +3 -1
  63. package/dist/bot/services/types.d.ts.map +1 -1
  64. package/dist/bot/services/typing-indicator.d.ts +8 -8
  65. package/dist/bot/services/typing-indicator.d.ts.map +1 -1
  66. package/dist/bot/services/typing-indicator.js +12 -10
  67. package/dist/bot/services/typing-indicator.js.map +1 -1
  68. package/dist/bot/services/workspace-refresh.d.ts +3 -3
  69. package/dist/bot/services/workspace-refresh.d.ts.map +1 -1
  70. package/dist/bot/services/workspace-refresh.js +23 -13
  71. package/dist/bot/services/workspace-refresh.js.map +1 -1
  72. package/dist/bot/tool-executor.d.ts +10 -6
  73. package/dist/bot/tool-executor.d.ts.map +1 -1
  74. package/dist/bot/tool-executor.js +12 -6
  75. package/dist/bot/tool-executor.js.map +1 -1
  76. package/dist/bot/workspace-overview.d.ts.map +1 -1
  77. package/dist/bot/workspace-overview.js +6 -3
  78. package/dist/bot/workspace-overview.js.map +1 -1
  79. package/dist/bot-config/activity-error.d.ts +47 -0
  80. package/dist/bot-config/activity-error.d.ts.map +1 -0
  81. package/dist/bot-config/activity-error.js +67 -0
  82. package/dist/bot-config/activity-error.js.map +1 -0
  83. package/dist/bot-config/context.d.ts +4 -4
  84. package/dist/bot-config/context.d.ts.map +1 -1
  85. package/dist/bot-config/context.js +18 -14
  86. package/dist/bot-config/context.js.map +1 -1
  87. package/dist/bot-config/events.d.ts +45 -0
  88. package/dist/bot-config/events.d.ts.map +1 -0
  89. package/dist/bot-config/events.js +51 -0
  90. package/dist/bot-config/events.js.map +1 -0
  91. package/dist/bot-config/index.d.ts +3 -0
  92. package/dist/bot-config/index.d.ts.map +1 -1
  93. package/dist/bot-config/index.js +8 -1
  94. package/dist/bot-config/index.js.map +1 -1
  95. package/dist/bot-config/loader.d.ts +3 -0
  96. package/dist/bot-config/loader.d.ts.map +1 -1
  97. package/dist/bot-config/loader.js +45 -20
  98. package/dist/bot-config/loader.js.map +1 -1
  99. package/dist/bot-config/persistence.js.map +1 -1
  100. package/dist/bot-config/reconciler.d.ts +11 -0
  101. package/dist/bot-config/reconciler.d.ts.map +1 -0
  102. package/dist/bot-config/reconciler.js +121 -0
  103. package/dist/bot-config/reconciler.js.map +1 -0
  104. package/dist/bot-config/state.d.ts.map +1 -1
  105. package/dist/bot-config/state.js.map +1 -1
  106. package/dist/bot-config/types.d.ts +32 -0
  107. package/dist/bot-config/types.d.ts.map +1 -1
  108. package/dist/bot-config/webhooks.d.ts.map +1 -1
  109. package/dist/bot-config/webhooks.js.map +1 -1
  110. package/dist/bot-config/workflow-installer.d.ts +37 -0
  111. package/dist/bot-config/workflow-installer.d.ts.map +1 -0
  112. package/dist/bot-config/workflow-installer.js +346 -0
  113. package/dist/bot-config/workflow-installer.js.map +1 -0
  114. package/dist/cli.d.ts +4 -1
  115. package/dist/cli.d.ts.map +1 -1
  116. package/dist/cli.js +92 -11
  117. package/dist/cli.js.map +1 -1
  118. package/dist/config.d.ts +23 -19
  119. package/dist/config.d.ts.map +1 -1
  120. package/dist/config.js +65 -27
  121. package/dist/config.js.map +1 -1
  122. package/dist/core.d.ts +6 -4
  123. package/dist/core.d.ts.map +1 -1
  124. package/dist/core.js +11 -16
  125. package/dist/core.js.map +1 -1
  126. package/dist/lib/logger.d.ts.map +1 -1
  127. package/dist/lib/logger.js +7 -4
  128. package/dist/lib/logger.js.map +1 -1
  129. package/dist/lib/request-logger.d.ts +19 -19
  130. package/dist/lib/request-logger.d.ts.map +1 -1
  131. package/dist/lib/request-logger.js +19 -19
  132. package/dist/lib/request-logger.js.map +1 -1
  133. package/dist/mcp/UserContextCache.d.ts +28 -22
  134. package/dist/mcp/UserContextCache.d.ts.map +1 -1
  135. package/dist/mcp/UserContextCache.js +23 -23
  136. package/dist/mcp/UserContextCache.js.map +1 -1
  137. package/dist/mcp/auth.js.map +1 -1
  138. package/dist/mcp/hailer-clients.d.ts +5 -4
  139. package/dist/mcp/hailer-clients.d.ts.map +1 -1
  140. package/dist/mcp/hailer-clients.js +83 -34
  141. package/dist/mcp/hailer-clients.js.map +1 -1
  142. package/dist/mcp/hailer-rpc.d.ts +40 -0
  143. package/dist/mcp/hailer-rpc.d.ts.map +1 -0
  144. package/dist/mcp/hailer-rpc.js +43 -0
  145. package/dist/mcp/hailer-rpc.js.map +1 -0
  146. package/dist/mcp/publish-auth-injector.d.ts +22 -0
  147. package/dist/mcp/publish-auth-injector.d.ts.map +1 -0
  148. package/dist/mcp/publish-auth-injector.js +100 -0
  149. package/dist/mcp/publish-auth-injector.js.map +1 -0
  150. package/dist/mcp/session-store.d.ts +16 -16
  151. package/dist/mcp/session-store.d.ts.map +1 -1
  152. package/dist/mcp/session-store.js +16 -16
  153. package/dist/mcp/session-store.js.map +1 -1
  154. package/dist/mcp/tool-profiles.d.ts +69 -0
  155. package/dist/mcp/tool-profiles.d.ts.map +1 -0
  156. package/dist/mcp/tool-profiles.js +176 -0
  157. package/dist/mcp/tool-profiles.js.map +1 -0
  158. package/dist/mcp/tool-registry.d.ts +16 -0
  159. package/dist/mcp/tool-registry.d.ts.map +1 -1
  160. package/dist/mcp/tool-registry.js +91 -39
  161. package/dist/mcp/tool-registry.js.map +1 -1
  162. package/dist/mcp/tools/activity.d.ts +2 -0
  163. package/dist/mcp/tools/activity.d.ts.map +1 -1
  164. package/dist/mcp/tools/activity.js +575 -218
  165. package/dist/mcp/tools/activity.js.map +1 -1
  166. package/dist/mcp/tools/aliases.d.ts +11 -0
  167. package/dist/mcp/tools/aliases.d.ts.map +1 -0
  168. package/dist/mcp/tools/aliases.js +182 -0
  169. package/dist/mcp/tools/aliases.js.map +1 -0
  170. package/dist/mcp/tools/app-core.d.ts +6 -8
  171. package/dist/mcp/tools/app-core.d.ts.map +1 -1
  172. package/dist/mcp/tools/app-core.js +355 -254
  173. package/dist/mcp/tools/app-core.js.map +1 -1
  174. package/dist/mcp/tools/app-marketplace.d.ts +8 -16
  175. package/dist/mcp/tools/app-marketplace.d.ts.map +1 -1
  176. package/dist/mcp/tools/app-marketplace.js +604 -932
  177. package/dist/mcp/tools/app-marketplace.js.map +1 -1
  178. package/dist/mcp/tools/app.d.ts +4 -7
  179. package/dist/mcp/tools/app.d.ts.map +1 -1
  180. package/dist/mcp/tools/app.js +4 -7
  181. package/dist/mcp/tools/app.js.map +1 -1
  182. package/dist/mcp/tools/bot-self.d.ts +21 -0
  183. package/dist/mcp/tools/bot-self.d.ts.map +1 -0
  184. package/dist/mcp/tools/bot-self.js +174 -0
  185. package/dist/mcp/tools/bot-self.js.map +1 -0
  186. package/dist/mcp/tools/calendar.d.ts +21 -0
  187. package/dist/mcp/tools/calendar.d.ts.map +1 -0
  188. package/dist/mcp/tools/calendar.js +741 -0
  189. package/dist/mcp/tools/calendar.js.map +1 -0
  190. package/dist/mcp/tools/company.d.ts.map +1 -1
  191. package/dist/mcp/tools/company.js +2 -1
  192. package/dist/mcp/tools/company.js.map +1 -1
  193. package/dist/mcp/tools/date.js.map +1 -1
  194. package/dist/mcp/tools/discussion.d.ts +29 -3
  195. package/dist/mcp/tools/discussion.d.ts.map +1 -1
  196. package/dist/mcp/tools/discussion.js +419 -534
  197. package/dist/mcp/tools/discussion.js.map +1 -1
  198. package/dist/mcp/tools/file.d.ts.map +1 -1
  199. package/dist/mcp/tools/file.js +18 -16
  200. package/dist/mcp/tools/file.js.map +1 -1
  201. package/dist/mcp/tools/index.js +4 -4
  202. package/dist/mcp/tools/index.js.map +1 -1
  203. package/dist/mcp/tools/insight.d.ts +24 -5
  204. package/dist/mcp/tools/insight.d.ts.map +1 -1
  205. package/dist/mcp/tools/insight.js +513 -480
  206. package/dist/mcp/tools/insight.js.map +1 -1
  207. package/dist/mcp/tools/user.d.ts.map +1 -1
  208. package/dist/mcp/tools/user.js +15 -13
  209. package/dist/mcp/tools/user.js.map +1 -1
  210. package/dist/mcp/tools/workflow-permissions.d.ts +2 -4
  211. package/dist/mcp/tools/workflow-permissions.d.ts.map +1 -1
  212. package/dist/mcp/tools/workflow-permissions.js +88 -97
  213. package/dist/mcp/tools/workflow-permissions.js.map +1 -1
  214. package/dist/mcp/tools/workflow.d.ts +9 -7
  215. package/dist/mcp/tools/workflow.d.ts.map +1 -1
  216. package/dist/mcp/tools/workflow.js +852 -860
  217. package/dist/mcp/tools/workflow.js.map +1 -1
  218. package/dist/mcp/utils/api-errors.d.ts.map +1 -1
  219. package/dist/mcp/utils/api-errors.js +2 -2
  220. package/dist/mcp/utils/api-errors.js.map +1 -1
  221. package/dist/mcp/utils/data-transformers.d.ts +0 -3
  222. package/dist/mcp/utils/data-transformers.d.ts.map +1 -1
  223. package/dist/mcp/utils/data-transformers.js +32 -5
  224. package/dist/mcp/utils/data-transformers.js.map +1 -1
  225. package/dist/mcp/utils/file-upload.d.ts.map +1 -1
  226. package/dist/mcp/utils/file-upload.js +1 -1
  227. package/dist/mcp/utils/file-upload.js.map +1 -1
  228. package/dist/mcp/utils/hailer-api-client.d.ts +81 -81
  229. package/dist/mcp/utils/hailer-api-client.d.ts.map +1 -1
  230. package/dist/mcp/utils/hailer-api-client.js +113 -103
  231. package/dist/mcp/utils/hailer-api-client.js.map +1 -1
  232. package/dist/mcp/utils/index.d.ts.map +1 -1
  233. package/dist/mcp/utils/index.js.map +1 -1
  234. package/dist/mcp/utils/logger.d.ts.map +1 -1
  235. package/dist/mcp/utils/logger.js.map +1 -1
  236. package/dist/mcp/utils/response-builder.d.ts.map +1 -1
  237. package/dist/mcp/utils/response-builder.js +8 -4
  238. package/dist/mcp/utils/response-builder.js.map +1 -1
  239. package/dist/mcp/utils/role-utils.d.ts.map +1 -1
  240. package/dist/mcp/utils/role-utils.js +6 -3
  241. package/dist/mcp/utils/role-utils.js.map +1 -1
  242. package/dist/mcp/utils/tool-helpers.d.ts.map +1 -1
  243. package/dist/mcp/utils/tool-helpers.js +2 -2
  244. package/dist/mcp/utils/tool-helpers.js.map +1 -1
  245. package/dist/mcp/utils/types.d.ts +2 -1
  246. package/dist/mcp/utils/types.d.ts.map +1 -1
  247. package/dist/mcp/utils/types.js.map +1 -1
  248. package/dist/mcp/webhook-handler.d.ts +43 -8
  249. package/dist/mcp/webhook-handler.d.ts.map +1 -1
  250. package/dist/mcp/webhook-handler.js +861 -116
  251. package/dist/mcp/webhook-handler.js.map +1 -1
  252. package/dist/mcp/workspace-admin-store.d.ts +49 -0
  253. package/dist/mcp/workspace-admin-store.d.ts.map +1 -0
  254. package/dist/mcp/workspace-admin-store.js +168 -0
  255. package/dist/mcp/workspace-admin-store.js.map +1 -0
  256. package/dist/mcp/workspace-cache.d.ts +2 -2
  257. package/dist/mcp/workspace-cache.d.ts.map +1 -1
  258. package/dist/mcp/workspace-cache.js +9 -5
  259. package/dist/mcp/workspace-cache.js.map +1 -1
  260. package/dist/mcp-server.d.ts +26 -11
  261. package/dist/mcp-server.d.ts.map +1 -1
  262. package/dist/mcp-server.js +367 -48
  263. package/dist/mcp-server.js.map +1 -1
  264. package/dist/plugins/vipunen/client.d.ts +41 -41
  265. package/dist/plugins/vipunen/client.d.ts.map +1 -1
  266. package/dist/plugins/vipunen/client.js +53 -48
  267. package/dist/plugins/vipunen/client.js.map +1 -1
  268. package/dist/plugins/vipunen/index.js.map +1 -1
  269. package/dist/plugins/vipunen/tools.d.ts.map +1 -1
  270. package/dist/plugins/vipunen/tools.js +6 -3
  271. package/dist/plugins/vipunen/tools.js.map +1 -1
  272. package/dist/public-chat/graduate.d.ts +29 -0
  273. package/dist/public-chat/graduate.d.ts.map +1 -0
  274. package/dist/public-chat/graduate.js +593 -0
  275. package/dist/public-chat/graduate.js.map +1 -0
  276. package/dist/public-chat/handler.d.ts +12 -0
  277. package/dist/public-chat/handler.d.ts.map +1 -0
  278. package/dist/public-chat/handler.js +183 -0
  279. package/dist/public-chat/handler.js.map +1 -0
  280. package/dist/public-chat/index.d.ts +16 -0
  281. package/dist/public-chat/index.d.ts.map +1 -0
  282. package/dist/public-chat/index.js +74 -0
  283. package/dist/public-chat/index.js.map +1 -0
  284. package/dist/public-chat/knowledge.d.ts +3 -0
  285. package/dist/public-chat/knowledge.d.ts.map +1 -0
  286. package/dist/public-chat/knowledge.js +1340 -0
  287. package/dist/public-chat/knowledge.js.map +1 -0
  288. package/dist/public-chat/rate-limit.d.ts +16 -0
  289. package/dist/public-chat/rate-limit.d.ts.map +1 -0
  290. package/dist/public-chat/rate-limit.js +51 -0
  291. package/dist/public-chat/rate-limit.js.map +1 -0
  292. package/dist/public-chat/session-store.d.ts +41 -0
  293. package/dist/public-chat/session-store.d.ts.map +1 -0
  294. package/dist/public-chat/session-store.js +95 -0
  295. package/dist/public-chat/session-store.js.map +1 -0
  296. package/dist/public-chat/studio-prewarm.d.ts +61 -0
  297. package/dist/public-chat/studio-prewarm.d.ts.map +1 -0
  298. package/dist/public-chat/studio-prewarm.js +162 -0
  299. package/dist/public-chat/studio-prewarm.js.map +1 -0
  300. package/dist/public-chat/system-prompt.d.ts +22 -0
  301. package/dist/public-chat/system-prompt.d.ts.map +1 -0
  302. package/dist/public-chat/system-prompt.js +435 -0
  303. package/dist/public-chat/system-prompt.js.map +1 -0
  304. package/package.json +15 -7
  305. package/scripts/build-public-chat-knowledge.py +101 -0
  306. package/scripts/smoke-public-chat-live.ts +148 -0
  307. package/scripts/smoke-public-chat.ts +110 -0
  308. package/.claude/CLAUDE.md +0 -126
  309. package/.claude/commands/app-squad.md +0 -131
  310. package/.claude/commands/audit-squad.md +0 -158
  311. package/.claude/commands/cleanup-squad.md +0 -98
  312. package/.claude/commands/config-squad.md +0 -106
  313. package/.claude/commands/crud-squad.md +0 -87
  314. package/.claude/commands/data-squad.md +0 -97
  315. package/.claude/commands/doc-squad.md +0 -65
  316. package/.claude/commands/help.md +0 -29
  317. package/.claude/commands/help:agents.md +0 -182
  318. package/.claude/commands/help:commands.md +0 -78
  319. package/.claude/commands/help:faq.md +0 -79
  320. package/.claude/commands/help:plugins.md +0 -50
  321. package/.claude/commands/help:skills.md +0 -87
  322. package/.claude/commands/help:tools.md +0 -75
  323. package/.claude/commands/hotfix-squad.md +0 -112
  324. package/.claude/commands/integration-squad.md +0 -82
  325. package/.claude/commands/janitor-squad.md +0 -167
  326. package/.claude/commands/onboard-squad.md +0 -130
  327. package/.claude/commands/swarm.md +0 -210
  328. package/.claude/commands/tool-builder.md +0 -39
  329. package/.claude/skills/publish-hailer-app/SKILL.md +0 -280
  330. package/dist/CLAUDE.md +0 -370
  331. package/dist/agents/bot-manager.d.ts +0 -48
  332. package/dist/agents/bot-manager.d.ts.map +0 -1
  333. package/dist/agents/bot-manager.js +0 -254
  334. package/dist/agents/bot-manager.js.map +0 -1
  335. package/dist/agents/bug-fixer/ai.d.ts +0 -80
  336. package/dist/agents/bug-fixer/ai.d.ts.map +0 -1
  337. package/dist/agents/bug-fixer/ai.js +0 -466
  338. package/dist/agents/bug-fixer/ai.js.map +0 -1
  339. package/dist/agents/bug-fixer/bot.d.ts +0 -92
  340. package/dist/agents/bug-fixer/bot.d.ts.map +0 -1
  341. package/dist/agents/bug-fixer/bot.js +0 -687
  342. package/dist/agents/bug-fixer/bot.js.map +0 -1
  343. package/dist/agents/bug-fixer/config.d.ts +0 -21
  344. package/dist/agents/bug-fixer/config.d.ts.map +0 -1
  345. package/dist/agents/bug-fixer/config.js +0 -218
  346. package/dist/agents/bug-fixer/config.js.map +0 -1
  347. package/dist/agents/bug-fixer/files.d.ts +0 -67
  348. package/dist/agents/bug-fixer/files.d.ts.map +0 -1
  349. package/dist/agents/bug-fixer/files.js +0 -386
  350. package/dist/agents/bug-fixer/files.js.map +0 -1
  351. package/dist/agents/bug-fixer/git.d.ts +0 -48
  352. package/dist/agents/bug-fixer/git.d.ts.map +0 -1
  353. package/dist/agents/bug-fixer/git.js +0 -298
  354. package/dist/agents/bug-fixer/git.js.map +0 -1
  355. package/dist/agents/bug-fixer/index.d.ts +0 -103
  356. package/dist/agents/bug-fixer/index.d.ts.map +0 -1
  357. package/dist/agents/bug-fixer/index.js +0 -262
  358. package/dist/agents/bug-fixer/index.js.map +0 -1
  359. package/dist/agents/bug-fixer/lsp.d.ts +0 -113
  360. package/dist/agents/bug-fixer/lsp.d.ts.map +0 -1
  361. package/dist/agents/bug-fixer/lsp.js +0 -485
  362. package/dist/agents/bug-fixer/lsp.js.map +0 -1
  363. package/dist/agents/bug-fixer/monitor.d.ts +0 -123
  364. package/dist/agents/bug-fixer/monitor.d.ts.map +0 -1
  365. package/dist/agents/bug-fixer/monitor.js +0 -629
  366. package/dist/agents/bug-fixer/monitor.js.map +0 -1
  367. package/dist/agents/bug-fixer/prompt.d.ts +0 -5
  368. package/dist/agents/bug-fixer/prompt.d.ts.map +0 -1
  369. package/dist/agents/bug-fixer/prompt.js +0 -94
  370. package/dist/agents/bug-fixer/prompt.js.map +0 -1
  371. package/dist/agents/bug-fixer/registries/pending-classification.d.ts +0 -28
  372. package/dist/agents/bug-fixer/registries/pending-classification.d.ts.map +0 -1
  373. package/dist/agents/bug-fixer/registries/pending-classification.js +0 -50
  374. package/dist/agents/bug-fixer/registries/pending-classification.js.map +0 -1
  375. package/dist/agents/bug-fixer/registries/pending-fix.d.ts +0 -33
  376. package/dist/agents/bug-fixer/registries/pending-fix.d.ts.map +0 -1
  377. package/dist/agents/bug-fixer/registries/pending-fix.js +0 -64
  378. package/dist/agents/bug-fixer/registries/pending-fix.js.map +0 -1
  379. package/dist/agents/bug-fixer/registries/pending.d.ts +0 -27
  380. package/dist/agents/bug-fixer/registries/pending.d.ts.map +0 -1
  381. package/dist/agents/bug-fixer/registries/pending.js +0 -49
  382. package/dist/agents/bug-fixer/registries/pending.js.map +0 -1
  383. package/dist/agents/bug-fixer/specialist-daemon.d.ts +0 -88
  384. package/dist/agents/bug-fixer/specialist-daemon.d.ts.map +0 -1
  385. package/dist/agents/bug-fixer/specialist-daemon.js +0 -431
  386. package/dist/agents/bug-fixer/specialist-daemon.js.map +0 -1
  387. package/dist/agents/bug-fixer/specialist.d.ts +0 -47
  388. package/dist/agents/bug-fixer/specialist.d.ts.map +0 -1
  389. package/dist/agents/bug-fixer/specialist.js +0 -327
  390. package/dist/agents/bug-fixer/specialist.js.map +0 -1
  391. package/dist/agents/bug-fixer/types.d.ts +0 -123
  392. package/dist/agents/bug-fixer/types.d.ts.map +0 -1
  393. package/dist/agents/bug-fixer/types.js +0 -9
  394. package/dist/agents/bug-fixer/types.js.map +0 -1
  395. package/dist/agents/factory.d.ts +0 -172
  396. package/dist/agents/factory.d.ts.map +0 -1
  397. package/dist/agents/factory.js +0 -706
  398. package/dist/agents/factory.js.map +0 -1
  399. package/dist/agents/hailer-expert/index.d.ts +0 -8
  400. package/dist/agents/hailer-expert/index.d.ts.map +0 -1
  401. package/dist/agents/hailer-expert/index.js +0 -14
  402. package/dist/agents/hailer-expert/index.js.map +0 -1
  403. package/dist/agents/hal/daemon.d.ts +0 -174
  404. package/dist/agents/hal/daemon.d.ts.map +0 -1
  405. package/dist/agents/hal/daemon.js +0 -1385
  406. package/dist/agents/hal/daemon.js.map +0 -1
  407. package/dist/agents/hal/definitions.d.ts +0 -42
  408. package/dist/agents/hal/definitions.d.ts.map +0 -1
  409. package/dist/agents/hal/definitions.js +0 -300
  410. package/dist/agents/hal/definitions.js.map +0 -1
  411. package/dist/agents/hal/index.d.ts +0 -3
  412. package/dist/agents/hal/index.d.ts.map +0 -1
  413. package/dist/agents/hal/index.js +0 -8
  414. package/dist/agents/hal/index.js.map +0 -1
  415. package/dist/agents/index.d.ts +0 -18
  416. package/dist/agents/index.d.ts.map +0 -1
  417. package/dist/agents/index.js +0 -48
  418. package/dist/agents/index.js.map +0 -1
  419. package/dist/agents/shared/base.d.ts +0 -253
  420. package/dist/agents/shared/base.d.ts.map +0 -1
  421. package/dist/agents/shared/base.js +0 -1122
  422. package/dist/agents/shared/base.js.map +0 -1
  423. package/dist/agents/shared/schemas/action-schema.d.ts +0 -62
  424. package/dist/agents/shared/schemas/action-schema.d.ts.map +0 -1
  425. package/dist/agents/shared/schemas/action-schema.js +0 -483
  426. package/dist/agents/shared/schemas/action-schema.js.map +0 -1
  427. package/dist/agents/shared/services/agent-registry.d.ts +0 -108
  428. package/dist/agents/shared/services/agent-registry.d.ts.map +0 -1
  429. package/dist/agents/shared/services/agent-registry.js +0 -469
  430. package/dist/agents/shared/services/agent-registry.js.map +0 -1
  431. package/dist/agents/shared/services/conversation-manager.d.ts +0 -57
  432. package/dist/agents/shared/services/conversation-manager.d.ts.map +0 -1
  433. package/dist/agents/shared/services/conversation-manager.js +0 -168
  434. package/dist/agents/shared/services/conversation-manager.js.map +0 -1
  435. package/dist/agents/shared/services/mcp-client.d.ts +0 -56
  436. package/dist/agents/shared/services/mcp-client.d.ts.map +0 -1
  437. package/dist/agents/shared/services/mcp-client.js +0 -124
  438. package/dist/agents/shared/services/mcp-client.js.map +0 -1
  439. package/dist/agents/shared/services/message-classifier.d.ts +0 -37
  440. package/dist/agents/shared/services/message-classifier.d.ts.map +0 -1
  441. package/dist/agents/shared/services/message-classifier.js +0 -203
  442. package/dist/agents/shared/services/message-classifier.js.map +0 -1
  443. package/dist/agents/shared/services/message-formatter.d.ts +0 -89
  444. package/dist/agents/shared/services/message-formatter.d.ts.map +0 -1
  445. package/dist/agents/shared/services/message-formatter.js +0 -390
  446. package/dist/agents/shared/services/message-formatter.js.map +0 -1
  447. package/dist/agents/shared/services/session-logger.d.ts +0 -162
  448. package/dist/agents/shared/services/session-logger.d.ts.map +0 -1
  449. package/dist/agents/shared/services/session-logger.js +0 -724
  450. package/dist/agents/shared/services/session-logger.js.map +0 -1
  451. package/dist/agents/shared/services/structured-output-executor.d.ts +0 -88
  452. package/dist/agents/shared/services/structured-output-executor.d.ts.map +0 -1
  453. package/dist/agents/shared/services/structured-output-executor.js +0 -296
  454. package/dist/agents/shared/services/structured-output-executor.js.map +0 -1
  455. package/dist/agents/shared/services/token-billing.d.ts +0 -72
  456. package/dist/agents/shared/services/token-billing.d.ts.map +0 -1
  457. package/dist/agents/shared/services/token-billing.js +0 -198
  458. package/dist/agents/shared/services/token-billing.js.map +0 -1
  459. package/dist/agents/shared/services/tool-executor.d.ts +0 -43
  460. package/dist/agents/shared/services/tool-executor.d.ts.map +0 -1
  461. package/dist/agents/shared/services/tool-executor.js +0 -175
  462. package/dist/agents/shared/services/tool-executor.js.map +0 -1
  463. package/dist/agents/shared/services/typing-indicator.d.ts +0 -24
  464. package/dist/agents/shared/services/typing-indicator.d.ts.map +0 -1
  465. package/dist/agents/shared/services/typing-indicator.js +0 -54
  466. package/dist/agents/shared/services/typing-indicator.js.map +0 -1
  467. package/dist/agents/shared/services/workspace-schema-cache.d.ts +0 -122
  468. package/dist/agents/shared/services/workspace-schema-cache.d.ts.map +0 -1
  469. package/dist/agents/shared/services/workspace-schema-cache.js +0 -507
  470. package/dist/agents/shared/services/workspace-schema-cache.js.map +0 -1
  471. package/dist/agents/shared/specialist.d.ts +0 -91
  472. package/dist/agents/shared/specialist.d.ts.map +0 -1
  473. package/dist/agents/shared/specialist.js +0 -399
  474. package/dist/agents/shared/specialist.js.map +0 -1
  475. package/dist/agents/shared/tool-schema-loader.d.ts +0 -65
  476. package/dist/agents/shared/tool-schema-loader.d.ts.map +0 -1
  477. package/dist/agents/shared/tool-schema-loader.js +0 -238
  478. package/dist/agents/shared/tool-schema-loader.js.map +0 -1
  479. package/dist/agents/shared/types.d.ts +0 -190
  480. package/dist/agents/shared/types.d.ts.map +0 -1
  481. package/dist/agents/shared/types.js +0 -13
  482. package/dist/agents/shared/types.js.map +0 -1
  483. package/dist/bot/bot-config.d.ts +0 -37
  484. package/dist/bot/bot-config.d.ts.map +0 -1
  485. package/dist/bot/bot-config.js +0 -219
  486. package/dist/bot/bot-config.js.map +0 -1
  487. package/dist/bot/services/__tests__/permission-guard.test.d.ts +0 -2
  488. package/dist/bot/services/__tests__/permission-guard.test.d.ts.map +0 -1
  489. package/dist/bot/services/__tests__/permission-guard.test.js +0 -357
  490. package/dist/bot/services/__tests__/permission-guard.test.js.map +0 -1
  491. package/dist/bot/services/session-logger.d.ts +0 -162
  492. package/dist/bot/services/session-logger.d.ts.map +0 -1
  493. package/dist/bot/services/session-logger.js +0 -724
  494. package/dist/bot/services/session-logger.js.map +0 -1
  495. package/dist/bot/services/workspace-schema-cache.d.ts +0 -122
  496. package/dist/bot/services/workspace-schema-cache.d.ts.map +0 -1
  497. package/dist/bot/services/workspace-schema-cache.js +0 -506
  498. package/dist/bot/services/workspace-schema-cache.js.map +0 -1
  499. package/dist/bot-config/tools.d.ts +0 -28
  500. package/dist/bot-config/tools.d.ts.map +0 -1
  501. package/dist/bot-config/tools.js +0 -279
  502. package/dist/bot-config/tools.js.map +0 -1
  503. package/dist/client/agents/base.d.ts +0 -207
  504. package/dist/client/agents/base.d.ts.map +0 -1
  505. package/dist/client/agents/base.js +0 -744
  506. package/dist/client/agents/base.js.map +0 -1
  507. package/dist/client/agents/definitions.d.ts +0 -53
  508. package/dist/client/agents/definitions.d.ts.map +0 -1
  509. package/dist/client/agents/definitions.js +0 -263
  510. package/dist/client/agents/definitions.js.map +0 -1
  511. package/dist/client/agents/orchestrator.d.ts +0 -141
  512. package/dist/client/agents/orchestrator.d.ts.map +0 -1
  513. package/dist/client/agents/orchestrator.js +0 -1062
  514. package/dist/client/agents/orchestrator.js.map +0 -1
  515. package/dist/client/agents/specialist.d.ts +0 -86
  516. package/dist/client/agents/specialist.d.ts.map +0 -1
  517. package/dist/client/agents/specialist.js +0 -340
  518. package/dist/client/agents/specialist.js.map +0 -1
  519. package/dist/client/bot-entrypoint.d.ts +0 -7
  520. package/dist/client/bot-entrypoint.d.ts.map +0 -1
  521. package/dist/client/bot-entrypoint.js +0 -103
  522. package/dist/client/bot-entrypoint.js.map +0 -1
  523. package/dist/client/bot-manager.d.ts +0 -44
  524. package/dist/client/bot-manager.d.ts.map +0 -1
  525. package/dist/client/bot-manager.js +0 -173
  526. package/dist/client/bot-manager.js.map +0 -1
  527. package/dist/client/bot-runner.d.ts +0 -35
  528. package/dist/client/bot-runner.d.ts.map +0 -1
  529. package/dist/client/bot-runner.js +0 -188
  530. package/dist/client/bot-runner.js.map +0 -1
  531. package/dist/client/chat-agent-daemon.d.ts +0 -464
  532. package/dist/client/chat-agent-daemon.d.ts.map +0 -1
  533. package/dist/client/chat-agent-daemon.js +0 -1774
  534. package/dist/client/chat-agent-daemon.js.map +0 -1
  535. package/dist/client/daemon-factory.d.ts +0 -106
  536. package/dist/client/daemon-factory.d.ts.map +0 -1
  537. package/dist/client/daemon-factory.js +0 -301
  538. package/dist/client/daemon-factory.js.map +0 -1
  539. package/dist/client/factory.d.ts +0 -111
  540. package/dist/client/factory.d.ts.map +0 -1
  541. package/dist/client/factory.js +0 -314
  542. package/dist/client/factory.js.map +0 -1
  543. package/dist/client/index.d.ts +0 -17
  544. package/dist/client/index.d.ts.map +0 -1
  545. package/dist/client/index.js +0 -38
  546. package/dist/client/index.js.map +0 -1
  547. package/dist/client/multi-bot-manager.d.ts +0 -42
  548. package/dist/client/multi-bot-manager.d.ts.map +0 -1
  549. package/dist/client/multi-bot-manager.js +0 -161
  550. package/dist/client/multi-bot-manager.js.map +0 -1
  551. package/dist/client/orchestrator-daemon.d.ts +0 -87
  552. package/dist/client/orchestrator-daemon.d.ts.map +0 -1
  553. package/dist/client/orchestrator-daemon.js +0 -444
  554. package/dist/client/orchestrator-daemon.js.map +0 -1
  555. package/dist/client/server.d.ts +0 -8
  556. package/dist/client/server.d.ts.map +0 -1
  557. package/dist/client/server.js +0 -251
  558. package/dist/client/server.js.map +0 -1
  559. package/dist/client/services/agent-registry.d.ts +0 -108
  560. package/dist/client/services/agent-registry.d.ts.map +0 -1
  561. package/dist/client/services/agent-registry.js +0 -630
  562. package/dist/client/services/agent-registry.js.map +0 -1
  563. package/dist/client/services/conversation-manager.d.ts +0 -50
  564. package/dist/client/services/conversation-manager.d.ts.map +0 -1
  565. package/dist/client/services/conversation-manager.js +0 -136
  566. package/dist/client/services/conversation-manager.js.map +0 -1
  567. package/dist/client/services/mcp-client.d.ts +0 -48
  568. package/dist/client/services/mcp-client.d.ts.map +0 -1
  569. package/dist/client/services/mcp-client.js +0 -105
  570. package/dist/client/services/mcp-client.js.map +0 -1
  571. package/dist/client/services/message-classifier.d.ts +0 -37
  572. package/dist/client/services/message-classifier.d.ts.map +0 -1
  573. package/dist/client/services/message-classifier.js +0 -187
  574. package/dist/client/services/message-classifier.js.map +0 -1
  575. package/dist/client/services/message-formatter.d.ts +0 -84
  576. package/dist/client/services/message-formatter.d.ts.map +0 -1
  577. package/dist/client/services/message-formatter.js +0 -353
  578. package/dist/client/services/message-formatter.js.map +0 -1
  579. package/dist/client/services/session-logger.d.ts +0 -106
  580. package/dist/client/services/session-logger.d.ts.map +0 -1
  581. package/dist/client/services/session-logger.js +0 -446
  582. package/dist/client/services/session-logger.js.map +0 -1
  583. package/dist/client/services/tool-executor.d.ts +0 -41
  584. package/dist/client/services/tool-executor.d.ts.map +0 -1
  585. package/dist/client/services/tool-executor.js +0 -169
  586. package/dist/client/services/tool-executor.js.map +0 -1
  587. package/dist/client/services/workspace-schema-cache.d.ts +0 -149
  588. package/dist/client/services/workspace-schema-cache.d.ts.map +0 -1
  589. package/dist/client/services/workspace-schema-cache.js +0 -732
  590. package/dist/client/services/workspace-schema-cache.js.map +0 -1
  591. package/dist/client/specialist-daemon.d.ts +0 -77
  592. package/dist/client/specialist-daemon.d.ts.map +0 -1
  593. package/dist/client/specialist-daemon.js +0 -197
  594. package/dist/client/specialist-daemon.js.map +0 -1
  595. package/dist/client/specialists.d.ts +0 -53
  596. package/dist/client/specialists.d.ts.map +0 -1
  597. package/dist/client/specialists.js +0 -178
  598. package/dist/client/specialists.js.map +0 -1
  599. package/dist/client/tool-schema-loader.d.ts +0 -62
  600. package/dist/client/tool-schema-loader.d.ts.map +0 -1
  601. package/dist/client/tool-schema-loader.js +0 -232
  602. package/dist/client/tool-schema-loader.js.map +0 -1
  603. package/dist/client/types.d.ts +0 -327
  604. package/dist/client/types.d.ts.map +0 -1
  605. package/dist/client/types.js +0 -121
  606. package/dist/client/types.js.map +0 -1
  607. package/dist/commands/seed-config.d.ts +0 -9
  608. package/dist/commands/seed-config.d.ts.map +0 -1
  609. package/dist/commands/seed-config.js +0 -377
  610. package/dist/commands/seed-config.js.map +0 -1
  611. package/dist/commands/setup.d.ts +0 -11
  612. package/dist/commands/setup.d.ts.map +0 -1
  613. package/dist/commands/setup.js +0 -320
  614. package/dist/commands/setup.js.map +0 -1
  615. package/dist/lib/discussion-lock.d.ts +0 -42
  616. package/dist/lib/discussion-lock.d.ts.map +0 -1
  617. package/dist/lib/discussion-lock.js +0 -110
  618. package/dist/lib/discussion-lock.js.map +0 -1
  619. package/dist/mcp/signal-handler.d.ts +0 -82
  620. package/dist/mcp/signal-handler.d.ts.map +0 -1
  621. package/dist/mcp/signal-handler.js +0 -406
  622. package/dist/mcp/signal-handler.js.map +0 -1
  623. package/dist/mcp/tools/__tests__/discussion-forward.test.d.ts +0 -2
  624. package/dist/mcp/tools/__tests__/discussion-forward.test.d.ts.map +0 -1
  625. package/dist/mcp/tools/__tests__/discussion-forward.test.js +0 -218
  626. package/dist/mcp/tools/__tests__/discussion-forward.test.js.map +0 -1
  627. package/dist/mcp/tools/app-member.d.ts +0 -14
  628. package/dist/mcp/tools/app-member.d.ts.map +0 -1
  629. package/dist/mcp/tools/app-member.js +0 -195
  630. package/dist/mcp/tools/app-member.js.map +0 -1
  631. package/dist/mcp/tools/app-scaffold.d.ts +0 -14
  632. package/dist/mcp/tools/app-scaffold.d.ts.map +0 -1
  633. package/dist/mcp/tools/app-scaffold.js +0 -581
  634. package/dist/mcp/tools/app-scaffold.js.map +0 -1
  635. package/dist/mcp/tools/bot-config/constants.d.ts +0 -23
  636. package/dist/mcp/tools/bot-config/constants.d.ts.map +0 -1
  637. package/dist/mcp/tools/bot-config/constants.js +0 -94
  638. package/dist/mcp/tools/bot-config/constants.js.map +0 -1
  639. package/dist/mcp/tools/bot-config/core.d.ts +0 -253
  640. package/dist/mcp/tools/bot-config/core.d.ts.map +0 -1
  641. package/dist/mcp/tools/bot-config/core.js +0 -2456
  642. package/dist/mcp/tools/bot-config/core.js.map +0 -1
  643. package/dist/mcp/tools/bot-config/index.d.ts +0 -10
  644. package/dist/mcp/tools/bot-config/index.d.ts.map +0 -1
  645. package/dist/mcp/tools/bot-config/index.js +0 -59
  646. package/dist/mcp/tools/bot-config/index.js.map +0 -1
  647. package/dist/mcp/tools/bot-config/tools.d.ts +0 -7
  648. package/dist/mcp/tools/bot-config/tools.d.ts.map +0 -1
  649. package/dist/mcp/tools/bot-config/tools.js +0 -15
  650. package/dist/mcp/tools/bot-config/tools.js.map +0 -1
  651. package/dist/mcp/tools/bot-config/types.d.ts +0 -50
  652. package/dist/mcp/tools/bot-config/types.d.ts.map +0 -1
  653. package/dist/mcp/tools/bot-config/types.js +0 -6
  654. package/dist/mcp/tools/bot-config/types.js.map +0 -1
  655. package/dist/mcp/tools/bug-fixer-tools.d.ts +0 -45
  656. package/dist/mcp/tools/bug-fixer-tools.d.ts.map +0 -1
  657. package/dist/mcp/tools/bug-fixer-tools.js +0 -1096
  658. package/dist/mcp/tools/bug-fixer-tools.js.map +0 -1
  659. package/dist/mcp/tools/document.d.ts +0 -11
  660. package/dist/mcp/tools/document.d.ts.map +0 -1
  661. package/dist/mcp/tools/document.js +0 -741
  662. package/dist/mcp/tools/document.js.map +0 -1
  663. package/dist/mcp/tools/investigate.d.ts +0 -9
  664. package/dist/mcp/tools/investigate.d.ts.map +0 -1
  665. package/dist/mcp/tools/investigate.js +0 -254
  666. package/dist/mcp/tools/investigate.js.map +0 -1
  667. package/dist/mcp/utils/pagination.d.ts +0 -40
  668. package/dist/mcp/utils/pagination.d.ts.map +0 -1
  669. package/dist/mcp/utils/pagination.js +0 -55
  670. package/dist/mcp/utils/pagination.js.map +0 -1
  671. package/dist/modules/bug-reports/bug-config.d.ts +0 -25
  672. package/dist/modules/bug-reports/bug-config.d.ts.map +0 -1
  673. package/dist/modules/bug-reports/bug-config.js +0 -187
  674. package/dist/modules/bug-reports/bug-config.js.map +0 -1
  675. package/dist/modules/bug-reports/bug-monitor.d.ts +0 -108
  676. package/dist/modules/bug-reports/bug-monitor.d.ts.map +0 -1
  677. package/dist/modules/bug-reports/bug-monitor.js +0 -510
  678. package/dist/modules/bug-reports/bug-monitor.js.map +0 -1
  679. package/dist/modules/bug-reports/giuseppe-agent.d.ts +0 -58
  680. package/dist/modules/bug-reports/giuseppe-agent.d.ts.map +0 -1
  681. package/dist/modules/bug-reports/giuseppe-agent.js +0 -467
  682. package/dist/modules/bug-reports/giuseppe-agent.js.map +0 -1
  683. package/dist/modules/bug-reports/giuseppe-ai.d.ts +0 -83
  684. package/dist/modules/bug-reports/giuseppe-ai.d.ts.map +0 -1
  685. package/dist/modules/bug-reports/giuseppe-ai.js +0 -466
  686. package/dist/modules/bug-reports/giuseppe-ai.js.map +0 -1
  687. package/dist/modules/bug-reports/giuseppe-bot.d.ts +0 -110
  688. package/dist/modules/bug-reports/giuseppe-bot.d.ts.map +0 -1
  689. package/dist/modules/bug-reports/giuseppe-bot.js +0 -804
  690. package/dist/modules/bug-reports/giuseppe-bot.js.map +0 -1
  691. package/dist/modules/bug-reports/giuseppe-daemon.d.ts +0 -80
  692. package/dist/modules/bug-reports/giuseppe-daemon.d.ts.map +0 -1
  693. package/dist/modules/bug-reports/giuseppe-daemon.js +0 -617
  694. package/dist/modules/bug-reports/giuseppe-daemon.js.map +0 -1
  695. package/dist/modules/bug-reports/giuseppe-files.d.ts +0 -64
  696. package/dist/modules/bug-reports/giuseppe-files.d.ts.map +0 -1
  697. package/dist/modules/bug-reports/giuseppe-files.js +0 -375
  698. package/dist/modules/bug-reports/giuseppe-files.js.map +0 -1
  699. package/dist/modules/bug-reports/giuseppe-git.d.ts +0 -48
  700. package/dist/modules/bug-reports/giuseppe-git.d.ts.map +0 -1
  701. package/dist/modules/bug-reports/giuseppe-git.js +0 -298
  702. package/dist/modules/bug-reports/giuseppe-git.js.map +0 -1
  703. package/dist/modules/bug-reports/giuseppe-lsp.d.ts +0 -113
  704. package/dist/modules/bug-reports/giuseppe-lsp.d.ts.map +0 -1
  705. package/dist/modules/bug-reports/giuseppe-lsp.js +0 -485
  706. package/dist/modules/bug-reports/giuseppe-lsp.js.map +0 -1
  707. package/dist/modules/bug-reports/giuseppe-prompt.d.ts +0 -5
  708. package/dist/modules/bug-reports/giuseppe-prompt.d.ts.map +0 -1
  709. package/dist/modules/bug-reports/giuseppe-prompt.js +0 -94
  710. package/dist/modules/bug-reports/giuseppe-prompt.js.map +0 -1
  711. package/dist/modules/bug-reports/index.d.ts +0 -77
  712. package/dist/modules/bug-reports/index.d.ts.map +0 -1
  713. package/dist/modules/bug-reports/index.js +0 -215
  714. package/dist/modules/bug-reports/index.js.map +0 -1
  715. package/dist/modules/bug-reports/pending-classification-registry.d.ts +0 -28
  716. package/dist/modules/bug-reports/pending-classification-registry.d.ts.map +0 -1
  717. package/dist/modules/bug-reports/pending-classification-registry.js +0 -50
  718. package/dist/modules/bug-reports/pending-classification-registry.js.map +0 -1
  719. package/dist/modules/bug-reports/pending-fix-registry.d.ts +0 -30
  720. package/dist/modules/bug-reports/pending-fix-registry.d.ts.map +0 -1
  721. package/dist/modules/bug-reports/pending-fix-registry.js +0 -42
  722. package/dist/modules/bug-reports/pending-fix-registry.js.map +0 -1
  723. package/dist/modules/bug-reports/pending-registry.d.ts +0 -27
  724. package/dist/modules/bug-reports/pending-registry.d.ts.map +0 -1
  725. package/dist/modules/bug-reports/pending-registry.js +0 -49
  726. package/dist/modules/bug-reports/pending-registry.js.map +0 -1
  727. package/dist/modules/bug-reports/types.d.ts +0 -123
  728. package/dist/modules/bug-reports/types.d.ts.map +0 -1
  729. package/dist/modules/bug-reports/types.js +0 -9
  730. package/dist/modules/bug-reports/types.js.map +0 -1
  731. package/dist/plugins/bug-fixer/index.d.ts +0 -2
  732. package/dist/plugins/bug-fixer/index.d.ts.map +0 -1
  733. package/dist/plugins/bug-fixer/index.js +0 -18
  734. package/dist/plugins/bug-fixer/index.js.map +0 -1
  735. package/dist/plugins/bug-fixer/tools.d.ts +0 -45
  736. package/dist/plugins/bug-fixer/tools.d.ts.map +0 -1
  737. package/dist/plugins/bug-fixer/tools.js +0 -1096
  738. package/dist/plugins/bug-fixer/tools.js.map +0 -1
  739. package/dist/plugins/vipunen/__tests__/tools.test.d.ts +0 -10
  740. package/dist/plugins/vipunen/__tests__/tools.test.d.ts.map +0 -1
  741. package/dist/plugins/vipunen/__tests__/tools.test.js +0 -646
  742. package/dist/plugins/vipunen/__tests__/tools.test.js.map +0 -1
  743. package/dist/routes/agents.d.ts +0 -44
  744. package/dist/routes/agents.d.ts.map +0 -1
  745. package/dist/routes/agents.js +0 -311
  746. package/dist/routes/agents.js.map +0 -1
  747. package/dist/services/agent-credential-store.d.ts +0 -73
  748. package/dist/services/agent-credential-store.d.ts.map +0 -1
  749. package/dist/services/agent-credential-store.js +0 -212
  750. package/dist/services/agent-credential-store.js.map +0 -1
  751. package/dist/stdio-server.d.ts +0 -14
  752. package/dist/stdio-server.d.ts.map +0 -1
  753. package/dist/stdio-server.js +0 -101
  754. package/dist/stdio-server.js.map +0 -1
  755. package/dist/workspace/context.d.ts +0 -148
  756. package/dist/workspace/context.d.ts.map +0 -1
  757. package/dist/workspace/context.js +0 -339
  758. package/dist/workspace/context.js.map +0 -1
  759. package/dist/workspace/credentials.d.ts +0 -55
  760. package/dist/workspace/credentials.d.ts.map +0 -1
  761. package/dist/workspace/credentials.js +0 -239
  762. package/dist/workspace/credentials.js.map +0 -1
  763. package/dist/workspace/index.d.ts +0 -21
  764. package/dist/workspace/index.d.ts.map +0 -1
  765. package/dist/workspace/index.js +0 -45
  766. package/dist/workspace/index.js.map +0 -1
  767. package/dist/workspace/loader.d.ts +0 -27
  768. package/dist/workspace/loader.d.ts.map +0 -1
  769. package/dist/workspace/loader.js +0 -222
  770. package/dist/workspace/loader.js.map +0 -1
  771. package/dist/workspace/schema.d.ts +0 -37
  772. package/dist/workspace/schema.d.ts.map +0 -1
  773. package/dist/workspace/schema.js +0 -192
  774. package/dist/workspace/schema.js.map +0 -1
@@ -39,11 +39,12 @@ var __importStar = (this && this.__importStar) || (function () {
39
39
  };
40
40
  })();
41
41
  Object.defineProperty(exports, "__esModule", { value: true });
42
+ exports.clearAdminKeyErrors = clearAdminKeyErrors;
42
43
  exports.generateWebhookSignature = generateWebhookSignature;
43
44
  exports.verifyWebhookSignature = verifyWebhookSignature;
44
45
  exports.getWebhookToken = getWebhookToken;
45
46
  exports.getWebhookPath = getWebhookPath;
46
- exports.onBotUpdate = onBotUpdate;
47
+ exports.destroyBot = destroyBot;
47
48
  exports.handleBotConfigWebhook = handleBotConfigWebhook;
48
49
  exports.listWorkspaceConfigs = listWorkspaceConfigs;
49
50
  const fs = __importStar(require("fs"));
@@ -52,23 +53,608 @@ const crypto = __importStar(require("crypto"));
52
53
  const logger_1 = require("../lib/logger");
53
54
  const config_1 = require("../config");
54
55
  const constants_1 = require("../bot-config/constants");
55
- // Optional: bot-config only available in bot server mode, not MCP terminal
56
- let invalidateConfigCache = null;
57
- let _loadConfigFile = null;
58
- let _saveConfigFile = null;
59
- let _listConfigFiles = null;
60
- try {
61
- const botConfig = require('../bot-config');
62
- invalidateConfigCache = botConfig.invalidateConfigCache;
63
- _loadConfigFile = botConfig.loadWorkspaceConfigFile;
64
- _saveConfigFile = botConfig.saveWorkspaceConfigFile;
65
- _listConfigFiles = botConfig.listWorkspaceConfigFiles;
66
- }
67
- catch {
68
- // Not available in MCP-only installs — safe to skip
69
- }
56
+ const loader_1 = require("../bot-config/loader");
57
+ const activity_error_1 = require("../bot-config/activity-error");
58
+ const events_1 = require("../bot-config/events");
59
+ const workspace_admin_store_1 = require("./workspace-admin-store");
60
+ const hailer_clients_1 = require("./hailer-clients");
61
+ const hailer_rpc_1 = require("./hailer-rpc");
62
+ const tool_helpers_1 = require("./utils/tool-helpers");
63
+ const hailer_api_client_1 = require("./utils/hailer-api-client");
70
64
  const logger = (0, logger_1.createLogger)({ component: 'webhook-handler' });
71
65
  const WEBHOOK_SECRET_FILE = 'webhook-secret.txt';
66
+ // AI Hub writes a "pending-…" placeholder into the password field at activity
67
+ // create time; we treat that as absent so we know to generate a real one.
68
+ const PENDING_PASSWORD_PREFIX = 'pending-';
69
+ const BOT_EMAIL_DOMAIN = 'hailer.com';
70
+ function generateSecurePassword() {
71
+ return crypto.randomBytes(16).toString('hex');
72
+ }
73
+ /**
74
+ * Mirror of AI Hub's `generateBotEmail` (ai-hub/src/api.ts) — used by the
75
+ * collision-retry path when Hailer rejects the AI Hub-supplied email with a
76
+ * duplicate (code:409) AND no sibling activity provisioned the bot. We
77
+ * regenerate locally, write the new email back to the activity, and retry
78
+ * the register call.
79
+ */
80
+ function generateBotEmail(firstname, lastname, workspaceId) {
81
+ const sanitize = (s) => s.toLowerCase().replace(/[^a-z0-9]/g, '');
82
+ const first = sanitize(firstname) || 'bot';
83
+ const last = sanitize(lastname);
84
+ const wsPrefix = sanitize(workspaceId).slice(0, 8);
85
+ const suffix = crypto.randomBytes(3).toString('hex');
86
+ const parts = [last ? `${first}.${last}` : first];
87
+ if (wsPrefix) {
88
+ parts.push(wsPrefix);
89
+ }
90
+ parts.push(suffix);
91
+ return `${parts.join('-')}@${BOT_EMAIL_DOMAIN}`;
92
+ }
93
+ // Hailer fires multiple webhooks per phase change (one per phase listening),
94
+ // so siblings race to provision the same bot. Re-read the activity to detect
95
+ // a sibling that already wrote hailerProfile/password — and to detect that
96
+ // the activity has been deleted out from under us.
97
+ //
98
+ // activities.load returns `fields` as an object keyed by the field's logical
99
+ // key (e.g. `hailerProfile`, `password`) — same shape v3.activity.updateMany
100
+ // accepts. No workflow-definition lookup needed.
101
+ async function probeActivity(adminClient, activityId) {
102
+ try {
103
+ const activity = await adminClient.socket.request(hailer_rpc_1.HailerRpc.Activities.load, [activityId]);
104
+ const fields = activity?.fields ?? {};
105
+ const uid = fields.hailerProfile || undefined;
106
+ const activityEmail = fields.agentEmailInHailer || undefined;
107
+ const rawPassword = fields.password;
108
+ const password = rawPassword && !String(rawPassword).startsWith(PENDING_PASSWORD_PREFIX)
109
+ ? String(rawPassword)
110
+ : undefined;
111
+ return { uid, password, email: activityEmail, discussion: activity?.discussion };
112
+ }
113
+ catch (err) {
114
+ if ((0, activity_error_1.isActivityGone)(err)) {
115
+ logger.debug('[Webhook] probe: activity is deleted', { activityId });
116
+ return { gone: true };
117
+ }
118
+ logger.debug('[Webhook] activities.load (probe) failed', {
119
+ activityId,
120
+ error: (0, tool_helpers_1.extractErrorMessage)(err),
121
+ });
122
+ return {};
123
+ }
124
+ }
125
+ // Hailer's concurrent-registration rejection codes:
126
+ // 409 "Email already registered!" — a sibling already created the user
127
+ // 127 "Unable to create new user." — race-guard
128
+ function isRegisterRaceError(err) {
129
+ const msg = (0, tool_helpers_1.extractErrorMessage)(err);
130
+ return msg.includes('"code":409') || msg.includes('"code":127');
131
+ }
132
+ function resolveUserDisplayName(users, uid) {
133
+ if (!uid || !users) {
134
+ return undefined;
135
+ }
136
+ const u = users[uid];
137
+ if (!u) {
138
+ return undefined;
139
+ }
140
+ const name = [u.firstname, u.lastname].filter(Boolean).join(' ').trim();
141
+ return name || u.email || undefined;
142
+ }
143
+ // Per-activity provisioning mutex. Hailer fires multiple webhooks per activity
144
+ // create (initial create + phase transition + …) and they hit Express in
145
+ // parallel. Without serialization each one independently calls v2.user.register
146
+ // before any sibling has written its uid back to the activity, so probeActivity
147
+ // keeps missing the in-flight provision — net result is N orphan Hailer users
148
+ // per bot and a final activity whose password no longer matches Hailer's record.
149
+ const provisionLocks = new Map();
150
+ // Track the last admin-key value we successfully persisted per workspace so we
151
+ // skip the Hailer-login validation roundtrip on every subsequent webhook that
152
+ // carries the same key. SHA-256 of the raw value — never store the plaintext.
153
+ // Cleared on process restart, which is fine: the first webhook re-validates and
154
+ // re-caches.
155
+ const lastAdminKeyHashByWorkspace = new Map();
156
+ /**
157
+ * Decode an admin API key stored in schemaConfig. AI Hub writes the key as
158
+ * `hex:<hex-encoded-utf8>` so a casual reader of the workspace data doesn't
159
+ * see the plaintext credential. Values without the `hex:` prefix are
160
+ * treated as legacy plaintext for backward compatibility with carriers
161
+ * written before this change shipped.
162
+ */
163
+ function decodeAdminKey(raw) {
164
+ if (!raw.startsWith('hex:')) {
165
+ return raw;
166
+ }
167
+ try {
168
+ return Buffer.from(raw.slice(4), 'hex').toString('utf8');
169
+ }
170
+ catch {
171
+ return raw;
172
+ }
173
+ }
174
+ /**
175
+ * Surface an admin-key rejection reason back to AI Hub through the activity's
176
+ * `schemaConfig.adminKeyError` — the only channel AI Hub can read without
177
+ * reaching the (browser-blocked, HTTP) MCP server directly. Writes only on a
178
+ * state change, so a re-delivered webhook can't loop. Best-effort: a failure
179
+ * here must never break the webhook flow.
180
+ */
181
+ async function markAdminKeyError(client, activityId, schemaConfig, error) {
182
+ const current = typeof schemaConfig.adminKeyError === 'string' ? schemaConfig.adminKeyError : null;
183
+ if (current === error) {
184
+ return;
185
+ }
186
+ const next = { ...schemaConfig };
187
+ if (error) {
188
+ next.adminKeyError = error;
189
+ }
190
+ if (!error) {
191
+ delete next.adminKeyError;
192
+ }
193
+ try {
194
+ await client.socket.request(hailer_rpc_1.HailerRpc.Activities.updateMany, [[
195
+ { _id: activityId, fields: { schemaConfig: JSON.stringify(next) } },
196
+ ]]);
197
+ }
198
+ catch (err) {
199
+ logger.warn('[Webhook] Failed to write adminKeyError status to activity', {
200
+ activityId, error: (0, tool_helpers_1.extractErrorMessage)(err),
201
+ });
202
+ }
203
+ }
204
+ // v2.core.init returns processes as an object keyed by process id on the
205
+ // live API, but parts of this codebase have also seen the array form (see
206
+ // normalizeInitProcesses in mcp/utils/types.ts and the array iteration in
207
+ // bot-config/workflow-installer.ts). Accept both so a shape drift can't
208
+ // silently turn the sweep into a no-op.
209
+ function toProcessMap(raw) {
210
+ if (!Array.isArray(raw)) {
211
+ return (raw ?? {});
212
+ }
213
+ const withIds = raw.filter((proc) => Boolean(proc?._id));
214
+ const map = {};
215
+ for (const proc of withIds) {
216
+ map[proc._id] = proc;
217
+ }
218
+ return map;
219
+ }
220
+ // Identify the Agent Directory structurally (field keys written by AI Hub's
221
+ // installer) rather than by name — names are localized ('🤖 Agent Directory'
222
+ // / '🤖 Agentit') and user-editable.
223
+ function looksLikeAgentDirectory(wf) {
224
+ const fieldKeys = new Set(Object.values(wf?.fields ?? {}).map((field) => field?.key));
225
+ return fieldKeys.has('schemaConfig') && fieldKeys.has('agentEmailInHailer');
226
+ }
227
+ async function clearAdminKeyErrorOnActivity(client, activityId) {
228
+ try {
229
+ const activity = await client.socket.request(hailer_rpc_1.HailerRpc.Activities.load, [activityId]);
230
+ const raw = activity?.fields?.schemaConfig;
231
+ if (typeof raw !== 'string' || !raw) {
232
+ return;
233
+ }
234
+ const parsed = JSON.parse(raw);
235
+ if (typeof parsed.adminKeyError !== 'string') {
236
+ return;
237
+ }
238
+ delete parsed.adminKeyError;
239
+ await client.socket.request(hailer_rpc_1.HailerRpc.Activities.updateMany, [[
240
+ { _id: activityId, fields: { schemaConfig: JSON.stringify(parsed) } },
241
+ ]]);
242
+ logger.info('[AdminKey] Cleared stale adminKeyError marker', { activityId });
243
+ }
244
+ catch (err) {
245
+ logger.debug('[AdminKey] clearAdminKeyErrors: skipped activity (non-fatal)', {
246
+ activityId, error: (0, tool_helpers_1.extractErrorMessage)(err),
247
+ });
248
+ }
249
+ }
250
+ async function clearAdminKeyErrorsInPhase(client, workflowId, phaseId) {
251
+ const result = await client.socket.request(hailer_rpc_1.HailerRpc.Activities.list, [
252
+ { processId: workflowId, phaseId },
253
+ { limit: 100, returnFlat: true },
254
+ ]);
255
+ const entries = result?.activities || result?.list || result?.data || [];
256
+ for (const entry of entries) {
257
+ if (!entry?._id) {
258
+ continue;
259
+ }
260
+ await clearAdminKeyErrorOnActivity(client, entry._id);
261
+ }
262
+ }
263
+ /**
264
+ * Sweep ALL activities of the workspace's Agent Directory and remove stale
265
+ * `schemaConfig.adminKeyError` markers. markAdminKeyError only clears the
266
+ * single activity whose webhook delivered a verified key, and the popup
267
+ * /admin-authorize path bypasses webhooks entirely — either way a marker
268
+ * left on a sibling (carrier or other bot) wedges AI Hub's red 'Verify
269
+ * email' pill: readAdminKeyErrorFromWorkflow scans every activity and any
270
+ * error wins over connected. Called from both success paths once a verified
271
+ * admin key is persisted. Best-effort by contract: never throws.
272
+ */
273
+ async function clearAdminKeyErrors(client, workspaceId, workflowId) {
274
+ try {
275
+ await (0, hailer_clients_1.withApiKeyLock)(client.sessionKey, async () => {
276
+ // Pin the key's ambient workspace pointer — it follows whatever
277
+ // the admin last viewed (same reason provisionBotUserLocked pins).
278
+ await client.socket.request(hailer_rpc_1.HailerRpc.Core.switchEcosystem, [workspaceId]);
279
+ const init = await client.socket.request(hailer_rpc_1.HailerRpc.Core.init, [['processes']]);
280
+ const processes = toProcessMap(init?.processes);
281
+ // init [['processes']] returns workflows from EVERY workspace the
282
+ // key can reach (see findExistingWorkflow in workflow-installer.ts)
283
+ // — without the cid filter a multi-workspace admin could resolve a
284
+ // sibling workspace's directory and leave the real markers wedged.
285
+ const resolvedId = workflowId ?? Object.keys(processes).find((id) => processes[id]?.cid === workspaceId && looksLikeAgentDirectory(processes[id]));
286
+ const phaseIds = resolvedId ? Object.keys(processes[resolvedId]?.phases ?? {}) : [];
287
+ if (!resolvedId || phaseIds.length === 0) {
288
+ logger.debug('[AdminKey] clearAdminKeyErrors: agent workflow not resolvable — nothing to clear', {
289
+ workspaceId, workflowId,
290
+ });
291
+ return;
292
+ }
293
+ for (const phaseId of phaseIds) {
294
+ await clearAdminKeyErrorsInPhase(client, resolvedId, phaseId);
295
+ }
296
+ });
297
+ }
298
+ catch (err) {
299
+ logger.warn('[AdminKey] clearAdminKeyErrors failed (non-fatal)', {
300
+ workspaceId, error: (0, tool_helpers_1.extractErrorMessage)(err),
301
+ });
302
+ }
303
+ }
304
+ /**
305
+ * If a webhook operation failed with an auth-shaped error ('Invalid
306
+ * Session', Unauthorized, "code":401/403), decide whether the ADMIN KEY
307
+ * itself is dead before forgetting it. Hailer uses code 403 for every
308
+ * permission denial — invite.send 'Validate your email.', a per-activity
309
+ * updateMany rejection — and none of those say anything about the key.
310
+ * So re-probe the key directly: getValidatedAdminRecord runs core.init
311
+ * with the stored key alone and removes the record only when THAT call
312
+ * is rejected (transient errors keep it). On removal, also clear the
313
+ * dedupe hash so a re-pasted key re-validates. Subsequent webhooks then
314
+ * skip cleanly ('No admin credentials') instead of hammering 403.
315
+ * Returns true if the credentials were cleared.
316
+ */
317
+ async function forgetAdminKeyOnAuthFailure(workspaceId, err) {
318
+ if (!(0, workspace_admin_store_1.looksLikeAuthFailure)((0, tool_helpers_1.extractErrorMessage)(err))) {
319
+ return false;
320
+ }
321
+ const record = await (0, workspace_admin_store_1.getValidatedAdminRecord)(workspaceId);
322
+ if (record) {
323
+ logger.warn('[Webhook] Operation failed with 401/403 but the stored admin key still validates — keeping credentials', {
324
+ workspaceId, error: (0, tool_helpers_1.extractErrorMessage)(err),
325
+ });
326
+ return false;
327
+ }
328
+ lastAdminKeyHashByWorkspace.delete(workspaceId);
329
+ logger.warn('[Webhook] Admin key rejected (auth failure) — cleared stored credentials; webhooks will skip until a valid key is re-connected', { workspaceId });
330
+ return true;
331
+ }
332
+ /**
333
+ * If the webhook payload's schemaConfig carries `adminApiKey`, validate it and
334
+ * persist as the workspace's admin credentials. This is the workflow-field
335
+ * delivery path: AI Hub writes the admin's user-api-key into schemaConfig and
336
+ * Hailer's phase webhook brings it server-side here, sidestepping the
337
+ * mixed-content blocker on the old browser-mediated /admin-authorize flow.
338
+ *
339
+ * Safe to call on every webhook — same-value writes are short-circuited by
340
+ * the hash cache, so we don't hammer Hailer with a v2.core.init per phase
341
+ * toggle.
342
+ */
343
+ async function maybePersistAdminKeyFromSchema(workspaceId, schemaConfig, activityId, workflowId) {
344
+ const stored = schemaConfig?.adminApiKey;
345
+ if (!schemaConfig || typeof stored !== 'string' || !stored) {
346
+ return;
347
+ }
348
+ const apiKey = decodeAdminKey(stored);
349
+ const hash = crypto.createHash('sha256').update(apiKey).digest('hex');
350
+ if (lastAdminKeyHashByWorkspace.get(workspaceId) === hash) {
351
+ return;
352
+ }
353
+ try {
354
+ const client = await (0, hailer_clients_1.createHailerClientByApiKey)(apiKey);
355
+ const identity = await (0, workspace_admin_store_1.resolveAdminIdentity)(client);
356
+ if (!identity.uid) {
357
+ logger.warn('[Webhook] schemaConfig.adminApiKey: identity resolution returned no uid — not persisting', { workspaceId });
358
+ return;
359
+ }
360
+ if (!identity.emailVerified) {
361
+ // Unverified admin email: Hailer's invite.send rejects the bot invite
362
+ // (403 'Validate your email.'), the activity never gets its
363
+ // hailerProfile stamp, and every webhook redelivery re-fires the
364
+ // invite — the reinvite doom loop. Skip persist, and deliberately do
365
+ // NOT set lastAdminKeyHashByWorkspace, so a re-check fires once the
366
+ // admin verifies. Fail-closed: missing/false counts as unverified.
367
+ logger.warn('[Webhook] schemaConfig.adminApiKey: admin email not verified — not persisting', { workspaceId, adminUid: identity.uid });
368
+ await markAdminKeyError(client, activityId, schemaConfig, 'email-not-verified');
369
+ return;
370
+ }
371
+ (0, workspace_admin_store_1.persistAdminCredentials)(workspaceId, apiKey, identity);
372
+ lastAdminKeyHashByWorkspace.set(workspaceId, hash);
373
+ // Clear rejection markers on ALL Agent Directory activities (not just
374
+ // this one) now that a verified key is stored — a marker left on a
375
+ // sibling carrier/bot would wedge AI Hub's 'Verify email' pill.
376
+ await clearAdminKeyErrors(client, workspaceId, workflowId);
377
+ logger.info('[Webhook] Admin credentials updated from schemaConfig.adminApiKey', { workspaceId, adminUid: identity.uid });
378
+ }
379
+ catch (err) {
380
+ logger.warn('[Webhook] schemaConfig.adminApiKey: validation failed (key may be invalid or revoked)', {
381
+ workspaceId,
382
+ error: (0, tool_helpers_1.extractErrorMessage)(err),
383
+ });
384
+ }
385
+ }
386
+ // In-memory cache of the freshly-provisioned user, keyed by activityId. The
387
+ // lock alone is not enough: even after the leader's `activities.updateMany`
388
+ // resolves, Hailer's `activities.load` (used by probeActivity) can return a
389
+ // stale snapshot for a brief window, so a freshly-released sibling re-enters
390
+ // the register loop and orphans another user. Caching the leader's result
391
+ // in memory lets the sibling skip Hailer entirely. TTL is generous because
392
+ // the burst of sibling webhooks all fires within seconds of activity create.
393
+ const PROVISIONED_RESULT_TTL_MS = 5 * 60 * 1000;
394
+ const provisionedResults = new Map();
395
+ async function withProvisionLock(activityId, fn) {
396
+ const prev = provisionLocks.get(activityId) ?? Promise.resolve();
397
+ const next = prev.then(fn, fn);
398
+ provisionLocks.set(activityId, next);
399
+ try {
400
+ return await next;
401
+ }
402
+ finally {
403
+ if (provisionLocks.get(activityId) === next) {
404
+ provisionLocks.delete(activityId);
405
+ }
406
+ }
407
+ }
408
+ async function provisionBotUser(adminClient, payload, workspaceId, email) {
409
+ // No inner withProvisionLock — handleBotConfigWebhook already holds the
410
+ // per-activity lock for the entire flow. Re-entering here would deadlock
411
+ // (same activityId waits on the outer's still-running promise). The
412
+ // provisionedResults cache still serves its purpose: a later webhook for
413
+ // the same activity within TTL skips the register loop entirely.
414
+ const cached = provisionedResults.get(payload._id);
415
+ if (cached) {
416
+ logger.info('[Webhook] Activity provisioned this session — reusing cached result', {
417
+ activityId: payload._id, uid: cached.uid, workspaceId,
418
+ });
419
+ return { ...cached, freshlyProvisioned: false };
420
+ }
421
+ const result = await provisionBotUserInner(adminClient, payload, workspaceId, email);
422
+ if (result?.uid && result.password) {
423
+ provisionedResults.set(payload._id, result);
424
+ const timer = setTimeout(() => {
425
+ provisionedResults.delete(payload._id);
426
+ }, PROVISIONED_RESULT_TTL_MS);
427
+ timer.unref?.();
428
+ }
429
+ return result;
430
+ }
431
+ async function provisionBotUserInner(adminClient, payload, workspaceId, email) {
432
+ // Wrap the entire provision flow in a per-API-key lock. The admin key's
433
+ // server-side "current workspace" is mutated by switchEcosystem and
434
+ // implicitly read by every subsequent call (init, probe, register).
435
+ // Without this lock, two workspaces sharing the same admin user would
436
+ // race the workspace context and provision into the wrong workspace.
437
+ return (0, hailer_clients_1.withApiKeyLock)(adminClient.sessionKey, () => provisionBotUserLocked(adminClient, payload, workspaceId, email));
438
+ }
439
+ async function provisionBotUserLocked(adminClient, payload, workspaceId, email) {
440
+ // Pin the admin's API-key context to the webhook's workspace. The key's
441
+ // current workspace follows whatever the admin last viewed in their
442
+ // browser, so we can't assume it matches `payload.cid`.
443
+ await adminClient.socket.request(hailer_rpc_1.HailerRpc.Core.switchEcosystem, [workspaceId]);
444
+ const sibling = await probeActivity(adminClient, payload._id);
445
+ if (sibling.gone) {
446
+ await removeBotFromConfig(workspaceId, payload._id);
447
+ logger.info('[Webhook] Activity no longer exists — skipping provision', {
448
+ activityId: payload._id, workspaceId,
449
+ });
450
+ return null;
451
+ }
452
+ if (sibling.uid) {
453
+ logger.info('[Webhook] Activity already provisioned — skipping register', {
454
+ activityId: payload._id, uid: sibling.uid, workspaceId,
455
+ });
456
+ }
457
+ if (sibling.uid && !sibling.password) {
458
+ return null;
459
+ }
460
+ if (sibling.uid && sibling.password) {
461
+ // The stamp proves the bot USER exists, not that the invite landed —
462
+ // hailerProfile/password are written BEFORE inviteSend (doom-loop
463
+ // fix below), so a transiently failed invite leaves a user that is
464
+ // not a workspace member. Verify membership and re-fire the invite
465
+ // before handing the credentials back for the config upsert.
466
+ await ensureWorkspaceMembership(adminClient, payload, workspaceId, sibling.email || email, sibling.uid);
467
+ return { uid: sibling.uid, password: sibling.password, freshlyProvisioned: false, discussion: sibling.discussion };
468
+ }
469
+ // teams → invite target; users → audit-message display name attribution.
470
+ const init = await adminClient.socket.request(hailer_rpc_1.HailerRpc.Core.init, [
471
+ ['teams', 'users'],
472
+ ]);
473
+ const newPassword = generateSecurePassword();
474
+ const firstname = getFieldValue(payload.fields, 'firstName') || 'Bot';
475
+ const lastname = getFieldValue(payload.fields, 'lastName') || payload.name;
476
+ const teamIds = init.teams ? Object.keys(init.teams) : [];
477
+ if (teamIds.length === 0) {
478
+ throw new Error('Workspace has no teams — cannot send invite');
479
+ }
480
+ const triggerUserName = resolveUserDisplayName(init.users, payload.uid);
481
+ // Register with retry-on-collision. 409 ("Email already registered") may be:
482
+ // (a) sibling activity won the race — recheck shows their uid, use it
483
+ // (b) email genuinely taken by an unrelated user (cross-workspace clash,
484
+ // birthday-paradox collision in random suffix) — regenerate and retry
485
+ // Bounded so we never spin against a permanently-stuck name.
486
+ const MAX_REGISTER_RETRIES = 3;
487
+ let uid = null;
488
+ for (let attempt = 0; attempt <= MAX_REGISTER_RETRIES; attempt++) {
489
+ try {
490
+ const result = await adminClient.socket.request(hailer_rpc_1.HailerRpc.User.register, [
491
+ { email, firstname, lastname, password: newPassword },
492
+ {},
493
+ 'en',
494
+ ]);
495
+ uid = result.uid;
496
+ break;
497
+ }
498
+ catch (registerErr) {
499
+ if (!isRegisterRaceError(registerErr)) {
500
+ throw registerErr;
501
+ }
502
+ // Sibling-race recheck only matters on the first 409. After that no
503
+ // sibling can appear (we hold the only provisioning attempt for this
504
+ // activity), so subsequent 409s are pure email collisions.
505
+ if (attempt === 0) {
506
+ const recheck = await probeActivity(adminClient, payload._id);
507
+ if (recheck.gone) {
508
+ logger.info('[Webhook] register hit race but activity is now gone — skipping', {
509
+ activityId: payload._id, workspaceId,
510
+ });
511
+ return null;
512
+ }
513
+ if (recheck.uid) {
514
+ logger.info('[Webhook] register lost race — using sibling-provisioned user', {
515
+ activityId: payload._id, uid: recheck.uid, workspaceId,
516
+ });
517
+ return recheck.password
518
+ ? { uid: recheck.uid, password: recheck.password, freshlyProvisioned: false, discussion: recheck.discussion }
519
+ : null;
520
+ }
521
+ }
522
+ if (attempt >= MAX_REGISTER_RETRIES) {
523
+ logger.warn('[Webhook] register: email collision exhausted retries — giving up', {
524
+ activityId: payload._id, lastEmail: (0, config_1.maskEmail)(email),
525
+ error: (0, tool_helpers_1.extractErrorMessage)(registerErr),
526
+ });
527
+ return null;
528
+ }
529
+ const nextEmail = generateBotEmail(firstname, lastname, workspaceId);
530
+ logger.info('[Webhook] register: email already registered — retrying with regenerated email', {
531
+ activityId: payload._id, attempt: attempt + 1,
532
+ previous: (0, config_1.maskEmail)(email), next: (0, config_1.maskEmail)(nextEmail),
533
+ });
534
+ // Write the new email back to the activity *before* the next register
535
+ // attempt — if a later step crashes after register succeeds, the
536
+ // activity must already show the email the user was registered with,
537
+ // not the original (now-taken) one.
538
+ await adminClient.socket.request(hailer_rpc_1.HailerRpc.Activities.updateMany, [[
539
+ { _id: payload._id, fields: { agentEmailInHailer: nextEmail } },
540
+ ]]);
541
+ email = nextEmail;
542
+ }
543
+ }
544
+ if (!uid) {
545
+ // Defensive: the loop above either breaks with a uid set, returns, or
546
+ // exhausts retries (which returns null). Ending here means the control
547
+ // flow regressed — surface loudly rather than write empty strings to
548
+ // hailerProfile / use an unauthenticated invite.
549
+ throw new Error(`provisionBotUser: register loop fell through without a uid (activityId=${payload._id})`);
550
+ }
551
+ // Hailer member role on the workspace. Defaults to 'user' to match the
552
+ // AI Hub bot pattern; public-chat graduation hints 'admin' via the
553
+ // schemaConfig field so the freshly-graduated workspace's bot has the
554
+ // permission to install workflows, invite users, and otherwise act as
555
+ // the workspace's first administrator on the visitor's behalf.
556
+ const memberRole = readMemberRoleFromSchemaConfig(payload.fields);
557
+ // Stamp the activity with the freshly-registered uid BEFORE sending the
558
+ // invite. inviteSend can fail (e.g. Hailer returns 403 'Validate your
559
+ // email.' for an unverified admin); if the stamp came after, the activity
560
+ // would stay unprovisioned and every webhook redelivery would re-register a
561
+ // NEW bot user (email collision → regenerated email) and re-fire the invite
562
+ // — the reinvite doom loop. Stamping first means the next probeActivity
563
+ // short-circuits on sibling.uid, so a failed invite costs one attempt, not
564
+ // a storm (and never spawns duplicate bot users).
565
+ await adminClient.socket.request(hailer_rpc_1.HailerRpc.Activities.updateMany, [[
566
+ { _id: payload._id, fields: { hailerProfile: uid, password: newPassword } },
567
+ ]]);
568
+ await adminClient.socket.request(hailer_rpc_1.HailerRpc.Network.inviteSend, [
569
+ { email, teams: [teamIds[0]], role: memberRole, name: `${firstname} ${lastname}`, cid: workspaceId },
570
+ ]);
571
+ logger.info('[Webhook] Auto-created bot user', { email: (0, config_1.maskEmail)(email), uid, workspaceId });
572
+ return { uid, password: newPassword, freshlyProvisioned: true, discussion: sibling.discussion, triggerUserName };
573
+ }
574
+ /**
575
+ * Recovery for the stamp-before-invite orphan: provisionBotUserLocked
576
+ * deliberately stamps hailerProfile/password before inviteSend, so a
577
+ * transient invite failure leaves a Hailer user that never became a
578
+ * workspace member while every later webhook short-circuits on
579
+ * sibling.uid. Detect the orphan (bot uid missing from
580
+ * init.network.members) and retry the invite. invite.send is safe to
581
+ * repeat: an existing member returns success without side effects, and a
582
+ * fresh bot user (member of no workspace) is added directly without a
583
+ * pending-invite record. Throws on failure so the caller's catch skips
584
+ * the config upsert — never start a bot that can't reach its workspace.
585
+ * Must run after switchEcosystem has pinned the admin context to
586
+ * workspaceId (the caller holds the API-key lock).
587
+ */
588
+ async function ensureWorkspaceMembership(adminClient, payload, workspaceId, email, uid) {
589
+ const init = await adminClient.socket.request(hailer_rpc_1.HailerRpc.Core.init, [
590
+ ['network', 'teams'],
591
+ ]);
592
+ const isMember = (init.network?.members || []).some((member) => member.uid === uid);
593
+ if (isMember) {
594
+ return;
595
+ }
596
+ const teamIds = init.teams ? Object.keys(init.teams) : [];
597
+ if (teamIds.length === 0) {
598
+ throw new Error('Workspace has no teams — cannot retry bot invite');
599
+ }
600
+ const firstname = getFieldValue(payload.fields, 'firstName') || 'Bot';
601
+ const lastname = getFieldValue(payload.fields, 'lastName') || payload.name;
602
+ const memberRole = readMemberRoleFromSchemaConfig(payload.fields);
603
+ logger.warn('[Webhook] Provisioned bot user is not a workspace member (earlier invite failed) — retrying invite', {
604
+ activityId: payload._id, uid, workspaceId, email: (0, config_1.maskEmail)(email),
605
+ });
606
+ await adminClient.socket.request(hailer_rpc_1.HailerRpc.Network.inviteSend, [
607
+ { email, teams: [teamIds[0]], role: memberRole, name: `${firstname} ${lastname}`, cid: workspaceId },
608
+ ]);
609
+ logger.info('[Webhook] Invite retry succeeded — bot user joined workspace', {
610
+ activityId: payload._id, uid, workspaceId,
611
+ });
612
+ }
613
+ // Best-effort audit trail in the bot's activity discussion. Failures must
614
+ // not surface — auto-provisioning has already succeeded by the time we get here.
615
+ //
616
+ // Held inside withApiKeyLock + a fresh switchEcosystem because provisionBotUser
617
+ // released the lock before returning. Without re-pinning the admin's server-
618
+ // side workspace pointer, a concurrent webhook for a different workspace
619
+ // could repoint the context and make activities.load resolve in the wrong
620
+ // workspace (or fail), even though messenger.send is discussion-scoped.
621
+ async function postProvisioningAudit(adminClient, workspaceId, activityId, result) {
622
+ await (0, hailer_clients_1.withApiKeyLock)(adminClient.sessionKey, async () => {
623
+ try {
624
+ await adminClient.socket.request(hailer_rpc_1.HailerRpc.Core.switchEcosystem, [workspaceId]);
625
+ let discussionId = result.discussion;
626
+ if (!discussionId) {
627
+ const activity = await adminClient.socket.request(hailer_rpc_1.HailerRpc.Activities.load, [activityId]);
628
+ discussionId = activity?.discussion;
629
+ }
630
+ if (!discussionId) {
631
+ return;
632
+ }
633
+ // activities.follow is a TOGGLE — calling it raw on an admin who's
634
+ // already following (e.g. they created the activity in AI Hub) flips
635
+ // them OFF and they get kicked out of the discussion. Use the toggle-
636
+ // aware wrapper so the admin ends up following regardless of prior state.
637
+ try {
638
+ await new hailer_api_client_1.HailerApiClient(adminClient).joinActivityDiscussion(activityId);
639
+ }
640
+ catch (joinErr) {
641
+ logger.debug('[Webhook] joinActivityDiscussion on audit join failed (non-fatal)', {
642
+ activityId, error: (0, tool_helpers_1.extractErrorMessage)(joinErr),
643
+ });
644
+ }
645
+ const msg = result.triggerUserName
646
+ ? `User auto-provisioned by ${result.triggerUserName}.`
647
+ : `User auto-provisioned.`;
648
+ await adminClient.socket.request(hailer_rpc_1.HailerRpc.Messenger.send, [{ msg }, discussionId]);
649
+ logger.debug('[Webhook] Posted audit discussion message', { activityId, discussionId });
650
+ }
651
+ catch (auditErr) {
652
+ logger.warn('[Webhook] Failed to post audit discussion message (non-fatal)', {
653
+ activityId, error: (0, tool_helpers_1.extractErrorMessage)(auditErr),
654
+ });
655
+ }
656
+ });
657
+ }
72
658
  // ============================================================================
73
659
  // WEBHOOK TOKEN SECURITY
74
660
  // ============================================================================
@@ -161,71 +747,107 @@ function getWebhookPath() {
161
747
  const token = getWebhookToken();
162
748
  return token ? `/${token}` : null;
163
749
  }
164
- let botUpdateCallback = null;
165
- function onBotUpdate(callback) {
166
- botUpdateCallback = callback;
167
- }
168
- /**
169
- * Get field value from webhook payload by key
170
- */
171
750
  function getFieldValue(fields, key) {
172
751
  const field = fields.find((f) => f.key === key);
173
752
  return field?.value ?? null;
174
753
  }
175
754
  /**
176
- * Load existing workspace config or create empty one.
177
- * Delegates to bot-config/loader (single owner of .bot-config/*.json files).
178
- * Falls back to direct file I/O if bot-config module not available.
755
+ * Pull the optional `memberRole` hint out of the activity's schemaConfig
756
+ * JSON. Used by provisionBotUserInner to decide what Hailer member role
757
+ * to invite the bot account with: 'user' (default, matches AI Hub) or
758
+ * 'admin' (set by public-chat graduation so the first bot in a brand-new
759
+ * workspace can install workflows and invite users).
760
+ *
761
+ * Anything we don't recognize falls back to 'user' so a malformed config
762
+ * can't accidentally elevate a bot.
179
763
  */
180
- function loadBotConfigFile(workspaceId) {
181
- if (_loadConfigFile) {
182
- return _loadConfigFile(workspaceId);
764
+ const ALLOWED_MEMBER_ROLES = ['user', 'admin'];
765
+ function readMemberRoleFromSchemaConfig(fields) {
766
+ const raw = getFieldValue(fields, 'schemaConfig');
767
+ if (typeof raw !== 'string' || raw.length === 0) {
768
+ return 'user';
183
769
  }
184
- // Fallback for MCP-only installs (no bot-config module)
185
- const configDir = constants_1.BOT_CONFIG_DIR;
186
- const configPath = path.join(configDir, `${workspaceId}.json`);
187
- if (fs.existsSync(configPath)) {
188
- try {
189
- return JSON.parse(fs.readFileSync(configPath, 'utf-8'));
190
- }
191
- catch (error) {
192
- logger.warn('Failed to load workspace config', { workspaceId, error: String(error) });
770
+ try {
771
+ const parsed = JSON.parse(raw);
772
+ const candidate = parsed?.memberRole;
773
+ if (typeof candidate === 'string' &&
774
+ ALLOWED_MEMBER_ROLES.includes(candidate)) {
775
+ return candidate;
193
776
  }
194
777
  }
195
- return {
196
- workspaceId,
197
- workspaceName: workspaceId,
198
- bots: [],
199
- lastSynced: new Date().toISOString(),
200
- };
778
+ catch {
779
+ // Falls through — schemaConfig will be reported as unparseable
780
+ // by the main handler later; no need to duplicate the warning.
781
+ }
782
+ return 'user';
201
783
  }
202
784
  /**
203
- * Save workspace config to file.
204
- * Delegates to bot-config/loader (single owner of .bot-config/*.json files).
205
- * Falls back to direct file I/O if bot-config module not available.
785
+ * Remove a bot entry from a workspace's config and emit a remove event so
786
+ * BotManager can shut the running bot down. Returns the removed entry if any.
206
787
  */
207
- function saveBotConfigFile(config) {
208
- if (_saveConfigFile) {
209
- _saveConfigFile(config);
210
- return;
788
+ async function removeBotFromConfig(workspaceId, activityId) {
789
+ const config = (0, loader_1.loadWorkspaceConfigFile)(workspaceId);
790
+ const idx = config.bots.findIndex((b) => b.activityId === activityId);
791
+ if (idx < 0) {
792
+ return null;
211
793
  }
212
- // Fallback for MCP-only installs (no bot-config module)
213
- const configDir = constants_1.BOT_CONFIG_DIR;
214
- if (!fs.existsSync(configDir)) {
215
- fs.mkdirSync(configDir, { recursive: true });
794
+ const [removed] = config.bots.splice(idx, 1);
795
+ (0, loader_1.saveWorkspaceConfigFile)(config);
796
+ (0, loader_1.invalidateConfigCache)();
797
+ await (0, events_1.emitBotEvent)({ workspaceId, bot: removed, action: 'remove' });
798
+ logger.info('Removed bot from config (activity deleted in Hailer)', {
799
+ workspaceId, activityId, email: (0, config_1.maskEmail)(removed.email),
800
+ });
801
+ return removed;
802
+ }
803
+ async function destroyBot(workspaceId, activityId, actor = {}) {
804
+ const config = (0, loader_1.loadWorkspaceConfigFile)(workspaceId);
805
+ const idx = config.bots.findIndex((b) => b.activityId === activityId);
806
+ if (idx < 0) {
807
+ logger.info('destroyBot: no config entry found', { workspaceId, activityId, actor });
808
+ return { removed: null, teardownOk: true };
216
809
  }
217
- const configPath = path.join(configDir, `${config.workspaceId}.json`);
218
- config.lastSynced = new Date().toISOString();
219
- fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
220
- logger.info('Saved workspace config', {
221
- workspaceId: config.workspaceId,
222
- path: configPath,
810
+ const [removed] = config.bots.splice(idx, 1);
811
+ (0, loader_1.saveWorkspaceConfigFile)(config);
812
+ (0, loader_1.invalidateConfigCache)();
813
+ const emit = await (0, events_1.emitBotEvent)({ workspaceId, bot: removed, action: 'destroy' });
814
+ if (emit.error !== undefined) {
815
+ const errMsg = (0, tool_helpers_1.extractErrorMessage)(emit.error);
816
+ logger.error('Destroyed bot config entry but session teardown failed', {
817
+ workspaceId, activityId, email: (0, config_1.maskEmail)(removed.email),
818
+ actorUid: actor.uid, actorName: actor.name, error: errMsg,
819
+ });
820
+ return { removed, teardownOk: false, teardownError: errMsg };
821
+ }
822
+ if (emit.listenerCount === 0) {
823
+ const errMsg = 'no destroy listener registered (MCP-only mode?)';
824
+ logger.warn('Destroyed bot config entry but no listener ran', {
825
+ workspaceId, activityId, email: (0, config_1.maskEmail)(removed.email),
826
+ actorUid: actor.uid, actorName: actor.name,
827
+ });
828
+ return { removed, teardownOk: false, teardownError: errMsg };
829
+ }
830
+ // NOTE: the Hailer user account is intentionally NOT deleted here — see
831
+ // Bot.destroy() in bot.ts. Hailer's inactive-user prune sweeps them
832
+ // out-of-band. The activity is removed by AI Hub separately.
833
+ logger.info('Destroyed bot (config entry + running session)', {
834
+ workspaceId, activityId, email: (0, config_1.maskEmail)(removed.email),
835
+ actorUid: actor.uid, actorName: actor.name,
223
836
  });
837
+ return { removed, teardownOk: true };
224
838
  }
225
839
  /**
226
840
  * Process webhook payload and update workspace config
227
841
  */
228
- function handleBotConfigWebhook(payload) {
842
+ async function handleBotConfigWebhook(payload) {
843
+ // Serialize ALL webhook processing per activity. Hailer fires multiple
844
+ // webhooks per activity create/phase transition and they hit Express in
845
+ // parallel — without an outer lock the load → modify → save → emit
846
+ // sequence races and bot-manager sees out-of-order add/remove events.
847
+ // Net result: bots not turning on/off reliably under burst traffic.
848
+ return withProvisionLock(payload._id, () => handleBotConfigWebhookLocked(payload));
849
+ }
850
+ async function handleBotConfigWebhookLocked(payload) {
229
851
  const workspaceId = payload.cid;
230
852
  logger.debug('Processing bot config webhook', {
231
853
  activityId: payload._id,
@@ -233,17 +855,151 @@ function handleBotConfigWebhook(payload) {
233
855
  workspaceId,
234
856
  phase: payload.currentPhase,
235
857
  });
236
- // Extract fields
858
+ // Extract fields. password/userId are reassigned by auto-provisioning below.
237
859
  const email = getFieldValue(payload.fields, 'agentEmailInHailer');
238
- const password = getFieldValue(payload.fields, 'password');
860
+ let password = getFieldValue(payload.fields, 'password');
239
861
  const botType = getFieldValue(payload.fields, 'botType');
240
- const userId = getFieldValue(payload.fields, 'hailerProfile');
862
+ let userId = getFieldValue(payload.fields, 'hailerProfile');
241
863
  const schemaConfigStr = getFieldValue(payload.fields, 'schemaConfig');
242
864
  const systemPrompt = getFieldValue(payload.fields, 'systemPrompt') || undefined;
243
865
  const accessLevel = getFieldValue(payload.fields, 'accessLevel') || undefined;
866
+ const seedContext = getFieldValue(payload.fields, 'seedContext') || undefined;
244
867
  // responseMode and allowBotMessages are stored inside schemaConfig JSON, not as separate fields
245
868
  let responseMode;
246
869
  let allowBotMessages = false;
870
+ let helperMode = false;
871
+ // Parse schemaConfig once, up here, so we can read `adminApiKey` from it
872
+ // before any code path that depends on workspace admin credentials runs
873
+ // (probe path, auto-provisioning, etc.). Reused later for the bot-config
874
+ // update without re-parsing.
875
+ let schemaConfig = null;
876
+ if (schemaConfigStr) {
877
+ try {
878
+ schemaConfig = JSON.parse(schemaConfigStr);
879
+ }
880
+ catch (e) {
881
+ logger.warn('Failed to parse schemaConfig', { schemaConfigStr });
882
+ }
883
+ }
884
+ // If the activity carries an admin api key in schemaConfig.adminApiKey,
885
+ // validate and persist it now — downstream getAdminApiKey() calls will
886
+ // see it immediately. Safe to run before the probe/provision branches.
887
+ await maybePersistAdminKeyFromSchema(workspaceId, schemaConfig, payload._id, payload.process);
888
+ // Carrier activities exist solely to deliver workspace-scoped config via
889
+ // schemaConfig (admin API key when no real bots exist). Not bots — skip
890
+ // the provisioning + bot-config branches. AI Hub filters them out of the
891
+ // bot list.
892
+ if (schemaConfig?._isCarrier) {
893
+ logger.info('[Webhook] Carrier activity processed — admin key persisted, skipping bot logic', {
894
+ workspaceId,
895
+ activityId: payload._id,
896
+ });
897
+ return {
898
+ success: true,
899
+ action: 'skip-carrier',
900
+ workspaceId,
901
+ botType,
902
+ };
903
+ }
904
+ // For already-provisioned bots (userId set), probe Hailer to confirm the
905
+ // activity still exists. Hailer queues webhooks during/after delete, so an
906
+ // orphan webhook for a deleted activity would otherwise re-add the bot
907
+ // entry and start a doomed bot. The auto-provision branch below has its
908
+ // own gone-detection — we only need this for the userId-already-set path.
909
+ if (userId) {
910
+ const adminApiKey = (0, workspace_admin_store_1.getAdminApiKey)(workspaceId);
911
+ if (adminApiKey) {
912
+ try {
913
+ const adminClient = await (0, hailer_clients_1.createHailerClientByApiKey)(adminApiKey);
914
+ // Hold the API-key lock across switchEcosystem + probe so a
915
+ // concurrent webhook for a different workspace using the same
916
+ // admin key can't repoint the server context mid-probe.
917
+ const probe = await (0, hailer_clients_1.withApiKeyLock)(adminClient.sessionKey, async () => {
918
+ await adminClient.socket.request(hailer_rpc_1.HailerRpc.Core.switchEcosystem, [workspaceId]);
919
+ return probeActivity(adminClient, payload._id);
920
+ });
921
+ if (probe.gone) {
922
+ const removed = await removeBotFromConfig(workspaceId, payload._id);
923
+ return {
924
+ success: true,
925
+ action: removed ? 'remove' : 'skip',
926
+ workspaceId,
927
+ botType,
928
+ };
929
+ }
930
+ }
931
+ catch (err) {
932
+ // Probe failures are non-fatal — fall through to the normal flow
933
+ // and let the bot-config update happen as usual. But if the admin
934
+ // key itself was rejected (auth failure), forget it so we don't
935
+ // keep hammering 403 on every webhook.
936
+ await forgetAdminKeyOnAuthFailure(workspaceId, err);
937
+ logger.debug('[Webhook] existence probe failed (non-fatal)', {
938
+ activityId: payload._id,
939
+ error: (0, tool_helpers_1.extractErrorMessage)(err),
940
+ });
941
+ }
942
+ }
943
+ }
944
+ // Auto-create bot Hailer account if email is set but no profile/password yet.
945
+ // A null result means a sibling webhook is mid-provision but hasn't written
946
+ // the password yet — fall through so the missing-credentials check below skips.
947
+ if (!userId && email) {
948
+ const adminApiKey = (0, workspace_admin_store_1.getAdminApiKey)(workspaceId);
949
+ if (!adminApiKey) {
950
+ logger.warn('[Webhook] No admin credentials for workspace — cannot auto-create bot user', { workspaceId });
951
+ return {
952
+ success: false,
953
+ action: 'skip',
954
+ workspaceId,
955
+ botType,
956
+ error: 'Missing admin credentials for auto-provisioning',
957
+ };
958
+ }
959
+ try {
960
+ const adminClient = await (0, hailer_clients_1.createHailerClientByApiKey)(adminApiKey);
961
+ const provisioned = await provisionBotUser(adminClient, payload, workspaceId, email);
962
+ if (!provisioned) {
963
+ // null means the activity was deleted, a sibling is mid-provision, or
964
+ // a dangling user blocks register. In every case the payload data is
965
+ // stale or the entry, if any, is in a transient state — do NOT fall
966
+ // through to upsert: that would re-add an entry for a deleted
967
+ // activity (bug seen with queued webhooks for already-deleted bots).
968
+ return {
969
+ success: true,
970
+ action: 'skip',
971
+ workspaceId,
972
+ botType,
973
+ };
974
+ }
975
+ userId = provisioned.uid;
976
+ password = provisioned.password;
977
+ if (provisioned.freshlyProvisioned) {
978
+ await postProvisioningAudit(adminClient, workspaceId, payload._id, provisioned);
979
+ }
980
+ }
981
+ catch (err) {
982
+ // Auto-provision failure is logged loudly but we return success so
983
+ // Hailer doesn't suspend webhook delivery after consecutive 500s.
984
+ // The activity update is real either way; the operator fixes the
985
+ // underlying cause (permissions, dangling users) and retries by
986
+ // toggling the bot in AI Hub.
987
+ const errMsg = (0, tool_helpers_1.extractErrorMessage)(err);
988
+ await forgetAdminKeyOnAuthFailure(workspaceId, err);
989
+ logger.error('[Webhook] Failed to auto-create bot user (returning 200 to avoid webhook suspension)', {
990
+ err: errMsg,
991
+ email: (0, config_1.maskEmail)(email),
992
+ activityId: payload._id,
993
+ });
994
+ return {
995
+ success: false,
996
+ action: 'skip',
997
+ workspaceId,
998
+ botType,
999
+ error: errMsg,
1000
+ };
1001
+ }
1002
+ }
247
1003
  // Validate required fields
248
1004
  if (!email || !password) {
249
1005
  logger.warn('Webhook missing credentials', {
@@ -263,26 +1019,26 @@ function handleBotConfigWebhook(payload) {
263
1019
  let deployedPhaseId = null;
264
1020
  let retiredPhaseId = null;
265
1021
  let allowedWorkflows;
266
- if (schemaConfigStr) {
267
- try {
268
- const schemaConfig = JSON.parse(schemaConfigStr);
269
- deployedPhaseId = schemaConfig.deployedPhaseId;
270
- retiredPhaseId = schemaConfig.retiredPhaseId;
271
- responseMode = schemaConfig.responseMode || undefined;
272
- allowBotMessages = !!schemaConfig.allowBotMessages;
273
- if (Array.isArray(schemaConfig.allowedWorkflows)) {
274
- allowedWorkflows = schemaConfig.allowedWorkflows;
275
- }
276
- }
277
- catch (e) {
278
- logger.warn('Failed to parse schemaConfig', { schemaConfigStr });
1022
+ if (schemaConfig) {
1023
+ deployedPhaseId = schemaConfig.deployedPhaseId ?? null;
1024
+ retiredPhaseId = schemaConfig.retiredPhaseId ?? null;
1025
+ responseMode = schemaConfig.responseMode || undefined;
1026
+ allowBotMessages = !!schemaConfig.allowBotMessages;
1027
+ helperMode = !!schemaConfig.helperMode;
1028
+ if (Array.isArray(schemaConfig.allowedWorkflows)) {
1029
+ allowedWorkflows = schemaConfig.allowedWorkflows;
279
1030
  }
280
1031
  }
281
- const isDeployed = deployedPhaseId ? payload.currentPhase === deployedPhaseId : true;
1032
+ // Fail-closed: if we don't know the deployed phase, treat the bot as
1033
+ // disabled. New activities start in the Retired phase, and trailing
1034
+ // webhooks (e.g. from a delete in AI Hub) often arrive with empty
1035
+ // schemaConfig — defaulting to enabled would re-start a bot the user
1036
+ // just disabled.
1037
+ const isDeployed = deployedPhaseId ? payload.currentPhase === deployedPhaseId : false;
282
1038
  const isRetired = retiredPhaseId ? payload.currentPhase === retiredPhaseId : false;
283
1039
  const enabled = isDeployed && !isRetired;
284
- // Load existing config
285
- const config = loadBotConfigFile(workspaceId);
1040
+ const config = (0, loader_1.loadWorkspaceConfigFile)(workspaceId);
1041
+ const existingEntry = config.bots.find((b) => b.activityId === payload._id);
286
1042
  const botEntry = {
287
1043
  activityId: payload._id,
288
1044
  userId: userId || null,
@@ -296,12 +1052,28 @@ function handleBotConfigWebhook(payload) {
296
1052
  allowedWorkflows,
297
1053
  allowBotMessages,
298
1054
  responseMode,
1055
+ helperMode,
1056
+ // Preserve the previously-stored seedContext if Hailer omitted the
1057
+ // field from this webhook (it only re-sends fields that changed in
1058
+ // the phase event, so subsequent transitions can wipe it).
1059
+ seedContext: seedContext ?? existingEntry?.seedContext,
1060
+ introPosted: existingEntry?.introPosted,
299
1061
  };
300
- // Find existing bot by activityId, or add new
301
- const existingIndex = config.bots.findIndex(b => b.activityId === payload._id);
1062
+ const existingIndex = existingEntry
1063
+ ? config.bots.indexOf(existingEntry)
1064
+ : -1;
302
1065
  let action;
303
1066
  if (existingIndex >= 0) {
304
- config.bots[existingIndex] = botEntry;
1067
+ // Carry forward "this bot has already done X" flags. Without this, a
1068
+ // phase toggle (e.g. Retire → Deploy) reconstructs the entry from the
1069
+ // webhook payload alone and the bot re-runs its one-shot self-intro
1070
+ // — which also re-toggles its activity-discussion membership and
1071
+ // produces a "left → joined" sequence in the UI.
1072
+ const existing = config.bots[existingIndex];
1073
+ config.bots[existingIndex] = {
1074
+ ...botEntry,
1075
+ introPosted: existing.introPosted,
1076
+ };
305
1077
  action = enabled ? 'update' : 'remove';
306
1078
  }
307
1079
  else if (enabled) {
@@ -312,45 +1084,18 @@ function handleBotConfigWebhook(payload) {
312
1084
  action = 'update';
313
1085
  }
314
1086
  logger.info('Updated bot', { workspaceId, email: (0, config_1.maskEmail)(email), botType, enabled, action });
315
- // Save config
316
- saveBotConfigFile(config);
317
- // Invalidate config cache so loadBotConfigs() reads fresh data
318
- if (invalidateConfigCache)
319
- invalidateConfigCache();
320
- // Trigger callback for hot reload
321
- if (botUpdateCallback) {
322
- botUpdateCallback(workspaceId, botEntry, action);
323
- }
1087
+ (0, loader_1.saveWorkspaceConfigFile)(config);
1088
+ (0, loader_1.invalidateConfigCache)();
1089
+ await (0, events_1.emitBotEvent)({ workspaceId, bot: botEntry, action });
324
1090
  return {
325
1091
  success: true,
326
1092
  action,
327
1093
  workspaceId,
328
1094
  botType,
1095
+ userId: userId || null,
329
1096
  };
330
1097
  }
331
- /**
332
- * List all workspace configs.
333
- * Delegates to bot-config/loader when available.
334
- */
335
1098
  function listWorkspaceConfigs() {
336
- if (_listConfigFiles) {
337
- return _listConfigFiles();
338
- }
339
- // Fallback for MCP-only installs
340
- const configDir = constants_1.BOT_CONFIG_DIR;
341
- if (!fs.existsSync(configDir))
342
- return [];
343
- const files = fs.readdirSync(configDir).filter((f) => f.endsWith('.json'));
344
- const configs = [];
345
- for (const file of files) {
346
- try {
347
- const content = fs.readFileSync(path.join(configDir, file), 'utf-8');
348
- configs.push(JSON.parse(content));
349
- }
350
- catch (error) {
351
- logger.warn('Failed to load workspace config', { file, error: String(error) });
352
- }
353
- }
354
- return configs;
1099
+ return (0, loader_1.listWorkspaceConfigFiles)();
355
1100
  }
356
1101
  //# sourceMappingURL=webhook-handler.js.map