@hailer/mcp 1.2.0 → 2.0.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (764) hide show
  1. package/.claude/agents/agent-hailer-helper.md +118 -0
  2. package/.claude/commands/app-squad.md +16 -110
  3. package/.claude/commands/debug-squad.md +13 -290
  4. package/.claude/commands/publish.md +2 -2
  5. package/.claude/commands/review-squad.md +17 -139
  6. package/.claude/skills/create-and-publish-app/SKILL.md +102 -83
  7. package/.claude/skills/hailer-app-builder/SKILL.md +2 -2
  8. package/.claude/skills/hailer-ui-guide/SKILL.md +265 -0
  9. package/.env.example +50 -1
  10. package/CLAUDE.md +136 -10
  11. package/dist/app.d.ts.map +1 -1
  12. package/dist/app.js +3 -0
  13. package/dist/app.js.map +1 -1
  14. package/dist/bot/bot-manager.d.ts +9 -6
  15. package/dist/bot/bot-manager.d.ts.map +1 -1
  16. package/dist/bot/bot-manager.js +142 -31
  17. package/dist/bot/bot-manager.js.map +1 -1
  18. package/dist/bot/bot.d.ts +59 -16
  19. package/dist/bot/bot.d.ts.map +1 -1
  20. package/dist/bot/bot.js +889 -142
  21. package/dist/bot/bot.js.map +1 -1
  22. package/dist/bot/operation-logger.d.ts.map +1 -1
  23. package/dist/bot/operation-logger.js +24 -12
  24. package/dist/bot/operation-logger.js.map +1 -1
  25. package/dist/bot/services/bot-permissions.d.ts +2 -2
  26. package/dist/bot/services/bot-permissions.d.ts.map +1 -1
  27. package/dist/bot/services/bot-permissions.js +28 -9
  28. package/dist/bot/services/bot-permissions.js.map +1 -1
  29. package/dist/bot/services/conversation-manager.d.ts +23 -23
  30. package/dist/bot/services/conversation-manager.d.ts.map +1 -1
  31. package/dist/bot/services/conversation-manager.js +52 -49
  32. package/dist/bot/services/conversation-manager.js.map +1 -1
  33. package/dist/bot/services/helper-prompt.d.ts +8 -0
  34. package/dist/bot/services/helper-prompt.d.ts.map +1 -0
  35. package/dist/bot/services/helper-prompt.js +177 -0
  36. package/dist/bot/services/helper-prompt.js.map +1 -0
  37. package/dist/bot/services/message-classifier.d.ts +16 -16
  38. package/dist/bot/services/message-classifier.d.ts.map +1 -1
  39. package/dist/bot/services/message-classifier.js +55 -49
  40. package/dist/bot/services/message-classifier.js.map +1 -1
  41. package/dist/bot/services/message-formatter.d.ts +38 -38
  42. package/dist/bot/services/message-formatter.d.ts.map +1 -1
  43. package/dist/bot/services/message-formatter.js +81 -74
  44. package/dist/bot/services/message-formatter.js.map +1 -1
  45. package/dist/bot/services/permission-guard.d.ts.map +1 -1
  46. package/dist/bot/services/permission-guard.js +20 -10
  47. package/dist/bot/services/permission-guard.js.map +1 -1
  48. package/dist/bot/services/signal-router.d.ts.map +1 -1
  49. package/dist/bot/services/signal-router.js +11 -6
  50. package/dist/bot/services/signal-router.js.map +1 -1
  51. package/dist/bot/services/system-prompt.d.ts +14 -0
  52. package/dist/bot/services/system-prompt.d.ts.map +1 -1
  53. package/dist/bot/services/system-prompt.js +179 -4
  54. package/dist/bot/services/system-prompt.js.map +1 -1
  55. package/dist/bot/services/token-billing.d.ts +23 -23
  56. package/dist/bot/services/token-billing.d.ts.map +1 -1
  57. package/dist/bot/services/token-billing.js +51 -36
  58. package/dist/bot/services/token-billing.js.map +1 -1
  59. package/dist/bot/services/types.d.ts +3 -1
  60. package/dist/bot/services/types.d.ts.map +1 -1
  61. package/dist/bot/services/typing-indicator.d.ts +8 -8
  62. package/dist/bot/services/typing-indicator.d.ts.map +1 -1
  63. package/dist/bot/services/typing-indicator.js +12 -10
  64. package/dist/bot/services/typing-indicator.js.map +1 -1
  65. package/dist/bot/services/workspace-refresh.d.ts +3 -3
  66. package/dist/bot/services/workspace-refresh.d.ts.map +1 -1
  67. package/dist/bot/services/workspace-refresh.js +23 -13
  68. package/dist/bot/services/workspace-refresh.js.map +1 -1
  69. package/dist/bot/tool-executor.d.ts +10 -6
  70. package/dist/bot/tool-executor.d.ts.map +1 -1
  71. package/dist/bot/tool-executor.js +12 -6
  72. package/dist/bot/tool-executor.js.map +1 -1
  73. package/dist/bot/workspace-overview.d.ts.map +1 -1
  74. package/dist/bot/workspace-overview.js +6 -3
  75. package/dist/bot/workspace-overview.js.map +1 -1
  76. package/dist/bot-config/activity-error.d.ts +47 -0
  77. package/dist/bot-config/activity-error.d.ts.map +1 -0
  78. package/dist/bot-config/activity-error.js +67 -0
  79. package/dist/bot-config/activity-error.js.map +1 -0
  80. package/dist/bot-config/context.d.ts +4 -4
  81. package/dist/bot-config/context.d.ts.map +1 -1
  82. package/dist/bot-config/context.js +18 -14
  83. package/dist/bot-config/context.js.map +1 -1
  84. package/dist/bot-config/events.d.ts +45 -0
  85. package/dist/bot-config/events.d.ts.map +1 -0
  86. package/dist/bot-config/events.js +51 -0
  87. package/dist/bot-config/events.js.map +1 -0
  88. package/dist/bot-config/index.d.ts +3 -0
  89. package/dist/bot-config/index.d.ts.map +1 -1
  90. package/dist/bot-config/index.js +8 -1
  91. package/dist/bot-config/index.js.map +1 -1
  92. package/dist/bot-config/loader.d.ts +3 -0
  93. package/dist/bot-config/loader.d.ts.map +1 -1
  94. package/dist/bot-config/loader.js +45 -20
  95. package/dist/bot-config/loader.js.map +1 -1
  96. package/dist/bot-config/persistence.js.map +1 -1
  97. package/dist/bot-config/reconciler.d.ts +11 -0
  98. package/dist/bot-config/reconciler.d.ts.map +1 -0
  99. package/dist/bot-config/reconciler.js +121 -0
  100. package/dist/bot-config/reconciler.js.map +1 -0
  101. package/dist/bot-config/state.d.ts.map +1 -1
  102. package/dist/bot-config/state.js.map +1 -1
  103. package/dist/bot-config/types.d.ts +32 -0
  104. package/dist/bot-config/types.d.ts.map +1 -1
  105. package/dist/bot-config/webhooks.d.ts.map +1 -1
  106. package/dist/bot-config/webhooks.js.map +1 -1
  107. package/dist/bot-config/workflow-installer.d.ts +37 -0
  108. package/dist/bot-config/workflow-installer.d.ts.map +1 -0
  109. package/dist/bot-config/workflow-installer.js +346 -0
  110. package/dist/bot-config/workflow-installer.js.map +1 -0
  111. package/dist/cli.d.ts.map +1 -1
  112. package/dist/cli.js +12 -0
  113. package/dist/cli.js.map +1 -1
  114. package/dist/config.d.ts +23 -19
  115. package/dist/config.d.ts.map +1 -1
  116. package/dist/config.js +65 -27
  117. package/dist/config.js.map +1 -1
  118. package/dist/core.d.ts +6 -4
  119. package/dist/core.d.ts.map +1 -1
  120. package/dist/core.js +11 -16
  121. package/dist/core.js.map +1 -1
  122. package/dist/lib/logger.d.ts.map +1 -1
  123. package/dist/lib/logger.js +7 -4
  124. package/dist/lib/logger.js.map +1 -1
  125. package/dist/lib/request-logger.d.ts +19 -19
  126. package/dist/lib/request-logger.d.ts.map +1 -1
  127. package/dist/lib/request-logger.js +19 -19
  128. package/dist/lib/request-logger.js.map +1 -1
  129. package/dist/mcp/UserContextCache.d.ts +28 -22
  130. package/dist/mcp/UserContextCache.d.ts.map +1 -1
  131. package/dist/mcp/UserContextCache.js +23 -23
  132. package/dist/mcp/UserContextCache.js.map +1 -1
  133. package/dist/mcp/auth.js.map +1 -1
  134. package/dist/mcp/hailer-clients.d.ts +5 -4
  135. package/dist/mcp/hailer-clients.d.ts.map +1 -1
  136. package/dist/mcp/hailer-clients.js +61 -27
  137. package/dist/mcp/hailer-clients.js.map +1 -1
  138. package/dist/mcp/hailer-rpc.d.ts +40 -0
  139. package/dist/mcp/hailer-rpc.d.ts.map +1 -0
  140. package/dist/mcp/hailer-rpc.js +43 -0
  141. package/dist/mcp/hailer-rpc.js.map +1 -0
  142. package/dist/mcp/session-store.d.ts +16 -16
  143. package/dist/mcp/session-store.d.ts.map +1 -1
  144. package/dist/mcp/session-store.js +16 -16
  145. package/dist/mcp/session-store.js.map +1 -1
  146. package/dist/mcp/tool-profiles.d.ts +69 -0
  147. package/dist/mcp/tool-profiles.d.ts.map +1 -0
  148. package/dist/mcp/tool-profiles.js +176 -0
  149. package/dist/mcp/tool-profiles.js.map +1 -0
  150. package/dist/mcp/tool-registry.d.ts +16 -0
  151. package/dist/mcp/tool-registry.d.ts.map +1 -1
  152. package/dist/mcp/tool-registry.js +91 -39
  153. package/dist/mcp/tool-registry.js.map +1 -1
  154. package/dist/mcp/tools/activity.d.ts.map +1 -1
  155. package/dist/mcp/tools/activity.js +398 -198
  156. package/dist/mcp/tools/activity.js.map +1 -1
  157. package/dist/mcp/tools/aliases.d.ts +11 -0
  158. package/dist/mcp/tools/aliases.d.ts.map +1 -0
  159. package/dist/mcp/tools/aliases.js +176 -0
  160. package/dist/mcp/tools/aliases.js.map +1 -0
  161. package/dist/mcp/tools/app-core.d.ts +6 -8
  162. package/dist/mcp/tools/app-core.d.ts.map +1 -1
  163. package/dist/mcp/tools/app-core.js +355 -254
  164. package/dist/mcp/tools/app-core.js.map +1 -1
  165. package/dist/mcp/tools/app-marketplace.d.ts +8 -16
  166. package/dist/mcp/tools/app-marketplace.d.ts.map +1 -1
  167. package/dist/mcp/tools/app-marketplace.js +604 -930
  168. package/dist/mcp/tools/app-marketplace.js.map +1 -1
  169. package/dist/mcp/tools/app.d.ts +4 -7
  170. package/dist/mcp/tools/app.d.ts.map +1 -1
  171. package/dist/mcp/tools/app.js +4 -7
  172. package/dist/mcp/tools/app.js.map +1 -1
  173. package/dist/mcp/tools/bot-self.d.ts +21 -0
  174. package/dist/mcp/tools/bot-self.d.ts.map +1 -0
  175. package/dist/mcp/tools/bot-self.js +174 -0
  176. package/dist/mcp/tools/bot-self.js.map +1 -0
  177. package/dist/mcp/tools/calendar.d.ts +21 -0
  178. package/dist/mcp/tools/calendar.d.ts.map +1 -0
  179. package/dist/mcp/tools/calendar.js +741 -0
  180. package/dist/mcp/tools/calendar.js.map +1 -0
  181. package/dist/mcp/tools/company.d.ts.map +1 -1
  182. package/dist/mcp/tools/company.js +2 -1
  183. package/dist/mcp/tools/company.js.map +1 -1
  184. package/dist/mcp/tools/date.js.map +1 -1
  185. package/dist/mcp/tools/discussion.d.ts +23 -3
  186. package/dist/mcp/tools/discussion.d.ts.map +1 -1
  187. package/dist/mcp/tools/discussion.js +417 -534
  188. package/dist/mcp/tools/discussion.js.map +1 -1
  189. package/dist/mcp/tools/file.d.ts.map +1 -1
  190. package/dist/mcp/tools/file.js +18 -16
  191. package/dist/mcp/tools/file.js.map +1 -1
  192. package/dist/mcp/tools/index.js +4 -4
  193. package/dist/mcp/tools/index.js.map +1 -1
  194. package/dist/mcp/tools/insight.d.ts +7 -5
  195. package/dist/mcp/tools/insight.d.ts.map +1 -1
  196. package/dist/mcp/tools/insight.js +419 -477
  197. package/dist/mcp/tools/insight.js.map +1 -1
  198. package/dist/mcp/tools/user.d.ts.map +1 -1
  199. package/dist/mcp/tools/user.js +15 -13
  200. package/dist/mcp/tools/user.js.map +1 -1
  201. package/dist/mcp/tools/workflow-permissions.d.ts +2 -4
  202. package/dist/mcp/tools/workflow-permissions.d.ts.map +1 -1
  203. package/dist/mcp/tools/workflow-permissions.js +88 -97
  204. package/dist/mcp/tools/workflow-permissions.js.map +1 -1
  205. package/dist/mcp/tools/workflow.d.ts +2 -7
  206. package/dist/mcp/tools/workflow.d.ts.map +1 -1
  207. package/dist/mcp/tools/workflow.js +817 -850
  208. package/dist/mcp/tools/workflow.js.map +1 -1
  209. package/dist/mcp/utils/api-errors.d.ts.map +1 -1
  210. package/dist/mcp/utils/api-errors.js +2 -2
  211. package/dist/mcp/utils/api-errors.js.map +1 -1
  212. package/dist/mcp/utils/data-transformers.d.ts.map +1 -1
  213. package/dist/mcp/utils/data-transformers.js +8 -4
  214. package/dist/mcp/utils/data-transformers.js.map +1 -1
  215. package/dist/mcp/utils/file-upload.d.ts.map +1 -1
  216. package/dist/mcp/utils/file-upload.js +1 -1
  217. package/dist/mcp/utils/file-upload.js.map +1 -1
  218. package/dist/mcp/utils/hailer-api-client.d.ts +81 -81
  219. package/dist/mcp/utils/hailer-api-client.d.ts.map +1 -1
  220. package/dist/mcp/utils/hailer-api-client.js +103 -101
  221. package/dist/mcp/utils/hailer-api-client.js.map +1 -1
  222. package/dist/mcp/utils/index.d.ts.map +1 -1
  223. package/dist/mcp/utils/index.js.map +1 -1
  224. package/dist/mcp/utils/logger.d.ts.map +1 -1
  225. package/dist/mcp/utils/logger.js.map +1 -1
  226. package/dist/mcp/utils/response-builder.d.ts.map +1 -1
  227. package/dist/mcp/utils/response-builder.js +8 -4
  228. package/dist/mcp/utils/response-builder.js.map +1 -1
  229. package/dist/mcp/utils/role-utils.d.ts.map +1 -1
  230. package/dist/mcp/utils/role-utils.js +6 -3
  231. package/dist/mcp/utils/role-utils.js.map +1 -1
  232. package/dist/mcp/utils/tool-helpers.d.ts.map +1 -1
  233. package/dist/mcp/utils/tool-helpers.js +2 -2
  234. package/dist/mcp/utils/tool-helpers.js.map +1 -1
  235. package/dist/mcp/utils/types.d.ts +1 -1
  236. package/dist/mcp/utils/types.d.ts.map +1 -1
  237. package/dist/mcp/utils/types.js.map +1 -1
  238. package/dist/mcp/webhook-handler.d.ts +43 -8
  239. package/dist/mcp/webhook-handler.d.ts.map +1 -1
  240. package/dist/mcp/webhook-handler.js +861 -116
  241. package/dist/mcp/webhook-handler.js.map +1 -1
  242. package/dist/mcp/workspace-admin-store.d.ts +49 -0
  243. package/dist/mcp/workspace-admin-store.d.ts.map +1 -0
  244. package/dist/mcp/workspace-admin-store.js +168 -0
  245. package/dist/mcp/workspace-admin-store.js.map +1 -0
  246. package/dist/mcp/workspace-cache.d.ts +2 -2
  247. package/dist/mcp/workspace-cache.d.ts.map +1 -1
  248. package/dist/mcp/workspace-cache.js +9 -5
  249. package/dist/mcp/workspace-cache.js.map +1 -1
  250. package/dist/mcp-server.d.ts +26 -11
  251. package/dist/mcp-server.d.ts.map +1 -1
  252. package/dist/mcp-server.js +360 -36
  253. package/dist/mcp-server.js.map +1 -1
  254. package/dist/plugins/vipunen/client.d.ts +41 -41
  255. package/dist/plugins/vipunen/client.d.ts.map +1 -1
  256. package/dist/plugins/vipunen/client.js +53 -48
  257. package/dist/plugins/vipunen/client.js.map +1 -1
  258. package/dist/plugins/vipunen/index.js.map +1 -1
  259. package/dist/plugins/vipunen/tools.d.ts.map +1 -1
  260. package/dist/plugins/vipunen/tools.js +6 -3
  261. package/dist/plugins/vipunen/tools.js.map +1 -1
  262. package/dist/public-chat/graduate.d.ts +29 -0
  263. package/dist/public-chat/graduate.d.ts.map +1 -0
  264. package/dist/public-chat/graduate.js +593 -0
  265. package/dist/public-chat/graduate.js.map +1 -0
  266. package/dist/public-chat/handler.d.ts +12 -0
  267. package/dist/public-chat/handler.d.ts.map +1 -0
  268. package/dist/public-chat/handler.js +179 -0
  269. package/dist/public-chat/handler.js.map +1 -0
  270. package/dist/public-chat/index.d.ts +16 -0
  271. package/dist/public-chat/index.d.ts.map +1 -0
  272. package/dist/public-chat/index.js +74 -0
  273. package/dist/public-chat/index.js.map +1 -0
  274. package/dist/public-chat/knowledge.d.ts +3 -0
  275. package/dist/public-chat/knowledge.d.ts.map +1 -0
  276. package/dist/public-chat/knowledge.js +1339 -0
  277. package/dist/public-chat/knowledge.js.map +1 -0
  278. package/dist/public-chat/rate-limit.d.ts +16 -0
  279. package/dist/public-chat/rate-limit.d.ts.map +1 -0
  280. package/dist/public-chat/rate-limit.js +51 -0
  281. package/dist/public-chat/rate-limit.js.map +1 -0
  282. package/dist/public-chat/session-store.d.ts +41 -0
  283. package/dist/public-chat/session-store.d.ts.map +1 -0
  284. package/dist/public-chat/session-store.js +95 -0
  285. package/dist/public-chat/session-store.js.map +1 -0
  286. package/dist/public-chat/studio-prewarm.d.ts +61 -0
  287. package/dist/public-chat/studio-prewarm.d.ts.map +1 -0
  288. package/dist/public-chat/studio-prewarm.js +162 -0
  289. package/dist/public-chat/studio-prewarm.js.map +1 -0
  290. package/dist/public-chat/system-prompt.d.ts +22 -0
  291. package/dist/public-chat/system-prompt.d.ts.map +1 -0
  292. package/dist/public-chat/system-prompt.js +428 -0
  293. package/dist/public-chat/system-prompt.js.map +1 -0
  294. package/package.json +14 -6
  295. package/scripts/build-public-chat-knowledge.py +101 -0
  296. package/scripts/probe-mcp-pricing.ts +52 -0
  297. package/scripts/smoke-public-chat-live.ts +148 -0
  298. package/scripts/smoke-public-chat.ts +110 -0
  299. package/.claude/CLAUDE.md +0 -126
  300. package/.claude/commands/audit-squad.md +0 -158
  301. package/.claude/commands/cleanup-squad.md +0 -98
  302. package/.claude/commands/config-squad.md +0 -106
  303. package/.claude/commands/crud-squad.md +0 -87
  304. package/.claude/commands/data-squad.md +0 -97
  305. package/.claude/commands/doc-squad.md +0 -65
  306. package/.claude/commands/help.md +0 -29
  307. package/.claude/commands/help:agents.md +0 -182
  308. package/.claude/commands/help:commands.md +0 -78
  309. package/.claude/commands/help:faq.md +0 -79
  310. package/.claude/commands/help:plugins.md +0 -50
  311. package/.claude/commands/help:skills.md +0 -87
  312. package/.claude/commands/help:tools.md +0 -75
  313. package/.claude/commands/hotfix-squad.md +0 -112
  314. package/.claude/commands/integration-squad.md +0 -82
  315. package/.claude/commands/janitor-squad.md +0 -167
  316. package/.claude/commands/onboard-squad.md +0 -130
  317. package/.claude/commands/swarm.md +0 -210
  318. package/.claude/commands/tool-builder.md +0 -39
  319. package/.claude/skills/publish-hailer-app/SKILL.md +0 -280
  320. package/dist/CLAUDE.md +0 -370
  321. package/dist/agents/bot-manager.d.ts +0 -48
  322. package/dist/agents/bot-manager.d.ts.map +0 -1
  323. package/dist/agents/bot-manager.js +0 -254
  324. package/dist/agents/bot-manager.js.map +0 -1
  325. package/dist/agents/bug-fixer/ai.d.ts +0 -80
  326. package/dist/agents/bug-fixer/ai.d.ts.map +0 -1
  327. package/dist/agents/bug-fixer/ai.js +0 -466
  328. package/dist/agents/bug-fixer/ai.js.map +0 -1
  329. package/dist/agents/bug-fixer/bot.d.ts +0 -92
  330. package/dist/agents/bug-fixer/bot.d.ts.map +0 -1
  331. package/dist/agents/bug-fixer/bot.js +0 -687
  332. package/dist/agents/bug-fixer/bot.js.map +0 -1
  333. package/dist/agents/bug-fixer/config.d.ts +0 -21
  334. package/dist/agents/bug-fixer/config.d.ts.map +0 -1
  335. package/dist/agents/bug-fixer/config.js +0 -218
  336. package/dist/agents/bug-fixer/config.js.map +0 -1
  337. package/dist/agents/bug-fixer/files.d.ts +0 -67
  338. package/dist/agents/bug-fixer/files.d.ts.map +0 -1
  339. package/dist/agents/bug-fixer/files.js +0 -386
  340. package/dist/agents/bug-fixer/files.js.map +0 -1
  341. package/dist/agents/bug-fixer/git.d.ts +0 -48
  342. package/dist/agents/bug-fixer/git.d.ts.map +0 -1
  343. package/dist/agents/bug-fixer/git.js +0 -298
  344. package/dist/agents/bug-fixer/git.js.map +0 -1
  345. package/dist/agents/bug-fixer/index.d.ts +0 -103
  346. package/dist/agents/bug-fixer/index.d.ts.map +0 -1
  347. package/dist/agents/bug-fixer/index.js +0 -262
  348. package/dist/agents/bug-fixer/index.js.map +0 -1
  349. package/dist/agents/bug-fixer/lsp.d.ts +0 -113
  350. package/dist/agents/bug-fixer/lsp.d.ts.map +0 -1
  351. package/dist/agents/bug-fixer/lsp.js +0 -485
  352. package/dist/agents/bug-fixer/lsp.js.map +0 -1
  353. package/dist/agents/bug-fixer/monitor.d.ts +0 -123
  354. package/dist/agents/bug-fixer/monitor.d.ts.map +0 -1
  355. package/dist/agents/bug-fixer/monitor.js +0 -629
  356. package/dist/agents/bug-fixer/monitor.js.map +0 -1
  357. package/dist/agents/bug-fixer/prompt.d.ts +0 -5
  358. package/dist/agents/bug-fixer/prompt.d.ts.map +0 -1
  359. package/dist/agents/bug-fixer/prompt.js +0 -94
  360. package/dist/agents/bug-fixer/prompt.js.map +0 -1
  361. package/dist/agents/bug-fixer/registries/pending-classification.d.ts +0 -28
  362. package/dist/agents/bug-fixer/registries/pending-classification.d.ts.map +0 -1
  363. package/dist/agents/bug-fixer/registries/pending-classification.js +0 -50
  364. package/dist/agents/bug-fixer/registries/pending-classification.js.map +0 -1
  365. package/dist/agents/bug-fixer/registries/pending-fix.d.ts +0 -33
  366. package/dist/agents/bug-fixer/registries/pending-fix.d.ts.map +0 -1
  367. package/dist/agents/bug-fixer/registries/pending-fix.js +0 -64
  368. package/dist/agents/bug-fixer/registries/pending-fix.js.map +0 -1
  369. package/dist/agents/bug-fixer/registries/pending.d.ts +0 -27
  370. package/dist/agents/bug-fixer/registries/pending.d.ts.map +0 -1
  371. package/dist/agents/bug-fixer/registries/pending.js +0 -49
  372. package/dist/agents/bug-fixer/registries/pending.js.map +0 -1
  373. package/dist/agents/bug-fixer/specialist-daemon.d.ts +0 -88
  374. package/dist/agents/bug-fixer/specialist-daemon.d.ts.map +0 -1
  375. package/dist/agents/bug-fixer/specialist-daemon.js +0 -431
  376. package/dist/agents/bug-fixer/specialist-daemon.js.map +0 -1
  377. package/dist/agents/bug-fixer/specialist.d.ts +0 -47
  378. package/dist/agents/bug-fixer/specialist.d.ts.map +0 -1
  379. package/dist/agents/bug-fixer/specialist.js +0 -327
  380. package/dist/agents/bug-fixer/specialist.js.map +0 -1
  381. package/dist/agents/bug-fixer/types.d.ts +0 -123
  382. package/dist/agents/bug-fixer/types.d.ts.map +0 -1
  383. package/dist/agents/bug-fixer/types.js +0 -9
  384. package/dist/agents/bug-fixer/types.js.map +0 -1
  385. package/dist/agents/factory.d.ts +0 -172
  386. package/dist/agents/factory.d.ts.map +0 -1
  387. package/dist/agents/factory.js +0 -706
  388. package/dist/agents/factory.js.map +0 -1
  389. package/dist/agents/hailer-expert/index.d.ts +0 -8
  390. package/dist/agents/hailer-expert/index.d.ts.map +0 -1
  391. package/dist/agents/hailer-expert/index.js +0 -14
  392. package/dist/agents/hailer-expert/index.js.map +0 -1
  393. package/dist/agents/hal/daemon.d.ts +0 -174
  394. package/dist/agents/hal/daemon.d.ts.map +0 -1
  395. package/dist/agents/hal/daemon.js +0 -1385
  396. package/dist/agents/hal/daemon.js.map +0 -1
  397. package/dist/agents/hal/definitions.d.ts +0 -42
  398. package/dist/agents/hal/definitions.d.ts.map +0 -1
  399. package/dist/agents/hal/definitions.js +0 -300
  400. package/dist/agents/hal/definitions.js.map +0 -1
  401. package/dist/agents/hal/index.d.ts +0 -3
  402. package/dist/agents/hal/index.d.ts.map +0 -1
  403. package/dist/agents/hal/index.js +0 -8
  404. package/dist/agents/hal/index.js.map +0 -1
  405. package/dist/agents/index.d.ts +0 -18
  406. package/dist/agents/index.d.ts.map +0 -1
  407. package/dist/agents/index.js +0 -48
  408. package/dist/agents/index.js.map +0 -1
  409. package/dist/agents/shared/base.d.ts +0 -253
  410. package/dist/agents/shared/base.d.ts.map +0 -1
  411. package/dist/agents/shared/base.js +0 -1122
  412. package/dist/agents/shared/base.js.map +0 -1
  413. package/dist/agents/shared/schemas/action-schema.d.ts +0 -62
  414. package/dist/agents/shared/schemas/action-schema.d.ts.map +0 -1
  415. package/dist/agents/shared/schemas/action-schema.js +0 -483
  416. package/dist/agents/shared/schemas/action-schema.js.map +0 -1
  417. package/dist/agents/shared/services/agent-registry.d.ts +0 -108
  418. package/dist/agents/shared/services/agent-registry.d.ts.map +0 -1
  419. package/dist/agents/shared/services/agent-registry.js +0 -469
  420. package/dist/agents/shared/services/agent-registry.js.map +0 -1
  421. package/dist/agents/shared/services/conversation-manager.d.ts +0 -57
  422. package/dist/agents/shared/services/conversation-manager.d.ts.map +0 -1
  423. package/dist/agents/shared/services/conversation-manager.js +0 -168
  424. package/dist/agents/shared/services/conversation-manager.js.map +0 -1
  425. package/dist/agents/shared/services/mcp-client.d.ts +0 -56
  426. package/dist/agents/shared/services/mcp-client.d.ts.map +0 -1
  427. package/dist/agents/shared/services/mcp-client.js +0 -124
  428. package/dist/agents/shared/services/mcp-client.js.map +0 -1
  429. package/dist/agents/shared/services/message-classifier.d.ts +0 -37
  430. package/dist/agents/shared/services/message-classifier.d.ts.map +0 -1
  431. package/dist/agents/shared/services/message-classifier.js +0 -203
  432. package/dist/agents/shared/services/message-classifier.js.map +0 -1
  433. package/dist/agents/shared/services/message-formatter.d.ts +0 -89
  434. package/dist/agents/shared/services/message-formatter.d.ts.map +0 -1
  435. package/dist/agents/shared/services/message-formatter.js +0 -390
  436. package/dist/agents/shared/services/message-formatter.js.map +0 -1
  437. package/dist/agents/shared/services/session-logger.d.ts +0 -162
  438. package/dist/agents/shared/services/session-logger.d.ts.map +0 -1
  439. package/dist/agents/shared/services/session-logger.js +0 -724
  440. package/dist/agents/shared/services/session-logger.js.map +0 -1
  441. package/dist/agents/shared/services/structured-output-executor.d.ts +0 -88
  442. package/dist/agents/shared/services/structured-output-executor.d.ts.map +0 -1
  443. package/dist/agents/shared/services/structured-output-executor.js +0 -296
  444. package/dist/agents/shared/services/structured-output-executor.js.map +0 -1
  445. package/dist/agents/shared/services/token-billing.d.ts +0 -72
  446. package/dist/agents/shared/services/token-billing.d.ts.map +0 -1
  447. package/dist/agents/shared/services/token-billing.js +0 -198
  448. package/dist/agents/shared/services/token-billing.js.map +0 -1
  449. package/dist/agents/shared/services/tool-executor.d.ts +0 -43
  450. package/dist/agents/shared/services/tool-executor.d.ts.map +0 -1
  451. package/dist/agents/shared/services/tool-executor.js +0 -175
  452. package/dist/agents/shared/services/tool-executor.js.map +0 -1
  453. package/dist/agents/shared/services/typing-indicator.d.ts +0 -24
  454. package/dist/agents/shared/services/typing-indicator.d.ts.map +0 -1
  455. package/dist/agents/shared/services/typing-indicator.js +0 -54
  456. package/dist/agents/shared/services/typing-indicator.js.map +0 -1
  457. package/dist/agents/shared/services/workspace-schema-cache.d.ts +0 -122
  458. package/dist/agents/shared/services/workspace-schema-cache.d.ts.map +0 -1
  459. package/dist/agents/shared/services/workspace-schema-cache.js +0 -507
  460. package/dist/agents/shared/services/workspace-schema-cache.js.map +0 -1
  461. package/dist/agents/shared/specialist.d.ts +0 -91
  462. package/dist/agents/shared/specialist.d.ts.map +0 -1
  463. package/dist/agents/shared/specialist.js +0 -399
  464. package/dist/agents/shared/specialist.js.map +0 -1
  465. package/dist/agents/shared/tool-schema-loader.d.ts +0 -65
  466. package/dist/agents/shared/tool-schema-loader.d.ts.map +0 -1
  467. package/dist/agents/shared/tool-schema-loader.js +0 -238
  468. package/dist/agents/shared/tool-schema-loader.js.map +0 -1
  469. package/dist/agents/shared/types.d.ts +0 -190
  470. package/dist/agents/shared/types.d.ts.map +0 -1
  471. package/dist/agents/shared/types.js +0 -13
  472. package/dist/agents/shared/types.js.map +0 -1
  473. package/dist/bot/bot-config.d.ts +0 -37
  474. package/dist/bot/bot-config.d.ts.map +0 -1
  475. package/dist/bot/bot-config.js +0 -219
  476. package/dist/bot/bot-config.js.map +0 -1
  477. package/dist/bot/services/__tests__/permission-guard.test.d.ts +0 -2
  478. package/dist/bot/services/__tests__/permission-guard.test.d.ts.map +0 -1
  479. package/dist/bot/services/__tests__/permission-guard.test.js +0 -357
  480. package/dist/bot/services/__tests__/permission-guard.test.js.map +0 -1
  481. package/dist/bot/services/session-logger.d.ts +0 -162
  482. package/dist/bot/services/session-logger.d.ts.map +0 -1
  483. package/dist/bot/services/session-logger.js +0 -724
  484. package/dist/bot/services/session-logger.js.map +0 -1
  485. package/dist/bot/services/workspace-schema-cache.d.ts +0 -122
  486. package/dist/bot/services/workspace-schema-cache.d.ts.map +0 -1
  487. package/dist/bot/services/workspace-schema-cache.js +0 -506
  488. package/dist/bot/services/workspace-schema-cache.js.map +0 -1
  489. package/dist/bot-config/tools.d.ts +0 -28
  490. package/dist/bot-config/tools.d.ts.map +0 -1
  491. package/dist/bot-config/tools.js +0 -279
  492. package/dist/bot-config/tools.js.map +0 -1
  493. package/dist/client/agents/base.d.ts +0 -207
  494. package/dist/client/agents/base.d.ts.map +0 -1
  495. package/dist/client/agents/base.js +0 -744
  496. package/dist/client/agents/base.js.map +0 -1
  497. package/dist/client/agents/definitions.d.ts +0 -53
  498. package/dist/client/agents/definitions.d.ts.map +0 -1
  499. package/dist/client/agents/definitions.js +0 -263
  500. package/dist/client/agents/definitions.js.map +0 -1
  501. package/dist/client/agents/orchestrator.d.ts +0 -141
  502. package/dist/client/agents/orchestrator.d.ts.map +0 -1
  503. package/dist/client/agents/orchestrator.js +0 -1062
  504. package/dist/client/agents/orchestrator.js.map +0 -1
  505. package/dist/client/agents/specialist.d.ts +0 -86
  506. package/dist/client/agents/specialist.d.ts.map +0 -1
  507. package/dist/client/agents/specialist.js +0 -340
  508. package/dist/client/agents/specialist.js.map +0 -1
  509. package/dist/client/bot-entrypoint.d.ts +0 -7
  510. package/dist/client/bot-entrypoint.d.ts.map +0 -1
  511. package/dist/client/bot-entrypoint.js +0 -103
  512. package/dist/client/bot-entrypoint.js.map +0 -1
  513. package/dist/client/bot-manager.d.ts +0 -44
  514. package/dist/client/bot-manager.d.ts.map +0 -1
  515. package/dist/client/bot-manager.js +0 -173
  516. package/dist/client/bot-manager.js.map +0 -1
  517. package/dist/client/bot-runner.d.ts +0 -35
  518. package/dist/client/bot-runner.d.ts.map +0 -1
  519. package/dist/client/bot-runner.js +0 -188
  520. package/dist/client/bot-runner.js.map +0 -1
  521. package/dist/client/chat-agent-daemon.d.ts +0 -464
  522. package/dist/client/chat-agent-daemon.d.ts.map +0 -1
  523. package/dist/client/chat-agent-daemon.js +0 -1774
  524. package/dist/client/chat-agent-daemon.js.map +0 -1
  525. package/dist/client/daemon-factory.d.ts +0 -106
  526. package/dist/client/daemon-factory.d.ts.map +0 -1
  527. package/dist/client/daemon-factory.js +0 -301
  528. package/dist/client/daemon-factory.js.map +0 -1
  529. package/dist/client/factory.d.ts +0 -111
  530. package/dist/client/factory.d.ts.map +0 -1
  531. package/dist/client/factory.js +0 -314
  532. package/dist/client/factory.js.map +0 -1
  533. package/dist/client/index.d.ts +0 -17
  534. package/dist/client/index.d.ts.map +0 -1
  535. package/dist/client/index.js +0 -38
  536. package/dist/client/index.js.map +0 -1
  537. package/dist/client/multi-bot-manager.d.ts +0 -42
  538. package/dist/client/multi-bot-manager.d.ts.map +0 -1
  539. package/dist/client/multi-bot-manager.js +0 -161
  540. package/dist/client/multi-bot-manager.js.map +0 -1
  541. package/dist/client/orchestrator-daemon.d.ts +0 -87
  542. package/dist/client/orchestrator-daemon.d.ts.map +0 -1
  543. package/dist/client/orchestrator-daemon.js +0 -444
  544. package/dist/client/orchestrator-daemon.js.map +0 -1
  545. package/dist/client/server.d.ts +0 -8
  546. package/dist/client/server.d.ts.map +0 -1
  547. package/dist/client/server.js +0 -251
  548. package/dist/client/server.js.map +0 -1
  549. package/dist/client/services/agent-registry.d.ts +0 -108
  550. package/dist/client/services/agent-registry.d.ts.map +0 -1
  551. package/dist/client/services/agent-registry.js +0 -630
  552. package/dist/client/services/agent-registry.js.map +0 -1
  553. package/dist/client/services/conversation-manager.d.ts +0 -50
  554. package/dist/client/services/conversation-manager.d.ts.map +0 -1
  555. package/dist/client/services/conversation-manager.js +0 -136
  556. package/dist/client/services/conversation-manager.js.map +0 -1
  557. package/dist/client/services/mcp-client.d.ts +0 -48
  558. package/dist/client/services/mcp-client.d.ts.map +0 -1
  559. package/dist/client/services/mcp-client.js +0 -105
  560. package/dist/client/services/mcp-client.js.map +0 -1
  561. package/dist/client/services/message-classifier.d.ts +0 -37
  562. package/dist/client/services/message-classifier.d.ts.map +0 -1
  563. package/dist/client/services/message-classifier.js +0 -187
  564. package/dist/client/services/message-classifier.js.map +0 -1
  565. package/dist/client/services/message-formatter.d.ts +0 -84
  566. package/dist/client/services/message-formatter.d.ts.map +0 -1
  567. package/dist/client/services/message-formatter.js +0 -353
  568. package/dist/client/services/message-formatter.js.map +0 -1
  569. package/dist/client/services/session-logger.d.ts +0 -106
  570. package/dist/client/services/session-logger.d.ts.map +0 -1
  571. package/dist/client/services/session-logger.js +0 -446
  572. package/dist/client/services/session-logger.js.map +0 -1
  573. package/dist/client/services/tool-executor.d.ts +0 -41
  574. package/dist/client/services/tool-executor.d.ts.map +0 -1
  575. package/dist/client/services/tool-executor.js +0 -169
  576. package/dist/client/services/tool-executor.js.map +0 -1
  577. package/dist/client/services/workspace-schema-cache.d.ts +0 -149
  578. package/dist/client/services/workspace-schema-cache.d.ts.map +0 -1
  579. package/dist/client/services/workspace-schema-cache.js +0 -732
  580. package/dist/client/services/workspace-schema-cache.js.map +0 -1
  581. package/dist/client/specialist-daemon.d.ts +0 -77
  582. package/dist/client/specialist-daemon.d.ts.map +0 -1
  583. package/dist/client/specialist-daemon.js +0 -197
  584. package/dist/client/specialist-daemon.js.map +0 -1
  585. package/dist/client/specialists.d.ts +0 -53
  586. package/dist/client/specialists.d.ts.map +0 -1
  587. package/dist/client/specialists.js +0 -178
  588. package/dist/client/specialists.js.map +0 -1
  589. package/dist/client/tool-schema-loader.d.ts +0 -62
  590. package/dist/client/tool-schema-loader.d.ts.map +0 -1
  591. package/dist/client/tool-schema-loader.js +0 -232
  592. package/dist/client/tool-schema-loader.js.map +0 -1
  593. package/dist/client/types.d.ts +0 -327
  594. package/dist/client/types.d.ts.map +0 -1
  595. package/dist/client/types.js +0 -121
  596. package/dist/client/types.js.map +0 -1
  597. package/dist/commands/seed-config.d.ts +0 -9
  598. package/dist/commands/seed-config.d.ts.map +0 -1
  599. package/dist/commands/seed-config.js +0 -377
  600. package/dist/commands/seed-config.js.map +0 -1
  601. package/dist/commands/setup.d.ts +0 -11
  602. package/dist/commands/setup.d.ts.map +0 -1
  603. package/dist/commands/setup.js +0 -320
  604. package/dist/commands/setup.js.map +0 -1
  605. package/dist/lib/discussion-lock.d.ts +0 -42
  606. package/dist/lib/discussion-lock.d.ts.map +0 -1
  607. package/dist/lib/discussion-lock.js +0 -110
  608. package/dist/lib/discussion-lock.js.map +0 -1
  609. package/dist/mcp/signal-handler.d.ts +0 -82
  610. package/dist/mcp/signal-handler.d.ts.map +0 -1
  611. package/dist/mcp/signal-handler.js +0 -406
  612. package/dist/mcp/signal-handler.js.map +0 -1
  613. package/dist/mcp/tools/__tests__/discussion-forward.test.d.ts +0 -2
  614. package/dist/mcp/tools/__tests__/discussion-forward.test.d.ts.map +0 -1
  615. package/dist/mcp/tools/__tests__/discussion-forward.test.js +0 -218
  616. package/dist/mcp/tools/__tests__/discussion-forward.test.js.map +0 -1
  617. package/dist/mcp/tools/app-member.d.ts +0 -14
  618. package/dist/mcp/tools/app-member.d.ts.map +0 -1
  619. package/dist/mcp/tools/app-member.js +0 -195
  620. package/dist/mcp/tools/app-member.js.map +0 -1
  621. package/dist/mcp/tools/app-scaffold.d.ts +0 -14
  622. package/dist/mcp/tools/app-scaffold.d.ts.map +0 -1
  623. package/dist/mcp/tools/app-scaffold.js +0 -581
  624. package/dist/mcp/tools/app-scaffold.js.map +0 -1
  625. package/dist/mcp/tools/bot-config/constants.d.ts +0 -23
  626. package/dist/mcp/tools/bot-config/constants.d.ts.map +0 -1
  627. package/dist/mcp/tools/bot-config/constants.js +0 -94
  628. package/dist/mcp/tools/bot-config/constants.js.map +0 -1
  629. package/dist/mcp/tools/bot-config/core.d.ts +0 -253
  630. package/dist/mcp/tools/bot-config/core.d.ts.map +0 -1
  631. package/dist/mcp/tools/bot-config/core.js +0 -2456
  632. package/dist/mcp/tools/bot-config/core.js.map +0 -1
  633. package/dist/mcp/tools/bot-config/index.d.ts +0 -10
  634. package/dist/mcp/tools/bot-config/index.d.ts.map +0 -1
  635. package/dist/mcp/tools/bot-config/index.js +0 -59
  636. package/dist/mcp/tools/bot-config/index.js.map +0 -1
  637. package/dist/mcp/tools/bot-config/tools.d.ts +0 -7
  638. package/dist/mcp/tools/bot-config/tools.d.ts.map +0 -1
  639. package/dist/mcp/tools/bot-config/tools.js +0 -15
  640. package/dist/mcp/tools/bot-config/tools.js.map +0 -1
  641. package/dist/mcp/tools/bot-config/types.d.ts +0 -50
  642. package/dist/mcp/tools/bot-config/types.d.ts.map +0 -1
  643. package/dist/mcp/tools/bot-config/types.js +0 -6
  644. package/dist/mcp/tools/bot-config/types.js.map +0 -1
  645. package/dist/mcp/tools/bug-fixer-tools.d.ts +0 -45
  646. package/dist/mcp/tools/bug-fixer-tools.d.ts.map +0 -1
  647. package/dist/mcp/tools/bug-fixer-tools.js +0 -1096
  648. package/dist/mcp/tools/bug-fixer-tools.js.map +0 -1
  649. package/dist/mcp/tools/document.d.ts +0 -11
  650. package/dist/mcp/tools/document.d.ts.map +0 -1
  651. package/dist/mcp/tools/document.js +0 -741
  652. package/dist/mcp/tools/document.js.map +0 -1
  653. package/dist/mcp/tools/investigate.d.ts +0 -9
  654. package/dist/mcp/tools/investigate.d.ts.map +0 -1
  655. package/dist/mcp/tools/investigate.js +0 -254
  656. package/dist/mcp/tools/investigate.js.map +0 -1
  657. package/dist/mcp/utils/pagination.d.ts +0 -40
  658. package/dist/mcp/utils/pagination.d.ts.map +0 -1
  659. package/dist/mcp/utils/pagination.js +0 -55
  660. package/dist/mcp/utils/pagination.js.map +0 -1
  661. package/dist/modules/bug-reports/bug-config.d.ts +0 -25
  662. package/dist/modules/bug-reports/bug-config.d.ts.map +0 -1
  663. package/dist/modules/bug-reports/bug-config.js +0 -187
  664. package/dist/modules/bug-reports/bug-config.js.map +0 -1
  665. package/dist/modules/bug-reports/bug-monitor.d.ts +0 -108
  666. package/dist/modules/bug-reports/bug-monitor.d.ts.map +0 -1
  667. package/dist/modules/bug-reports/bug-monitor.js +0 -510
  668. package/dist/modules/bug-reports/bug-monitor.js.map +0 -1
  669. package/dist/modules/bug-reports/giuseppe-agent.d.ts +0 -58
  670. package/dist/modules/bug-reports/giuseppe-agent.d.ts.map +0 -1
  671. package/dist/modules/bug-reports/giuseppe-agent.js +0 -467
  672. package/dist/modules/bug-reports/giuseppe-agent.js.map +0 -1
  673. package/dist/modules/bug-reports/giuseppe-ai.d.ts +0 -83
  674. package/dist/modules/bug-reports/giuseppe-ai.d.ts.map +0 -1
  675. package/dist/modules/bug-reports/giuseppe-ai.js +0 -466
  676. package/dist/modules/bug-reports/giuseppe-ai.js.map +0 -1
  677. package/dist/modules/bug-reports/giuseppe-bot.d.ts +0 -110
  678. package/dist/modules/bug-reports/giuseppe-bot.d.ts.map +0 -1
  679. package/dist/modules/bug-reports/giuseppe-bot.js +0 -804
  680. package/dist/modules/bug-reports/giuseppe-bot.js.map +0 -1
  681. package/dist/modules/bug-reports/giuseppe-daemon.d.ts +0 -80
  682. package/dist/modules/bug-reports/giuseppe-daemon.d.ts.map +0 -1
  683. package/dist/modules/bug-reports/giuseppe-daemon.js +0 -617
  684. package/dist/modules/bug-reports/giuseppe-daemon.js.map +0 -1
  685. package/dist/modules/bug-reports/giuseppe-files.d.ts +0 -64
  686. package/dist/modules/bug-reports/giuseppe-files.d.ts.map +0 -1
  687. package/dist/modules/bug-reports/giuseppe-files.js +0 -375
  688. package/dist/modules/bug-reports/giuseppe-files.js.map +0 -1
  689. package/dist/modules/bug-reports/giuseppe-git.d.ts +0 -48
  690. package/dist/modules/bug-reports/giuseppe-git.d.ts.map +0 -1
  691. package/dist/modules/bug-reports/giuseppe-git.js +0 -298
  692. package/dist/modules/bug-reports/giuseppe-git.js.map +0 -1
  693. package/dist/modules/bug-reports/giuseppe-lsp.d.ts +0 -113
  694. package/dist/modules/bug-reports/giuseppe-lsp.d.ts.map +0 -1
  695. package/dist/modules/bug-reports/giuseppe-lsp.js +0 -485
  696. package/dist/modules/bug-reports/giuseppe-lsp.js.map +0 -1
  697. package/dist/modules/bug-reports/giuseppe-prompt.d.ts +0 -5
  698. package/dist/modules/bug-reports/giuseppe-prompt.d.ts.map +0 -1
  699. package/dist/modules/bug-reports/giuseppe-prompt.js +0 -94
  700. package/dist/modules/bug-reports/giuseppe-prompt.js.map +0 -1
  701. package/dist/modules/bug-reports/index.d.ts +0 -77
  702. package/dist/modules/bug-reports/index.d.ts.map +0 -1
  703. package/dist/modules/bug-reports/index.js +0 -215
  704. package/dist/modules/bug-reports/index.js.map +0 -1
  705. package/dist/modules/bug-reports/pending-classification-registry.d.ts +0 -28
  706. package/dist/modules/bug-reports/pending-classification-registry.d.ts.map +0 -1
  707. package/dist/modules/bug-reports/pending-classification-registry.js +0 -50
  708. package/dist/modules/bug-reports/pending-classification-registry.js.map +0 -1
  709. package/dist/modules/bug-reports/pending-fix-registry.d.ts +0 -30
  710. package/dist/modules/bug-reports/pending-fix-registry.d.ts.map +0 -1
  711. package/dist/modules/bug-reports/pending-fix-registry.js +0 -42
  712. package/dist/modules/bug-reports/pending-fix-registry.js.map +0 -1
  713. package/dist/modules/bug-reports/pending-registry.d.ts +0 -27
  714. package/dist/modules/bug-reports/pending-registry.d.ts.map +0 -1
  715. package/dist/modules/bug-reports/pending-registry.js +0 -49
  716. package/dist/modules/bug-reports/pending-registry.js.map +0 -1
  717. package/dist/modules/bug-reports/types.d.ts +0 -123
  718. package/dist/modules/bug-reports/types.d.ts.map +0 -1
  719. package/dist/modules/bug-reports/types.js +0 -9
  720. package/dist/modules/bug-reports/types.js.map +0 -1
  721. package/dist/plugins/bug-fixer/index.d.ts +0 -2
  722. package/dist/plugins/bug-fixer/index.d.ts.map +0 -1
  723. package/dist/plugins/bug-fixer/index.js +0 -18
  724. package/dist/plugins/bug-fixer/index.js.map +0 -1
  725. package/dist/plugins/bug-fixer/tools.d.ts +0 -45
  726. package/dist/plugins/bug-fixer/tools.d.ts.map +0 -1
  727. package/dist/plugins/bug-fixer/tools.js +0 -1096
  728. package/dist/plugins/bug-fixer/tools.js.map +0 -1
  729. package/dist/plugins/vipunen/__tests__/tools.test.d.ts +0 -10
  730. package/dist/plugins/vipunen/__tests__/tools.test.d.ts.map +0 -1
  731. package/dist/plugins/vipunen/__tests__/tools.test.js +0 -646
  732. package/dist/plugins/vipunen/__tests__/tools.test.js.map +0 -1
  733. package/dist/routes/agents.d.ts +0 -44
  734. package/dist/routes/agents.d.ts.map +0 -1
  735. package/dist/routes/agents.js +0 -311
  736. package/dist/routes/agents.js.map +0 -1
  737. package/dist/services/agent-credential-store.d.ts +0 -73
  738. package/dist/services/agent-credential-store.d.ts.map +0 -1
  739. package/dist/services/agent-credential-store.js +0 -212
  740. package/dist/services/agent-credential-store.js.map +0 -1
  741. package/dist/stdio-server.d.ts +0 -14
  742. package/dist/stdio-server.d.ts.map +0 -1
  743. package/dist/stdio-server.js +0 -101
  744. package/dist/stdio-server.js.map +0 -1
  745. package/dist/workspace/context.d.ts +0 -148
  746. package/dist/workspace/context.d.ts.map +0 -1
  747. package/dist/workspace/context.js +0 -339
  748. package/dist/workspace/context.js.map +0 -1
  749. package/dist/workspace/credentials.d.ts +0 -55
  750. package/dist/workspace/credentials.d.ts.map +0 -1
  751. package/dist/workspace/credentials.js +0 -239
  752. package/dist/workspace/credentials.js.map +0 -1
  753. package/dist/workspace/index.d.ts +0 -21
  754. package/dist/workspace/index.d.ts.map +0 -1
  755. package/dist/workspace/index.js +0 -45
  756. package/dist/workspace/index.js.map +0 -1
  757. package/dist/workspace/loader.d.ts +0 -27
  758. package/dist/workspace/loader.d.ts.map +0 -1
  759. package/dist/workspace/loader.js +0 -222
  760. package/dist/workspace/loader.js.map +0 -1
  761. package/dist/workspace/schema.d.ts +0 -37
  762. package/dist/workspace/schema.d.ts.map +0 -1
  763. package/dist/workspace/schema.js +0 -192
  764. package/dist/workspace/schema.js.map +0 -1
