@hailer/mcp 1.2.1 → 1.3.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (774) hide show
  1. package/.claude/agents/agent-hailer-helper.md +118 -0
  2. package/.claude/commands/debug-squad.md +13 -290
  3. package/.claude/commands/publish.md +2 -2
  4. package/.claude/commands/review-squad.md +17 -139
  5. package/.claude/skills/create-and-publish-app/SKILL.md +133 -143
  6. package/.claude/skills/hailer-app-builder/SKILL.md +29 -2
  7. package/.claude/skills/hailer-ui-guide/SKILL.md +265 -0
  8. package/.env.example +50 -1
  9. package/CLAUDE.md +141 -10
  10. package/dist/app-prep.d.ts +27 -0
  11. package/dist/app-prep.d.ts.map +1 -0
  12. package/dist/app-prep.js +94 -0
  13. package/dist/app-prep.js.map +1 -0
  14. package/dist/app.d.ts.map +1 -1
  15. package/dist/app.js +3 -0
  16. package/dist/app.js.map +1 -1
  17. package/dist/bot/bot-manager.d.ts +9 -6
  18. package/dist/bot/bot-manager.d.ts.map +1 -1
  19. package/dist/bot/bot-manager.js +142 -31
  20. package/dist/bot/bot-manager.js.map +1 -1
  21. package/dist/bot/bot.d.ts +61 -16
  22. package/dist/bot/bot.d.ts.map +1 -1
  23. package/dist/bot/bot.js +927 -151
  24. package/dist/bot/bot.js.map +1 -1
  25. package/dist/bot/operation-logger.d.ts.map +1 -1
  26. package/dist/bot/operation-logger.js +24 -12
  27. package/dist/bot/operation-logger.js.map +1 -1
  28. package/dist/bot/services/bot-permissions.d.ts +37 -5
  29. package/dist/bot/services/bot-permissions.d.ts.map +1 -1
  30. package/dist/bot/services/bot-permissions.js +159 -35
  31. package/dist/bot/services/bot-permissions.js.map +1 -1
  32. package/dist/bot/services/conversation-manager.d.ts +23 -23
  33. package/dist/bot/services/conversation-manager.d.ts.map +1 -1
  34. package/dist/bot/services/conversation-manager.js +52 -49
  35. package/dist/bot/services/conversation-manager.js.map +1 -1
  36. package/dist/bot/services/helper-prompt.d.ts +8 -0
  37. package/dist/bot/services/helper-prompt.d.ts.map +1 -0
  38. package/dist/bot/services/helper-prompt.js +177 -0
  39. package/dist/bot/services/helper-prompt.js.map +1 -0
  40. package/dist/bot/services/message-classifier.d.ts +16 -16
  41. package/dist/bot/services/message-classifier.d.ts.map +1 -1
  42. package/dist/bot/services/message-classifier.js +55 -49
  43. package/dist/bot/services/message-classifier.js.map +1 -1
  44. package/dist/bot/services/message-formatter.d.ts +47 -38
  45. package/dist/bot/services/message-formatter.d.ts.map +1 -1
  46. package/dist/bot/services/message-formatter.js +99 -80
  47. package/dist/bot/services/message-formatter.js.map +1 -1
  48. package/dist/bot/services/permission-guard.d.ts.map +1 -1
  49. package/dist/bot/services/permission-guard.js +20 -10
  50. package/dist/bot/services/permission-guard.js.map +1 -1
  51. package/dist/bot/services/signal-router.d.ts.map +1 -1
  52. package/dist/bot/services/signal-router.js +11 -6
  53. package/dist/bot/services/signal-router.js.map +1 -1
  54. package/dist/bot/services/system-prompt.d.ts +14 -0
  55. package/dist/bot/services/system-prompt.d.ts.map +1 -1
  56. package/dist/bot/services/system-prompt.js +181 -4
  57. package/dist/bot/services/system-prompt.js.map +1 -1
  58. package/dist/bot/services/token-billing.d.ts +23 -23
  59. package/dist/bot/services/token-billing.d.ts.map +1 -1
  60. package/dist/bot/services/token-billing.js +51 -36
  61. package/dist/bot/services/token-billing.js.map +1 -1
  62. package/dist/bot/services/types.d.ts +3 -1
  63. package/dist/bot/services/types.d.ts.map +1 -1
  64. package/dist/bot/services/typing-indicator.d.ts +8 -8
  65. package/dist/bot/services/typing-indicator.d.ts.map +1 -1
  66. package/dist/bot/services/typing-indicator.js +12 -10
  67. package/dist/bot/services/typing-indicator.js.map +1 -1
  68. package/dist/bot/services/workspace-refresh.d.ts +3 -3
  69. package/dist/bot/services/workspace-refresh.d.ts.map +1 -1
  70. package/dist/bot/services/workspace-refresh.js +23 -13
  71. package/dist/bot/services/workspace-refresh.js.map +1 -1
  72. package/dist/bot/tool-executor.d.ts +10 -6
  73. package/dist/bot/tool-executor.d.ts.map +1 -1
  74. package/dist/bot/tool-executor.js +12 -6
  75. package/dist/bot/tool-executor.js.map +1 -1
  76. package/dist/bot/workspace-overview.d.ts.map +1 -1
  77. package/dist/bot/workspace-overview.js +6 -3
  78. package/dist/bot/workspace-overview.js.map +1 -1
  79. package/dist/bot-config/activity-error.d.ts +47 -0
  80. package/dist/bot-config/activity-error.d.ts.map +1 -0
  81. package/dist/bot-config/activity-error.js +67 -0
  82. package/dist/bot-config/activity-error.js.map +1 -0
  83. package/dist/bot-config/context.d.ts +4 -4
  84. package/dist/bot-config/context.d.ts.map +1 -1
  85. package/dist/bot-config/context.js +18 -14
  86. package/dist/bot-config/context.js.map +1 -1
  87. package/dist/bot-config/events.d.ts +45 -0
  88. package/dist/bot-config/events.d.ts.map +1 -0
  89. package/dist/bot-config/events.js +51 -0
  90. package/dist/bot-config/events.js.map +1 -0
  91. package/dist/bot-config/index.d.ts +3 -0
  92. package/dist/bot-config/index.d.ts.map +1 -1
  93. package/dist/bot-config/index.js +8 -1
  94. package/dist/bot-config/index.js.map +1 -1
  95. package/dist/bot-config/loader.d.ts +3 -0
  96. package/dist/bot-config/loader.d.ts.map +1 -1
  97. package/dist/bot-config/loader.js +45 -20
  98. package/dist/bot-config/loader.js.map +1 -1
  99. package/dist/bot-config/persistence.js.map +1 -1
  100. package/dist/bot-config/reconciler.d.ts +11 -0
  101. package/dist/bot-config/reconciler.d.ts.map +1 -0
  102. package/dist/bot-config/reconciler.js +121 -0
  103. package/dist/bot-config/reconciler.js.map +1 -0
  104. package/dist/bot-config/state.d.ts.map +1 -1
  105. package/dist/bot-config/state.js.map +1 -1
  106. package/dist/bot-config/types.d.ts +32 -0
  107. package/dist/bot-config/types.d.ts.map +1 -1
  108. package/dist/bot-config/webhooks.d.ts.map +1 -1
  109. package/dist/bot-config/webhooks.js.map +1 -1
  110. package/dist/bot-config/workflow-installer.d.ts +37 -0
  111. package/dist/bot-config/workflow-installer.d.ts.map +1 -0
  112. package/dist/bot-config/workflow-installer.js +346 -0
  113. package/dist/bot-config/workflow-installer.js.map +1 -0
  114. package/dist/cli.d.ts +4 -1
  115. package/dist/cli.d.ts.map +1 -1
  116. package/dist/cli.js +92 -11
  117. package/dist/cli.js.map +1 -1
  118. package/dist/config.d.ts +23 -19
  119. package/dist/config.d.ts.map +1 -1
  120. package/dist/config.js +65 -27
  121. package/dist/config.js.map +1 -1
  122. package/dist/core.d.ts +6 -4
  123. package/dist/core.d.ts.map +1 -1
  124. package/dist/core.js +11 -16
  125. package/dist/core.js.map +1 -1
  126. package/dist/lib/logger.d.ts.map +1 -1
  127. package/dist/lib/logger.js +7 -4
  128. package/dist/lib/logger.js.map +1 -1
  129. package/dist/lib/request-logger.d.ts +19 -19
  130. package/dist/lib/request-logger.d.ts.map +1 -1
  131. package/dist/lib/request-logger.js +19 -19
  132. package/dist/lib/request-logger.js.map +1 -1
  133. package/dist/mcp/UserContextCache.d.ts +28 -22
  134. package/dist/mcp/UserContextCache.d.ts.map +1 -1
  135. package/dist/mcp/UserContextCache.js +23 -23
  136. package/dist/mcp/UserContextCache.js.map +1 -1
  137. package/dist/mcp/auth.js.map +1 -1
  138. package/dist/mcp/hailer-clients.d.ts +5 -4
  139. package/dist/mcp/hailer-clients.d.ts.map +1 -1
  140. package/dist/mcp/hailer-clients.js +83 -34
  141. package/dist/mcp/hailer-clients.js.map +1 -1
  142. package/dist/mcp/hailer-rpc.d.ts +40 -0
  143. package/dist/mcp/hailer-rpc.d.ts.map +1 -0
  144. package/dist/mcp/hailer-rpc.js +43 -0
  145. package/dist/mcp/hailer-rpc.js.map +1 -0
  146. package/dist/mcp/publish-auth-injector.d.ts +22 -0
  147. package/dist/mcp/publish-auth-injector.d.ts.map +1 -0
  148. package/dist/mcp/publish-auth-injector.js +100 -0
  149. package/dist/mcp/publish-auth-injector.js.map +1 -0
  150. package/dist/mcp/session-store.d.ts +16 -16
  151. package/dist/mcp/session-store.d.ts.map +1 -1
  152. package/dist/mcp/session-store.js +16 -16
  153. package/dist/mcp/session-store.js.map +1 -1
  154. package/dist/mcp/tool-profiles.d.ts +69 -0
  155. package/dist/mcp/tool-profiles.d.ts.map +1 -0
  156. package/dist/mcp/tool-profiles.js +176 -0
  157. package/dist/mcp/tool-profiles.js.map +1 -0
  158. package/dist/mcp/tool-registry.d.ts +16 -0
  159. package/dist/mcp/tool-registry.d.ts.map +1 -1
  160. package/dist/mcp/tool-registry.js +91 -39
  161. package/dist/mcp/tool-registry.js.map +1 -1
  162. package/dist/mcp/tools/activity.d.ts +2 -0
  163. package/dist/mcp/tools/activity.d.ts.map +1 -1
  164. package/dist/mcp/tools/activity.js +575 -218
  165. package/dist/mcp/tools/activity.js.map +1 -1
  166. package/dist/mcp/tools/aliases.d.ts +11 -0
  167. package/dist/mcp/tools/aliases.d.ts.map +1 -0
  168. package/dist/mcp/tools/aliases.js +182 -0
  169. package/dist/mcp/tools/aliases.js.map +1 -0
  170. package/dist/mcp/tools/app-core.d.ts +6 -8
  171. package/dist/mcp/tools/app-core.d.ts.map +1 -1
  172. package/dist/mcp/tools/app-core.js +355 -254
  173. package/dist/mcp/tools/app-core.js.map +1 -1
  174. package/dist/mcp/tools/app-marketplace.d.ts +8 -16
  175. package/dist/mcp/tools/app-marketplace.d.ts.map +1 -1
  176. package/dist/mcp/tools/app-marketplace.js +604 -932
  177. package/dist/mcp/tools/app-marketplace.js.map +1 -1
  178. package/dist/mcp/tools/app.d.ts +4 -7
  179. package/dist/mcp/tools/app.d.ts.map +1 -1
  180. package/dist/mcp/tools/app.js +4 -7
  181. package/dist/mcp/tools/app.js.map +1 -1
  182. package/dist/mcp/tools/bot-self.d.ts +21 -0
  183. package/dist/mcp/tools/bot-self.d.ts.map +1 -0
  184. package/dist/mcp/tools/bot-self.js +174 -0
  185. package/dist/mcp/tools/bot-self.js.map +1 -0
  186. package/dist/mcp/tools/calendar.d.ts +21 -0
  187. package/dist/mcp/tools/calendar.d.ts.map +1 -0
  188. package/dist/mcp/tools/calendar.js +741 -0
  189. package/dist/mcp/tools/calendar.js.map +1 -0
  190. package/dist/mcp/tools/company.d.ts.map +1 -1
  191. package/dist/mcp/tools/company.js +2 -1
  192. package/dist/mcp/tools/company.js.map +1 -1
  193. package/dist/mcp/tools/date.js.map +1 -1
  194. package/dist/mcp/tools/discussion.d.ts +29 -3
  195. package/dist/mcp/tools/discussion.d.ts.map +1 -1
  196. package/dist/mcp/tools/discussion.js +419 -534
  197. package/dist/mcp/tools/discussion.js.map +1 -1
  198. package/dist/mcp/tools/file.d.ts.map +1 -1
  199. package/dist/mcp/tools/file.js +18 -16
  200. package/dist/mcp/tools/file.js.map +1 -1
  201. package/dist/mcp/tools/index.js +4 -4
  202. package/dist/mcp/tools/index.js.map +1 -1
  203. package/dist/mcp/tools/insight.d.ts +24 -5
  204. package/dist/mcp/tools/insight.d.ts.map +1 -1
  205. package/dist/mcp/tools/insight.js +513 -480
  206. package/dist/mcp/tools/insight.js.map +1 -1
  207. package/dist/mcp/tools/user.d.ts.map +1 -1
  208. package/dist/mcp/tools/user.js +15 -13
  209. package/dist/mcp/tools/user.js.map +1 -1
  210. package/dist/mcp/tools/workflow-permissions.d.ts +2 -4
  211. package/dist/mcp/tools/workflow-permissions.d.ts.map +1 -1
  212. package/dist/mcp/tools/workflow-permissions.js +88 -97
  213. package/dist/mcp/tools/workflow-permissions.js.map +1 -1
  214. package/dist/mcp/tools/workflow.d.ts +9 -7
  215. package/dist/mcp/tools/workflow.d.ts.map +1 -1
  216. package/dist/mcp/tools/workflow.js +852 -860
  217. package/dist/mcp/tools/workflow.js.map +1 -1
  218. package/dist/mcp/utils/api-errors.d.ts.map +1 -1
  219. package/dist/mcp/utils/api-errors.js +2 -2
  220. package/dist/mcp/utils/api-errors.js.map +1 -1
  221. package/dist/mcp/utils/data-transformers.d.ts +0 -3
  222. package/dist/mcp/utils/data-transformers.d.ts.map +1 -1
  223. package/dist/mcp/utils/data-transformers.js +32 -5
  224. package/dist/mcp/utils/data-transformers.js.map +1 -1
  225. package/dist/mcp/utils/file-upload.d.ts.map +1 -1
  226. package/dist/mcp/utils/file-upload.js +1 -1
  227. package/dist/mcp/utils/file-upload.js.map +1 -1
  228. package/dist/mcp/utils/hailer-api-client.d.ts +81 -81
  229. package/dist/mcp/utils/hailer-api-client.d.ts.map +1 -1
  230. package/dist/mcp/utils/hailer-api-client.js +113 -103
  231. package/dist/mcp/utils/hailer-api-client.js.map +1 -1
  232. package/dist/mcp/utils/index.d.ts.map +1 -1
  233. package/dist/mcp/utils/index.js.map +1 -1
  234. package/dist/mcp/utils/logger.d.ts.map +1 -1
  235. package/dist/mcp/utils/logger.js.map +1 -1
  236. package/dist/mcp/utils/response-builder.d.ts.map +1 -1
  237. package/dist/mcp/utils/response-builder.js +8 -4
  238. package/dist/mcp/utils/response-builder.js.map +1 -1
  239. package/dist/mcp/utils/role-utils.d.ts.map +1 -1
  240. package/dist/mcp/utils/role-utils.js +6 -3
  241. package/dist/mcp/utils/role-utils.js.map +1 -1
  242. package/dist/mcp/utils/tool-helpers.d.ts.map +1 -1
  243. package/dist/mcp/utils/tool-helpers.js +2 -2
  244. package/dist/mcp/utils/tool-helpers.js.map +1 -1
  245. package/dist/mcp/utils/types.d.ts +2 -1
  246. package/dist/mcp/utils/types.d.ts.map +1 -1
  247. package/dist/mcp/utils/types.js.map +1 -1
  248. package/dist/mcp/webhook-handler.d.ts +43 -8
  249. package/dist/mcp/webhook-handler.d.ts.map +1 -1
  250. package/dist/mcp/webhook-handler.js +861 -116
  251. package/dist/mcp/webhook-handler.js.map +1 -1
  252. package/dist/mcp/workspace-admin-store.d.ts +49 -0
  253. package/dist/mcp/workspace-admin-store.d.ts.map +1 -0
  254. package/dist/mcp/workspace-admin-store.js +168 -0
  255. package/dist/mcp/workspace-admin-store.js.map +1 -0
  256. package/dist/mcp/workspace-cache.d.ts +2 -2
  257. package/dist/mcp/workspace-cache.d.ts.map +1 -1
  258. package/dist/mcp/workspace-cache.js +9 -5
  259. package/dist/mcp/workspace-cache.js.map +1 -1
  260. package/dist/mcp-server.d.ts +26 -11
  261. package/dist/mcp-server.d.ts.map +1 -1
  262. package/dist/mcp-server.js +367 -48
  263. package/dist/mcp-server.js.map +1 -1
  264. package/dist/plugins/vipunen/client.d.ts +41 -41
  265. package/dist/plugins/vipunen/client.d.ts.map +1 -1
  266. package/dist/plugins/vipunen/client.js +53 -48
  267. package/dist/plugins/vipunen/client.js.map +1 -1
  268. package/dist/plugins/vipunen/index.js.map +1 -1
  269. package/dist/plugins/vipunen/tools.d.ts.map +1 -1
  270. package/dist/plugins/vipunen/tools.js +6 -3
  271. package/dist/plugins/vipunen/tools.js.map +1 -1
  272. package/dist/public-chat/graduate.d.ts +29 -0
  273. package/dist/public-chat/graduate.d.ts.map +1 -0
  274. package/dist/public-chat/graduate.js +593 -0
  275. package/dist/public-chat/graduate.js.map +1 -0
  276. package/dist/public-chat/handler.d.ts +12 -0
  277. package/dist/public-chat/handler.d.ts.map +1 -0
  278. package/dist/public-chat/handler.js +183 -0
  279. package/dist/public-chat/handler.js.map +1 -0
  280. package/dist/public-chat/index.d.ts +16 -0
  281. package/dist/public-chat/index.d.ts.map +1 -0
  282. package/dist/public-chat/index.js +74 -0
  283. package/dist/public-chat/index.js.map +1 -0
  284. package/dist/public-chat/knowledge.d.ts +3 -0
  285. package/dist/public-chat/knowledge.d.ts.map +1 -0
  286. package/dist/public-chat/knowledge.js +1340 -0
  287. package/dist/public-chat/knowledge.js.map +1 -0
  288. package/dist/public-chat/rate-limit.d.ts +16 -0
  289. package/dist/public-chat/rate-limit.d.ts.map +1 -0
  290. package/dist/public-chat/rate-limit.js +51 -0
  291. package/dist/public-chat/rate-limit.js.map +1 -0
  292. package/dist/public-chat/session-store.d.ts +41 -0
  293. package/dist/public-chat/session-store.d.ts.map +1 -0
  294. package/dist/public-chat/session-store.js +95 -0
  295. package/dist/public-chat/session-store.js.map +1 -0
  296. package/dist/public-chat/studio-prewarm.d.ts +61 -0
  297. package/dist/public-chat/studio-prewarm.d.ts.map +1 -0
  298. package/dist/public-chat/studio-prewarm.js +162 -0
  299. package/dist/public-chat/studio-prewarm.js.map +1 -0
  300. package/dist/public-chat/system-prompt.d.ts +22 -0
  301. package/dist/public-chat/system-prompt.d.ts.map +1 -0
  302. package/dist/public-chat/system-prompt.js +435 -0
  303. package/dist/public-chat/system-prompt.js.map +1 -0
  304. package/package.json +15 -7
  305. package/scripts/build-public-chat-knowledge.py +101 -0
  306. package/scripts/smoke-public-chat-live.ts +148 -0
  307. package/scripts/smoke-public-chat.ts +110 -0
  308. package/.claude/CLAUDE.md +0 -126
  309. package/.claude/commands/app-squad.md +0 -131
  310. package/.claude/commands/audit-squad.md +0 -158
  311. package/.claude/commands/cleanup-squad.md +0 -98
  312. package/.claude/commands/config-squad.md +0 -106
  313. package/.claude/commands/crud-squad.md +0 -87
  314. package/.claude/commands/data-squad.md +0 -97
  315. package/.claude/commands/doc-squad.md +0 -65
  316. package/.claude/commands/help.md +0 -29
  317. package/.claude/commands/help:agents.md +0 -182
  318. package/.claude/commands/help:commands.md +0 -78
  319. package/.claude/commands/help:faq.md +0 -79
  320. package/.claude/commands/help:plugins.md +0 -50
  321. package/.claude/commands/help:skills.md +0 -87
  322. package/.claude/commands/help:tools.md +0 -75
  323. package/.claude/commands/hotfix-squad.md +0 -112
  324. package/.claude/commands/integration-squad.md +0 -82
  325. package/.claude/commands/janitor-squad.md +0 -167
  326. package/.claude/commands/onboard-squad.md +0 -130
  327. package/.claude/commands/swarm.md +0 -210
  328. package/.claude/commands/tool-builder.md +0 -39
  329. package/.claude/skills/publish-hailer-app/SKILL.md +0 -280
  330. package/dist/CLAUDE.md +0 -370
  331. package/dist/agents/bot-manager.d.ts +0 -48
  332. package/dist/agents/bot-manager.d.ts.map +0 -1
  333. package/dist/agents/bot-manager.js +0 -254
  334. package/dist/agents/bot-manager.js.map +0 -1
  335. package/dist/agents/bug-fixer/ai.d.ts +0 -80
  336. package/dist/agents/bug-fixer/ai.d.ts.map +0 -1
  337. package/dist/agents/bug-fixer/ai.js +0 -466
  338. package/dist/agents/bug-fixer/ai.js.map +0 -1
  339. package/dist/agents/bug-fixer/bot.d.ts +0 -92
  340. package/dist/agents/bug-fixer/bot.d.ts.map +0 -1
  341. package/dist/agents/bug-fixer/bot.js +0 -687
  342. package/dist/agents/bug-fixer/bot.js.map +0 -1
  343. package/dist/agents/bug-fixer/config.d.ts +0 -21
  344. package/dist/agents/bug-fixer/config.d.ts.map +0 -1
  345. package/dist/agents/bug-fixer/config.js +0 -218
  346. package/dist/agents/bug-fixer/config.js.map +0 -1
  347. package/dist/agents/bug-fixer/files.d.ts +0 -67
  348. package/dist/agents/bug-fixer/files.d.ts.map +0 -1
  349. package/dist/agents/bug-fixer/files.js +0 -386
  350. package/dist/agents/bug-fixer/files.js.map +0 -1
  351. package/dist/agents/bug-fixer/git.d.ts +0 -48
  352. package/dist/agents/bug-fixer/git.d.ts.map +0 -1
  353. package/dist/agents/bug-fixer/git.js +0 -298
  354. package/dist/agents/bug-fixer/git.js.map +0 -1
  355. package/dist/agents/bug-fixer/index.d.ts +0 -103
  356. package/dist/agents/bug-fixer/index.d.ts.map +0 -1
  357. package/dist/agents/bug-fixer/index.js +0 -262
  358. package/dist/agents/bug-fixer/index.js.map +0 -1
  359. package/dist/agents/bug-fixer/lsp.d.ts +0 -113
  360. package/dist/agents/bug-fixer/lsp.d.ts.map +0 -1
  361. package/dist/agents/bug-fixer/lsp.js +0 -485
  362. package/dist/agents/bug-fixer/lsp.js.map +0 -1
  363. package/dist/agents/bug-fixer/monitor.d.ts +0 -123
  364. package/dist/agents/bug-fixer/monitor.d.ts.map +0 -1
  365. package/dist/agents/bug-fixer/monitor.js +0 -629
  366. package/dist/agents/bug-fixer/monitor.js.map +0 -1
  367. package/dist/agents/bug-fixer/prompt.d.ts +0 -5
  368. package/dist/agents/bug-fixer/prompt.d.ts.map +0 -1
  369. package/dist/agents/bug-fixer/prompt.js +0 -94
  370. package/dist/agents/bug-fixer/prompt.js.map +0 -1
  371. package/dist/agents/bug-fixer/registries/pending-classification.d.ts +0 -28
  372. package/dist/agents/bug-fixer/registries/pending-classification.d.ts.map +0 -1
  373. package/dist/agents/bug-fixer/registries/pending-classification.js +0 -50
  374. package/dist/agents/bug-fixer/registries/pending-classification.js.map +0 -1
  375. package/dist/agents/bug-fixer/registries/pending-fix.d.ts +0 -33
  376. package/dist/agents/bug-fixer/registries/pending-fix.d.ts.map +0 -1
  377. package/dist/agents/bug-fixer/registries/pending-fix.js +0 -64
  378. package/dist/agents/bug-fixer/registries/pending-fix.js.map +0 -1
  379. package/dist/agents/bug-fixer/registries/pending.d.ts +0 -27
  380. package/dist/agents/bug-fixer/registries/pending.d.ts.map +0 -1
  381. package/dist/agents/bug-fixer/registries/pending.js +0 -49
  382. package/dist/agents/bug-fixer/registries/pending.js.map +0 -1
  383. package/dist/agents/bug-fixer/specialist-daemon.d.ts +0 -88
  384. package/dist/agents/bug-fixer/specialist-daemon.d.ts.map +0 -1
  385. package/dist/agents/bug-fixer/specialist-daemon.js +0 -431
  386. package/dist/agents/bug-fixer/specialist-daemon.js.map +0 -1
  387. package/dist/agents/bug-fixer/specialist.d.ts +0 -47
  388. package/dist/agents/bug-fixer/specialist.d.ts.map +0 -1
  389. package/dist/agents/bug-fixer/specialist.js +0 -327
  390. package/dist/agents/bug-fixer/specialist.js.map +0 -1
  391. package/dist/agents/bug-fixer/types.d.ts +0 -123
  392. package/dist/agents/bug-fixer/types.d.ts.map +0 -1
  393. package/dist/agents/bug-fixer/types.js +0 -9
  394. package/dist/agents/bug-fixer/types.js.map +0 -1
  395. package/dist/agents/factory.d.ts +0 -172
  396. package/dist/agents/factory.d.ts.map +0 -1
  397. package/dist/agents/factory.js +0 -706
  398. package/dist/agents/factory.js.map +0 -1
  399. package/dist/agents/hailer-expert/index.d.ts +0 -8
  400. package/dist/agents/hailer-expert/index.d.ts.map +0 -1
  401. package/dist/agents/hailer-expert/index.js +0 -14
  402. package/dist/agents/hailer-expert/index.js.map +0 -1
  403. package/dist/agents/hal/daemon.d.ts +0 -174
  404. package/dist/agents/hal/daemon.d.ts.map +0 -1
  405. package/dist/agents/hal/daemon.js +0 -1385
  406. package/dist/agents/hal/daemon.js.map +0 -1
  407. package/dist/agents/hal/definitions.d.ts +0 -42
  408. package/dist/agents/hal/definitions.d.ts.map +0 -1
  409. package/dist/agents/hal/definitions.js +0 -300
  410. package/dist/agents/hal/definitions.js.map +0 -1
  411. package/dist/agents/hal/index.d.ts +0 -3
  412. package/dist/agents/hal/index.d.ts.map +0 -1
  413. package/dist/agents/hal/index.js +0 -8
  414. package/dist/agents/hal/index.js.map +0 -1
  415. package/dist/agents/index.d.ts +0 -18
  416. package/dist/agents/index.d.ts.map +0 -1
  417. package/dist/agents/index.js +0 -48
  418. package/dist/agents/index.js.map +0 -1
  419. package/dist/agents/shared/base.d.ts +0 -253
  420. package/dist/agents/shared/base.d.ts.map +0 -1
  421. package/dist/agents/shared/base.js +0 -1122
  422. package/dist/agents/shared/base.js.map +0 -1
  423. package/dist/agents/shared/schemas/action-schema.d.ts +0 -62
  424. package/dist/agents/shared/schemas/action-schema.d.ts.map +0 -1
  425. package/dist/agents/shared/schemas/action-schema.js +0 -483
  426. package/dist/agents/shared/schemas/action-schema.js.map +0 -1
  427. package/dist/agents/shared/services/agent-registry.d.ts +0 -108
  428. package/dist/agents/shared/services/agent-registry.d.ts.map +0 -1
  429. package/dist/agents/shared/services/agent-registry.js +0 -469
  430. package/dist/agents/shared/services/agent-registry.js.map +0 -1
  431. package/dist/agents/shared/services/conversation-manager.d.ts +0 -57
  432. package/dist/agents/shared/services/conversation-manager.d.ts.map +0 -1
  433. package/dist/agents/shared/services/conversation-manager.js +0 -168
  434. package/dist/agents/shared/services/conversation-manager.js.map +0 -1
  435. package/dist/agents/shared/services/mcp-client.d.ts +0 -56
  436. package/dist/agents/shared/services/mcp-client.d.ts.map +0 -1
  437. package/dist/agents/shared/services/mcp-client.js +0 -124
  438. package/dist/agents/shared/services/mcp-client.js.map +0 -1
  439. package/dist/agents/shared/services/message-classifier.d.ts +0 -37
  440. package/dist/agents/shared/services/message-classifier.d.ts.map +0 -1
  441. package/dist/agents/shared/services/message-classifier.js +0 -203
  442. package/dist/agents/shared/services/message-classifier.js.map +0 -1
  443. package/dist/agents/shared/services/message-formatter.d.ts +0 -89
  444. package/dist/agents/shared/services/message-formatter.d.ts.map +0 -1
  445. package/dist/agents/shared/services/message-formatter.js +0 -390
  446. package/dist/agents/shared/services/message-formatter.js.map +0 -1
  447. package/dist/agents/shared/services/session-logger.d.ts +0 -162
  448. package/dist/agents/shared/services/session-logger.d.ts.map +0 -1
  449. package/dist/agents/shared/services/session-logger.js +0 -724
  450. package/dist/agents/shared/services/session-logger.js.map +0 -1
  451. package/dist/agents/shared/services/structured-output-executor.d.ts +0 -88
  452. package/dist/agents/shared/services/structured-output-executor.d.ts.map +0 -1
  453. package/dist/agents/shared/services/structured-output-executor.js +0 -296
  454. package/dist/agents/shared/services/structured-output-executor.js.map +0 -1
  455. package/dist/agents/shared/services/token-billing.d.ts +0 -72
  456. package/dist/agents/shared/services/token-billing.d.ts.map +0 -1
  457. package/dist/agents/shared/services/token-billing.js +0 -198
  458. package/dist/agents/shared/services/token-billing.js.map +0 -1
  459. package/dist/agents/shared/services/tool-executor.d.ts +0 -43
  460. package/dist/agents/shared/services/tool-executor.d.ts.map +0 -1
  461. package/dist/agents/shared/services/tool-executor.js +0 -175
  462. package/dist/agents/shared/services/tool-executor.js.map +0 -1
  463. package/dist/agents/shared/services/typing-indicator.d.ts +0 -24
  464. package/dist/agents/shared/services/typing-indicator.d.ts.map +0 -1
  465. package/dist/agents/shared/services/typing-indicator.js +0 -54
  466. package/dist/agents/shared/services/typing-indicator.js.map +0 -1
  467. package/dist/agents/shared/services/workspace-schema-cache.d.ts +0 -122
  468. package/dist/agents/shared/services/workspace-schema-cache.d.ts.map +0 -1
  469. package/dist/agents/shared/services/workspace-schema-cache.js +0 -507
  470. package/dist/agents/shared/services/workspace-schema-cache.js.map +0 -1
  471. package/dist/agents/shared/specialist.d.ts +0 -91
  472. package/dist/agents/shared/specialist.d.ts.map +0 -1
  473. package/dist/agents/shared/specialist.js +0 -399
  474. package/dist/agents/shared/specialist.js.map +0 -1
  475. package/dist/agents/shared/tool-schema-loader.d.ts +0 -65
  476. package/dist/agents/shared/tool-schema-loader.d.ts.map +0 -1
  477. package/dist/agents/shared/tool-schema-loader.js +0 -238
  478. package/dist/agents/shared/tool-schema-loader.js.map +0 -1
  479. package/dist/agents/shared/types.d.ts +0 -190
  480. package/dist/agents/shared/types.d.ts.map +0 -1
  481. package/dist/agents/shared/types.js +0 -13
  482. package/dist/agents/shared/types.js.map +0 -1
  483. package/dist/bot/bot-config.d.ts +0 -37
  484. package/dist/bot/bot-config.d.ts.map +0 -1
  485. package/dist/bot/bot-config.js +0 -219
  486. package/dist/bot/bot-config.js.map +0 -1
  487. package/dist/bot/services/__tests__/permission-guard.test.d.ts +0 -2
  488. package/dist/bot/services/__tests__/permission-guard.test.d.ts.map +0 -1
  489. package/dist/bot/services/__tests__/permission-guard.test.js +0 -357
  490. package/dist/bot/services/__tests__/permission-guard.test.js.map +0 -1
  491. package/dist/bot/services/session-logger.d.ts +0 -162
  492. package/dist/bot/services/session-logger.d.ts.map +0 -1
  493. package/dist/bot/services/session-logger.js +0 -724
  494. package/dist/bot/services/session-logger.js.map +0 -1
  495. package/dist/bot/services/workspace-schema-cache.d.ts +0 -122
  496. package/dist/bot/services/workspace-schema-cache.d.ts.map +0 -1
  497. package/dist/bot/services/workspace-schema-cache.js +0 -506
  498. package/dist/bot/services/workspace-schema-cache.js.map +0 -1
  499. package/dist/bot-config/tools.d.ts +0 -28
  500. package/dist/bot-config/tools.d.ts.map +0 -1
  501. package/dist/bot-config/tools.js +0 -279
  502. package/dist/bot-config/tools.js.map +0 -1
  503. package/dist/client/agents/base.d.ts +0 -207
  504. package/dist/client/agents/base.d.ts.map +0 -1
  505. package/dist/client/agents/base.js +0 -744
  506. package/dist/client/agents/base.js.map +0 -1
  507. package/dist/client/agents/definitions.d.ts +0 -53
  508. package/dist/client/agents/definitions.d.ts.map +0 -1
  509. package/dist/client/agents/definitions.js +0 -263
  510. package/dist/client/agents/definitions.js.map +0 -1
  511. package/dist/client/agents/orchestrator.d.ts +0 -141
  512. package/dist/client/agents/orchestrator.d.ts.map +0 -1
  513. package/dist/client/agents/orchestrator.js +0 -1062
  514. package/dist/client/agents/orchestrator.js.map +0 -1
  515. package/dist/client/agents/specialist.d.ts +0 -86
  516. package/dist/client/agents/specialist.d.ts.map +0 -1
  517. package/dist/client/agents/specialist.js +0 -340
  518. package/dist/client/agents/specialist.js.map +0 -1
  519. package/dist/client/bot-entrypoint.d.ts +0 -7
  520. package/dist/client/bot-entrypoint.d.ts.map +0 -1
  521. package/dist/client/bot-entrypoint.js +0 -103
  522. package/dist/client/bot-entrypoint.js.map +0 -1
  523. package/dist/client/bot-manager.d.ts +0 -44
  524. package/dist/client/bot-manager.d.ts.map +0 -1
  525. package/dist/client/bot-manager.js +0 -173
  526. package/dist/client/bot-manager.js.map +0 -1
  527. package/dist/client/bot-runner.d.ts +0 -35
  528. package/dist/client/bot-runner.d.ts.map +0 -1
  529. package/dist/client/bot-runner.js +0 -188
  530. package/dist/client/bot-runner.js.map +0 -1
  531. package/dist/client/chat-agent-daemon.d.ts +0 -464
  532. package/dist/client/chat-agent-daemon.d.ts.map +0 -1
  533. package/dist/client/chat-agent-daemon.js +0 -1774
  534. package/dist/client/chat-agent-daemon.js.map +0 -1
  535. package/dist/client/daemon-factory.d.ts +0 -106
  536. package/dist/client/daemon-factory.d.ts.map +0 -1
  537. package/dist/client/daemon-factory.js +0 -301
  538. package/dist/client/daemon-factory.js.map +0 -1
  539. package/dist/client/factory.d.ts +0 -111
  540. package/dist/client/factory.d.ts.map +0 -1
  541. package/dist/client/factory.js +0 -314
  542. package/dist/client/factory.js.map +0 -1
  543. package/dist/client/index.d.ts +0 -17
  544. package/dist/client/index.d.ts.map +0 -1
  545. package/dist/client/index.js +0 -38
  546. package/dist/client/index.js.map +0 -1
  547. package/dist/client/multi-bot-manager.d.ts +0 -42
  548. package/dist/client/multi-bot-manager.d.ts.map +0 -1
  549. package/dist/client/multi-bot-manager.js +0 -161
  550. package/dist/client/multi-bot-manager.js.map +0 -1
  551. package/dist/client/orchestrator-daemon.d.ts +0 -87
  552. package/dist/client/orchestrator-daemon.d.ts.map +0 -1
  553. package/dist/client/orchestrator-daemon.js +0 -444
  554. package/dist/client/orchestrator-daemon.js.map +0 -1
  555. package/dist/client/server.d.ts +0 -8
  556. package/dist/client/server.d.ts.map +0 -1
  557. package/dist/client/server.js +0 -251
  558. package/dist/client/server.js.map +0 -1
  559. package/dist/client/services/agent-registry.d.ts +0 -108
  560. package/dist/client/services/agent-registry.d.ts.map +0 -1
  561. package/dist/client/services/agent-registry.js +0 -630
  562. package/dist/client/services/agent-registry.js.map +0 -1
  563. package/dist/client/services/conversation-manager.d.ts +0 -50
  564. package/dist/client/services/conversation-manager.d.ts.map +0 -1
  565. package/dist/client/services/conversation-manager.js +0 -136
  566. package/dist/client/services/conversation-manager.js.map +0 -1
  567. package/dist/client/services/mcp-client.d.ts +0 -48
  568. package/dist/client/services/mcp-client.d.ts.map +0 -1
  569. package/dist/client/services/mcp-client.js +0 -105
  570. package/dist/client/services/mcp-client.js.map +0 -1
  571. package/dist/client/services/message-classifier.d.ts +0 -37
  572. package/dist/client/services/message-classifier.d.ts.map +0 -1
  573. package/dist/client/services/message-classifier.js +0 -187
  574. package/dist/client/services/message-classifier.js.map +0 -1
  575. package/dist/client/services/message-formatter.d.ts +0 -84
  576. package/dist/client/services/message-formatter.d.ts.map +0 -1
  577. package/dist/client/services/message-formatter.js +0 -353
  578. package/dist/client/services/message-formatter.js.map +0 -1
  579. package/dist/client/services/session-logger.d.ts +0 -106
  580. package/dist/client/services/session-logger.d.ts.map +0 -1
  581. package/dist/client/services/session-logger.js +0 -446
  582. package/dist/client/services/session-logger.js.map +0 -1
  583. package/dist/client/services/tool-executor.d.ts +0 -41
  584. package/dist/client/services/tool-executor.d.ts.map +0 -1
  585. package/dist/client/services/tool-executor.js +0 -169
  586. package/dist/client/services/tool-executor.js.map +0 -1
  587. package/dist/client/services/workspace-schema-cache.d.ts +0 -149
  588. package/dist/client/services/workspace-schema-cache.d.ts.map +0 -1
  589. package/dist/client/services/workspace-schema-cache.js +0 -732
  590. package/dist/client/services/workspace-schema-cache.js.map +0 -1
  591. package/dist/client/specialist-daemon.d.ts +0 -77
  592. package/dist/client/specialist-daemon.d.ts.map +0 -1
  593. package/dist/client/specialist-daemon.js +0 -197
  594. package/dist/client/specialist-daemon.js.map +0 -1
  595. package/dist/client/specialists.d.ts +0 -53
  596. package/dist/client/specialists.d.ts.map +0 -1
  597. package/dist/client/specialists.js +0 -178
  598. package/dist/client/specialists.js.map +0 -1
  599. package/dist/client/tool-schema-loader.d.ts +0 -62
  600. package/dist/client/tool-schema-loader.d.ts.map +0 -1
  601. package/dist/client/tool-schema-loader.js +0 -232
  602. package/dist/client/tool-schema-loader.js.map +0 -1
  603. package/dist/client/types.d.ts +0 -327
  604. package/dist/client/types.d.ts.map +0 -1
  605. package/dist/client/types.js +0 -121
  606. package/dist/client/types.js.map +0 -1
  607. package/dist/commands/seed-config.d.ts +0 -9
  608. package/dist/commands/seed-config.d.ts.map +0 -1
  609. package/dist/commands/seed-config.js +0 -377
  610. package/dist/commands/seed-config.js.map +0 -1
  611. package/dist/commands/setup.d.ts +0 -11
  612. package/dist/commands/setup.d.ts.map +0 -1
  613. package/dist/commands/setup.js +0 -320
  614. package/dist/commands/setup.js.map +0 -1
  615. package/dist/lib/discussion-lock.d.ts +0 -42
  616. package/dist/lib/discussion-lock.d.ts.map +0 -1
  617. package/dist/lib/discussion-lock.js +0 -110
  618. package/dist/lib/discussion-lock.js.map +0 -1
  619. package/dist/mcp/signal-handler.d.ts +0 -82
  620. package/dist/mcp/signal-handler.d.ts.map +0 -1
  621. package/dist/mcp/signal-handler.js +0 -406
  622. package/dist/mcp/signal-handler.js.map +0 -1
  623. package/dist/mcp/tools/__tests__/discussion-forward.test.d.ts +0 -2
  624. package/dist/mcp/tools/__tests__/discussion-forward.test.d.ts.map +0 -1
  625. package/dist/mcp/tools/__tests__/discussion-forward.test.js +0 -218
  626. package/dist/mcp/tools/__tests__/discussion-forward.test.js.map +0 -1
  627. package/dist/mcp/tools/app-member.d.ts +0 -14
  628. package/dist/mcp/tools/app-member.d.ts.map +0 -1
  629. package/dist/mcp/tools/app-member.js +0 -195
  630. package/dist/mcp/tools/app-member.js.map +0 -1
  631. package/dist/mcp/tools/app-scaffold.d.ts +0 -14
  632. package/dist/mcp/tools/app-scaffold.d.ts.map +0 -1
  633. package/dist/mcp/tools/app-scaffold.js +0 -581
  634. package/dist/mcp/tools/app-scaffold.js.map +0 -1
  635. package/dist/mcp/tools/bot-config/constants.d.ts +0 -23
  636. package/dist/mcp/tools/bot-config/constants.d.ts.map +0 -1
  637. package/dist/mcp/tools/bot-config/constants.js +0 -94
  638. package/dist/mcp/tools/bot-config/constants.js.map +0 -1
  639. package/dist/mcp/tools/bot-config/core.d.ts +0 -253
  640. package/dist/mcp/tools/bot-config/core.d.ts.map +0 -1
  641. package/dist/mcp/tools/bot-config/core.js +0 -2456
  642. package/dist/mcp/tools/bot-config/core.js.map +0 -1
  643. package/dist/mcp/tools/bot-config/index.d.ts +0 -10
  644. package/dist/mcp/tools/bot-config/index.d.ts.map +0 -1
  645. package/dist/mcp/tools/bot-config/index.js +0 -59
  646. package/dist/mcp/tools/bot-config/index.js.map +0 -1
  647. package/dist/mcp/tools/bot-config/tools.d.ts +0 -7
  648. package/dist/mcp/tools/bot-config/tools.d.ts.map +0 -1
  649. package/dist/mcp/tools/bot-config/tools.js +0 -15
  650. package/dist/mcp/tools/bot-config/tools.js.map +0 -1
  651. package/dist/mcp/tools/bot-config/types.d.ts +0 -50
  652. package/dist/mcp/tools/bot-config/types.d.ts.map +0 -1
  653. package/dist/mcp/tools/bot-config/types.js +0 -6
  654. package/dist/mcp/tools/bot-config/types.js.map +0 -1
  655. package/dist/mcp/tools/bug-fixer-tools.d.ts +0 -45
  656. package/dist/mcp/tools/bug-fixer-tools.d.ts.map +0 -1
  657. package/dist/mcp/tools/bug-fixer-tools.js +0 -1096
  658. package/dist/mcp/tools/bug-fixer-tools.js.map +0 -1
  659. package/dist/mcp/tools/document.d.ts +0 -11
  660. package/dist/mcp/tools/document.d.ts.map +0 -1
  661. package/dist/mcp/tools/document.js +0 -741
  662. package/dist/mcp/tools/document.js.map +0 -1
  663. package/dist/mcp/tools/investigate.d.ts +0 -9
  664. package/dist/mcp/tools/investigate.d.ts.map +0 -1
  665. package/dist/mcp/tools/investigate.js +0 -254
  666. package/dist/mcp/tools/investigate.js.map +0 -1
  667. package/dist/mcp/utils/pagination.d.ts +0 -40
  668. package/dist/mcp/utils/pagination.d.ts.map +0 -1
  669. package/dist/mcp/utils/pagination.js +0 -55
  670. package/dist/mcp/utils/pagination.js.map +0 -1
  671. package/dist/modules/bug-reports/bug-config.d.ts +0 -25
  672. package/dist/modules/bug-reports/bug-config.d.ts.map +0 -1
  673. package/dist/modules/bug-reports/bug-config.js +0 -187
  674. package/dist/modules/bug-reports/bug-config.js.map +0 -1
  675. package/dist/modules/bug-reports/bug-monitor.d.ts +0 -108
  676. package/dist/modules/bug-reports/bug-monitor.d.ts.map +0 -1
  677. package/dist/modules/bug-reports/bug-monitor.js +0 -510
  678. package/dist/modules/bug-reports/bug-monitor.js.map +0 -1
  679. package/dist/modules/bug-reports/giuseppe-agent.d.ts +0 -58
  680. package/dist/modules/bug-reports/giuseppe-agent.d.ts.map +0 -1
  681. package/dist/modules/bug-reports/giuseppe-agent.js +0 -467
  682. package/dist/modules/bug-reports/giuseppe-agent.js.map +0 -1
  683. package/dist/modules/bug-reports/giuseppe-ai.d.ts +0 -83
  684. package/dist/modules/bug-reports/giuseppe-ai.d.ts.map +0 -1
  685. package/dist/modules/bug-reports/giuseppe-ai.js +0 -466
  686. package/dist/modules/bug-reports/giuseppe-ai.js.map +0 -1
  687. package/dist/modules/bug-reports/giuseppe-bot.d.ts +0 -110
  688. package/dist/modules/bug-reports/giuseppe-bot.d.ts.map +0 -1
  689. package/dist/modules/bug-reports/giuseppe-bot.js +0 -804
  690. package/dist/modules/bug-reports/giuseppe-bot.js.map +0 -1
  691. package/dist/modules/bug-reports/giuseppe-daemon.d.ts +0 -80
  692. package/dist/modules/bug-reports/giuseppe-daemon.d.ts.map +0 -1
  693. package/dist/modules/bug-reports/giuseppe-daemon.js +0 -617
  694. package/dist/modules/bug-reports/giuseppe-daemon.js.map +0 -1
  695. package/dist/modules/bug-reports/giuseppe-files.d.ts +0 -64
  696. package/dist/modules/bug-reports/giuseppe-files.d.ts.map +0 -1
  697. package/dist/modules/bug-reports/giuseppe-files.js +0 -375
  698. package/dist/modules/bug-reports/giuseppe-files.js.map +0 -1
  699. package/dist/modules/bug-reports/giuseppe-git.d.ts +0 -48
  700. package/dist/modules/bug-reports/giuseppe-git.d.ts.map +0 -1
  701. package/dist/modules/bug-reports/giuseppe-git.js +0 -298
  702. package/dist/modules/bug-reports/giuseppe-git.js.map +0 -1
  703. package/dist/modules/bug-reports/giuseppe-lsp.d.ts +0 -113
  704. package/dist/modules/bug-reports/giuseppe-lsp.d.ts.map +0 -1
  705. package/dist/modules/bug-reports/giuseppe-lsp.js +0 -485
  706. package/dist/modules/bug-reports/giuseppe-lsp.js.map +0 -1
  707. package/dist/modules/bug-reports/giuseppe-prompt.d.ts +0 -5
  708. package/dist/modules/bug-reports/giuseppe-prompt.d.ts.map +0 -1
  709. package/dist/modules/bug-reports/giuseppe-prompt.js +0 -94
  710. package/dist/modules/bug-reports/giuseppe-prompt.js.map +0 -1
  711. package/dist/modules/bug-reports/index.d.ts +0 -77
  712. package/dist/modules/bug-reports/index.d.ts.map +0 -1
  713. package/dist/modules/bug-reports/index.js +0 -215
  714. package/dist/modules/bug-reports/index.js.map +0 -1
  715. package/dist/modules/bug-reports/pending-classification-registry.d.ts +0 -28
  716. package/dist/modules/bug-reports/pending-classification-registry.d.ts.map +0 -1
  717. package/dist/modules/bug-reports/pending-classification-registry.js +0 -50
  718. package/dist/modules/bug-reports/pending-classification-registry.js.map +0 -1
  719. package/dist/modules/bug-reports/pending-fix-registry.d.ts +0 -30
  720. package/dist/modules/bug-reports/pending-fix-registry.d.ts.map +0 -1
  721. package/dist/modules/bug-reports/pending-fix-registry.js +0 -42
  722. package/dist/modules/bug-reports/pending-fix-registry.js.map +0 -1
  723. package/dist/modules/bug-reports/pending-registry.d.ts +0 -27
  724. package/dist/modules/bug-reports/pending-registry.d.ts.map +0 -1
  725. package/dist/modules/bug-reports/pending-registry.js +0 -49
  726. package/dist/modules/bug-reports/pending-registry.js.map +0 -1
  727. package/dist/modules/bug-reports/types.d.ts +0 -123
  728. package/dist/modules/bug-reports/types.d.ts.map +0 -1
  729. package/dist/modules/bug-reports/types.js +0 -9
  730. package/dist/modules/bug-reports/types.js.map +0 -1
  731. package/dist/plugins/bug-fixer/index.d.ts +0 -2
  732. package/dist/plugins/bug-fixer/index.d.ts.map +0 -1
  733. package/dist/plugins/bug-fixer/index.js +0 -18
  734. package/dist/plugins/bug-fixer/index.js.map +0 -1
  735. package/dist/plugins/bug-fixer/tools.d.ts +0 -45
  736. package/dist/plugins/bug-fixer/tools.d.ts.map +0 -1
  737. package/dist/plugins/bug-fixer/tools.js +0 -1096
  738. package/dist/plugins/bug-fixer/tools.js.map +0 -1
  739. package/dist/plugins/vipunen/__tests__/tools.test.d.ts +0 -10
  740. package/dist/plugins/vipunen/__tests__/tools.test.d.ts.map +0 -1
  741. package/dist/plugins/vipunen/__tests__/tools.test.js +0 -646
  742. package/dist/plugins/vipunen/__tests__/tools.test.js.map +0 -1
  743. package/dist/routes/agents.d.ts +0 -44
  744. package/dist/routes/agents.d.ts.map +0 -1
  745. package/dist/routes/agents.js +0 -311
  746. package/dist/routes/agents.js.map +0 -1
  747. package/dist/services/agent-credential-store.d.ts +0 -73
  748. package/dist/services/agent-credential-store.d.ts.map +0 -1
  749. package/dist/services/agent-credential-store.js +0 -212
  750. package/dist/services/agent-credential-store.js.map +0 -1
  751. package/dist/stdio-server.d.ts +0 -14
  752. package/dist/stdio-server.d.ts.map +0 -1
  753. package/dist/stdio-server.js +0 -101
  754. package/dist/stdio-server.js.map +0 -1
  755. package/dist/workspace/context.d.ts +0 -148
  756. package/dist/workspace/context.d.ts.map +0 -1
  757. package/dist/workspace/context.js +0 -339
  758. package/dist/workspace/context.js.map +0 -1
  759. package/dist/workspace/credentials.d.ts +0 -55
  760. package/dist/workspace/credentials.d.ts.map +0 -1
  761. package/dist/workspace/credentials.js +0 -239
  762. package/dist/workspace/credentials.js.map +0 -1
  763. package/dist/workspace/index.d.ts +0 -21
  764. package/dist/workspace/index.d.ts.map +0 -1
  765. package/dist/workspace/index.js +0 -45
  766. package/dist/workspace/index.js.map +0 -1
  767. package/dist/workspace/loader.d.ts +0 -27
  768. package/dist/workspace/loader.d.ts.map +0 -1
  769. package/dist/workspace/loader.js +0 -222
  770. package/dist/workspace/loader.js.map +0 -1
  771. package/dist/workspace/schema.d.ts +0 -37
  772. package/dist/workspace/schema.d.ts.map +0 -1
  773. package/dist/workspace/schema.js +0 -192
  774. package/dist/workspace/schema.js.map +0 -1
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,201 @@ 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
+ /** Model-facing text for a pre-execution permission denial. */
150
+ function permissionDeniedMessage(denied) {
151
+ if (denied.reason === 'bot-scope') {
152
+ return `Permission denied: This bot does not have access to workflow ${denied.workflowId}.`;
153
+ }
154
+ if (denied.reason === 'unverified-insight') {
155
+ return `Permission denied: Could not verify which workflows insight ${denied.workflowId} reads from — `
156
+ + 'it may have been deleted. Call list_insights to see valid insight IDs, then retry.';
157
+ }
158
+ return `Permission denied: You do not have access to workflow ${denied.workflowId}.`;
159
+ }
160
+ const MODEL_HAIKU = 'claude-haiku-4-5';
161
+ const MODEL_SONNET = 'claude-sonnet-4-6';
162
+ const MAX_TOOL_RESULT_CHARS = 40000;
163
+ const MAX_PROMPT_TRIM_ATTEMPTS = 5;
51
164
  const IMAGE_MIME_TYPES = new Set(['image/jpeg', 'image/png', 'image/gif', 'image/webp']);