package/dist/bot/bot.js CHANGED
@@ -9,13 +9,49 @@
9
9
  * - buildSystemPrompt: LLM system prompt construction
10
10
  * - ConversationManager, MessageClassifier, MessageFormatterService, etc.
11
11
  */
12
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
13
+ if (k2 === undefined) k2 = k;
14
+ var desc = Object.getOwnPropertyDescriptor(m, k);
15
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
16
+ desc = { enumerable: true, get: function() { return m[k]; } };
17
+ }
18
+ Object.defineProperty(o, k2, desc);
19
+ }) : (function(o, m, k, k2) {
20
+ if (k2 === undefined) k2 = k;
21
+ o[k2] = m[k];
22
+ }));
23
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
24
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
25
+ }) : function(o, v) {
26
+ o["default"] = v;
27
+ });
28
+ var __importStar = (this && this.__importStar) || (function () {
29
+ var ownKeys = function(o) {
30
+ ownKeys = Object.getOwnPropertyNames || function (o) {
31
+ var ar = [];
32
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
33
+ return ar;
34
+ };
35
+ return ownKeys(o);
36
+ };
37
+ return function (mod) {
38
+ if (mod && mod.__esModule) return mod;
39
+ var result = {};
40
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
41
+ __setModuleDefault(result, mod);
42
+ return result;
43
+ };
44
+ })();
12
45
  var __importDefault = (this && this.__importDefault) || function (mod) {
13
46
  return (mod && mod.__esModule) ? mod : { "default": mod };
14
47
  };
15
48
  Object.defineProperty(exports, "__esModule", { value: true });
16
- exports.Bot = void 0;
49
+ exports.Bot = exports.ActivityGoneError = void 0;
50
+ const v8 = __importStar(require("v8"));
17
51
  const sdk_1 = __importDefault(require("@anthropic-ai/sdk"));
18
52
  const tool_registry_1 = require("../mcp/tool-registry");
53
+ const tool_profiles_1 = require("../mcp/tool-profiles");
54
+ const hailer_rpc_1 = require("../mcp/hailer-rpc");
19
55
  const hailer_clients_1 = require("../mcp/hailer-clients");
20
56
  const hailer_api_client_1 = require("../mcp/utils/hailer-api-client");
21
57
  const types_1 = require("../mcp/utils/types");
@@ -24,43 +60,190 @@ const tool_executor_1 = require("./tool-executor");
24
60
  const workspace_overview_1 = require("./workspace-overview");
25
61
  const operation_logger_1 = require("./operation-logger");
26
62
  const services_1 = require("./services");
63
+ const bot_config_1 = require("../bot-config");
27
64
  const logger_1 = require("../lib/logger");
65
+ const config_1 = require("../config");
28
66
  // ===== CONSTANTS =====
67
+ /**
68
+ * Parse the optional `seedContext` field on the bot config — a JSON array
69
+ * of prior chat turns from the public demo — into Anthropic message
70
+ * params suitable for prepending to the self-intro request. Caps the
71
+ * count so a misbehaving caller can't blow the context budget.
72
+ *
73
+ * Returns `[]` for missing, malformed, or empty input; the bot falls
74
+ * back to the generic intro path in that case.
75
+ */
76
+ const SEED_TURNS_MAX = 24;
77
+ function parseSeedTurns(raw, log) {
78
+ const empty = { turns: [], viewedSlides: [] };
79
+ if (!raw) {
80
+ return empty;
81
+ }
82
+ let parsed;
83
+ try {
84
+ parsed = JSON.parse(raw);
85
+ }
86
+ catch (err) {
87
+ log.warn('seedContext: JSON parse failed — skipping', {
88
+ err: err instanceof Error ? err.message : String(err),
89
+ });
90
+ return empty;
91
+ }
92
+ // Two supported shapes:
93
+ // - bare array of {role, content} turns (legacy)
94
+ // - object { turns: [...], viewedSlides: [...] } (current)
95
+ let turnSource;
96
+ let viewedSlides = [];
97
+ if (Array.isArray(parsed)) {
98
+ turnSource = parsed;
99
+ }
100
+ else if (parsed && typeof parsed === 'object') {
101
+ turnSource = parsed.turns;
102
+ const slidesRaw = parsed.viewedSlides;
103
+ if (Array.isArray(slidesRaw)) {
104
+ viewedSlides = slidesRaw.filter((id) => typeof id === 'string' && id.length > 0);
105
+ }
106
+ }
107
+ if (!Array.isArray(turnSource)) {
108
+ return { turns: [], viewedSlides };
109
+ }
110
+ const turns = [];
111
+ for (const item of turnSource) {
112
+ if (!item || typeof item !== 'object') {
113
+ continue;
114
+ }
115
+ const role = item.role;
116
+ const content = item.content;
117
+ if ((role !== 'user' && role !== 'assistant') || typeof content !== 'string' || !content) {
118
+ continue;
119
+ }
120
+ turns.push({ role, content });
121
+ if (turns.length >= SEED_TURNS_MAX) {
122
+ break;
123
+ }
124
+ }
125
+ return { turns, viewedSlides };
126
+ }
127
+ /**
128
+ * Thrown by Bot.start() when the bot's own Agent Directory activity has been
129
+ * deleted in Hailer. BotManager catches this and discards the bot without
130
+ * adding it to the running set; the entry has already been removed from
131
+ * .bot-config/{workspaceId}.json by the time this is thrown.
132
+ */
133
+ class ActivityGoneError extends Error {
134
+ activityId;
135
+ workspaceId;
136
+ constructor(activityId, workspaceId) {
137
+ super(`Activity ${activityId} no longer exists in workspace ${workspaceId}`);
138
+ this.activityId = activityId;
139
+ this.workspaceId = workspaceId;
140
+ this.name = 'ActivityGoneError';
141
+ }
142
+ }
143
+ exports.ActivityGoneError = ActivityGoneError;
29
144
  const WRITE_TOOLS = new Set(['create_activity', 'update_activity']);