52
165
  const DOCUMENT_MIME_TYPES = new Set(['application/pdf']);
53
166
  const TEXT_MIME_TYPES = new Set(['text/plain', 'text/csv', 'text/html', 'text/markdown', 'application/json', 'application/xml']);
167
+ const EXCEL_MIME_TYPES = new Set([
168
+ 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', // .xlsx only
169
+ ]);
170
+ const WORD_MIME_TYPES = new Set([
171
+ 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', // .docx
172
+ ]);
54
173
  const MAX_FILE_SIZE = 5 * 1024 * 1024;
174
+ const MAX_OFFICE_FILE_SIZE = 10 * 1024 * 1024;
175
+ const OFFICE_TEXT_CAP = 512 * 1024;
176
+ const HEAP_BACKPRESSURE_THRESHOLD = 0.7;
177
+ function fileSizeLimit(mime) {
178
+ return EXCEL_MIME_TYPES.has(mime) || WORD_MIME_TYPES.has(mime) ? MAX_OFFICE_FILE_SIZE : MAX_FILE_SIZE;
179
+ }
180
+ const ATTACHMENT_KINDS = [
181
+ { label: 'Image', trailing: 'included below for vision', matches: (mimeType) => IMAGE_MIME_TYPES.has(mimeType) },
182
+ { label: 'Document', trailing: 'included below', matches: (mimeType) => DOCUMENT_MIME_TYPES.has(mimeType) || TEXT_MIME_TYPES.has(mimeType) },
183
+ { label: 'Spreadsheet', trailing: 'included below as CSV per sheet', matches: (mimeType) => EXCEL_MIME_TYPES.has(mimeType) },
184
+ { label: 'Word document', trailing: 'included below as plain text', matches: (mimeType) => WORD_MIME_TYPES.has(mimeType) },
185
+ ];
186
+ function describeAttachment(mime, filename, fileId) {
187
+ const matched = ATTACHMENT_KINDS.find((kind) => kind.matches(mime));
188
+ if (!matched) {
189
+ return null;
190
+ }
191
+ return `[${matched.label} attached: ${filename} (fileId: ${fileId}) — ${matched.trailing}]`;
192
+ }
193
+ function isSupportedMime(mime) {
194
+ return IMAGE_MIME_TYPES.has(mime) || DOCUMENT_MIME_TYPES.has(mime) || TEXT_MIME_TYPES.has(mime)
195
+ || EXCEL_MIME_TYPES.has(mime) || WORD_MIME_TYPES.has(mime);
196
+ }
197
+ function isOfficeMime(mime) {
198
+ return EXCEL_MIME_TYPES.has(mime) || WORD_MIME_TYPES.has(mime);
199
+ }
200
+ function capText(text) {
201
+ return text.length > OFFICE_TEXT_CAP ? text.slice(0, OFFICE_TEXT_CAP) + '\n\n[...content truncated...]' : text;
202
+ }
203
+ function isHeapUnderPressure() {
204
+ const { heapUsed } = process.memoryUsage();
205
+ const heapLimit = v8.getHeapStatistics().heap_size_limit;
206
+ return heapUsed / heapLimit > HEAP_BACKPRESSURE_THRESHOLD;
207
+ }
208
+ function cellToCsv(value) {
209
+ if (value === null || value === undefined) {
210
+ return '';
211
+ }
212
+ if (value instanceof Date) {
213
+ return value.toISOString();
214
+ }
215
+ if (typeof value === 'object') {
216
+ const v = value;
217
+ if (typeof v.result !== 'undefined') {
218
+ return cellToCsv(v.result);
219
+ }
220
+ if (typeof v.text === 'string') {
221
+ return cellToCsv(v.text);
222
+ }
223
+ if (Array.isArray(v.richText)) {
224
+ return v.richText.map((rt) => rt.text || '').join('');
225
+ }
226
+ if (typeof v.error === 'string') {
227
+ return v.error;
228
+ }
229
+ return '';
230
+ }
231
+ const s = String(value);
232
+ return /[",\n]/.test(s) ? `"${s.replace(/"/g, '""')}"` : s;
233
+ }
234
+ // Global mutex — serialize Office downloads + parses across the pod to bound peak memory
235
+ let officeParseQueue = Promise.resolve();
236
+ function withOfficeParseLock(fn) {
237
+ const next = officeParseQueue.then(fn, fn);
238
+ officeParseQueue = next.catch(() => undefined);
239
+ return next;
240
+ }
241
+ const SONNET_ROUTE = { model: MODEL_SONNET, maxTokens: 16384 };
55
242
  const TOOL_STATUS_LABELS = {
56
- list_activities: 'Searching activities', count_activities: 'Counting activities',
243
+ list_activities: 'Searching activities',
57
244
  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',
245
+ update_activity: 'Updating activity',
246
+ describe_workflows: 'Reading workflows',
247
+ update_workflow_structure: 'Updating workflow structure',
248
+ run_insight: 'Running report', save_insight: 'Saving report',
249
+ search_workspace_users: 'Searching users',
62
250
  fetch_discussion_messages: 'Reading messages', add_discussion_message: 'Sending message',
63
251
  join_discussion: 'Joining discussion',
252
+ query_events: 'Loading events', manage_calendar: 'Managing calendars',
253
+ create_event: 'Creating event',
254
+ update_event: 'Updating event', delete_event: 'Deleting event',
255
+ respond_to_invite: 'Responding to invite',
256
+ set_workflow_permission: 'Updating workflow access',
257
+ manage_my_profile: 'Updating my profile',
64
258
  };
65
259
  // ===== BOT CLASS =====
66
260
  class Bot {
@@ -97,37 +291,47 @@ class Bot {
97
291
  workspaceUpdatedHandler = null;
98
292
  cacheInvalidateHandler = null;
99
293
  _connected = false;
100
- // Config
101
294
  config;
295
+ anthropicApiKey;
102
296
  botManager;
103
- constructor(config) {
297
+ constructor(config, runtime) {
104
298
  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,
299
+ ...config,
300
+ accessLevel: config.accessLevel ?? 'all',
301
+ allowedWorkflows: config.allowedWorkflows ?? [],
302
+ allowBotMessages: config.allowBotMessages ?? false,
303
+ helperMode: config.helperMode ?? false,
113
304
  };
114
- this.botManager = config.botManager || null;
305
+ this.anthropicApiKey = runtime.anthropicApiKey;
306
+ this.botManager = runtime.botManager ?? null;
115
307
  this._systemPrompt = config.systemPrompt;
116
- this._responseMode = config.responseMode || 'always';
308
+ this._responseMode = config.responseMode ?? 'always';
117
309
  this.logger = (0, logger_1.createLogger)({ component: 'Bot' });
118
310
  this.clientManager = new hailer_clients_1.HailerClientManager(config.apiHost, config.email, config.password);
119
- this.toolExecutor = new tool_executor_1.ToolExecutor(config.toolRegistry);
311
+ this.toolExecutor = new tool_executor_1.ToolExecutor(runtime.toolRegistry);
120
312
  this.signalRouter = new services_1.SignalRouter(this.logger);
121
313
  this.permissions = new services_1.BotPermissions(this.config.allowedWorkflows, this.logger);
122
314
  this.workspaceRefresh = new services_1.WorkspaceRefresh(this.logger);
123
315
  }
124
316
  // 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; }
317
+ get email() {
318
+ return this.config.email;
319
+ }
320
+ get password() {
321
+ return this.config.password;
322
+ }
323
+ get accessLevel() {
324
+ return this.config.accessLevel;
325
+ }
326
+ get connected() {
327
+ return this._connected;
328
+ }
329
+ get workspaceId() {
330
+ return this._workspaceId;
331
+ }
332
+ get botUserId() {
333
+ return this.userId;
334
+ }
131
335
  updateSystemPrompt(prompt) {
132
336
  this._systemPrompt = prompt;
133
337
  this.logger.info('System prompt updated live', { hasPrompt: !!prompt });
@@ -136,21 +340,88 @@ class Bot {
136
340
  this._responseMode = mode || 'always';
137
341
  this.logger.info('Response mode updated live', { responseMode: this._responseMode });
138
342
  }
343
+ updateHelperMode(helperMode) {
344
+ this.config.helperMode = !!helperMode;
345
+ this.logger.info('Helper mode updated live', { helperMode: this.config.helperMode });
346
+ }
139
347
  // ===== LIFECYCLE =====
140
348
  async start() {
141
- if (this._connected)
349
+ if (this._connected) {
142
350
  return;
351
+ }
143
352
  this.logger.debug('Starting bot', { email: this.config.email });
144
353
  // 1. Connect
145
354
  this.client = await this.clientManager.connect();
146
355
  this.config.password = ''; // Clear from memory — connection is established
147
356
  // 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
- ]);
357
+ const initFields = ['user', 'processes', 'users', 'network', 'networks', 'teams', 'groups'];
358
+ this.init = await this.client.socket.request(hailer_rpc_1.HailerRpc.Core.init, [initFields]);
359
+ try {
360
+ const pendingInvites = await this.client.socket.request(hailer_rpc_1.HailerRpc.User.inviteList, []);
361
+ if (pendingInvites?.length) {
362
+ for (const invite of pendingInvites) {
363
+ await this.client.socket.request(hailer_rpc_1.HailerRpc.User.inviteAccept, [invite.invite_key]);
364
+ await this.client.socket.request(hailer_rpc_1.HailerRpc.Core.switchEcosystem, [invite.cid]);
365
+ this.logger.info('Accepted workspace invite', { workspaceId: invite.cid, workspaceName: invite.network?.name });
366
+ }
367
+ this.init = await this.client.socket.request(hailer_rpc_1.HailerRpc.Core.init, [initFields]);
368
+ }
369
+ }
370
+ catch (err) {
371
+ this.logger.warn('Failed to check/accept pending invites', { error: err instanceof Error ? err.message : err });
372
+ }
373
+ // Hailer drops password-auth users into their personal "My Hailer" ecosystem
374
+ // on each fresh login, even after they've accepted a workspace invite. Force
375
+ // the configured workspace as the active ecosystem so the bot operates where
376
+ // it was provisioned, not in its personal workspace.
377
+ if (this.config.workspaceId && this.init.network?._id !== this.config.workspaceId) {
378
+ const fromWorkspaceId = this.init.network?._id;
379
+ try {
380
+ await this.client.socket.request(hailer_rpc_1.HailerRpc.Core.switchEcosystem, [this.config.workspaceId]);
381
+ this.init = await this.client.socket.request(hailer_rpc_1.HailerRpc.Core.init, [initFields]);
382
+ this.logger.info('Switched to configured workspace', {
383
+ from: fromWorkspaceId, to: this.config.workspaceId,
384
+ });
385
+ }
386
+ catch (err) {
387
+ this.logger.warn('Failed to switch to configured workspace', {
388
+ workspaceId: this.config.workspaceId,
389
+ error: err instanceof Error ? err.message : err,
390
+ });
391
+ }
392
+ }
393
+ // Self-prune: probe the bot's own Agent Directory activity. If the
394
+ // activity is gone (definitively deleted OR otherwise unreachable in
395
+ // a way that matches the gone signals), drop the local config entry
396
+ // so we stop trying to run this bot. The bot's Hailer user account
397
+ // is NEVER deleted from here — a previous version did, and the
398
+ // classifier shared a numeric code with "Permission denied" which
399
+ // caused mass user-account deletion on transient permission errors.
400
+ // Orphaned bot users are reaped separately by Hailer's inactive-user
401
+ // prune (out-of-band).
402
+ if (this.config.activityId && this.config.workspaceId) {
403
+ try {
404
+ await this.client.socket.request(hailer_rpc_1.HailerRpc.Activities.load, [this.config.activityId]);
405
+ }
406
+ catch (err) {
407
+ const shape = (0, bot_config_1.extractHailerError)(err);
408
+ if ((0, bot_config_1.isActivityGone)(shape)) {
409
+ this.logger.info('Self-probe: activity gone — pruning local config entry (keeping Hailer user)', {
410
+ activityId: this.config.activityId, workspaceId: this.config.workspaceId,
411
+ msg: shape.msg, code: shape.code,
412
+ });
413
+ this.pruneSelfFromConfig();
414
+ throw new ActivityGoneError(this.config.activityId, this.config.workspaceId);
415
+ }
416
+ this.logger.debug('Self-probe non-deletion error — continuing startup', {
417
+ activityId: this.config.activityId, msg: shape.msg, code: shape.code,
418
+ });
419
+ }
420
+ }
151
421
  this.userId = this.init.user?._id || '';
152
- if (!this.userId)
422
+ if (!this.userId) {
153
423
  throw new Error('Could not determine bot user ID');
424
+ }
154
425
  (0, types_1.normalizeInitProcesses)(this.init);
155
426
  this._workspaceId = this.init.network?._id || this.config.workspaceId;
156
427
  // 3. Build caches
@@ -172,7 +443,7 @@ class Bot {
172
443
  workflowNames: this.init.processes.map(p => p.name),
173
444
  });
174
445
  // 4. Anthropic client
175
- this.anthropic = new sdk_1.default({ apiKey: this.config.anthropicApiKey });
446
+ this.anthropic = new sdk_1.default({ apiKey: this.anthropicApiKey });
176
447
  // 5. Services
177
448
  const botConnection = {
178
449
  client: this.client,
@@ -194,11 +465,13 @@ class Bot {
194
465
  email: this.config.email, password: '', // Intentionally empty — cleared after connect
195
466
  workspaceRoles: { [currentWorkspaceId]: 'admin' },
196
467
  currentWorkspaceId, allowedGroups: [tool_registry_1.ToolGroup.READ, tool_registry_1.ToolGroup.WRITE, tool_registry_1.ToolGroup.BOT_INTERNAL],
468
+ botActivityId: this.config.activityId,
197
469
  };
198
470
  // 7. Wire workspace refresh
199
471
  this.workspaceRefresh.setHandler(async (scopes) => {
200
- if (!this.client || !this.init)
472
+ if (!this.client || !this.init) {
201
473
  return;
474
+ }
202
475
  const result = await services_1.WorkspaceRefresh.refresh(this.client, scopes, this.init, this.config.workspaceId, this.permissions, this.userContext, this.logger);
203
476
  this.init = result.init;
204
477
  this.workspaceCache = result.workspaceCache;
@@ -206,10 +479,17 @@ class Bot {
206
479
  this._workspaceId = result.workspaceId;
207
480
  });
208
481
  // 8. Subscribe to signals
209
- this.signalHandler = (data) => this.handleSignal({
210
- type: 'messenger.new', data, timestamp: Date.now(),
211
- workspaceId: data.sid,
212
- });
482
+ this.signalHandler = (data) => {
483
+ this.logger.info('Bot received messenger.new signal', {
484
+ discussion: data.discussion,
485
+ uid: data.uid,
486
+ msg_id: data.msg_id,
487
+ });
488
+ this.handleSignal({
489
+ type: 'messenger.new', data, timestamp: Date.now(),
490
+ workspaceId: data.sid,
491
+ });
492
+ };
213
493
  this.clientManager.onSignal('messenger.new', this.signalHandler);
214
494
  this.processUpdatedHandler = () => this.workspaceRefresh.schedule('processes');
215
495
  this.workspaceUpdatedHandler = () => this.workspaceRefresh.schedule('network');
@@ -219,6 +499,285 @@ class Bot {
219
499
  this.clientManager.onSignal('cache.invalidate', this.cacheInvalidateHandler);
220
500
  this._connected = true;
221
501
  this.logger.debug('Bot started', { userId: this.userId, workspaceId: this._workspaceId });
502
+ // Fire-and-forget: re-assert that the bot is following its own
503
+ // activity discussion on every startup. The self-intro path used to be
504
+ // the only caller of joinActivityDiscussion, but it short-circuits on
505
+ // `introPosted: true`, leaving bots that were unfollowed in the past
506
+ // (e.g. by the pre-fix raw activities.follow toggle, or by any other
507
+ // path that flipped their follow state) silently subscribed to nothing.
508
+ // Running joinActivityDiscussion here closes that loop — it's
509
+ // idempotent (no-op if already following).
510
+ this.ensureFollowingOwnDiscussion().catch((err) => {
511
+ const { msg, code } = (0, bot_config_1.extractHailerError)(err);
512
+ this.logger.warn('ensureFollowingOwnDiscussion threw (non-fatal)', { msg, code });
513
+ });
514
+ // Fire-and-forget self-introduction. One-shot per bot (persisted via
515
+ // BotEntry.introPosted), so restarts don't re-spam the discussion. Errors
516
+ // are logged inside the method — this catch is only a safety net.
517
+ this.introduceSelfIfNeeded().catch((err) => {
518
+ const { msg, code } = (0, bot_config_1.extractHailerError)(err);
519
+ this.logger.warn('Self-intro threw (non-fatal)', { msg, code });
520
+ });
521
+ }
522
+ /**
523
+ * Re-join the bot's own activity discussion if (and only if) the bot has
524
+ * drifted out of it. Runs every startup so bots that lost their follow
525
+ * state (e.g. via the pre-51254a2 raw activities.follow toggle) recover.
526
+ *
527
+ * Reads the activity's `followers` list and skips the join when the bot's
528
+ * userId is already there. activities.follow is a toggle that emits a
529
+ * leave/join event on every call — even toggle-toggle pairs — so calling
530
+ * unconditionally pollutes the discussion with "left / joined" pairs on
531
+ * every restart (visible in the timeline after deploy → retire → deploy).
532
+ */
533
+ async ensureFollowingOwnDiscussion() {
534
+ if (!this.config.activityId || !this.hailerApi || !this.userId) {
535
+ return;
536
+ }
537
+ try {
538
+ const activity = await this.hailerApi.fetchActivityById(this.config.activityId);
539
+ const followers = Array.isArray(activity?.followers) ? activity.followers : [];
540
+ if (followers.includes(this.userId)) {
541
+ this.logger.debug('Already following own discussion — skipping toggle', {
542
+ activityId: this.config.activityId,
543
+ });
544
+ return;
545
+ }
546
+ await this.hailerApi.joinActivityDiscussion(this.config.activityId);
547
+ }
548
+ catch (err) {
549
+ const { msg, code } = (0, bot_config_1.extractHailerError)(err);
550
+ this.logger.debug('ensureFollowingOwnDiscussion failed (non-fatal)', { msg, code });
551
+ }
552
+ }
553
+ /**
554
+ * Post a one-time greeting in the bot's own activity discussion explaining
555
+ * what users can ask the bot to change about itself (system prompt, etc.).
556
+ * Marks the entry's `introPosted` flag in `.bot-config` so subsequent
557
+ * restarts don't repeat the message.
558
+ *
559
+ * Follow state is handled separately by ensureFollowingOwnDiscussion()
560
+ * which runs on every startup. We don't flip `introPosted` until the send
561
+ * succeeds, so a permission failure on first start retries on the next
562
+ * start instead of silently giving up.
563
+ */
564
+ async introduceSelfIfNeeded() {
565
+ if (!this.config.activityId || !this.config.workspaceId || !this.client) {
566
+ return;
567
+ }
568
+ const cfg = (0, bot_config_1.loadWorkspaceConfigFile)(this.config.workspaceId);
569
+ const entry = cfg.bots.find((b) => b.activityId === this.config.activityId);
570
+ if (!entry) {
571
+ return;
572
+ }
573
+ if (entry.introPosted) {
574
+ return;
575
+ }
576
+ let discussionId;
577
+ try {
578
+ const activity = await this.client.socket.request(hailer_rpc_1.HailerRpc.Activities.load, [this.config.activityId]);
579
+ discussionId = activity?.discussion;
580
+ }
581
+ catch (err) {
582
+ const { msg, code } = (0, bot_config_1.extractHailerError)(err);
583
+ this.logger.warn('Self-intro: activities.load failed', { msg, code });
584
+ return;
585
+ }
586
+ if (!discussionId) {
587
+ return;
588
+ }
589
+ if (!this.anthropic) {
590
+ return;
591
+ }
592
+ // Generate the intro via LLM so each bot speaks in its own voice. The
593
+ // bot's system prompt already explains its self-management capabilities,
594
+ // so a "pirate" bot greets in pirate voice while still mentioning users
595
+ // can change it.
596
+ const systemPrompt = (0, services_1.buildSystemPrompt)({
597
+ init: this.init, userId: this.userId,
598
+ workspaceOverview: this.workspaceOverview, customPrompt: this._systemPrompt,
599
+ helperMode: this.config.helperMode,
600
+ hasSeedContext: !!this.config.seedContext,
601
+ responseMode: this._responseMode,
602
+ accessLevel: this.config.accessLevel,
603
+ allowBotMessages: this.config.allowBotMessages,
604
+ });
605
+ const { turns: seedTurns, viewedSlides } = parseSeedTurns(this.config.seedContext, this.logger);
606
+ const hasSeed = seedTurns.length > 0;
607
+ // Map slide ids → short human labels for the prompt. Anything not in
608
+ // the map is dropped (defence against stale ids leaking through).
609
+ const SLIDE_LABEL = {
610
+ title: 'the Hailer overview cover',
611
+ what: 'what Hailer is in one line',
612
+ problem: 'the trackers-vs-chat problem framing',
613
+ 'core-label': 'the core-concepts section',
614
+ workspaces: 'Workspaces',
615
+ workflows: 'Workflows',
616
+ activities: 'Activities',
617
+ discussions: 'Discussions',
618
+ 'build-label': 'the build-and-extend section',
619
+ 'apps-studio': 'Apps & Hailer Studio',
620
+ sdk: 'the Hailer SDK',
621
+ 'sdk-code': 'the workflow-as-code example',
622
+ mcp: 'Hailer MCP',
623
+ insights: 'Insights & Automations',
624
+ closer: 'the closing one-platform statement',
625
+ };
626
+ const slideLabels = viewedSlides
627
+ .map((id) => SLIDE_LABEL[id])
628
+ .filter((s) => typeof s === 'string');
629
+ const slideHint = slideLabels.length > 0
630
+ ? `\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."`
631
+ : '';
632
+ // Only promise an automatic build when Studio session creation is
633
+ // configured for this deployment; otherwise nothing builds the
634
+ // workspace and the bot must not promise a build that never runs. The
635
+ // graduation flow gates createStudioSession on the same env var, so
636
+ // "build promised" matches "build attempted".
637
+ const studioBuilding = !!config_1.environment.STUDIO_SESSIONS_CREATE_URL;
638
+ const introInstruction = hasSeed
639
+ ? (studioBuilding
640
+ ? `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.
641
+
642
+ What this first message needs to do:
643
+
644
+ 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").
645
+
646
+ 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.
647
+
648
+ 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.
649
+
650
+ 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.
651
+
652
+ Tone: conversational, friendly, reassuring. No section headers, no bullet lists. Keep it under ~150 words.`
653
+ : `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.
654
+
655
+ What this first message needs to do:
656
+
657
+ 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").
658
+
659
+ 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.
660
+
661
+ 3. If the demo is too vague to start, ask ONE or TWO concrete clarifying questions instead.
662
+
663
+ 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.
664
+
665
+ Tone: conversational, friendly, action-oriented. No section headers; short bullets are fine only when naming proposed phases or fields. Keep it under ~180 words.`)
666
+ : `You are being posted in your own activity discussion for the first time. Introduce yourself briefly in your own voice.
667
+
668
+ 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).
669
+
670
+ 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.
671
+
672
+ 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.
673
+
674
+ Keep it short and conversational. No bullet lists, no headers.`;
675
+ const introInstructionFinal = introInstruction + slideHint;
676
+ const messages = [
677
+ ...seedTurns,
678
+ { role: 'user', content: introInstructionFinal },
679
+ ];
680
+ let response;
681
+ try {
682
+ response = await this.anthropic.messages.create({
683
+ model: MODEL_HAIKU,
684
+ max_tokens: 400,
685
+ temperature: 0.7,
686
+ system: systemPrompt,
687
+ messages,
688
+ });
689
+ }
690
+ catch (err) {
691
+ this.logger.warn('Self-intro: LLM call failed', {
692
+ activityId: this.config.activityId,
693
+ error: err instanceof Error ? err.message : String(err),
694
+ });
695
+ return;
696
+ }
697
+ const text = response.content
698
+ .filter((b) => b.type === 'text')
699
+ .map((b) => b.text)
700
+ .join('')
701
+ .trim();
702
+ if (!text) {
703
+ this.logger.warn('Self-intro: empty LLM response', { activityId: this.config.activityId });
704
+ return;
705
+ }
706
+ // Bill the intro generation to the workspace — same as any other LLM call.
707
+ if (this.tokenBilling && this._workspaceId) {
708
+ const usage = response.usage;
709
+ const cacheCreation = usage.cache_creation_input_tokens || 0;
710
+ const cacheRead = usage.cache_read_input_tokens || 0;
711
+ const cost = this.tokenBilling.calculateCost(usage.input_tokens, usage.output_tokens, cacheCreation, cacheRead, MODEL_HAIKU);
712
+ this.tokenBilling.burnTokens({
713
+ workspaceId: this._workspaceId,
714
+ inputTokens: usage.input_tokens, outputTokens: usage.output_tokens,
715
+ cacheCreationTokens: cacheCreation, cacheReadTokens: cacheRead, costUsd: cost,
716
+ sessionId: discussionId, model: MODEL_HAIKU,
717
+ });
718
+ }
719
+ try {
720
+ await this.client.socket.request(hailer_rpc_1.HailerRpc.Messenger.send, [{ msg: text }, discussionId]);
721
+ }
722
+ catch (err) {
723
+ const { msg: errMsg, code } = (0, bot_config_1.extractHailerError)(err);
724
+ this.logger.warn('Self-intro: messenger.send failed', {
725
+ activityId: this.config.activityId,
726
+ discussionId,
727
+ msg: errMsg,
728
+ code,
729
+ });
730
+ return;
731
+ }
732
+ entry.introPosted = true;
733
+ (0, bot_config_1.saveWorkspaceConfigFile)(cfg);
734
+ (0, bot_config_1.invalidateConfigCache)();
735
+ this.logger.info('Posted self-intro in own discussion', {
736
+ activityId: this.config.activityId,
737
+ discussionId,
738
+ length: text.length,
739
+ });
740
+ }
741
+ /**
742
+ * Teardown: stop the bot's websocket and live state. We intentionally do
743
+ * NOT delete the Hailer user account from here — that was previously a
744
+ * source of mass user-account deletion when the gone-classifier fired on
745
+ * transient permission errors. Orphaned bot users are reaped out-of-band
746
+ * by Hailer's inactive-user prune.
747
+ */
748
+ async destroy() {
749
+ await this.stop();
750
+ }
751
+ /**
752
+ * Remove this bot's entry from .bot-config/{workspaceId}.json. Called when
753
+ * the bot's own activity has been deleted in Hailer (detected via the
754
+ * self-probe in start()). Idempotent — safe if the entry is already gone.
755
+ */
756
+ pruneSelfFromConfig() {
757
+ if (!this.config.activityId || !this.config.workspaceId) {
758
+ return;
759
+ }
760
+ try {
761
+ const cfg = (0, bot_config_1.loadWorkspaceConfigFile)(this.config.workspaceId);
762
+ const before = cfg.bots.length;
763
+ cfg.bots = cfg.bots.filter((b) => b.activityId !== this.config.activityId);
764
+ if (cfg.bots.length === before) {
765
+ return;
766
+ }
767
+ (0, bot_config_1.saveWorkspaceConfigFile)(cfg);
768
+ (0, bot_config_1.invalidateConfigCache)();
769
+ this.logger.info('Pruned self from bot config', {
770
+ activityId: this.config.activityId,
771
+ workspaceId: this.config.workspaceId,
772
+ remaining: cfg.bots.length,
773
+ });
774
+ }
775
+ catch (err) {
776
+ this.logger.warn('Failed to prune self from bot config', {
777
+ activityId: this.config.activityId,
778
+ error: err instanceof Error ? err.message : err,
779
+ });
780
+ }
222
781
  }
223
782
  async stop() {
224
783
  this.logger.debug('Stopping bot');
@@ -247,8 +806,9 @@ class Bot {
247
806
  }
248
807
  // ===== SIGNAL HANDLING =====
249
808
  async handleSignal(signal) {
250
- if (!this._connected || !this.messageClassifier)
809
+ if (!this._connected || !this.messageClassifier) {
251
810
  return;
811
+ }
252
812
  try {
253
813
  const rawMsgId = signal.data.msg_id;
254
814
  const discussionId = signal.data.discussion;
@@ -257,23 +817,27 @@ class Bot {
257
817
  this.logger.warn('messenger.new signal has no dedup key');
258
818
  return;
259
819
  }
260
- if (this.signalRouter.isDuplicate(dedupKey))
820
+ if (this.signalRouter.isDuplicate(dedupKey)) {
261
821
  return;
822
+ }
262
823
  const message = await this.messageClassifier.extractIncomingMessage(signal);
263
824
  if (!message) {
264
- if (rawMsgId)
825
+ if (rawMsgId) {
265
826
  this.signalRouter.removeDedupKey(rawMsgId);
827
+ }
266
828
  return;
267
829
  }
268
830
  // Self-message guard — always skip own messages
269
- if (message.senderId === this.userId)
831
+ if (message.senderId === this.userId) {
270
832
  return;
833
+ }
271
834
  // Bot-to-bot guard
272
835
  if (this.botManager && this._workspaceId) {
273
836
  const botUserIds = this.botManager.getBotUserIdsForWorkspace(this._workspaceId);
274
837
  if (botUserIds.has(message.senderId)) {
275
- if (!this.config.allowBotMessages)
276
- return; // Hard block if not opted in
838
+ if (!this.config.allowBotMessages) {
839
+ return;
840
+ } // Hard block if not opted in
277
841
  // Only respond to bot messages if explicitly mentioned or replied to
278
842
  if (!message.isMention && !message.isReplyToBot) {
279
843
  this.logger.debug('Ignoring bot message - no mention or reply', {
@@ -304,27 +868,31 @@ class Bot {
304
868
  }
305
869
  }
306
870
  // Rate limiting
307
- if (this.signalRouter.isRateLimited(message.discussionId))
871
+ if (this.signalRouter.isRateLimited(message.discussionId)) {
308
872
  return;
873
+ }
309
874
  // Layer 1: Workspace membership
310
875
  if (!this.permissions.isMember(message.senderId)) {
311
876
  this.logger.debug('Ignoring message - not a workspace member', { senderId: message.senderId });
312
- if (rawMsgId)
877
+ if (rawMsgId) {
313
878
  this.signalRouter.removeDedupKey(rawMsgId);
879
+ }
314
880
  return;
315
881
  }
316
882
  // Layer 2: Access level
317
883
  if (!this.permissions.meetsAccessLevel(message.senderId, this.config.accessLevel)) {
318
884
  this.logger.debug('Ignoring message - access level not met', { senderId: message.senderId });
319
- if (rawMsgId)
885
+ if (rawMsgId) {
320
886
  this.signalRouter.removeDedupKey(rawMsgId);
887
+ }
321
888
  return;
322
889
  }
323
890
  // Engagement logic
324
891
  const state = this.signalRouter.getOrCreateState(message.discussionId);
325
892
  state.contextBuffer.push(message);
326
- if (!this.signalRouter.checkTrigger(message, this._responseMode))
893
+ if (!this.signalRouter.checkTrigger(message, this._responseMode)) {
327
894
  return;
895
+ }
328
896
  const isExplicit = this.signalRouter.isExplicitTrigger(message);
329
897
  if (state.state === 'idle') {
330
898
  if (isExplicit || this._responseMode === 'always') {
@@ -336,8 +904,9 @@ class Bot {
336
904
  return;
337
905
  }
338
906
  }
339
- if (this._responseMode !== 'always' && !isExplicit)
907
+ if (this._responseMode !== 'always' && !isExplicit) {
340
908
  return;
909
+ }
341
910
  // Process if not already running
342
911
  if (!this.signalRouter.processingDiscussions.has(message.discussionId)) {
343
912
  this.processDiscussion(message.discussionId).catch(err => {
@@ -352,17 +921,20 @@ class Bot {
352
921
  }
353
922
  // ===== DISCUSSION PROCESSING =====
354
923
  async processDiscussion(discussionId) {
355
- if (this.signalRouter.processingDiscussions.has(discussionId))
924
+ if (this.signalRouter.processingDiscussions.has(discussionId)) {
356
925
  return;
926
+ }
357
927
  this.signalRouter.processingDiscussions.add(discussionId);
358
928
  const state = this.signalRouter.getOrCreateState(discussionId);
359
929
  try {
360
930
  while (true) {
361
931
  const messages = state.contextBuffer.splice(0);
362
- if (messages.length === 0)
932
+ if (messages.length === 0) {
363
933
  break;
364
- if (messages.length > 1)
934
+ }
935
+ if (messages.length > 1) {
365
936
  this.opLogger.coalesce(discussionId, messages.length);
937
+ }
366
938
  // Build conversation entry
367
939
  const conversation = this.conversationManager.getConversation(discussionId);
368
940
  const parts = messages.map(msg => this.formatIncomingMessage(msg));
@@ -380,8 +952,9 @@ class Bot {
380
952
  const primaryMessage = messages[messages.length - 1];
381
953
  state.lastProgressTime = 0;
382
954
  state.abortController = new AbortController();
383
- for (const msg of messages)
955
+ for (const msg of messages) {
384
956
  this.opLogger.messageIn(msg.discussionId, msg.senderName, msg.content);
957
+ }
385
958
  let responded;
386
959
  try {
387
960
  responded = await this.processMessage(primaryMessage, state.abortController.signal);
@@ -404,12 +977,14 @@ class Bot {
404
977
  break;
405
978
  }
406
979
  }
407
- if (state.contextBuffer.length === 0)
980
+ if (state.contextBuffer.length === 0) {
408
981
  break;
982
+ }
409
983
  if (state.state === 'idle') {
410
984
  const hasExplicit = state.contextBuffer.some(m => this.signalRouter.isExplicitTrigger(m));
411
- if (!hasExplicit)
985
+ if (!hasExplicit) {
412
986
  break;
987
+ }
413
988
  state.state = 'engaged';
414
989
  state.consecutiveNonResponses = 0;
415
990
  this.opLogger.engage(discussionId, 'reengaged');
@@ -443,8 +1018,9 @@ class Bot {
443
1018
  return await this.runLlmLoop(message, route, signal);
444
1019
  }
445
1020
  catch (error) {
446
- if (error instanceof sdk_1.default.APIUserAbortError)
1021
+ if (error instanceof sdk_1.default.APIUserAbortError) {
447
1022
  throw error;
1023
+ }
448
1024
  this.logger.error('Message processing failed', error);
449
1025
  this.typingIndicator?.stop(message.discussionId);
450
1026
  conversation.length = snapshotLength;
@@ -454,6 +1030,14 @@ class Bot {
454
1030
  // ===== MODEL ROUTING =====
455
1031
  async routeMessage(message, conversation, signal) {
456
1032
  const defaultRoute = { model: MODEL_HAIKU, maxTokens: 2000 };
1033
+ // Any file attachment forces COMPLEX: reading/analysing an attachment plus the
1034
+ // tool calls that typically follow easily blows Haiku's 2000-token budget,
1035
+ // and a truncated response with an unfinished tool_use poisons the conversation.
1036
+ if (message.fileAttachments && message.fileAttachments.length > 0) {
1037
+ const route = { ...SONNET_ROUTE };
1038
+ this.opLogger.route(message.discussionId, 'COMPLEX (attachments)', route.model, message.content);
1039
+ return route;
1040
+ }
457
1041
  try {
458
1042
  const wsName = this.init?.network?.name || 'Workspace';
459
1043
  const recentContext = this.getRecentContext(conversation);
@@ -465,7 +1049,7 @@ class Bot {
465
1049
  this.trackTokenUsage(response, message, MODEL_HAIKU);
466
1050
  const text = response.content.filter((b) => b.type === 'text').map(b => b.text).join('').trim().toUpperCase();
467
1051
  if (text.includes('COMPLEX')) {
468
- const route = { model: MODEL_SONNET, maxTokens: 16384 };
1052
+ const route = { ...SONNET_ROUTE };
469
1053
  this.opLogger.route(message.discussionId, 'COMPLEX', route.model, message.content);
470
1054
  return route;
471
1055
  }
@@ -488,8 +1072,9 @@ class Bot {
488
1072
  else if (Array.isArray(msg.content)) {
489
1073
  text = msg.content.filter((b) => b.type === 'text').map((b) => b.text).join(' ');
490
1074
  }
491
- if (!text)
1075
+ if (!text) {
492
1076
  continue;
1077
+ }
493
1078
  lines.unshift(`${msg.role === 'user' ? 'User' : 'Assistant'}: ${text.length > 200 ? text.slice(0, 200) + '...' : text}`);
494
1079
  count++;
495
1080
  }
@@ -505,38 +1090,54 @@ class Bot {
505
1090
  const systemPrompt = (0, services_1.buildSystemPrompt)({
506
1091
  init: this.init, userId: this.userId,
507
1092
  workspaceOverview: this.workspaceOverview, customPrompt: this._systemPrompt,
508
- botExchangeContext,
1093
+ botExchangeContext, helperMode: this.config.helperMode,
1094
+ hasSeedContext: !!this.config.seedContext,
1095
+ responseMode: this._responseMode,
1096
+ accessLevel: this.config.accessLevel,
1097
+ allowBotMessages: this.config.allowBotMessages,
509
1098
  });
510
1099
  const tools = this.cachedTools || this.getAnthropicTools();
511
1100
  for (let i = 0;; i++) {
512
- const cachedConversation = this.conversationManager.prepareForCaching(conversation);
513
1101
  this.typingIndicator?.updateStatus(message.discussionId, i === 0 ? 'Thinking' : 'Processing');
514
1102
  let response;
515
1103
  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();
1104
+ let trimAttempts = 0;
1105
+ while (true) {
1106
+ try {
1107
+ const cachedConversation = this.conversationManager.prepareForCaching(conversation);
533
1108
  response = await this.anthropic.messages.create({
534
- model: MODEL_HAIKU, max_tokens: 2000, temperature: 0,
1109
+ model: route.model, max_tokens: route.maxTokens, temperature: 0,
535
1110
  system: [{ type: 'text', text: systemPrompt, cache_control: { type: 'ephemeral' } }],
536
1111
  messages: cachedConversation, tools,
537
1112
  }, { signal });
1113
+ break;
538
1114
  }
539
- else {
1115
+ catch (error) {
1116
+ if (error instanceof sdk_1.default.APIUserAbortError) {
1117
+ this.cleanupIncompleteExchange(conversation);
1118
+ this.opLogger.interrupt(message.discussionId, 'new message received');
1119
+ return false;
1120
+ }
1121
+ const isPromptTooLong = error instanceof sdk_1.default.BadRequestError &&
1122
+ /prompt is too long/i.test(error.message || '');
1123
+ if (isPromptTooLong && trimAttempts < MAX_PROMPT_TRIM_ATTEMPTS && conversation.length >= 4) {
1124
+ trimAttempts++;
1125
+ const dropped = conversation.splice(0, 2);
1126
+ this.logger.warn('Prompt too long — dropped oldest conversation pair', {
1127
+ attempt: trimAttempts,
1128
+ droppedRoles: dropped.map(msg => msg.role),
1129
+ remainingMessages: conversation.length,
1130
+ model: route.model,
1131
+ });
1132
+ llmStart = Date.now();
1133
+ continue;
1134
+ }
1135
+ if (route.model !== MODEL_HAIKU && !isPromptTooLong) {
1136
+ this.logger.warn('Sonnet failed, falling back to Haiku');
1137
+ route = { model: MODEL_HAIKU, maxTokens: 2000 };
1138
+ llmStart = Date.now();
1139
+ continue;
1140
+ }
540
1141
  throw error;
541
1142
  }
542
1143
  }
@@ -546,12 +1147,37 @@ class Bot {
546
1147
  const cacheRead = usage.cache_read_input_tokens || 0;
547
1148
  const totalInput = usage.input_tokens + cacheRead + (usage.cache_creation_input_tokens || 0);
548
1149
  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)
1150
+ if (!response.content || response.content.length === 0) {
550
1151
  break;
1152
+ }
551
1153
  conversation.push({ role: 'assistant', content: response.content });
552
- // Truncation guard
1154
+ // Truncation guard. When the response is cut off at max_tokens
1155
+ // AND the truncated assistant content contains tool_use blocks,
1156
+ // Anthropic's API requires the very next message to carry
1157
+ // matching tool_result blocks — otherwise every subsequent
1158
+ // request fails with `tool_use ids were found without tool_result
1159
+ // blocks immediately after`. We can't actually execute the
1160
+ // truncated tools (JSON inputs may be malformed, and the model
1161
+ // expected all of them to run together), so we synthesize error
1162
+ // tool_results that tell the model exactly why nothing ran.
553
1163
  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.' });
1164
+ const truncatedToolUses = response.content.filter((b) => b.type === 'tool_use');
1165
+ 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.';
1166
+ if (truncatedToolUses.length > 0) {
1167
+ const errorResults = truncatedToolUses.map(b => ({
1168
+ type: 'tool_result',
1169
+ tool_use_id: b.id,
1170
+ content: 'Tool call was truncated before it could run because the response exceeded the output token limit. Try again with a smaller batch.',
1171
+ is_error: true,
1172
+ }));
1173
+ conversation.push({
1174
+ role: 'user',
1175
+ content: [...errorResults, { type: 'text', text: reminder }],
1176
+ });
1177
+ }
1178
+ else {
1179
+ conversation.push({ role: 'user', content: reminder });
1180
+ }
555
1181
  continue;
556
1182
  }
557
1183
  // Tool calls
@@ -565,7 +1191,7 @@ class Bot {
565
1191
  if (route.model === MODEL_HAIKU) {
566
1192
  const failedCount = toolResults.filter(r => r.is_error).length;
567
1193
  if (failedCount >= 2) {
568
- route = { model: MODEL_SONNET, maxTokens: 16384 };
1194
+ route = { ...SONNET_ROUTE };
569
1195
  await this.sendMessage(message.discussionId, 'Switching to a more capable model to handle this.');
570
1196
  }
571
1197
  }
@@ -595,25 +1221,49 @@ class Bot {
595
1221
  for (const block of toolUseBlocks) {
596
1222
  const toolStart = Date.now();
597
1223
  const args = block.input;
598
- // Admin-only gate
599
- if (this.permissions.isAdminOnlyTool(block.name) && !this.permissions.isAdminOrOwner(message.senderId)) {
1224
+ // Bot profile gate — the model is only offered BOT_TOOLS, but enforce
1225
+ // at execution too so a hallucinated tool name can't reach the registry.
1226
+ // Resolve deprecation aliases first so mid-conversation calls under
1227
+ // old v1 names keep working during the grace release.
1228
+ const canonicalName = this.toolExecutor.resolveName(block.name);
1229
+ if (!tool_profiles_1.BOT_TOOLS.has(canonicalName)) {
1230
+ this.opLogger.permDenied(message.discussionId, block.name, 'n/a', 'not-in-bot-tools');
1231
+ results.push({
1232
+ type: 'tool_result',
1233
+ tool_use_id: block.id,
1234
+ content: `Tool not available: ${block.name} is not part of this bot's toolset. `
1235
+ + 'Use only the tools you were given — do not retry.',
1236
+ is_error: true,
1237
+ });
1238
+ continue;
1239
+ }
1240
+ // Admin-only gate (args-aware: merged tools gate per-action)
1241
+ if (this.permissions.isAdminOnlyTool(block.name, args) && !this.permissions.isAdminOrOwner(message.senderId)) {
600
1242
  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 });
1243
+ results.push({
1244
+ type: 'tool_result',
1245
+ tool_use_id: block.id,
1246
+ 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.`,
1247
+ is_error: true,
1248
+ });
602
1249
  continue;
603
1250
  }
604
- // Pre-execution permission check
1251
+ // Pre-execution permission check. An UNKNOWN insightId is
1252
+ // resolved against the server first — an insight the bot can't
1253
+ // map to workflows is denied, not run, because the workflow
1254
+ // check can't see inside it (it would fail open).
605
1255
  if (!this.permissions.isPostCheckTool(block.name)) {
606
- const denied = this.permissions.checkArgs(args, message.senderId);
1256
+ const denied = await this.permissions.checkArgsResolving(args, message.senderId, () => this.fetchInsightWorkflowMap());
607
1257
  if (denied) {
608
1258
  this.opLogger.permDenied(message.discussionId, block.name, denied.workflowId, denied.reason);
609
- results.push({ type: 'tool_result', tool_use_id: block.id, content: denied.reason === 'bot-scope' ? `Permission denied: This bot does not have access to workflow ${denied.workflowId}.` : `Permission denied: You do not have access to workflow ${denied.workflowId}.`, is_error: true });
1259
+ results.push({ type: 'tool_result', tool_use_id: block.id, content: permissionDeniedMessage(denied), is_error: true });
610
1260
  continue;
611
1261
  }
612
1262
  }
613
1263
  // Discussion isolation: prevent leaking DMs and discussions the user shouldn't access
614
1264
  if (DISCUSSION_TOOLS.has(block.name) && args.discussionId && args.discussionId !== message.discussionId) {
615
1265
  try {
616
- const discResult = await this.client.socket.request('v3.discussion.message.latest', [args.discussionId]);
1266
+ const discResult = await this.client.socket.request(hailer_rpc_1.HailerRpc.Discussion.messageLatest, [args.discussionId]);
617
1267
  const disc = discResult?.discussion || {};
618
1268
  const participants = disc.participants || [];
619
1269
  const isPrivate = disc.private === true;
@@ -648,22 +1298,24 @@ class Bot {
648
1298
  // Auto-inject for join_discussion
649
1299
  if (block.name === 'join_discussion') {
650
1300
  toolArgs = { ...toolArgs };
651
- if (!toolArgs.inviteUserId && message.senderId)
1301
+ if (!toolArgs.inviteUserId && message.senderId) {
652
1302
  toolArgs.inviteUserId = message.senderId;
653
- if (!toolArgs.welcomeReason && message.content)
1303
+ }
1304
+ if (!toolArgs.welcomeReason && message.content) {
654
1305
  toolArgs.welcomeReason = message.content;
1306
+ }
655
1307
  // Only auto-inject sourceActivityId if explicitly provided — don't link DMs to random activities
656
1308
  }
657
1309
  const result = await this.toolExecutor.execute(block.name, toolArgs, this.getUserContext());
658
1310
  const text = result?.content?.[0]?.text ?? JSON.stringify(result);
659
1311
  let contentStr = typeof text === 'string' ? text : JSON.stringify(text);
660
1312
  const toolDuration = (Date.now() - toolStart) / 1000;
661
- // Cache insight mappings
662
- if (block.name === 'create_insight' && !contentStr.includes('❌')) {
663
- this.permissions.cacheInsightWorkflows(contentStr, args);
664
- }
665
- // Post-filter list results
666
- contentStr = await this.permissions.postFilterListResults(block.name, contentStr, message.senderId, message.discussionId, this.opLogger);
1313
+ // Cache insight mappings (keyed on the canonical name —
1314
+ // create_insight is an alias of save_insight)
1315
+ this.permissions.maybeCacheInsight(canonicalName, contentStr, args);
1316
+ // Post-filter list results (canonical name: alias calls
1317
+ // produce the new tools' output format)
1318
+ contentStr = await this.permissions.postFilterListResults(canonicalName, contentStr, message.senderId, message.discussionId, this.opLogger);
667
1319
  // Post-execution permission check
668
1320
  if (this.permissions.isPostCheckTool(block.name)) {
669
1321
  const wfId = this.permissions.extractWorkflowIdFromResult(block.name, contentStr);
@@ -685,6 +1337,11 @@ class Bot {
685
1337
  if (signal?.aborted && WRITE_TOOLS.has(block.name)) {
686
1338
  this.logger.warn('Write tool completed before abort', { tool: block.name });
687
1339
  }
1340
+ if (contentStr.length > MAX_TOOL_RESULT_CHARS) {
1341
+ const originalLen = contentStr.length;
1342
+ 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 run_insight with aggregate SQL.]`;
1343
+ this.logger.warn('Tool result truncated', { tool: block.name, originalLen, truncatedTo: MAX_TOOL_RESULT_CHARS });
1344
+ }
688
1345
  results.push({ type: 'tool_result', tool_use_id: block.id, content: contentStr });
689
1346
  }
690
1347
  catch (error) {
@@ -708,43 +1365,47 @@ class Bot {
708
1365
  const parts = [];
709
1366
  const unsupported = [];
710
1367
  for (const f of message.fileAttachments) {
711
- if (!f.mime || (f.size && f.size > MAX_FILE_SIZE)) {
1368
+ if (!f.mime || (f.size && f.size > fileSizeLimit(f.mime))) {
712
1369
  unsupported.push(f.fileId);
1370
+ continue;
713
1371
  }
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 {
1372
+ const desc = describeAttachment(f.mime, f.filename, f.fileId);
1373
+ if (!desc) {
721
1374
  unsupported.push(f.fileId);
1375
+ continue;
722
1376
  }
1377
+ parts.push(desc);
723
1378
  }
724
- if (unsupported.length)
1379
+ if (unsupported.length) {
725
1380
  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)
1381
+ }
1382
+ if (parts.length) {
727
1383
  fileInfo = '\n' + parts.join('\n');
1384
+ }
728
1385
  }
729
1386
  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>`;
1387
+ const aiContext = message.meta?.aiContext ? `<context>${JSON.stringify(message.meta.aiContext)}</context>\n\n` : '';
1388
+ 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
1389
  }
732
1390
  async resolveFileAttachments(messages) {
733
- if (!this.hailerApi)
1391
+ if (!this.hailerApi) {
734
1392
  return [];
735
- const eligible = [];
1393
+ }
1394
+ const nonOffice = [];
1395
+ const office = [];
1396
+ const skipped = [];
736
1397
  for (const msg of messages) {
737
1398
  for (const f of msg.fileAttachments || []) {
738
- if (!f.mime || (f.size && f.size > MAX_FILE_SIZE))
1399
+ if (!f.mime || (f.size && f.size > fileSizeLimit(f.mime))) {
739
1400
  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
1401
  }
1402
+ if (!isSupportedMime(f.mime)) {
1403
+ continue;
1404
+ }
1405
+ (isOfficeMime(f.mime) ? office : nonOffice).push({ fileId: f.fileId, mime: f.mime, filename: f.filename });
743
1406
  }
744
1407
  }
745
- if (!eligible.length)
746
- return [];
747
- const results = await Promise.all(eligible.map(async (f) => {
1408
+ const nonOfficeResults = await Promise.all(nonOffice.map(async (f) => {
748
1409
  try {
749
1410
  const result = await this.hailerApi.downloadFile(f.fileId);
750
1411
  if (IMAGE_MIME_TYPES.has(f.mime) && result.encoding === 'base64') {
@@ -768,11 +1429,98 @@ class Bot {
768
1429
  }
769
1430
  }
770
1431
  catch (err) {
771
- this.logger.warn('Failed to download file', { fileId: f.fileId, mime: f.mime });
1432
+ this.logger.warn('Failed to read file attachment', { fileId: f.fileId, mime: f.mime, err: err instanceof Error ? err.message : err });
1433
+ skipped.push({ filename: f.filename || f.fileId, reason: 'download failed' });
772
1434
  }
773
1435
  return null;
774
1436
  }));
775
- return results.filter((b) => b !== null);
1437
+ // Download Office files in parallel (I/O-bound), parse serially under the lock (memory-bound)
1438
+ const officeDownloads = await Promise.all(office.map(async (f) => {
1439
+ try {
1440
+ const result = await this.hailerApi.downloadFile(f.fileId);
1441
+ return { f, result };
1442
+ }
1443
+ catch (err) {
1444
+ this.logger.warn('Failed to download Office file', { fileId: f.fileId, mime: f.mime, err: err instanceof Error ? err.message : err });
1445
+ skipped.push({ filename: f.filename || f.fileId, reason: 'download failed' });
1446
+ return null;
1447
+ }
1448
+ }));
1449
+ const officeResults = [];
1450
+ for (const entry of officeDownloads) {
1451
+ if (!entry) {
1452
+ continue;
1453
+ }
1454
+ const { f, result } = entry;
1455
+ if (result.encoding !== 'base64') {
1456
+ this.logger.warn('Office file has unexpected encoding, skipping', { fileId: f.fileId, mime: f.mime, encoding: result.encoding });
1457
+ skipped.push({ filename: f.filename || f.fileId, reason: 'unexpected encoding from download' });
1458
+ continue;
1459
+ }
1460
+ if (isHeapUnderPressure()) {
1461
+ this.logger.warn('Heap under pressure, skipping Office parse', { fileId: f.fileId, mime: f.mime });
1462
+ skipped.push({ filename: f.filename || f.fileId, reason: 'bot is under memory pressure — ask the user to retry in a moment' });
1463
+ continue;
1464
+ }
1465
+ const block = await withOfficeParseLock(async () => {
1466
+ try {
1467
+ if (EXCEL_MIME_TYPES.has(f.mime)) {
1468
+ const ExcelJS = (await Promise.resolve().then(() => __importStar(require('exceljs')))).default;
1469
+ const buffer = Buffer.from(result.content, 'base64');
1470
+ const wb = new ExcelJS.Workbook();
1471
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Node 24 Buffer<ArrayBuffer> vs exceljs Buffer typing mismatch
1472
+ await wb.xlsx.load(buffer);
1473
+ const parts = [];
1474
+ wb.eachSheet((sheet) => {
1475
+ const rows = [];
1476
+ sheet.eachRow({ includeEmpty: false }, (row) => {
1477
+ const values = Array.isArray(row.values) ? row.values.slice(1) : [];
1478
+ rows.push(values.map(cellToCsv).join(','));
1479
+ });
1480
+ parts.push(`=== Sheet: ${sheet.name} (${rows.length} rows) ===\n${rows.join('\n')}`);
1481
+ });
1482
+ return {
1483
+ type: 'document',
1484
+ source: { type: 'text', media_type: 'text/plain', data: capText(`${f.filename || 'spreadsheet'}\n\n${parts.join('\n\n')}`) },
1485
+ };
1486
+ }
1487
+ if (WORD_MIME_TYPES.has(f.mime)) {
1488
+ const mammoth = await Promise.resolve().then(() => __importStar(require('mammoth')));
1489
+ const buffer = Buffer.from(result.content, 'base64');
1490
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Node 24 Buffer<ArrayBuffer> vs mammoth Buffer typing mismatch
1491
+ const { value } = await mammoth.extractRawText({ buffer: buffer });
1492
+ return {
1493
+ type: 'document',
1494
+ source: { type: 'text', media_type: 'text/plain', data: capText(`${f.filename || 'document'}\n\n${value}`) },
1495
+ };
1496
+ }
1497
+ }
1498
+ catch (err) {
1499
+ this.logger.warn('Failed to parse Office file', { fileId: f.fileId, mime: f.mime, err: err instanceof Error ? err.message : err });
1500
+ skipped.push({ filename: f.filename || f.fileId, reason: 'parse error' });
1501
+ }
1502
+ return null;
1503
+ });
1504
+ if (block) {
1505
+ officeResults.push(block);
1506
+ }
1507
+ }
1508
+ const blocks = [
1509
+ ...nonOfficeResults.filter((b) => b !== null),
1510
+ ...officeResults,
1511
+ ];
1512
+ if (skipped.length > 0) {
1513
+ const lines = skipped.map((s) => ` - ${s.filename}: ${s.reason}`).join('\n');
1514
+ blocks.push({
1515
+ type: 'document',
1516
+ source: {
1517
+ type: 'text',
1518
+ media_type: 'text/plain',
1519
+ 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}`,
1520
+ },
1521
+ });
1522
+ }
1523
+ return blocks;
776
1524
  }
777
1525
  async formatOutgoingMessage(text) {
778
1526
  let formatted = await this.messageFormatter.resolveUserTags(text);
@@ -785,27 +1533,31 @@ class Bot {
785
1533
  formatted = formatted.replace(/(\[hailerTag\|[^\]]+\]\([a-f0-9]{24}\)\uFEFF?)\s*\([^)]+\)/gi, '$1');
786
1534
  // Strip hailerTags inside markdown table rows (pipe in hailerTag|Name breaks table columns)
787
1535
  formatted = formatted.split('\n').map(line => {
788
- if (!line.trimStart().startsWith('|'))
1536
+ if (!line.trimStart().startsWith('|')) {
789
1537
  return line;
1538
+ }
790
1539
  return line.replace(/\uFEFF?\[hailerTag\|([^\]]+)\]\([a-f0-9]{24}\)\uFEFF?/gi, '$1');
791
1540
  }).join('\n');
792
1541
  formatted = await this.resolveBareIds(formatted);
793
1542
  return formatted;
794
1543
  }
795
1544
  async resolveBareIds(text) {
796
- const bareIdPattern = /(?<!\()([a-f0-9]{24})(?!\)[^\[]*\[hailerTag)/gi;
1545
+ const bareIdPattern = /(?<!\()([a-f0-9]{24})(?!\)[^[]*\[hailerTag)/gi;
797
1546
  const matches = [...text.matchAll(bareIdPattern)];
798
1547
  const idsToResolve = [];
799
1548
  for (const match of matches) {
800
1549
  const id = match[1];
801
- if (new RegExp(`\\[hailerTag\\|[^\\]]+\\]\\(${id}\\)`, 'i').test(text))
1550
+ if (new RegExp(`\\[hailerTag\\|[^\\]]+\\]\\(${id}\\)`, 'i').test(text)) {
802
1551
  continue;
1552
+ }
803
1553
  idsToResolve.push(id);
804
- if (idsToResolve.length >= 5)
1554
+ if (idsToResolve.length >= 5) {
805
1555
  break;
1556
+ }
806
1557
  }
807
- if (idsToResolve.length === 0)
1558
+ if (idsToResolve.length === 0) {
808
1559
  return text;
1560
+ }
809
1561
  const resolutions = await Promise.all(idsToResolve.map(async (id) => {
810
1562
  try {
811
1563
  const result = await this.toolExecutor.execute('show_activity_by_id', { activityId: id }, this.getUserContext());
@@ -814,8 +1566,9 @@ class Bot {
814
1566
  const j = resultText.match(/\{[\s\S]*\}/);
815
1567
  if (j) {
816
1568
  const p = JSON.parse(j[0]);
817
- if (p.name)
1569
+ if (p.name) {
818
1570
  return { id, name: p.name };
1571
+ }
819
1572
  }
820
1573
  }
821
1574
  }
@@ -823,8 +1576,9 @@ class Bot {
823
1576
  return null;
824
1577
  }));
825
1578
  for (const r of resolutions) {
826
- if (!r)
1579
+ if (!r) {
827
1580
  continue;
1581
+ }
828
1582
  text = text.replace(r.id, `\uFEFF[hailerTag|${r.name}](${r.id})\uFEFF`);
829
1583
  }
830
1584
  return text;
@@ -832,15 +1586,17 @@ class Bot {
832
1586
  // ===== HELPERS =====
833
1587
  async injectPendingContext(discussionId, conversation) {
834
1588
  const state = this.signalRouter.getState(discussionId);
835
- if (!state || state.contextBuffer.length === 0)
1589
+ if (!state || state.contextBuffer.length === 0) {
836
1590
  return;
1591
+ }
837
1592
  const pending = state.contextBuffer.splice(0);
838
1593
  const lastMsg = conversation[conversation.length - 1];
839
1594
  if (lastMsg?.role === 'user' && Array.isArray(lastMsg.content)) {
840
1595
  const content = lastMsg.content;
841
1596
  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))
1597
+ for (const block of await this.resolveFileAttachments(pending)) {
843
1598
  content.push(block);
1599
+ }
844
1600
  this.opLogger.contextInject(discussionId, pending.length);
845
1601
  }
846
1602
  }
@@ -860,30 +1616,34 @@ class Bot {
860
1616
  }
861
1617
  }
862
1618
  getToolStatus(toolUseBlocks) {
863
- if (toolUseBlocks.length === 1)
1619
+ if (toolUseBlocks.length === 1) {
864
1620
  return TOOL_STATUS_LABELS[toolUseBlocks[0].name] || toolUseBlocks[0].name.replace(/_/g, ' ');
1621
+ }
865
1622
  return `${TOOL_STATUS_LABELS[toolUseBlocks[0].name] || toolUseBlocks[0].name.replace(/_/g, ' ')} (+${toolUseBlocks.length - 1} more)`;
866
1623
  }
867
1624
  getAnthropicTools() {
868
- if (this.cachedTools)
1625
+ if (this.cachedTools) {
869
1626
  return this.cachedTools;
1627
+ }
870
1628
  const defs = this.toolExecutor.getToolDefinitions({
871
1629
  allowedGroups: [tool_registry_1.ToolGroup.READ, tool_registry_1.ToolGroup.WRITE, tool_registry_1.ToolGroup.PLAYGROUND, tool_registry_1.ToolGroup.BOT_INTERNAL],
872
1630
  });
873
- const tools = defs.filter(d => BOT_TOOLS.has(d.name)).map(d => ({
1631
+ const tools = defs.filter(d => tool_profiles_1.BOT_TOOLS.has(d.name)).map(d => ({
874
1632
  name: d.name, description: d.description, input_schema: d.inputSchema,
875
1633
  }));
876
- if (tools.length > 0)
1634
+ if (tools.length > 0) {
877
1635
  tools[tools.length - 1].cache_control = { type: 'ephemeral' };
1636
+ }
878
1637
  this.cachedTools = tools;
879
1638
  return tools;
880
1639
  }
881
1640
  async sendMessage(discussionId, text, links) {
882
1641
  try {
883
1642
  const msgData = { msg: text };
884
- if (links?.length)
1643
+ if (links?.length) {
885
1644
  msgData.links = links;
886
- await this.client.socket.request('messenger.send', [msgData, discussionId]);
1645
+ }
1646
+ await this.client.socket.request(hailer_rpc_1.HailerRpc.Messenger.send, [msgData, discussionId]);
887
1647
  this.opLogger.messageOut(discussionId, text.length, (text.match(/\[hailerTag\|/g) || []).length);
888
1648
  }
889
1649
  catch (error) {
@@ -891,13 +1651,29 @@ class Bot {
891
1651
  }
892
1652
  }
893
1653
  getUserContext() {
894
- if (!this.userContext)
1654
+ if (!this.userContext) {
895
1655
  throw new Error('Bot not started');
1656
+ }
896
1657
  return this.userContext;
897
1658
  }
1659
+ /** Full insight → source-workflow map from v3.insight.list (the endpoint list_insights renders). */
1660
+ async fetchInsightWorkflowMap() {
1661
+ const result = await this.getUserContext().hailer.request('v3.insight.list', [this._workspaceId]);
1662
+ const insights = Array.isArray(result) ? result : (result?.details || result?.insights || []);
1663
+ const map = new Map();
1664
+ for (const insight of insights) {
1665
+ if (!insight?._id) {
1666
+ continue;
1667
+ }
1668
+ const wfIds = (insight.sources || []).map((src) => src?.workflowId).filter(Boolean);
1669
+ map.set(insight._id, new Set(wfIds));
1670
+ }
1671
+ return map;
1672
+ }
898
1673
  trackTokenUsage(response, message, model) {
899
- if (!response.usage)
1674
+ if (!response.usage) {
900
1675
  return;
1676
+ }
901
1677
  const { input_tokens, output_tokens } = response.usage;
902
1678
  const cacheCreation = response.usage.cache_creation_input_tokens || 0;
903
1679
  const cacheRead = response.usage.cache_read_input_tokens || 0;