30
145
  const DISCUSSION_TOOLS = new Set([
31
146
  'fetch_discussion_messages', 'fetch_previous_discussion_messages',
32
147
  'add_discussion_message', 'invite_discussion_members', 'get_activity_from_discussion',
33
148
  ]);
34
- const BOT_TOOLS = new Set([
35
- 'list_workflows', 'list_workflows_minimal', 'list_workflow_phases', 'get_workflow_schema',
36
- 'list_activities', 'show_activity_by_id', 'count_activities',
37
- 'search_workspace_users', 'get_workspace_balance',
38
- 'create_activity', 'update_activity',
39
- 'install_workflow',
40
- 'list_my_discussions', 'fetch_discussion_messages', 'fetch_previous_discussion_messages',
41
- 'add_discussion_message', 'join_discussion', 'leave_discussion',
42
- 'invite_discussion_members', 'get_activity_from_discussion',
43
- 'upload_files', 'download_file',
44
- 'list_insights', 'get_insight_data', 'preview_insight', 'create_insight', 'update_insight',
45
- 'list_workflow_permissions', 'check_user_permissions',
46
- 'grant_workflow_permission', 'revoke_workflow_permission',
47
- 'resolve_date',
48
- ]);
49
- const MODEL_HAIKU = 'claude-haiku-4-5-20251001';
50
- const MODEL_SONNET = 'claude-sonnet-4-5-20250929';
149
+ const MODEL_HAIKU = 'claude-haiku-4-5';
150
+ const MODEL_SONNET = 'claude-sonnet-4-6';
151
+ const MAX_TOOL_RESULT_CHARS = 40000;
152
+ const MAX_PROMPT_TRIM_ATTEMPTS = 5;
51
153
  const IMAGE_MIME_TYPES = new Set(['image/jpeg', 'image/png', 'image/gif', 'image/webp']);
52
154
  const DOCUMENT_MIME_TYPES = new Set(['application/pdf']);
53
155
  const TEXT_MIME_TYPES = new Set(['text/plain', 'text/csv', 'text/html', 'text/markdown', 'application/json', 'application/xml']);
156
+ const EXCEL_MIME_TYPES = new Set([
157
+ 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', // .xlsx only
158
+ ]);
159
+ const WORD_MIME_TYPES = new Set([
160
+ 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', // .docx
161
+ ]);
54
162
  const MAX_FILE_SIZE = 5 * 1024 * 1024;
163
+ const MAX_OFFICE_FILE_SIZE = 10 * 1024 * 1024;
164
+ const OFFICE_TEXT_CAP = 512 * 1024;
165
+ const HEAP_BACKPRESSURE_THRESHOLD = 0.7;
166
+ function fileSizeLimit(mime) {
167
+ return EXCEL_MIME_TYPES.has(mime) || WORD_MIME_TYPES.has(mime) ? MAX_OFFICE_FILE_SIZE : MAX_FILE_SIZE;
168
+ }
169
+ const ATTACHMENT_KINDS = [
170
+ { label: 'Image', trailing: 'included below for vision', matches: (mimeType) => IMAGE_MIME_TYPES.has(mimeType) },
171
+ { label: 'Document', trailing: 'included below', matches: (mimeType) => DOCUMENT_MIME_TYPES.has(mimeType) || TEXT_MIME_TYPES.has(mimeType) },
172
+ { label: 'Spreadsheet', trailing: 'included below as CSV per sheet', matches: (mimeType) => EXCEL_MIME_TYPES.has(mimeType) },
173
+ { label: 'Word document', trailing: 'included below as plain text', matches: (mimeType) => WORD_MIME_TYPES.has(mimeType) },
174
+ ];
175
+ function describeAttachment(mime, filename, fileId) {
176
+ const matched = ATTACHMENT_KINDS.find((kind) => kind.matches(mime));
177
+ if (!matched) {
178
+ return null;
179
+ }
180
+ return `[${matched.label} attached: ${filename} (fileId: ${fileId}) — ${matched.trailing}]`;
181
+ }
182
+ function isSupportedMime(mime) {
183
+ return IMAGE_MIME_TYPES.has(mime) || DOCUMENT_MIME_TYPES.has(mime) || TEXT_MIME_TYPES.has(mime)
184
+ || EXCEL_MIME_TYPES.has(mime) || WORD_MIME_TYPES.has(mime);
185
+ }
186
+ function isOfficeMime(mime) {
187
+ return EXCEL_MIME_TYPES.has(mime) || WORD_MIME_TYPES.has(mime);
188
+ }
189
+ function capText(text) {
190
+ return text.length > OFFICE_TEXT_CAP ? text.slice(0, OFFICE_TEXT_CAP) + '\n\n[...content truncated...]' : text;
191
+ }
192
+ function isHeapUnderPressure() {
193
+ const { heapUsed } = process.memoryUsage();
194
+ const heapLimit = v8.getHeapStatistics().heap_size_limit;
195
+ return heapUsed / heapLimit > HEAP_BACKPRESSURE_THRESHOLD;
196
+ }
197
+ function cellToCsv(value) {
198
+ if (value === null || value === undefined) {
199
+ return '';
200
+ }
201
+ if (value instanceof Date) {
202
+ return value.toISOString();
203
+ }
204
+ if (typeof value === 'object') {
205
+ const v = value;
206
+ if (typeof v.result !== 'undefined') {
207
+ return cellToCsv(v.result);
208
+ }
209
+ if (typeof v.text === 'string') {
210
+ return cellToCsv(v.text);
211
+ }
212
+ if (Array.isArray(v.richText)) {
213
+ return v.richText.map((rt) => rt.text || '').join('');
214
+ }
215
+ if (typeof v.error === 'string') {
216
+ return v.error;
217
+ }
218
+ return '';
219
+ }
220
+ const s = String(value);
221
+ return /[",\n]/.test(s) ? `"${s.replace(/"/g, '""')}"` : s;
222
+ }
223
+ // Global mutex — serialize Office downloads + parses across the pod to bound peak memory
224
+ let officeParseQueue = Promise.resolve();
225
+ function withOfficeParseLock(fn) {
226
+ const next = officeParseQueue.then(fn, fn);
227
+ officeParseQueue = next.catch(() => undefined);
228
+ return next;
229
+ }
230
+ const SONNET_ROUTE = { model: MODEL_SONNET, maxTokens: 16384 };
55
231
  const TOOL_STATUS_LABELS = {
56
- list_activities: 'Searching activities', count_activities: 'Counting activities',
232
+ list_activities: 'Searching activities',
57
233
  show_activity_by_id: 'Reading activity', create_activity: 'Creating activity',
58
- update_activity: 'Updating activity', list_workflows: 'Loading workflows',
59
- list_workflows_minimal: 'Loading workflows', get_workflow_schema: 'Reading workflow schema',
60
- list_workflow_phases: 'Loading phases', preview_insight: 'Running query',
61
- get_insight_data: 'Running report', search_workspace_users: 'Searching users',
234
+ update_activity: 'Updating activity',
235
+ describe_workflows: 'Reading workflows',
236
+ update_workflow_structure: 'Updating workflow structure',
237
+ run_insight: 'Running report', save_insight: 'Saving report',
238
+ search_workspace_users: 'Searching users',
62
239
  fetch_discussion_messages: 'Reading messages', add_discussion_message: 'Sending message',
63
240
  join_discussion: 'Joining discussion',
241
+ query_events: 'Loading events', manage_calendar: 'Managing calendars',
242
+ create_event: 'Creating event',
243
+ update_event: 'Updating event', delete_event: 'Deleting event',
244
+ respond_to_invite: 'Responding to invite',
245
+ set_workflow_permission: 'Updating workflow access',
246
+ manage_my_profile: 'Updating my profile',
64
247
  };
65
248
  // ===== BOT CLASS =====
66
249
  class Bot {
@@ -97,37 +280,47 @@ class Bot {
97
280
  workspaceUpdatedHandler = null;
98
281
  cacheInvalidateHandler = null;
99
282
  _connected = false;
100
- // Config
101
283
  config;
284
+ anthropicApiKey;
102
285
  botManager;
103
- constructor(config) {
286
+ constructor(config, runtime) {
104
287
  this.config = {
105
- email: config.email, password: config.password, apiHost: config.apiHost,
106
- anthropicApiKey: config.anthropicApiKey,
107
- model: config.model || MODEL_HAIKU,
108
- toolRegistry: config.toolRegistry,
109
- workspaceId: config.workspaceId, systemPrompt: config.systemPrompt,
110
- accessLevel: config.accessLevel || 'all',
111
- allowedWorkflows: config.allowedWorkflows || [],
112
- allowBotMessages: config.allowBotMessages || false,
288
+ ...config,
289
+ accessLevel: config.accessLevel ?? 'all',
290
+ allowedWorkflows: config.allowedWorkflows ?? [],
291
+ allowBotMessages: config.allowBotMessages ?? false,
292
+ helperMode: config.helperMode ?? false,
113
293
  };
114
- this.botManager = config.botManager || null;
294
+ this.anthropicApiKey = runtime.anthropicApiKey;
295
+ this.botManager = runtime.botManager ?? null;
115
296
  this._systemPrompt = config.systemPrompt;
116
- this._responseMode = config.responseMode || 'always';
297
+ this._responseMode = config.responseMode ?? 'always';
117
298
  this.logger = (0, logger_1.createLogger)({ component: 'Bot' });
118
299
  this.clientManager = new hailer_clients_1.HailerClientManager(config.apiHost, config.email, config.password);
119
- this.toolExecutor = new tool_executor_1.ToolExecutor(config.toolRegistry);
300
+ this.toolExecutor = new tool_executor_1.ToolExecutor(runtime.toolRegistry);
120
301
  this.signalRouter = new services_1.SignalRouter(this.logger);
121
302
  this.permissions = new services_1.BotPermissions(this.config.allowedWorkflows, this.logger);
122
303
  this.workspaceRefresh = new services_1.WorkspaceRefresh(this.logger);
123
304
  }
124
305
  // Public accessors (used by BotManager for hot-reload)
125
- get email() { return this.config.email; }
126
- get password() { return this.config.password; }
127
- get accessLevel() { return this.config.accessLevel; }
128
- get connected() { return this._connected; }
129
- get workspaceId() { return this._workspaceId; }
130
- get botUserId() { return this.userId; }
306
+ get email() {
307
+ return this.config.email;
308
+ }
309
+ get password() {
310
+ return this.config.password;
311
+ }
312
+ get accessLevel() {
313
+ return this.config.accessLevel;
314
+ }
315
+ get connected() {
316
+ return this._connected;
317
+ }
318
+ get workspaceId() {
319
+ return this._workspaceId;
320
+ }
321
+ get botUserId() {
322
+ return this.userId;
323
+ }
131
324
  updateSystemPrompt(prompt) {
132
325
  this._systemPrompt = prompt;
133
326
  this.logger.info('System prompt updated live', { hasPrompt: !!prompt });
@@ -136,21 +329,88 @@ class Bot {
136
329
  this._responseMode = mode || 'always';
137
330
  this.logger.info('Response mode updated live', { responseMode: this._responseMode });
138
331
  }
332
+ updateHelperMode(helperMode) {
333
+ this.config.helperMode = !!helperMode;
334
+ this.logger.info('Helper mode updated live', { helperMode: this.config.helperMode });
335
+ }
139
336
  // ===== LIFECYCLE =====
140
337
  async start() {
141
- if (this._connected)
338
+ if (this._connected) {
142
339
  return;
340
+ }
143
341
  this.logger.debug('Starting bot', { email: this.config.email });
144
342
  // 1. Connect
145
343
  this.client = await this.clientManager.connect();
146
344
  this.config.password = ''; // Clear from memory — connection is established
147
345
  // 2. Fetch workspace data + user in one call
148
- this.init = await this.client.socket.request('v2.core.init', [
149
- ['user', 'processes', 'users', 'network', 'networks', 'teams', 'groups'],
150
- ]);
346
+ const initFields = ['user', 'processes', 'users', 'network', 'networks', 'teams', 'groups'];
347
+ this.init = await this.client.socket.request(hailer_rpc_1.HailerRpc.Core.init, [initFields]);
348
+ try {
349
+ const pendingInvites = await this.client.socket.request(hailer_rpc_1.HailerRpc.User.inviteList, []);
350
+ if (pendingInvites?.length) {
351
+ for (const invite of pendingInvites) {
352
+ await this.client.socket.request(hailer_rpc_1.HailerRpc.User.inviteAccept, [invite.invite_key]);
353
+ await this.client.socket.request(hailer_rpc_1.HailerRpc.Core.switchEcosystem, [invite.cid]);
354
+ this.logger.info('Accepted workspace invite', { workspaceId: invite.cid, workspaceName: invite.network?.name });
355
+ }
356
+ this.init = await this.client.socket.request(hailer_rpc_1.HailerRpc.Core.init, [initFields]);
357
+ }
358
+ }
359
+ catch (err) {
360
+ this.logger.warn('Failed to check/accept pending invites', { error: err instanceof Error ? err.message : err });
361
+ }
362
+ // Hailer drops password-auth users into their personal "My Hailer" ecosystem
363
+ // on each fresh login, even after they've accepted a workspace invite. Force
364
+ // the configured workspace as the active ecosystem so the bot operates where
365
+ // it was provisioned, not in its personal workspace.
366
+ if (this.config.workspaceId && this.init.network?._id !== this.config.workspaceId) {
367
+ const fromWorkspaceId = this.init.network?._id;
368
+ try {
369
+ await this.client.socket.request(hailer_rpc_1.HailerRpc.Core.switchEcosystem, [this.config.workspaceId]);
370
+ this.init = await this.client.socket.request(hailer_rpc_1.HailerRpc.Core.init, [initFields]);
371
+ this.logger.info('Switched to configured workspace', {
372
+ from: fromWorkspaceId, to: this.config.workspaceId,
373
+ });
374
+ }
375
+ catch (err) {
376
+ this.logger.warn('Failed to switch to configured workspace', {
377
+ workspaceId: this.config.workspaceId,
378
+ error: err instanceof Error ? err.message : err,
379
+ });
380
+ }
381
+ }
382
+ // Self-prune: probe the bot's own Agent Directory activity. If the
383
+ // activity is gone (definitively deleted OR otherwise unreachable in
384
+ // a way that matches the gone signals), drop the local config entry
385
+ // so we stop trying to run this bot. The bot's Hailer user account
386
+ // is NEVER deleted from here — a previous version did, and the
387
+ // classifier shared a numeric code with "Permission denied" which
388
+ // caused mass user-account deletion on transient permission errors.
389
+ // Orphaned bot users are reaped separately by Hailer's inactive-user
390
+ // prune (out-of-band).
391
+ if (this.config.activityId && this.config.workspaceId) {
392
+ try {
393
+ await this.client.socket.request(hailer_rpc_1.HailerRpc.Activities.load, [this.config.activityId]);
394
+ }
395
+ catch (err) {
396
+ const shape = (0, bot_config_1.extractHailerError)(err);
397
+ if ((0, bot_config_1.isActivityGone)(shape)) {
398
+ this.logger.info('Self-probe: activity gone — pruning local config entry (keeping Hailer user)', {
399
+ activityId: this.config.activityId, workspaceId: this.config.workspaceId,
400
+ msg: shape.msg, code: shape.code,
401
+ });
402
+ this.pruneSelfFromConfig();
403
+ throw new ActivityGoneError(this.config.activityId, this.config.workspaceId);
404
+ }
405
+ this.logger.debug('Self-probe non-deletion error — continuing startup', {
406
+ activityId: this.config.activityId, msg: shape.msg, code: shape.code,
407
+ });
408
+ }
409
+ }
151
410
  this.userId = this.init.user?._id || '';
152
- if (!this.userId)
411
+ if (!this.userId) {
153
412
  throw new Error('Could not determine bot user ID');
413
+ }
154
414
  (0, types_1.normalizeInitProcesses)(this.init);
155
415
  this._workspaceId = this.init.network?._id || this.config.workspaceId;
156
416
  // 3. Build caches
@@ -172,7 +432,7 @@ class Bot {
172
432
  workflowNames: this.init.processes.map(p => p.name),
173
433
  });
174
434
  // 4. Anthropic client
175
- this.anthropic = new sdk_1.default({ apiKey: this.config.anthropicApiKey });
435
+ this.anthropic = new sdk_1.default({ apiKey: this.anthropicApiKey });
176
436
  // 5. Services
177
437
  const botConnection = {
178
438
  client: this.client,
@@ -194,11 +454,13 @@ class Bot {
194
454
  email: this.config.email, password: '', // Intentionally empty — cleared after connect
195
455
  workspaceRoles: { [currentWorkspaceId]: 'admin' },
196
456
  currentWorkspaceId, allowedGroups: [tool_registry_1.ToolGroup.READ, tool_registry_1.ToolGroup.WRITE, tool_registry_1.ToolGroup.BOT_INTERNAL],
457
+ botActivityId: this.config.activityId,
197
458
  };
198
459
  // 7. Wire workspace refresh
199
460
  this.workspaceRefresh.setHandler(async (scopes) => {
200
- if (!this.client || !this.init)
461
+ if (!this.client || !this.init) {
201
462
  return;
463
+ }
202
464
  const result = await services_1.WorkspaceRefresh.refresh(this.client, scopes, this.init, this.config.workspaceId, this.permissions, this.userContext, this.logger);
203
465
  this.init = result.init;
204
466
  this.workspaceCache = result.workspaceCache;
@@ -206,10 +468,17 @@ class Bot {
206
468
  this._workspaceId = result.workspaceId;
207
469
  });
208
470
  // 8. Subscribe to signals
209
- this.signalHandler = (data) => this.handleSignal({
210
- type: 'messenger.new', data, timestamp: Date.now(),
211
- workspaceId: data.sid,
212
- });
471
+ this.signalHandler = (data) => {
472
+ this.logger.info('Bot received messenger.new signal', {
473
+ discussion: data.discussion,
474
+ uid: data.uid,
475
+ msg_id: data.msg_id,
476
+ });
477
+ this.handleSignal({
478
+ type: 'messenger.new', data, timestamp: Date.now(),
479
+ workspaceId: data.sid,
480
+ });
481
+ };
213
482
  this.clientManager.onSignal('messenger.new', this.signalHandler);
214
483
  this.processUpdatedHandler = () => this.workspaceRefresh.schedule('processes');
215
484
  this.workspaceUpdatedHandler = () => this.workspaceRefresh.schedule('network');
@@ -219,6 +488,285 @@ class Bot {
219
488
  this.clientManager.onSignal('cache.invalidate', this.cacheInvalidateHandler);
220
489
  this._connected = true;
221
490
  this.logger.debug('Bot started', { userId: this.userId, workspaceId: this._workspaceId });
491
+ // Fire-and-forget: re-assert that the bot is following its own
492
+ // activity discussion on every startup. The self-intro path used to be
493
+ // the only caller of joinActivityDiscussion, but it short-circuits on
494
+ // `introPosted: true`, leaving bots that were unfollowed in the past
495
+ // (e.g. by the pre-fix raw activities.follow toggle, or by any other
496
+ // path that flipped their follow state) silently subscribed to nothing.
497
+ // Running joinActivityDiscussion here closes that loop — it's
498
+ // idempotent (no-op if already following).
499
+ this.ensureFollowingOwnDiscussion().catch((err) => {
500
+ const { msg, code } = (0, bot_config_1.extractHailerError)(err);
501
+ this.logger.warn('ensureFollowingOwnDiscussion threw (non-fatal)', { msg, code });
502
+ });
503
+ // Fire-and-forget self-introduction. One-shot per bot (persisted via
504
+ // BotEntry.introPosted), so restarts don't re-spam the discussion. Errors
505
+ // are logged inside the method — this catch is only a safety net.
506
+ this.introduceSelfIfNeeded().catch((err) => {
507
+ const { msg, code } = (0, bot_config_1.extractHailerError)(err);
508
+ this.logger.warn('Self-intro threw (non-fatal)', { msg, code });
509
+ });
510
+ }
511
+ /**
512
+ * Re-join the bot's own activity discussion if (and only if) the bot has
513
+ * drifted out of it. Runs every startup so bots that lost their follow
514
+ * state (e.g. via the pre-51254a2 raw activities.follow toggle) recover.
515
+ *
516
+ * Reads the activity's `followers` list and skips the join when the bot's
517
+ * userId is already there. activities.follow is a toggle that emits a
518
+ * leave/join event on every call — even toggle-toggle pairs — so calling
519
+ * unconditionally pollutes the discussion with "left / joined" pairs on
520
+ * every restart (visible in the timeline after deploy → retire → deploy).
521
+ */
522
+ async ensureFollowingOwnDiscussion() {
523
+ if (!this.config.activityId || !this.hailerApi || !this.userId) {
524
+ return;
525
+ }
526
+ try {
527
+ const activity = await this.hailerApi.fetchActivityById(this.config.activityId);
528
+ const followers = Array.isArray(activity?.followers) ? activity.followers : [];
529
+ if (followers.includes(this.userId)) {
530
+ this.logger.debug('Already following own discussion — skipping toggle', {
531
+ activityId: this.config.activityId,
532
+ });
533
+ return;
534
+ }
535
+ await this.hailerApi.joinActivityDiscussion(this.config.activityId);
536
+ }
537
+ catch (err) {
538
+ const { msg, code } = (0, bot_config_1.extractHailerError)(err);
539
+ this.logger.debug('ensureFollowingOwnDiscussion failed (non-fatal)', { msg, code });
540
+ }
541
+ }
542
+ /**
543
+ * Post a one-time greeting in the bot's own activity discussion explaining
544
+ * what users can ask the bot to change about itself (system prompt, etc.).
545
+ * Marks the entry's `introPosted` flag in `.bot-config` so subsequent
546
+ * restarts don't repeat the message.
547
+ *
548
+ * Follow state is handled separately by ensureFollowingOwnDiscussion()
549
+ * which runs on every startup. We don't flip `introPosted` until the send
550
+ * succeeds, so a permission failure on first start retries on the next
551
+ * start instead of silently giving up.
552
+ */
553
+ async introduceSelfIfNeeded() {
554
+ if (!this.config.activityId || !this.config.workspaceId || !this.client) {
555
+ return;
556
+ }
557
+ const cfg = (0, bot_config_1.loadWorkspaceConfigFile)(this.config.workspaceId);
558
+ const entry = cfg.bots.find((b) => b.activityId === this.config.activityId);
559
+ if (!entry) {
560
+ return;
561
+ }
562
+ if (entry.introPosted) {
563
+ return;
564
+ }
565
+ let discussionId;
566
+ try {
567
+ const activity = await this.client.socket.request(hailer_rpc_1.HailerRpc.Activities.load, [this.config.activityId]);
568
+ discussionId = activity?.discussion;
569
+ }
570
+ catch (err) {
571
+ const { msg, code } = (0, bot_config_1.extractHailerError)(err);
572
+ this.logger.warn('Self-intro: activities.load failed', { msg, code });
573
+ return;
574
+ }
575
+ if (!discussionId) {
576
+ return;
577
+ }
578
+ if (!this.anthropic) {
579
+ return;
580
+ }
581
+ // Generate the intro via LLM so each bot speaks in its own voice. The
582
+ // bot's system prompt already explains its self-management capabilities,
583
+ // so a "pirate" bot greets in pirate voice while still mentioning users
584
+ // can change it.
585
+ const systemPrompt = (0, services_1.buildSystemPrompt)({
586
+ init: this.init, userId: this.userId,
587
+ workspaceOverview: this.workspaceOverview, customPrompt: this._systemPrompt,
588
+ helperMode: this.config.helperMode,
589
+ hasSeedContext: !!this.config.seedContext,
590
+ responseMode: this._responseMode,
591
+ accessLevel: this.config.accessLevel,
592
+ allowBotMessages: this.config.allowBotMessages,
593
+ });
594
+ const { turns: seedTurns, viewedSlides } = parseSeedTurns(this.config.seedContext, this.logger);
595
+ const hasSeed = seedTurns.length > 0;
596
+ // Map slide ids → short human labels for the prompt. Anything not in
597
+ // the map is dropped (defence against stale ids leaking through).
598
+ const SLIDE_LABEL = {
599
+ title: 'the Hailer overview cover',
600
+ what: 'what Hailer is in one line',
601
+ problem: 'the trackers-vs-chat problem framing',
602
+ 'core-label': 'the core-concepts section',
603
+ workspaces: 'Workspaces',
604
+ workflows: 'Workflows',
605
+ activities: 'Activities',
606
+ discussions: 'Discussions',
607
+ 'build-label': 'the build-and-extend section',
608
+ 'apps-studio': 'Apps & Hailer Studio',
609
+ sdk: 'the Hailer SDK',
610
+ 'sdk-code': 'the workflow-as-code example',
611
+ mcp: 'Hailer MCP',
612
+ insights: 'Insights & Automations',
613
+ closer: 'the closing one-platform statement',
614
+ };
615
+ const slideLabels = viewedSlides
616
+ .map((id) => SLIDE_LABEL[id])
617
+ .filter((s) => typeof s === 'string');
618
+ const slideHint = slideLabels.length > 0
619
+ ? `\n\nAdditional signal: during the demo the visitor explicitly opened these overview slides — ${slideLabels.join(', ')}. Treat that as an interest signal. Weight your concrete suggestions toward those concepts when the demo conversation is ambiguous, but don't read more into it than "they paid attention here."`
620
+ : '';
621
+ // Only promise an automatic build when Studio session creation is
622
+ // configured for this deployment; otherwise nothing builds the
623
+ // workspace and the bot must not promise a build that never runs. The
624
+ // graduation flow gates createStudioSession on the same env var, so
625
+ // "build promised" matches "build attempted".
626
+ const studioBuilding = !!config_1.environment.STUDIO_SESSIONS_CREATE_URL;
627
+ const introInstruction = hasSeed
628
+ ? (studioBuilding
629
+ ? `You are being posted in your own activity discussion for the first time. The user just graduated from a public demo chat with you — the messages above are the conversation you both had there.
630
+
631
+ What this first message needs to do:
632
+
633
+ 1. Greet them warmly and acknowledge you remember the demo. Be specific — name the thing they were exploring (e.g. "the plumbing-company job tracker you were sketching out" rather than "your business").
634
+
635
+ 2. Tell them what's happening RIGHT NOW: based on that conversation, their workspace is being set up for them automatically — the workflow(s) to run that process, a few sample records so they can see it in action, and a custom app on top. It takes a couple of minutes. Do NOT offer to build it yourself and do NOT ask "want me to set this up?" — it is already being built. You are not the one building it; just let them know it's underway.
636
+
637
+ 3. Tell them what comes next: as soon as the workflows are ready you'll walk them through their new workspace with a quick guided tour, so there's nothing they need to do yet — they can sit tight or keep chatting with you here.
638
+
639
+ 4. Mention in passing that they can shape how you behave (tone, persona, language, even your picture) just by asking you here, and that account-level settings live in the AI Hub app.
640
+
641
+ Tone: conversational, friendly, reassuring. No section headers, no bullet lists. Keep it under ~150 words.`
642
+ : `You are being posted in your own activity discussion for the first time. The user just graduated from a public demo chat with you — the messages above are the conversation you both had there. NOTE: there is no automatic workspace builder running in this deployment, so YOU are how they get set up.
643
+
644
+ What this first message needs to do:
645
+
646
+ 1. Greet them warmly and acknowledge you remember the demo. Be specific — name the thing they were exploring (e.g. "the plumbing-company job tracker you were sketching out" rather than "your business").
647
+
648
+ 2. Scan the demo for concrete setup intent — a process with stages, or a list of records they want to manage. Offer to set it up for them now: be concrete, naming the phases you'd create (e.g. Quoted → Scheduled → In Progress → Invoiced → Paid) for a lifecycle, or describing it as a simple list for reference data. End with a clear yes/no like "Want me to set this up?" — don't start building unilaterally.
649
+
650
+ 3. If the demo is too vague to start, ask ONE or TWO concrete clarifying questions instead.
651
+
652
+ 4. Mention in passing that they can shape how you behave (tone, persona, language, even your picture) just by asking you here, and that account-level settings live in the AI Hub app.
653
+
654
+ Tone: conversational, friendly, action-oriented. No section headers; short bullets are fine only when naming proposed phases or fields. Keep it under ~180 words.`)
655
+ : `You are being posted in your own activity discussion for the first time. Introduce yourself briefly in your own voice.
656
+
657
+ CRITICAL: do NOT invent a backstory or claim to be a real person, celebrity, or fictional character based on your name alone. Your name was just chosen by the user — they may have meant a specific person/character, or they may have just liked the sound of it. If you don't have explicit persona instructions, acknowledge your name but be honest that you're a fresh assistant without a defined persona yet, and ask what kind of assistant they want you to be (or invite them to configure you).
658
+
659
+ In all cases, let the user know they can change how you behave — your tone, persona, language, dos and donts, even your profile picture — just by asking you here in chat. They can also ask to see your current configuration. For account-level settings (credentials, who can talk to you, etc.) point them at the AI Hub app.
660
+
661
+ Tell them how to actually get your attention: describe your current response mode in one sentence (you can see it in <your-settings>). For example, if you only respond to mentions or replies, say so — otherwise they'll wonder why you're silent in shared discussions. Mention that they can switch you to a different mode in AI Hub if it doesn't suit them.
662
+
663
+ Keep it short and conversational. No bullet lists, no headers.`;
664
+ const introInstructionFinal = introInstruction + slideHint;
665
+ const messages = [
666
+ ...seedTurns,
667
+ { role: 'user', content: introInstructionFinal },
668
+ ];
669
+ let response;
670
+ try {
671
+ response = await this.anthropic.messages.create({
672
+ model: MODEL_HAIKU,
673
+ max_tokens: 400,
674
+ temperature: 0.7,
675
+ system: systemPrompt,
676
+ messages,
677
+ });
678
+ }
679
+ catch (err) {
680
+ this.logger.warn('Self-intro: LLM call failed', {
681
+ activityId: this.config.activityId,
682
+ error: err instanceof Error ? err.message : String(err),
683
+ });
684
+ return;
685
+ }
686
+ const text = response.content
687
+ .filter((b) => b.type === 'text')
688
+ .map((b) => b.text)
689
+ .join('')
690
+ .trim();
691
+ if (!text) {
692
+ this.logger.warn('Self-intro: empty LLM response', { activityId: this.config.activityId });
693
+ return;
694
+ }
695
+ // Bill the intro generation to the workspace — same as any other LLM call.
696
+ if (this.tokenBilling && this._workspaceId) {
697
+ const usage = response.usage;
698
+ const cacheCreation = usage.cache_creation_input_tokens || 0;
699
+ const cacheRead = usage.cache_read_input_tokens || 0;
700
+ const cost = this.tokenBilling.calculateCost(usage.input_tokens, usage.output_tokens, cacheCreation, cacheRead, MODEL_HAIKU);
701
+ this.tokenBilling.burnTokens({
702
+ workspaceId: this._workspaceId,
703
+ inputTokens: usage.input_tokens, outputTokens: usage.output_tokens,
704
+ cacheCreationTokens: cacheCreation, cacheReadTokens: cacheRead, costUsd: cost,
705
+ sessionId: discussionId, model: MODEL_HAIKU,
706
+ });
707
+ }
708
+ try {
709
+ await this.client.socket.request(hailer_rpc_1.HailerRpc.Messenger.send, [{ msg: text }, discussionId]);
710
+ }
711
+ catch (err) {
712
+ const { msg: errMsg, code } = (0, bot_config_1.extractHailerError)(err);
713
+ this.logger.warn('Self-intro: messenger.send failed', {
714
+ activityId: this.config.activityId,
715
+ discussionId,
716
+ msg: errMsg,
717
+ code,
718
+ });
719
+ return;
720
+ }
721
+ entry.introPosted = true;
722
+ (0, bot_config_1.saveWorkspaceConfigFile)(cfg);
723
+ (0, bot_config_1.invalidateConfigCache)();
724
+ this.logger.info('Posted self-intro in own discussion', {
725
+ activityId: this.config.activityId,
726
+ discussionId,
727
+ length: text.length,
728
+ });
729
+ }
730
+ /**
731
+ * Teardown: stop the bot's websocket and live state. We intentionally do
732
+ * NOT delete the Hailer user account from here — that was previously a
733
+ * source of mass user-account deletion when the gone-classifier fired on
734
+ * transient permission errors. Orphaned bot users are reaped out-of-band
735
+ * by Hailer's inactive-user prune.
736
+ */
737
+ async destroy() {
738
+ await this.stop();
739
+ }
740
+ /**
741
+ * Remove this bot's entry from .bot-config/{workspaceId}.json. Called when
742
+ * the bot's own activity has been deleted in Hailer (detected via the
743
+ * self-probe in start()). Idempotent — safe if the entry is already gone.
744
+ */
745
+ pruneSelfFromConfig() {
746
+ if (!this.config.activityId || !this.config.workspaceId) {
747
+ return;
748
+ }
749
+ try {
750
+ const cfg = (0, bot_config_1.loadWorkspaceConfigFile)(this.config.workspaceId);
751
+ const before = cfg.bots.length;
752
+ cfg.bots = cfg.bots.filter((b) => b.activityId !== this.config.activityId);
753
+ if (cfg.bots.length === before) {
754
+ return;
755
+ }
756
+ (0, bot_config_1.saveWorkspaceConfigFile)(cfg);
757
+ (0, bot_config_1.invalidateConfigCache)();
758
+ this.logger.info('Pruned self from bot config', {
759
+ activityId: this.config.activityId,
760
+ workspaceId: this.config.workspaceId,
761
+ remaining: cfg.bots.length,
762
+ });
763
+ }
764
+ catch (err) {
765
+ this.logger.warn('Failed to prune self from bot config', {
766
+ activityId: this.config.activityId,
767
+ error: err instanceof Error ? err.message : err,
768
+ });
769
+ }
222
770
  }
223
771
  async stop() {
224
772
  this.logger.debug('Stopping bot');
@@ -247,8 +795,9 @@ class Bot {
247
795
  }
248
796
  // ===== SIGNAL HANDLING =====
249
797
  async handleSignal(signal) {
250
- if (!this._connected || !this.messageClassifier)
798
+ if (!this._connected || !this.messageClassifier) {
251
799
  return;
800
+ }
252
801
  try {
253
802
  const rawMsgId = signal.data.msg_id;
254
803
  const discussionId = signal.data.discussion;
@@ -257,23 +806,27 @@ class Bot {
257
806
  this.logger.warn('messenger.new signal has no dedup key');
258
807
  return;
259
808
  }
260
- if (this.signalRouter.isDuplicate(dedupKey))
809
+ if (this.signalRouter.isDuplicate(dedupKey)) {
261
810
  return;
811
+ }
262
812
  const message = await this.messageClassifier.extractIncomingMessage(signal);
263
813
  if (!message) {
264
- if (rawMsgId)
814
+ if (rawMsgId) {
265
815
  this.signalRouter.removeDedupKey(rawMsgId);
816
+ }
266
817
  return;
267
818
  }
268
819
  // Self-message guard — always skip own messages
269
- if (message.senderId === this.userId)
820
+ if (message.senderId === this.userId) {
270
821
  return;
822
+ }
271
823
  // Bot-to-bot guard
272
824
  if (this.botManager && this._workspaceId) {
273
825
  const botUserIds = this.botManager.getBotUserIdsForWorkspace(this._workspaceId);
274
826
  if (botUserIds.has(message.senderId)) {
275
- if (!this.config.allowBotMessages)
276
- return; // Hard block if not opted in
827
+ if (!this.config.allowBotMessages) {
828
+ return;
829
+ } // Hard block if not opted in
277
830
  // Only respond to bot messages if explicitly mentioned or replied to
278
831
  if (!message.isMention && !message.isReplyToBot) {
279
832
  this.logger.debug('Ignoring bot message - no mention or reply', {
@@ -304,27 +857,31 @@ class Bot {
304
857
  }
305
858
  }
306
859
  // Rate limiting
307
- if (this.signalRouter.isRateLimited(message.discussionId))
860
+ if (this.signalRouter.isRateLimited(message.discussionId)) {
308
861
  return;
862
+ }
309
863
  // Layer 1: Workspace membership
310
864
  if (!this.permissions.isMember(message.senderId)) {
311
865
  this.logger.debug('Ignoring message - not a workspace member', { senderId: message.senderId });
312
- if (rawMsgId)
866
+ if (rawMsgId) {
313
867
  this.signalRouter.removeDedupKey(rawMsgId);
868
+ }
314
869
  return;
315
870
  }
316
871
  // Layer 2: Access level
317
872
  if (!this.permissions.meetsAccessLevel(message.senderId, this.config.accessLevel)) {
318
873
  this.logger.debug('Ignoring message - access level not met', { senderId: message.senderId });
319
- if (rawMsgId)
874
+ if (rawMsgId) {
320
875
  this.signalRouter.removeDedupKey(rawMsgId);
876
+ }
321
877
  return;
322
878
  }
323
879
  // Engagement logic
324
880
  const state = this.signalRouter.getOrCreateState(message.discussionId);
325
881
  state.contextBuffer.push(message);
326
- if (!this.signalRouter.checkTrigger(message, this._responseMode))
882
+ if (!this.signalRouter.checkTrigger(message, this._responseMode)) {
327
883
  return;
884
+ }
328
885
  const isExplicit = this.signalRouter.isExplicitTrigger(message);
329
886
  if (state.state === 'idle') {
330
887
  if (isExplicit || this._responseMode === 'always') {
@@ -336,8 +893,9 @@ class Bot {
336
893
  return;
337
894
  }
338
895
  }
339
- if (this._responseMode !== 'always' && !isExplicit)
896
+ if (this._responseMode !== 'always' && !isExplicit) {
340
897
  return;
898
+ }
341
899
  // Process if not already running
342
900
  if (!this.signalRouter.processingDiscussions.has(message.discussionId)) {
343
901
  this.processDiscussion(message.discussionId).catch(err => {
@@ -352,17 +910,20 @@ class Bot {
352
910
  }
353
911
  // ===== DISCUSSION PROCESSING =====
354
912
  async processDiscussion(discussionId) {
355
- if (this.signalRouter.processingDiscussions.has(discussionId))
913
+ if (this.signalRouter.processingDiscussions.has(discussionId)) {
356
914
  return;
915
+ }
357
916
  this.signalRouter.processingDiscussions.add(discussionId);
358
917
  const state = this.signalRouter.getOrCreateState(discussionId);
359
918
  try {
360
919
  while (true) {
361
920
  const messages = state.contextBuffer.splice(0);
362
- if (messages.length === 0)
921
+ if (messages.length === 0) {
363
922
  break;
364
- if (messages.length > 1)
923
+ }
924
+ if (messages.length > 1) {
365
925
  this.opLogger.coalesce(discussionId, messages.length);
926
+ }
366
927
  // Build conversation entry
367
928
  const conversation = this.conversationManager.getConversation(discussionId);
368
929
  const parts = messages.map(msg => this.formatIncomingMessage(msg));
@@ -380,8 +941,9 @@ class Bot {
380
941
  const primaryMessage = messages[messages.length - 1];
381
942
  state.lastProgressTime = 0;
382
943
  state.abortController = new AbortController();
383
- for (const msg of messages)
944
+ for (const msg of messages) {
384
945
  this.opLogger.messageIn(msg.discussionId, msg.senderName, msg.content);
946
+ }
385
947
  let responded;
386
948
  try {
387
949
  responded = await this.processMessage(primaryMessage, state.abortController.signal);
@@ -404,12 +966,14 @@ class Bot {
404
966
  break;
405
967
  }
406
968
  }
407
- if (state.contextBuffer.length === 0)
969
+ if (state.contextBuffer.length === 0) {
408
970
  break;
971
+ }
409
972
  if (state.state === 'idle') {
410
973
  const hasExplicit = state.contextBuffer.some(m => this.signalRouter.isExplicitTrigger(m));
411
- if (!hasExplicit)
974
+ if (!hasExplicit) {
412
975
  break;
976
+ }
413
977
  state.state = 'engaged';
414
978
  state.consecutiveNonResponses = 0;
415
979
  this.opLogger.engage(discussionId, 'reengaged');
@@ -443,8 +1007,9 @@ class Bot {
443
1007
  return await this.runLlmLoop(message, route, signal);
444
1008
  }
445
1009
  catch (error) {
446
- if (error instanceof sdk_1.default.APIUserAbortError)
1010
+ if (error instanceof sdk_1.default.APIUserAbortError) {
447
1011
  throw error;
1012
+ }
448
1013
  this.logger.error('Message processing failed', error);
449
1014
  this.typingIndicator?.stop(message.discussionId);
450
1015
  conversation.length = snapshotLength;
@@ -454,6 +1019,14 @@ class Bot {
454
1019
  // ===== MODEL ROUTING =====
455
1020
  async routeMessage(message, conversation, signal) {
456
1021
  const defaultRoute = { model: MODEL_HAIKU, maxTokens: 2000 };
1022
+ // Any file attachment forces COMPLEX: reading/analysing an attachment plus the
1023
+ // tool calls that typically follow easily blows Haiku's 2000-token budget,
1024
+ // and a truncated response with an unfinished tool_use poisons the conversation.
1025
+ if (message.fileAttachments && message.fileAttachments.length > 0) {
1026
+ const route = { ...SONNET_ROUTE };
1027
+ this.opLogger.route(message.discussionId, 'COMPLEX (attachments)', route.model, message.content);
1028
+ return route;
1029
+ }
457
1030
  try {
458
1031
  const wsName = this.init?.network?.name || 'Workspace';
459
1032
  const recentContext = this.getRecentContext(conversation);
@@ -465,7 +1038,7 @@ class Bot {
465
1038
  this.trackTokenUsage(response, message, MODEL_HAIKU);
466
1039
  const text = response.content.filter((b) => b.type === 'text').map(b => b.text).join('').trim().toUpperCase();
467
1040
  if (text.includes('COMPLEX')) {
468
- const route = { model: MODEL_SONNET, maxTokens: 16384 };
1041
+ const route = { ...SONNET_ROUTE };
469
1042
  this.opLogger.route(message.discussionId, 'COMPLEX', route.model, message.content);
470
1043
  return route;
471
1044
  }
@@ -488,8 +1061,9 @@ class Bot {
488
1061
  else if (Array.isArray(msg.content)) {
489
1062
  text = msg.content.filter((b) => b.type === 'text').map((b) => b.text).join(' ');
490
1063
  }
491
- if (!text)
1064
+ if (!text) {
492
1065
  continue;
1066
+ }
493
1067
  lines.unshift(`${msg.role === 'user' ? 'User' : 'Assistant'}: ${text.length > 200 ? text.slice(0, 200) + '...' : text}`);
494
1068
  count++;
495
1069
  }
@@ -505,38 +1079,54 @@ class Bot {
505
1079
  const systemPrompt = (0, services_1.buildSystemPrompt)({
506
1080
  init: this.init, userId: this.userId,
507
1081
  workspaceOverview: this.workspaceOverview, customPrompt: this._systemPrompt,
508
- botExchangeContext,
1082
+ botExchangeContext, helperMode: this.config.helperMode,
1083
+ hasSeedContext: !!this.config.seedContext,
1084
+ responseMode: this._responseMode,
1085
+ accessLevel: this.config.accessLevel,
1086
+ allowBotMessages: this.config.allowBotMessages,
509
1087
  });
510
1088
  const tools = this.cachedTools || this.getAnthropicTools();
511
1089
  for (let i = 0;; i++) {
512
- const cachedConversation = this.conversationManager.prepareForCaching(conversation);
513
1090
  this.typingIndicator?.updateStatus(message.discussionId, i === 0 ? 'Thinking' : 'Processing');
514
1091
  let response;
515
1092
  let llmStart = Date.now();
516
- try {
517
- response = await this.anthropic.messages.create({
518
- model: route.model, max_tokens: route.maxTokens, temperature: 0,
519
- system: [{ type: 'text', text: systemPrompt, cache_control: { type: 'ephemeral' } }],
520
- messages: cachedConversation, tools,
521
- }, { signal });
522
- }
523
- catch (error) {
524
- if (error instanceof sdk_1.default.APIUserAbortError) {
525
- this.cleanupIncompleteExchange(conversation);
526
- this.opLogger.interrupt(message.discussionId, 'new message received');
527
- return false;
528
- }
529
- if (route.model !== MODEL_HAIKU) {
530
- this.logger.warn('Sonnet failed, falling back to Haiku');
531
- route = { model: MODEL_HAIKU, maxTokens: 2000 };
532
- llmStart = Date.now();
1093
+ let trimAttempts = 0;
1094
+ while (true) {
1095
+ try {
1096
+ const cachedConversation = this.conversationManager.prepareForCaching(conversation);
533
1097
  response = await this.anthropic.messages.create({
534
- model: MODEL_HAIKU, max_tokens: 2000, temperature: 0,
1098
+ model: route.model, max_tokens: route.maxTokens, temperature: 0,
535
1099
  system: [{ type: 'text', text: systemPrompt, cache_control: { type: 'ephemeral' } }],
536
1100
  messages: cachedConversation, tools,
537
1101
  }, { signal });
1102
+ break;
538
1103
  }
539
- else {
1104
+ catch (error) {
1105
+ if (error instanceof sdk_1.default.APIUserAbortError) {
1106
+ this.cleanupIncompleteExchange(conversation);
1107
+ this.opLogger.interrupt(message.discussionId, 'new message received');
1108
+ return false;
1109
+ }
1110
+ const isPromptTooLong = error instanceof sdk_1.default.BadRequestError &&
1111
+ /prompt is too long/i.test(error.message || '');
1112
+ if (isPromptTooLong && trimAttempts < MAX_PROMPT_TRIM_ATTEMPTS && conversation.length >= 4) {
1113
+ trimAttempts++;
1114
+ const dropped = conversation.splice(0, 2);
1115
+ this.logger.warn('Prompt too long — dropped oldest conversation pair', {
1116
+ attempt: trimAttempts,
1117
+ droppedRoles: dropped.map(msg => msg.role),
1118
+ remainingMessages: conversation.length,
1119
+ model: route.model,
1120
+ });
1121
+ llmStart = Date.now();
1122
+ continue;
1123
+ }
1124
+ if (route.model !== MODEL_HAIKU && !isPromptTooLong) {
1125
+ this.logger.warn('Sonnet failed, falling back to Haiku');
1126
+ route = { model: MODEL_HAIKU, maxTokens: 2000 };
1127
+ llmStart = Date.now();
1128
+ continue;
1129
+ }
540
1130
  throw error;
541
1131
  }
542
1132
  }
@@ -546,12 +1136,37 @@ class Bot {
546
1136
  const cacheRead = usage.cache_read_input_tokens || 0;
547
1137
  const totalInput = usage.input_tokens + cacheRead + (usage.cache_creation_input_tokens || 0);
548
1138
  this.opLogger.llmCall(message.discussionId, route.model, usage.input_tokens, usage.output_tokens, totalInput > 0 ? Math.round((cacheRead / totalInput) * 100) : 0, llmDuration);
549
- if (!response.content || response.content.length === 0)
1139
+ if (!response.content || response.content.length === 0) {
550
1140
  break;
1141
+ }
551
1142
  conversation.push({ role: 'assistant', content: response.content });
552
- // Truncation guard
1143
+ // Truncation guard. When the response is cut off at max_tokens
1144
+ // AND the truncated assistant content contains tool_use blocks,
1145
+ // Anthropic's API requires the very next message to carry
1146
+ // matching tool_result blocks — otherwise every subsequent
1147
+ // request fails with `tool_use ids were found without tool_result
1148
+ // blocks immediately after`. We can't actually execute the
1149
+ // truncated tools (JSON inputs may be malformed, and the model
1150
+ // expected all of them to run together), so we synthesize error
1151
+ // tool_results that tell the model exactly why nothing ran.
553
1152
  if (response.stop_reason === 'max_tokens') {
554
- conversation.push({ role: 'user', content: 'Your previous response was truncated because it exceeded the output token limit. Break it into smaller batches of 25-50 items per tool call.' });
1153
+ const truncatedToolUses = response.content.filter((b) => b.type === 'tool_use');
1154
+ const reminder = 'Your previous response was truncated because it exceeded the output token limit. Break it into smaller batches of 25-50 items per tool call.';
1155
+ if (truncatedToolUses.length > 0) {
1156
+ const errorResults = truncatedToolUses.map(b => ({
1157
+ type: 'tool_result',
1158
+ tool_use_id: b.id,
1159
+ content: 'Tool call was truncated before it could run because the response exceeded the output token limit. Try again with a smaller batch.',
1160
+ is_error: true,
1161
+ }));
1162
+ conversation.push({
1163
+ role: 'user',
1164
+ content: [...errorResults, { type: 'text', text: reminder }],
1165
+ });
1166
+ }
1167
+ else {
1168
+ conversation.push({ role: 'user', content: reminder });
1169
+ }
555
1170
  continue;
556
1171
  }
557
1172
  // Tool calls
@@ -565,7 +1180,7 @@ class Bot {
565
1180
  if (route.model === MODEL_HAIKU) {
566
1181
  const failedCount = toolResults.filter(r => r.is_error).length;
567
1182
  if (failedCount >= 2) {
568
- route = { model: MODEL_SONNET, maxTokens: 16384 };
1183
+ route = { ...SONNET_ROUTE };
569
1184
  await this.sendMessage(message.discussionId, 'Switching to a more capable model to handle this.');
570
1185
  }
571
1186
  }
@@ -595,10 +1210,30 @@ class Bot {
595
1210
  for (const block of toolUseBlocks) {
596
1211
  const toolStart = Date.now();
597
1212
  const args = block.input;
598
- // Admin-only gate
599
- if (this.permissions.isAdminOnlyTool(block.name) && !this.permissions.isAdminOrOwner(message.senderId)) {
1213
+ // Bot profile gate — the model is only offered BOT_TOOLS, but enforce
1214
+ // at execution too so a hallucinated tool name can't reach the registry.
1215
+ // Resolve deprecation aliases first so mid-conversation calls under
1216
+ // old v1 names keep working during the grace release.
1217
+ if (!tool_profiles_1.BOT_TOOLS.has(this.toolExecutor.resolveName(block.name))) {
1218
+ this.opLogger.permDenied(message.discussionId, block.name, 'n/a', 'not-in-bot-tools');
1219
+ results.push({
1220
+ type: 'tool_result',
1221
+ tool_use_id: block.id,
1222
+ content: `Tool not available: ${block.name} is not part of this bot's toolset. `
1223
+ + 'Use only the tools you were given — do not retry.',
1224
+ is_error: true,
1225
+ });
1226
+ continue;
1227
+ }
1228
+ // Admin-only gate (args-aware: merged tools gate per-action)
1229
+ if (this.permissions.isAdminOnlyTool(block.name, args) && !this.permissions.isAdminOrOwner(message.senderId)) {
600
1230
  this.opLogger.permDenied(message.discussionId, block.name, 'n/a', 'requires-admin');
601
- results.push({ type: 'tool_result', tool_use_id: block.id, content: 'Permission denied: Only workspace admins can modify workflow permissions.', is_error: true });
1231
+ results.push({
1232
+ type: 'tool_result',
1233
+ tool_use_id: block.id,
1234
+ content: `Permission denied: ${block.name} requires workspace admin or owner permission. Explain to the user that this action is restricted to admins/owners — do not retry, do not try a workaround, do not pretend it succeeded.`,
1235
+ is_error: true,
1236
+ });
602
1237
  continue;
603
1238
  }
604
1239
  // Pre-execution permission check
@@ -613,7 +1248,7 @@ class Bot {
613
1248
  // Discussion isolation: prevent leaking DMs and discussions the user shouldn't access
614
1249
  if (DISCUSSION_TOOLS.has(block.name) && args.discussionId && args.discussionId !== message.discussionId) {
615
1250
  try {
616
- const discResult = await this.client.socket.request('v3.discussion.message.latest', [args.discussionId]);
1251
+ const discResult = await this.client.socket.request(hailer_rpc_1.HailerRpc.Discussion.messageLatest, [args.discussionId]);
617
1252
  const disc = discResult?.discussion || {};
618
1253
  const participants = disc.participants || [];
619
1254
  const isPrivate = disc.private === true;
@@ -648,10 +1283,12 @@ class Bot {
648
1283
  // Auto-inject for join_discussion
649
1284
  if (block.name === 'join_discussion') {
650
1285
  toolArgs = { ...toolArgs };
651
- if (!toolArgs.inviteUserId && message.senderId)
1286
+ if (!toolArgs.inviteUserId && message.senderId) {
652
1287
  toolArgs.inviteUserId = message.senderId;
653
- if (!toolArgs.welcomeReason && message.content)
1288
+ }
1289
+ if (!toolArgs.welcomeReason && message.content) {
654
1290
  toolArgs.welcomeReason = message.content;
1291
+ }
655
1292
  // Only auto-inject sourceActivityId if explicitly provided — don't link DMs to random activities
656
1293
  }
657
1294
  const result = await this.toolExecutor.execute(block.name, toolArgs, this.getUserContext());
@@ -685,6 +1322,11 @@ class Bot {
685
1322
  if (signal?.aborted && WRITE_TOOLS.has(block.name)) {
686
1323
  this.logger.warn('Write tool completed before abort', { tool: block.name });
687
1324
  }
1325
+ if (contentStr.length > MAX_TOOL_RESULT_CHARS) {
1326
+ const originalLen = contentStr.length;
1327
+ contentStr = `${contentStr.slice(0, MAX_TOOL_RESULT_CHARS)}\n\n[Tool result truncated. Original: ${originalLen} chars (~${Math.round(originalLen / 4)} tokens). Narrow your query: use 'fields' parameter, add filters, lower 'limit', or use preview_insight for aggregates.]`;
1328
+ this.logger.warn('Tool result truncated', { tool: block.name, originalLen, truncatedTo: MAX_TOOL_RESULT_CHARS });
1329
+ }
688
1330
  results.push({ type: 'tool_result', tool_use_id: block.id, content: contentStr });
689
1331
  }
690
1332
  catch (error) {
@@ -708,43 +1350,47 @@ class Bot {
708
1350
  const parts = [];
709
1351
  const unsupported = [];
710
1352
  for (const f of message.fileAttachments) {
711
- if (!f.mime || (f.size && f.size > MAX_FILE_SIZE)) {
1353
+ if (!f.mime || (f.size && f.size > fileSizeLimit(f.mime))) {
712
1354
  unsupported.push(f.fileId);
1355
+ continue;
713
1356
  }
714
- else if (IMAGE_MIME_TYPES.has(f.mime)) {
715
- parts.push(`[Image attached: ${f.filename} — included below for vision]`);
716
- }
717
- else if (DOCUMENT_MIME_TYPES.has(f.mime) || TEXT_MIME_TYPES.has(f.mime)) {
718
- parts.push(`[Document attached: ${f.filename} — included below]`);
719
- }
720
- else {
1357
+ const desc = describeAttachment(f.mime, f.filename, f.fileId);
1358
+ if (!desc) {
721
1359
  unsupported.push(f.fileId);
1360
+ continue;
722
1361
  }
1362
+ parts.push(desc);
723
1363
  }
724
- if (unsupported.length)
1364
+ if (unsupported.length) {
725
1365
  parts.push(`[File attached: ${unsupported.length} file(s) - IDs: ${unsupported.join(', ')}]\nUse download_file tool with fileId to read file contents.`);
726
- if (parts.length)
1366
+ }
1367
+ if (parts.length) {
727
1368
  fileInfo = '\n' + parts.join('\n');
1369
+ }
728
1370
  }
729
1371
  const dmNote = isDm ? '\n[This is a private DM conversation, not an activity discussion.]' : '';
730
- return `<incoming discussion="${message.discussionId}"${typeAttr}${nameAttr}${activityAttr} from="${message.senderName}" user_id="${message.senderId}" timestamp="${new Date(message.timestamp).toISOString()}">\n${message.content}${fileInfo}${dmNote}\n</incoming>`;
1372
+ const aiContext = message.meta?.aiContext ? `<context>${JSON.stringify(message.meta.aiContext)}</context>\n\n` : '';
1373
+ return `<incoming discussion="${message.discussionId}"${typeAttr}${nameAttr}${activityAttr} from="${message.senderName}" user_id="${message.senderId}" timestamp="${new Date(message.timestamp).toISOString()}">\n${aiContext}${message.content}${fileInfo}${dmNote}\n</incoming>`;
731
1374
  }
732
1375
  async resolveFileAttachments(messages) {
733
- if (!this.hailerApi)
1376
+ if (!this.hailerApi) {
734
1377
  return [];
735
- const eligible = [];
1378
+ }
1379
+ const nonOffice = [];
1380
+ const office = [];
1381
+ const skipped = [];
736
1382
  for (const msg of messages) {
737
1383
  for (const f of msg.fileAttachments || []) {
738
- if (!f.mime || (f.size && f.size > MAX_FILE_SIZE))
1384
+ if (!f.mime || (f.size && f.size > fileSizeLimit(f.mime))) {
1385
+ continue;
1386
+ }
1387
+ if (!isSupportedMime(f.mime)) {
739
1388
  continue;
740
- if (IMAGE_MIME_TYPES.has(f.mime) || DOCUMENT_MIME_TYPES.has(f.mime) || TEXT_MIME_TYPES.has(f.mime)) {
741
- eligible.push({ fileId: f.fileId, mime: f.mime });
742
1389
  }
1390
+ (isOfficeMime(f.mime) ? office : nonOffice).push({ fileId: f.fileId, mime: f.mime, filename: f.filename });
743
1391
  }
744
1392
  }
745
- if (!eligible.length)
746
- return [];
747
- const results = await Promise.all(eligible.map(async (f) => {
1393
+ const nonOfficeResults = await Promise.all(nonOffice.map(async (f) => {
748
1394
  try {
749
1395
  const result = await this.hailerApi.downloadFile(f.fileId);
750
1396
  if (IMAGE_MIME_TYPES.has(f.mime) && result.encoding === 'base64') {
@@ -768,11 +1414,98 @@ class Bot {
768
1414
  }
769
1415
  }
770
1416
  catch (err) {
771
- this.logger.warn('Failed to download file', { fileId: f.fileId, mime: f.mime });
1417
+ this.logger.warn('Failed to read file attachment', { fileId: f.fileId, mime: f.mime, err: err instanceof Error ? err.message : err });
1418
+ skipped.push({ filename: f.filename || f.fileId, reason: 'download failed' });
772
1419
  }
773
1420
  return null;
774
1421
  }));
775
- return results.filter((b) => b !== null);
1422
+ // Download Office files in parallel (I/O-bound), parse serially under the lock (memory-bound)
1423
+ const officeDownloads = await Promise.all(office.map(async (f) => {
1424
+ try {
1425
+ const result = await this.hailerApi.downloadFile(f.fileId);
1426
+ return { f, result };
1427
+ }
1428
+ catch (err) {
1429
+ this.logger.warn('Failed to download Office file', { fileId: f.fileId, mime: f.mime, err: err instanceof Error ? err.message : err });
1430
+ skipped.push({ filename: f.filename || f.fileId, reason: 'download failed' });
1431
+ return null;
1432
+ }
1433
+ }));
1434
+ const officeResults = [];
1435
+ for (const entry of officeDownloads) {
1436
+ if (!entry) {
1437
+ continue;
1438
+ }
1439
+ const { f, result } = entry;
1440
+ if (result.encoding !== 'base64') {
1441
+ this.logger.warn('Office file has unexpected encoding, skipping', { fileId: f.fileId, mime: f.mime, encoding: result.encoding });
1442
+ skipped.push({ filename: f.filename || f.fileId, reason: 'unexpected encoding from download' });
1443
+ continue;
1444
+ }
1445
+ if (isHeapUnderPressure()) {
1446
+ this.logger.warn('Heap under pressure, skipping Office parse', { fileId: f.fileId, mime: f.mime });
1447
+ skipped.push({ filename: f.filename || f.fileId, reason: 'bot is under memory pressure — ask the user to retry in a moment' });
1448
+ continue;
1449
+ }
1450
+ const block = await withOfficeParseLock(async () => {
1451
+ try {
1452
+ if (EXCEL_MIME_TYPES.has(f.mime)) {
1453
+ const ExcelJS = (await Promise.resolve().then(() => __importStar(require('exceljs')))).default;
1454
+ const buffer = Buffer.from(result.content, 'base64');
1455
+ const wb = new ExcelJS.Workbook();
1456
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Node 24 Buffer<ArrayBuffer> vs exceljs Buffer typing mismatch
1457
+ await wb.xlsx.load(buffer);
1458
+ const parts = [];
1459
+ wb.eachSheet((sheet) => {
1460
+ const rows = [];
1461
+ sheet.eachRow({ includeEmpty: false }, (row) => {
1462
+ const values = Array.isArray(row.values) ? row.values.slice(1) : [];
1463
+ rows.push(values.map(cellToCsv).join(','));
1464
+ });
1465
+ parts.push(`=== Sheet: ${sheet.name} (${rows.length} rows) ===\n${rows.join('\n')}`);
1466
+ });
1467
+ return {
1468
+ type: 'document',
1469
+ source: { type: 'text', media_type: 'text/plain', data: capText(`${f.filename || 'spreadsheet'}\n\n${parts.join('\n\n')}`) },
1470
+ };
1471
+ }
1472
+ if (WORD_MIME_TYPES.has(f.mime)) {
1473
+ const mammoth = await Promise.resolve().then(() => __importStar(require('mammoth')));
1474
+ const buffer = Buffer.from(result.content, 'base64');
1475
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Node 24 Buffer<ArrayBuffer> vs mammoth Buffer typing mismatch
1476
+ const { value } = await mammoth.extractRawText({ buffer: buffer });
1477
+ return {
1478
+ type: 'document',
1479
+ source: { type: 'text', media_type: 'text/plain', data: capText(`${f.filename || 'document'}\n\n${value}`) },
1480
+ };
1481
+ }
1482
+ }
1483
+ catch (err) {
1484
+ this.logger.warn('Failed to parse Office file', { fileId: f.fileId, mime: f.mime, err: err instanceof Error ? err.message : err });
1485
+ skipped.push({ filename: f.filename || f.fileId, reason: 'parse error' });
1486
+ }
1487
+ return null;
1488
+ });
1489
+ if (block) {
1490
+ officeResults.push(block);
1491
+ }
1492
+ }
1493
+ const blocks = [
1494
+ ...nonOfficeResults.filter((b) => b !== null),
1495
+ ...officeResults,
1496
+ ];
1497
+ if (skipped.length > 0) {
1498
+ const lines = skipped.map((s) => ` - ${s.filename}: ${s.reason}`).join('\n');
1499
+ blocks.push({
1500
+ type: 'document',
1501
+ source: {
1502
+ type: 'text',
1503
+ media_type: 'text/plain',
1504
+ data: `=== SYSTEM NOTICE: some attachments could not be processed ===\nThe following files were attached but could NOT be read. Tell the user clearly which files failed and why. Do not pretend to have read them.\n${lines}`,
1505
+ },
1506
+ });
1507
+ }
1508
+ return blocks;
776
1509
  }
777
1510
  async formatOutgoingMessage(text) {
778
1511
  let formatted = await this.messageFormatter.resolveUserTags(text);
@@ -785,27 +1518,31 @@ class Bot {
785
1518
  formatted = formatted.replace(/(\[hailerTag\|[^\]]+\]\([a-f0-9]{24}\)\uFEFF?)\s*\([^)]+\)/gi, '$1');
786
1519
  // Strip hailerTags inside markdown table rows (pipe in hailerTag|Name breaks table columns)
787
1520
  formatted = formatted.split('\n').map(line => {
788
- if (!line.trimStart().startsWith('|'))
1521
+ if (!line.trimStart().startsWith('|')) {
789
1522
  return line;
1523
+ }
790
1524
  return line.replace(/\uFEFF?\[hailerTag\|([^\]]+)\]\([a-f0-9]{24}\)\uFEFF?/gi, '$1');
791
1525
  }).join('\n');
792
1526
  formatted = await this.resolveBareIds(formatted);
793
1527
  return formatted;
794
1528
  }
795
1529
  async resolveBareIds(text) {
796
- const bareIdPattern = /(?<!\()([a-f0-9]{24})(?!\)[^\[]*\[hailerTag)/gi;
1530
+ const bareIdPattern = /(?<!\()([a-f0-9]{24})(?!\)[^[]*\[hailerTag)/gi;
797
1531
  const matches = [...text.matchAll(bareIdPattern)];
798
1532
  const idsToResolve = [];
799
1533
  for (const match of matches) {
800
1534
  const id = match[1];
801
- if (new RegExp(`\\[hailerTag\\|[^\\]]+\\]\\(${id}\\)`, 'i').test(text))
1535
+ if (new RegExp(`\\[hailerTag\\|[^\\]]+\\]\\(${id}\\)`, 'i').test(text)) {
802
1536
  continue;
1537
+ }
803
1538
  idsToResolve.push(id);
804
- if (idsToResolve.length >= 5)
1539
+ if (idsToResolve.length >= 5) {
805
1540
  break;
1541
+ }
806
1542
  }
807
- if (idsToResolve.length === 0)
1543
+ if (idsToResolve.length === 0) {
808
1544
  return text;
1545
+ }
809
1546
  const resolutions = await Promise.all(idsToResolve.map(async (id) => {
810
1547
  try {
811
1548
  const result = await this.toolExecutor.execute('show_activity_by_id', { activityId: id }, this.getUserContext());
@@ -814,8 +1551,9 @@ class Bot {
814
1551
  const j = resultText.match(/\{[\s\S]*\}/);
815
1552
  if (j) {
816
1553
  const p = JSON.parse(j[0]);
817
- if (p.name)
1554
+ if (p.name) {
818
1555
  return { id, name: p.name };
1556
+ }
819
1557
  }
820
1558
  }
821
1559
  }
@@ -823,8 +1561,9 @@ class Bot {
823
1561
  return null;
824
1562
  }));
825
1563
  for (const r of resolutions) {
826
- if (!r)
1564
+ if (!r) {
827
1565
  continue;
1566
+ }
828
1567
  text = text.replace(r.id, `\uFEFF[hailerTag|${r.name}](${r.id})\uFEFF`);
829
1568
  }
830
1569
  return text;
@@ -832,15 +1571,17 @@ class Bot {
832
1571
  // ===== HELPERS =====
833
1572
  async injectPendingContext(discussionId, conversation) {
834
1573
  const state = this.signalRouter.getState(discussionId);
835
- if (!state || state.contextBuffer.length === 0)
1574
+ if (!state || state.contextBuffer.length === 0) {
836
1575
  return;
1576
+ }
837
1577
  const pending = state.contextBuffer.splice(0);
838
1578
  const lastMsg = conversation[conversation.length - 1];
839
1579
  if (lastMsg?.role === 'user' && Array.isArray(lastMsg.content)) {
840
1580
  const content = lastMsg.content;
841
1581
  content.push({ type: 'text', text: `<context type="messages-during-processing">\n${pending.map(m => this.formatIncomingMessage(m)).join('\n\n')}\n</context>` });
842
- for (const block of await this.resolveFileAttachments(pending))
1582
+ for (const block of await this.resolveFileAttachments(pending)) {
843
1583
  content.push(block);
1584
+ }
844
1585
  this.opLogger.contextInject(discussionId, pending.length);
845
1586
  }
846
1587
  }
@@ -860,30 +1601,34 @@ class Bot {
860
1601
  }
861
1602
  }
862
1603
  getToolStatus(toolUseBlocks) {
863
- if (toolUseBlocks.length === 1)
1604
+ if (toolUseBlocks.length === 1) {
864
1605
  return TOOL_STATUS_LABELS[toolUseBlocks[0].name] || toolUseBlocks[0].name.replace(/_/g, ' ');
1606
+ }
865
1607
  return `${TOOL_STATUS_LABELS[toolUseBlocks[0].name] || toolUseBlocks[0].name.replace(/_/g, ' ')} (+${toolUseBlocks.length - 1} more)`;
866
1608
  }
867
1609
  getAnthropicTools() {
868
- if (this.cachedTools)
1610
+ if (this.cachedTools) {
869
1611
  return this.cachedTools;
1612
+ }
870
1613
  const defs = this.toolExecutor.getToolDefinitions({
871
1614
  allowedGroups: [tool_registry_1.ToolGroup.READ, tool_registry_1.ToolGroup.WRITE, tool_registry_1.ToolGroup.PLAYGROUND, tool_registry_1.ToolGroup.BOT_INTERNAL],
872
1615
  });
873
- const tools = defs.filter(d => BOT_TOOLS.has(d.name)).map(d => ({
1616
+ const tools = defs.filter(d => tool_profiles_1.BOT_TOOLS.has(d.name)).map(d => ({
874
1617
  name: d.name, description: d.description, input_schema: d.inputSchema,
875
1618
  }));
876
- if (tools.length > 0)
1619
+ if (tools.length > 0) {
877
1620
  tools[tools.length - 1].cache_control = { type: 'ephemeral' };
1621
+ }
878
1622
  this.cachedTools = tools;
879
1623
  return tools;
880
1624
  }
881
1625
  async sendMessage(discussionId, text, links) {
882
1626
  try {
883
1627
  const msgData = { msg: text };
884
- if (links?.length)
1628
+ if (links?.length) {
885
1629
  msgData.links = links;
886
- await this.client.socket.request('messenger.send', [msgData, discussionId]);
1630
+ }
1631
+ await this.client.socket.request(hailer_rpc_1.HailerRpc.Messenger.send, [msgData, discussionId]);
887
1632
  this.opLogger.messageOut(discussionId, text.length, (text.match(/\[hailerTag\|/g) || []).length);
888
1633
  }
889
1634
  catch (error) {
@@ -891,13 +1636,15 @@ class Bot {
891
1636
  }
892
1637
  }
893
1638
  getUserContext() {
894
- if (!this.userContext)
1639
+ if (!this.userContext) {
895
1640
  throw new Error('Bot not started');
1641
+ }
896
1642
  return this.userContext;
897
1643
  }
898
1644
  trackTokenUsage(response, message, model) {
899
- if (!response.usage)
1645
+ if (!response.usage) {
900
1646
  return;
1647
+ }
901
1648
  const { input_tokens, output_tokens } = response.usage;
902
1649
  const cacheCreation = response.usage.cache_creation_input_tokens || 0;
903
1650
  const cacheRead = response.usage.cache_read_input_tokens || 0;