@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
@@ -10,6 +10,7 @@
10
10
  */
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.activityTools = exports.updateActivityTool = exports.createActivityTool = exports.showActivityByIdTool = exports.listActivitiesTool = void 0;
13
+ exports.mergeBulkPage = mergeBulkPage;
13
14
  const zod_1 = require("zod");
14
15
  const tool_registry_1 = require("../tool-registry");
15
16
  const index_1 = require("../utils/index");
@@ -32,7 +33,7 @@ function validateAndGetWorkflow(workflowId, init) {
32
33
  */
33
34
  async function resolvePhaseForListing(workflow, args, _init) {
34
35
  if (!args.phaseId) {
35
- throw new Error(`Phase ID is required. Use the list_workflow_phases tool to get available phase IDs for workflow "${workflow.name}".`);
36
+ throw new Error(`Phase ID is required. Use describe_workflows with include: ['phases'] to get available phase IDs for workflow "${workflow.name}".`);
36
37
  }
37
38
  return args.phaseId;
38
39
  }
@@ -98,7 +99,7 @@ function convertActivityFilters(mcpToolActivityListFilters) {
98
99
  let malformatFilterErrorMessage = undefined;
99
100
  for (const [fieldId, filterConfig] of Object.entries(mcpToolActivityListFilters)) {
100
101
  switch (filterConfig.operator) {
101
- case "text_search":
102
+ case 'text_search':
102
103
  if (filterConfig.value !== undefined) {
103
104
  apiActivityFilters.and.push({ [fieldId]: { textSearch: filterConfig.value } });
104
105
  }
@@ -106,7 +107,7 @@ function convertActivityFilters(mcpToolActivityListFilters) {
106
107
  malformatFilterErrorMessage = 'text_search filter requires a value';
107
108
  }
108
109
  break;
109
- case "equals":
110
+ case 'equals':
110
111
  if (filterConfig.value !== undefined) {
111
112
  apiActivityFilters.and.push({ [fieldId]: { equalTo: filterConfig.value } });
112
113
  }
@@ -114,7 +115,7 @@ function convertActivityFilters(mcpToolActivityListFilters) {
114
115
  malformatFilterErrorMessage = 'equals filter requires a value';
115
116
  }
116
117
  break;
117
- case "not_equals":
118
+ case 'not_equals':
118
119
  if (filterConfig.value !== undefined) {
119
120
  apiActivityFilters.and.push({ [fieldId]: { notEqualTo: filterConfig.value } });
120
121
  }
@@ -122,7 +123,7 @@ function convertActivityFilters(mcpToolActivityListFilters) {
122
123
  malformatFilterErrorMessage = 'not_equals filter requires a value';
123
124
  }
124
125
  break;
125
- case "contains":
126
+ case 'contains':
126
127
  if (filterConfig.value !== undefined) {
127
128
  apiActivityFilters.and.push({ [fieldId]: { contains: filterConfig.value } });
128
129
  }
@@ -130,7 +131,7 @@ function convertActivityFilters(mcpToolActivityListFilters) {
130
131
  malformatFilterErrorMessage = 'contains filter requires a value';
131
132
  }
132
133
  break;
133
- case "greater_than":
134
+ case 'greater_than':
134
135
  if (filterConfig.value !== undefined && typeof filterConfig.value === 'number') {
135
136
  apiActivityFilters.and.push({ [fieldId]: { greaterThan: filterConfig.value } });
136
137
  }
@@ -138,7 +139,7 @@ function convertActivityFilters(mcpToolActivityListFilters) {
138
139
  malformatFilterErrorMessage = 'greater_than filter requires a numeric value';
139
140
  }
140
141
  break;
141
- case "greater_than_or_equal":
142
+ case 'greater_than_or_equal':
142
143
  if (filterConfig.value !== undefined && typeof filterConfig.value === 'number') {
143
144
  apiActivityFilters.and.push({ [fieldId]: { greaterThanOrEqual: filterConfig.value } });
144
145
  }
@@ -146,7 +147,7 @@ function convertActivityFilters(mcpToolActivityListFilters) {
146
147
  malformatFilterErrorMessage = 'greater_than_or_equal filter requires a numeric value';
147
148
  }
148
149
  break;
149
- case "less_than":
150
+ case 'less_than':
150
151
  if (filterConfig.value !== undefined && typeof filterConfig.value === 'number') {
151
152
  apiActivityFilters.and.push({ [fieldId]: { lessThan: filterConfig.value } });
152
153
  }
@@ -154,7 +155,7 @@ function convertActivityFilters(mcpToolActivityListFilters) {
154
155
  malformatFilterErrorMessage = 'less_than filter requires a numeric value';
155
156
  }
156
157
  break;
157
- case "less_than_or_equal":
158
+ case 'less_than_or_equal':
158
159
  if (filterConfig.value !== undefined && typeof filterConfig.value === 'number') {
159
160
  apiActivityFilters.and.push({ [fieldId]: { lessThanOrEqual: filterConfig.value } });
160
161
  }
@@ -162,7 +163,7 @@ function convertActivityFilters(mcpToolActivityListFilters) {
162
163
  malformatFilterErrorMessage = 'less_than_or_equal filter requires a numeric value';
163
164
  }
164
165
  break;
165
- case "range":
166
+ case 'range':
166
167
  if (!filterConfig.start || !filterConfig.end) {
167
168
  malformatFilterErrorMessage = 'Incorrect filter format, either start or end not provided for range';
168
169
  break;
@@ -181,19 +182,27 @@ function convertActivityFilters(mcpToolActivityListFilters) {
181
182
  */
182
183
  function formatActivityListResponseWithPagination(activityData, workflow, init, phaseName, args) {
183
184
  const activities = Array.isArray(activityData) ? activityData : (activityData.activities || activityData || []);
185
+ const metadata = (!Array.isArray(activityData) && activityData.metadata) || {};
184
186
  const cleanedActivities = (0, index_1.transformActivities)(activities, workflow, init.users);
185
187
  const filteredActivities = args?.fields
186
188
  ? filterFieldsAndValues(cleanedActivities, args.fields, workflow.fields)
187
189
  : cleanedActivities;
188
190
  const currentPage = args?.page || 0;
189
191
  const limit = args?.limit || 50;
190
- const hasMorePages = activities.length === limit;
192
+ // The server always returns metadata.totalCount — use it for exact page math
193
+ // instead of the old length === limit guess (0 means the count query failed).
194
+ const reportedTotal = typeof metadata.totalCount === 'number' && metadata.totalCount > 0 ? metadata.totalCount : 0;
195
+ const totalPages = reportedTotal > 0 ? Math.ceil(reportedTotal / limit) : undefined;
196
+ const hasMorePages = reportedTotal > 0 ? (currentPage + 1) * limit < reportedTotal : activities.length === limit;
191
197
  let responseText = `šŸ“Š **PAGINATION INFO:**\n`;
192
- responseText += `- Current page: ${currentPage + 1}\n`;
198
+ responseText += `- Current page: ${currentPage + 1}${totalPages ? ` of ${totalPages}` : ''}\n`;
199
+ if (reportedTotal > 0) {
200
+ responseText += `- Total matching activities: ${reportedTotal}\n`;
201
+ }
193
202
  responseText += `- Activities on this page: ${activities.length}\n`;
194
203
  responseText += `- Limit per page: ${limit}\n`;
195
204
  if (hasMorePages) {
196
- responseText += `- āš ļø **MORE DATA AVAILABLE**: Use page=${currentPage + 1} to get next ${limit} activities\n`;
205
+ responseText += `- āš ļø **MORE DATA AVAILABLE**: Use page=${currentPage + 1} to get the next ${limit} activities\n`;
197
206
  }
198
207
  if (activities.length === limit && currentPage === 0) {
199
208
  responseText += `\nšŸ’” **TIP**: This shows the first ${limit} activities.\n`;
@@ -205,7 +214,7 @@ function formatActivityListResponseWithPagination(activityData, workflow, init,
205
214
  return {
206
215
  content: [
207
216
  {
208
- type: "text",
217
+ type: 'text',
209
218
  text: responseText,
210
219
  },
211
220
  ],
@@ -221,22 +230,27 @@ function formatFilteredActivityListResponse(activityData, workflow, init, args)
221
230
  const filteredActivities = args.fields
222
231
  ? filterFieldsAndValues(cleanedActivities, args.fields, workflow.fields)
223
232
  : cleanedActivities;
224
- const totalCount = metadata.totalCount || activities.length;
225
233
  const currentPage = args?.page || 0;
226
234
  const limit = args?.limit || 50;
227
- const hasMorePages = activities.length === limit;
228
- const totalPages = Math.ceil(totalCount / limit);
235
+ // 0 means the count query failed — fall back to the full-page heuristic
236
+ // instead of declaring a full page complete.
237
+ const reportedTotal = typeof metadata.totalCount === 'number' && metadata.totalCount > 0 ? metadata.totalCount : 0;
238
+ const totalCount = reportedTotal || activities.length;
239
+ const hasMorePages = reportedTotal > 0 ? (currentPage + 1) * limit < reportedTotal : activities.length === limit;
240
+ const totalPages = Math.max(1, Math.ceil(totalCount / limit));
229
241
  let responseText = `šŸŽÆ **FILTERED ACTIVITIES** in "${workflow.name}":\n\n`;
230
242
  const filterCount = Object.keys(args.filters || {}).length;
231
243
  responseText += `**Applied Filters:** ${filterCount} field filter(s)\n`;
232
244
  for (const [fieldId, filter] of Object.entries(args.filters || {})) {
233
245
  const filterConfig = filter;
234
246
  responseText += `- Field \`${fieldId}\`: ${filterConfig.operator}`;
235
- if (filterConfig.value !== undefined)
247
+ if (filterConfig.value !== undefined) {
236
248
  responseText += ` = "${filterConfig.value}"`;
237
- if (filterConfig.start !== undefined)
249
+ }
250
+ if (filterConfig.start !== undefined) {
238
251
  responseText += ` from ${filterConfig.start} to ${filterConfig.end}`;
239
- responseText += "\n";
252
+ }
253
+ responseText += '\n';
240
254
  }
241
255
  if (args.search) {
242
256
  responseText += `- Text search: "${args.search}"\n`;
@@ -254,10 +268,10 @@ function formatFilteredActivityListResponse(activityData, workflow, init, args)
254
268
  responseText += `šŸ’” **TROUBLESHOOTING:**\n`;
255
269
  responseText += `- Try broader filter criteria\n`;
256
270
  responseText += `- Remove some filters to see if data exists\n`;
257
- responseText += `- Call get_workflow_schema to verify field IDs are correct\n`;
271
+ responseText += `- Call describe_workflows with include: ['schema'] to verify field IDs are correct\n`;
258
272
  responseText += `- Use list_activities without filters to see all activities`;
259
273
  return {
260
- content: [{ type: "text", text: responseText }],
274
+ content: [{ type: 'text', text: responseText }],
261
275
  };
262
276
  }
263
277
  responseText += `\n` + (0, index_1.formatActivityListResponse)(filteredActivities, workflow, undefined);
@@ -266,23 +280,273 @@ function formatFilteredActivityListResponse(activityData, workflow, init, args)
266
280
  responseText += `- Use 'range' operator for date/number ranges (created/updated timestamps)\n`;
267
281
  responseText += `- Use 'contains' or 'text_search' for partial text matching\n`;
268
282
  responseText += `- Combine multiple filters for precise results\n`;
269
- responseText += `- Call get_workflow_schema to discover available fields and their types`;
283
+ responseText += `- Call describe_workflows with include: ['schema'] to discover available fields and their types`;
270
284
  return {
271
285
  content: [
272
286
  {
273
- type: "text",
287
+ type: 'text',
274
288
  text: responseText,
275
289
  },
276
290
  ],
277
291
  };
278
292
  }
293
+ // Bulk reads: the backend reliably serves at most ~200 activities per call
294
+ // (larger limits fail silently as []), so "a lot of data at once" means many
295
+ // skip-pages — fetched in parallel inside ONE tool call instead of one model
296
+ // turn per page.
297
+ const BULK_PAGE_SIZE = 200;
298
+ const BULK_CONCURRENCY = 5;
299
+ const BULK_MAX_RECORDS = 5000;
300
+ /** Merges one page response into the accumulator; returns the page's row count. */
301
+ function mergeBulkPage(pageResult, byId) {
302
+ const activities = Array.isArray(pageResult) ? pageResult : (pageResult?.activities || []);
303
+ for (const activity of activities) {
304
+ byId.set(activity._id, activity);
305
+ }
306
+ return activities.length;
307
+ }
308
+ /**
309
+ * Bulk-read body of list_activities (maxRecords). Pages are fetched sorted
310
+ * created asc: skip pagination over the default updated-desc ordering shifts
311
+ * rows across page boundaries mid-fetch (duplicates/gaps); created order is
312
+ * append-only. Page one runs alone to learn totalCount, the rest run in
313
+ * parallel batches. An empty non-final page means the backend query failed
314
+ * (it reports errors as empty results) — surfaced loudly, never as "no data".
315
+ */
316
+ async function executeBulkRead(args, workflow, phaseId, apiFilters, context) {
317
+ const fetchPage = (pageIndex) => context.hailer.fetchActivityList(args.workflowId, phaseId, BULK_PAGE_SIZE, {
318
+ page: pageIndex,
319
+ search: args.search,
320
+ sortBy: 'created',
321
+ sortOrder: 'asc',
322
+ filters: apiFilters,
323
+ returnFlat: true,
324
+ });
325
+ const firstPage = await fetchPage(0);
326
+ const byId = new Map();
327
+ const firstPageCount = mergeBulkPage(firstPage, byId);
328
+ const totalCount = typeof firstPage?.metadata?.totalCount === 'number' ? firstPage.metadata.totalCount : 0;
329
+ const requested = Math.min(args.maxRecords || BULK_PAGE_SIZE, BULK_MAX_RECORDS);
330
+ let failedPages = 0;
331
+ let maybeMore = false;
332
+ if (totalCount === 0 && firstPageCount === BULK_PAGE_SIZE) {
333
+ // Count query failed (0) but the first page is full — the total is
334
+ // unknown. Walk pages sequentially until a short page so a 200-row cap
335
+ // is never silently presented as the complete dataset.
336
+ let pageIndex = 1;
337
+ let lastCount = firstPageCount;
338
+ while (lastCount === BULK_PAGE_SIZE && byId.size < requested) {
339
+ const result = await fetchPage(pageIndex).catch(() => null);
340
+ if (!result) {
341
+ failedPages += 1;
342
+ break;
343
+ }
344
+ lastCount = mergeBulkPage(result, byId);
345
+ pageIndex += 1;
346
+ }
347
+ maybeMore = lastCount === BULK_PAGE_SIZE && byId.size >= requested;
348
+ }
349
+ const target = Math.min(requested, Math.max(totalCount, byId.size));
350
+ const pageCount = Math.max(1, Math.ceil(target / BULK_PAGE_SIZE));
351
+ for (let start = 1; start < pageCount && totalCount > 0; start += BULK_CONCURRENCY) {
352
+ const end = Math.min(start + BULK_CONCURRENCY, pageCount);
353
+ const batch = [];
354
+ for (let pageIndex = start; pageIndex < end; pageIndex += 1) {
355
+ batch.push(fetchPage(pageIndex).catch(() => null));
356
+ }
357
+ const results = await Promise.all(batch);
358
+ for (const result of results) {
359
+ const merged = result ? mergeBulkPage(result, byId) : 0;
360
+ if (merged === 0) {
361
+ failedPages += 1;
362
+ }
363
+ }
364
+ }
365
+ const allActivities = Array.from(byId.values()).slice(0, target);
366
+ const displayTotal = Math.max(totalCount, allActivities.length);
367
+ const cleanedActivities = (0, index_1.transformActivities)(allActivities, workflow, context.init.users);
368
+ const projectedActivities = args.fields
369
+ ? filterFieldsAndValues(cleanedActivities, args.fields, workflow.fields)
370
+ : cleanedActivities;
371
+ let responseText = `šŸ“¦ **BULK FETCH:**\n`;
372
+ responseText += `- Retrieved: ${allActivities.length} of ${displayTotal} matching activities (${pageCount} page(s) in parallel)\n`;
373
+ if (displayTotal > requested) {
374
+ responseText += `- ā„¹ļø Only the first ${requested} were fetched (maxRecords). ` +
375
+ `${displayTotal - requested} more match — raise maxRecords (max ${BULK_MAX_RECORDS}) or narrow with filters\n`;
376
+ }
377
+ if (allActivities.length < target || failedPages > 0) {
378
+ responseText += `- āš ļø **INCOMPLETE**: expected ${target} but got ${allActivities.length}` +
379
+ `${failedPages ? ` (${failedPages} page(s) returned empty/failed)` : ''}. ` +
380
+ `Retry, or narrow with filters — do NOT treat this as the full dataset\n`;
381
+ }
382
+ if (maybeMore) {
383
+ responseText += `- āš ļø The server's total count was unavailable and the last page was full — ` +
384
+ `more activities likely exist beyond maxRecords. Raise maxRecords or narrow with filters\n`;
385
+ }
386
+ responseText += `\n` + (0, index_1.formatActivityListResponse)(projectedActivities, workflow);
387
+ return {
388
+ content: [{ type: 'text', text: responseText }],
389
+ };
390
+ }
391
+ /**
392
+ * countOnly fast path for list_activities — preserved verbatim from the retired
393
+ * count_activities tool. O(1): calls v3.activity.count, never fetches activities.
394
+ */
395
+ async function executeActivityCount(workflowId, context) {
396
+ logger.debug('Counting activities', {
397
+ workflowId,
398
+ apiKey: context.apiKey.substring(0, 8) + '...',
399
+ });
400
+ try {
401
+ // Get workflow name from cached data (matches by _id or key)
402
+ const workflow = (context.init.processes || []).find((proc) => proc._id === workflowId || proc.key === workflowId);
403
+ if (!workflow) {
404
+ return {
405
+ content: [{
406
+ type: 'text',
407
+ text: `āŒ Workflow "${workflowId}" not found`,
408
+ }],
409
+ };
410
+ }
411
+ logger.debug('Calling v3.activity.count', {
412
+ workflowId,
413
+ workflowName: workflow.name,
414
+ });
415
+ // Call v3.activity.count endpoint
416
+ // Returns object with phase IDs as keys and counts as values
417
+ const result = await context.hailer.request('v3.activity.count', [workflowId]);
418
+ logger.debug('Activity count retrieved', {
419
+ result: JSON.stringify(result),
420
+ });
421
+ // Sum all counts across phases
422
+ const count = Object.values(result).reduce((sum, phaseCount) => sum + phaseCount, 0);
423
+ let responseText = `šŸ”¢ **Activity Count for "${workflow.name}"**\n\n`;
424
+ responseText += `**Workflow ID:** \`${workflowId}\`\n`;
425
+ responseText += `**Total Activities:** ${count}\n\n`;
426
+ if (count === 0) {
427
+ responseText += `šŸ’” This workflow has no activities yet. Use \`create_activity\` to add one.\n`;
428
+ return {
429
+ content: [{ type: 'text', text: responseText }],
430
+ };
431
+ }
432
+ responseText += `šŸ’” **Next Steps:**\n`;
433
+ responseText += `- Use \`list_activities\` to see the activities\n`;
434
+ responseText += `- Use \`describe_workflows\` with include: ['schema'] to see workflow structure\n`;
435
+ return {
436
+ content: [{ type: 'text', text: responseText }],
437
+ };
438
+ }
439
+ catch (error) {
440
+ if (!request_logger_1.RequestLogger.getCurrent()) {
441
+ logger.error('Error counting activities', error);
442
+ }
443
+ return {
444
+ content: [{
445
+ type: 'text',
446
+ text: `āŒ Error counting activities: ${error instanceof Error ? error.message : String(error)}\n\n**Tips:**\n` +
447
+ '- Check that workflow ID is valid (24 characters)\n- Use `describe_workflows` to find workflow IDs',
448
+ }],
449
+ };
450
+ }
451
+ }
452
+ /**
453
+ * Validate the keys of a fields object against a workflow's field definitions.
454
+ * The server silently ignores unknown keys (e.g. field NAMES instead of IDs) and
455
+ * reports success — the #1 documented footgun — so we error out before the API call.
456
+ *
457
+ * ORDERING: in both create_activity and update_activity this runs AFTER the
458
+ * date/activitylink auto-fixups and immediately before the API call. The fixups
459
+ * rewrite values only, never keys, so the validated key set is identical either way.
460
+ *
461
+ * Accepts field IDs and field keys (the API resolves both).
462
+ * Returns error text for unknown keys, or undefined when all keys are known.
463
+ */
464
+ function validateFieldKeys(fields, workflowFields) {
465
+ const knownKeys = new Set();
466
+ const labelToId = new Map();
467
+ for (const [fieldId, fieldDef] of Object.entries(workflowFields)) {
468
+ const def = fieldDef;
469
+ knownKeys.add(fieldId);
470
+ if (def.key) {
471
+ knownKeys.add(def.key);
472
+ }
473
+ if (def.label) {
474
+ labelToId.set(String(def.label).toLowerCase(), fieldId);
475
+ }
476
+ }
477
+ const unknownKeys = Object.keys(fields).filter((key) => !knownKeys.has(key));
478
+ if (unknownKeys.length === 0) {
479
+ return undefined;
480
+ }
481
+ const lines = [];
482
+ let needsFieldList = false;
483
+ for (const key of unknownKeys) {
484
+ const labelMatchId = labelToId.get(key.toLowerCase());
485
+ if (labelMatchId) {
486
+ const label = workflowFields[labelMatchId].label;
487
+ lines.push(`Field "${key}" must be referenced by ID: use "${labelMatchId}" (label: "${label}")`);
488
+ continue;
489
+ }
490
+ lines.push(`Unknown field key "${key}".`);
491
+ needsFieldList = true;
492
+ }
493
+ if (needsFieldList) {
494
+ const available = Object.entries(workflowFields)
495
+ .slice(0, 20)
496
+ .map(([fid, def]) => `- "${fid}" (label: "${def.label || def.key || fid}")`);
497
+ lines.push('', 'Available field IDs:', ...available);
498
+ }
499
+ return lines.join('\n');
500
+ }
501
+ /**
502
+ * update_activity field-key validation: resolves the activity's workflow (the
503
+ * workflowId is not a tool param) via fetchActivityById → activity.process, then
504
+ * validates the fields object's keys. Fail-open on resolution problems (broken
505
+ * function fields, deleted activity, workflow missing from init) — those must not
506
+ * block updates; unknown keys in a resolved workflow still hard-error.
507
+ * Returns formatted error text, or undefined when valid or unresolvable.
508
+ */
509
+ async function validateUpdateFieldKeys(activityId, fields, context, knownWorkflowFields) {
510
+ if (Object.keys(fields).length === 0) {
511
+ return undefined;
512
+ }
513
+ let workflowFields = knownWorkflowFields;
514
+ if (!workflowFields) {
515
+ try {
516
+ const activity = await context.hailer.fetchActivityById(activityId);
517
+ const workflow = context.init.processes?.find((proc) => proc._id === activity?.process);
518
+ workflowFields = workflow?.fields;
519
+ }
520
+ catch (error) {
521
+ logger.warn('Skipping field-key validation - could not resolve workflow for activity', {
522
+ activityId,
523
+ error: (0, tool_helpers_1.extractErrorMessage)(error),
524
+ });
525
+ return undefined;
526
+ }
527
+ }
528
+ if (!workflowFields) {
529
+ return undefined;
530
+ }
531
+ const keyError = validateFieldKeys(fields, workflowFields);
532
+ if (!keyError) {
533
+ return undefined;
534
+ }
535
+ if (knownWorkflowFields) {
536
+ // The caller-supplied workflowId may simply be wrong for this activity —
537
+ // re-resolve the workflow from the activity itself before rejecting.
538
+ return validateUpdateFieldKeys(activityId, fields, context);
539
+ }
540
+ return `āŒ Invalid field keys for activity ${activityId} — nothing was updated.\n\n${keyError}`;
541
+ }
279
542
  /** Auto-fix date fields: convert ISO date strings to Unix timestamps (ms).
280
543
  * If workspaceCache is available, only converts confirmed date/datetime/time fields.
281
544
  * If not available, converts any value matching ISO date format (safe — non-date fields won't have date strings). */
282
545
  function autoFixDateFields(fields, context) {
283
546
  for (const [fieldId, fieldValue] of Object.entries(fields)) {
284
- if (typeof fieldValue !== 'string' || !/^\d{4}-\d{2}-\d{2}/.test(fieldValue))
547
+ if (typeof fieldValue !== 'string' || !/^\d{4}-\d{2}-\d{2}/.test(fieldValue)) {
285
548
  continue;
549
+ }
286
550
  // Try to confirm field type from cache
287
551
  let fieldType;
288
552
  if (context.workspaceCache) {
@@ -297,15 +561,16 @@ function autoFixDateFields(fields, context) {
297
561
  // Convert if confirmed date type, OR if no cache (assume date — non-date fields won't have ISO date strings)
298
562
  if (!fieldType || fieldType === 'date' || fieldType === 'datetime' || fieldType === 'time') {
299
563
  const parsed = new Date(fieldValue.length === 10 ? fieldValue + 'T12:00:00' : fieldValue).getTime();
300
- if (!isNaN(parsed))
564
+ if (!isNaN(parsed)) {
301
565
  fields[fieldId] = parsed;
566
+ }
302
567
  }
303
568
  }
304
569
  }
305
570
  /** Build activity update object */
306
571
  function buildActivityUpdate(args, context) {
307
572
  let parsedFields = args.fields;
308
- if (typeof args.fields === "string") {
573
+ if (typeof args.fields === 'string') {
309
574
  try {
310
575
  parsedFields = JSON.parse(args.fields);
311
576
  }
@@ -314,25 +579,25 @@ function buildActivityUpdate(args, context) {
314
579
  }
315
580
  }
316
581
  // Auto-fix activitylink fields: if LLM passes an object instead of just the ID string
317
- if (parsedFields && typeof parsedFields === "object") {
582
+ if (parsedFields && typeof parsedFields === 'object') {
318
583
  for (const [fieldId, fieldValue] of Object.entries(parsedFields)) {
319
- if (fieldValue && typeof fieldValue === "object" && !Array.isArray(fieldValue)) {
584
+ if (fieldValue && typeof fieldValue === 'object' && !Array.isArray(fieldValue)) {
320
585
  const obj = fieldValue;
321
586
  let extractedId = null;
322
587
  // Case 1: {type: "activitylink", value: {_id: "...", name: "..."}}
323
- if (obj.type && obj.value && typeof obj.value === "object" && obj.value._id) {
588
+ if (obj.type && obj.value && typeof obj.value === 'object' && obj.value._id) {
324
589
  extractedId = obj.value._id;
325
590
  }
326
591
  // Case 2: {_id: "...", name: "..."}
327
- else if (obj._id && typeof obj._id === "string") {
592
+ if (!extractedId && obj._id && typeof obj._id === 'string') {
328
593
  extractedId = obj._id;
329
594
  }
330
595
  // Case 3: {value: "..."} where value is the ID string
331
- else if (obj.value && typeof obj.value === "string" && /^[a-f0-9]{24}$/i.test(obj.value)) {
596
+ if (!extractedId && obj.value && typeof obj.value === 'string' && /^[a-f0-9]{24}$/i.test(obj.value)) {
332
597
  extractedId = obj.value;
333
598
  }
334
599
  if (extractedId) {
335
- logger.warn("Auto-fixing activitylink field - extracting ID from object", {
600
+ logger.warn('Auto-fixing activitylink field - extracting ID from object', {
336
601
  fieldId,
337
602
  original: JSON.stringify(fieldValue),
338
603
  extracted: extractedId,
@@ -343,20 +608,21 @@ function buildActivityUpdate(args, context) {
343
608
  }
344
609
  }
345
610
  // Field-type aware validation and auto-fix
346
- if (parsedFields && typeof parsedFields === "object" && context.workspaceCache) {
611
+ if (parsedFields && typeof parsedFields === 'object' && context.workspaceCache) {
347
612
  autoFixDateFields(parsedFields, context);
348
613
  const invalidUsers = [];
349
614
  for (const [fieldId, fieldValue] of Object.entries(parsedFields)) {
350
615
  // Only check string values that look like IDs
351
- if (typeof fieldValue !== "string" || !/^[a-f0-9]{24}$/i.test(fieldValue)) {
616
+ if (typeof fieldValue !== 'string' || !/^[a-f0-9]{24}$/i.test(fieldValue)) {
352
617
  continue;
353
618
  }
354
619
  // Find the field definition to check its type
355
620
  let fieldType;
356
621
  for (const workflow of context.workspaceCache.rawInit.processes) {
357
622
  const workflowFields = workflow.fields;
358
- if (!workflowFields)
623
+ if (!workflowFields) {
359
624
  continue;
625
+ }
360
626
  const field = workflowFields[fieldId];
361
627
  if (field) {
362
628
  fieldType = field.type;
@@ -373,14 +639,14 @@ function buildActivityUpdate(args, context) {
373
639
  // Skip validation for 'activitylink' and other field types
374
640
  }
375
641
  if (invalidUsers.length > 0) {
376
- throw new Error(`Invalid user IDs in user fields: ${invalidUsers.join(", ")}. Use search_workspace_users to find valid user IDs.`);
642
+ throw new Error(`Invalid user IDs in user fields: ${invalidUsers.join(', ')}. Use search_workspace_users to find valid user IDs.`);
377
643
  }
378
644
  }
379
645
  return {
380
646
  _id: args.activityId,
381
647
  ...(args.name && { name: args.name }),
382
648
  ...(parsedFields &&
383
- typeof parsedFields === "object" && {
649
+ typeof parsedFields === 'object' && {
384
650
  fields: parsedFields,
385
651
  }),
386
652
  ...(args.phaseId && { phaseId: args.phaseId }),
@@ -391,43 +657,165 @@ function buildActivityUpdate(args, context) {
391
657
  */
392
658
  function formatUpdateActivityResponse(args, result) {
393
659
  const changesText = [
394
- args.name ? `- Name: "${args.name}"` : "",
395
- args.fields ? `- Fields: ${JSON.stringify(args.fields, null, 2)}` : "",
396
- args.phaseId ? `- Moved to phase: ${args.phaseId}` : "",
660
+ args.name ? `- Name: "${args.name}"` : '',
661
+ args.fields ? `- Fields: ${JSON.stringify(args.fields, null, 2)}` : '',
662
+ args.phaseId ? `- Moved to phase: ${args.phaseId}` : '',
397
663
  ]
398
664
  .filter(Boolean)
399
- .join("\n");
665
+ .join('\n');
400
666
  const responseText = `āœ… Successfully updated activity ${args.activityId}!\n\nšŸ“ Changes applied:\n${changesText}\n\nšŸ’” The activity has been updated in your Hailer workspace.\n\nAPI Response:\n${JSON.stringify(result, null, 2)}`;
401
667
  return {
402
668
  content: [
403
669
  {
404
- type: "text",
670
+ type: 'text',
405
671
  text: responseText,
406
672
  },
407
673
  ],
408
674
  };
409
675
  }
676
+ /**
677
+ * Resolves a workflow's field definitions from the cached core.init. Lets
678
+ * update_activity validate field keys with zero per-activity server reads
679
+ * when the caller supplies workflowId.
680
+ */
681
+ function resolveKnownWorkflowFields(workflowId, context) {
682
+ if (!workflowId) {
683
+ return undefined;
684
+ }
685
+ const workflow = context.init.processes?.find((proc) => proc._id === workflowId || proc.key === workflowId);
686
+ return workflow?.fields;
687
+ }
688
+ /** Bulk-mode body of update_activity — extracted so the per-item field-key validation keeps flat control flow. */
689
+ async function executeBulkUpdate(activities, context, workflowId) {
690
+ logger.debug('Bulk update mode', {
691
+ activityCount: activities.length,
692
+ activities: JSON.stringify(activities, null, 2)
693
+ });
694
+ // Auto-fix common parameter name mistakes
695
+ for (const activity of activities) {
696
+ // Fix activityId -> _id
697
+ if (!activity._id && activity.activityId) {
698
+ logger.warn('Auto-fixing: activityId -> _id', { activityId: activity.activityId });
699
+ activity._id = activity.activityId;
700
+ delete activity.activityId;
701
+ }
702
+ // Fix fieldsAndValues -> fields
703
+ if (!activity.fields && activity.fieldsAndValues) {
704
+ logger.warn('Auto-fixing: fieldsAndValues -> fields', { activityId: activity._id });
705
+ activity.fields = activity.fieldsAndValues;
706
+ delete activity.fieldsAndValues;
707
+ }
708
+ }
709
+ // Validate that all activities have _id
710
+ const invalidActivities = activities.filter((act) => !act._id || typeof act._id !== 'string' || act._id.length < 24);
711
+ if (invalidActivities.length > 0) {
712
+ return {
713
+ content: [{
714
+ type: 'text',
715
+ text: `āŒ **Error: Invalid bulk update request**\n\nEach activity in the "activities" array MUST have a valid "_id" field (24-character activity ID).\n\n**What you sent:** ${JSON.stringify(activities, null, 2)}\n\n**Correct format:**\n\`\`\`json\n{\n "activities": [\n { "_id": "691ffe654217e9e8434e577c", "fields": { "fieldId": "value" } },\n { "_id": "691ffe654217e9e8434e5774", "name": "New Name" }\n ]\n}\n\`\`\`\n\n**Tip:** First use list_activities to get the activity IDs, then pass them in the _id field.`,
716
+ }],
717
+ };
718
+ }
719
+ // Build updates for each activity
720
+ const updates = activities.map((activity) => {
721
+ const activityUpdate = { _id: activity._id };
722
+ if (activity.name) {
723
+ activityUpdate.name = activity.name;
724
+ }
725
+ if (activity.fields) {
726
+ // Parse fields if string
727
+ const parsedFields = typeof activity.fields === 'string'
728
+ ? JSON.parse(activity.fields)
729
+ : activity.fields;
730
+ // Auto-fix activitylink fields: if LLM passes object with _id, extract just the ID
731
+ const linkFixEntries = parsedFields && typeof parsedFields === 'object'
732
+ ? Object.entries(parsedFields)
733
+ : [];
734
+ for (const [fieldId, fieldValue] of linkFixEntries) {
735
+ const isLinkObject = Boolean(fieldValue) &&
736
+ typeof fieldValue === 'object' &&
737
+ !Array.isArray(fieldValue) &&
738
+ '_id' in fieldValue &&
739
+ typeof fieldValue._id === 'string';
740
+ if (!isLinkObject) {
741
+ continue;
742
+ }
743
+ logger.warn('Auto-fixing activitylink field in bulk mode', {
744
+ activityId: activity._id,
745
+ fieldId,
746
+ extracted: fieldValue._id,
747
+ });
748
+ parsedFields[fieldId] = fieldValue._id;
749
+ }
750
+ autoFixDateFields(parsedFields, context);
751
+ activityUpdate.fields = parsedFields;
752
+ }
753
+ return activityUpdate;
754
+ });
755
+ // Per-item field-key validation — runs AFTER the auto-fixups above
756
+ // (values only, keys unchanged; see validateFieldKeys). Unknown keys silently
757
+ // no-op server-side, so this is the only guard against lost updates. With
758
+ // workflowId the field defs come from the cached init (zero server reads);
759
+ // without it the per-activity workflow lookups run in parallel — the old
760
+ // sequential awaits made bulk updates cost one round trip per activity.
761
+ const knownWorkflowFields = resolveKnownWorkflowFields(workflowId, context);
762
+ // Without workflowId each validation fetches its activity — bound the fan-out
763
+ // so a 2000-item bulk update can't fire 2000 concurrent backend reads. With
764
+ // workflowId the validation is pure CPU and runs in one batch.
765
+ const validationConcurrency = knownWorkflowFields ? updates.length : BULK_CONCURRENCY;
766
+ let keyError;
767
+ for (let start = 0; start < updates.length && !keyError; start += validationConcurrency) {
768
+ const chunk = updates.slice(start, start + validationConcurrency);
769
+ const chunkErrors = await Promise.all(chunk.map((update) => update.fields
770
+ ? validateUpdateFieldKeys(update._id, update.fields, context, knownWorkflowFields)
771
+ : undefined));
772
+ keyError = chunkErrors.find(Boolean);
773
+ }
774
+ if (keyError) {
775
+ return {
776
+ content: [{ type: 'text', text: keyError }],
777
+ };
778
+ }
779
+ // Collect unique phase IDs (most activities will have the same phase)
780
+ const phaseIds = activities
781
+ .map((act) => act.phaseId)
782
+ .filter((pid) => pid);
783
+ const commonPhaseId = phaseIds.length > 0 ? phaseIds[0] : undefined;
784
+ // Call API with all updates
785
+ const options = commonPhaseId ? { phaseId: commonPhaseId } : undefined;
786
+ await context.hailer.updateActivities(updates, options);
787
+ // Format bulk response
788
+ return {
789
+ content: [
790
+ {
791
+ type: 'text',
792
+ text: `šŸŽ‰ Successfully updated ${activities.length} activities!\n\nšŸ“Š **Bulk Update Summary:**\n- **Total Updated**: ${activities.length} activities\n- **Status**: All activities updated successfully\n\nāœ… All activities have been updated in your Hailer workspace!`,
793
+ },
794
+ ],
795
+ };
796
+ }
410
797
  const listActivitiesDescription = `List activities (items/records/tasks) from a workflow phase.
411
798
 
412
799
  **Prerequisites:** You need workflowId, phaseId, and field IDs. Get them via:
413
- 1. \`list_workflows_minimal\` → workflowId
414
- 2. \`list_workflow_phases\` → phaseId
415
- 3. \`get_workflow_schema\` → field IDs for the \`fields\` parameter
800
+ 1. \`describe_workflows\` → workflowId
801
+ 2. \`describe_workflows\` with include: ['phases'] → phaseId
802
+ 3. \`describe_workflows\` with include: ['schema'] → field IDs for the \`fields\` parameter
416
803
 
417
804
  **Required params:** workflowId, phaseId, fields[] (array of field IDs to return)
418
805
 
419
- **Example flow:** User says "show my tasks" →
420
- 1. list_workflows_minimal → find "Tasks" workflow
421
- 2. list_workflow_phases → find "Open" phase
422
- 3. get_workflow_schema → get field IDs
423
- 4. list_activities with those IDs`;
806
+ **Fast path:** \`countOnly: true\` returns only the workflow's total activity count (O(1), needs just workflowId — no phaseId/fields).
807
+
808
+ **Large reads:** \`maxRecords\` (≤5000) fetches the whole result set in ONE call — pages are pulled in parallel server-side. Use 2-3 \`fields\` to stay under the response size cap. For counts, sums, group-bys, or cross-workflow joins prefer \`run_insight\` (SQL) where available — aggregates beat raw rows.`;
424
809
  exports.listActivitiesTool = {
425
810
  name: 'list_activities',
426
811
  group: tool_registry_1.ToolGroup.READ,
427
812
  description: listActivitiesDescription,
428
813
  schema: zod_1.z.object({
429
- workflowId: zod_1.z.string().describe("Workflow ID or key to list activities from"),
430
- phaseId: zod_1.z.string().describe("Phase ID or key to filter activities (required - use list_workflow_phases to get available phases)"),
814
+ workflowId: zod_1.z.string().describe('Workflow ID or key to list activities from'),
815
+ phaseId: zod_1.z.string().optional()
816
+ .describe("Phase ID or key to filter activities. Required unless countOnly=true. Use describe_workflows with include: ['phases'] for phases"),
817
+ countOnly: zod_1.z.coerce.boolean().optional().default(false).describe('Fast path: return only the total activity count for the workflow (O(1) v3.activity.count). ' +
818
+ 'Needs just workflowId; phaseId/fields/filters are ignored.'),
431
819
  fields: zod_1.z.preprocess((val) => {
432
820
  if (typeof val === 'string') {
433
821
  try {
@@ -440,31 +828,37 @@ exports.listActivitiesTool = {
440
828
  }
441
829
  }
442
830
  return val;
443
- }, zod_1.z.array(zod_1.z.string()).optional()).describe("Array of field IDs or keys to return (use get_workflow_schema to see available fields). Select the fields needed for the task - use fewer fields for listings (name, status, etc.) and more fields when detailed information is required. If not provided, you must call get_workflow_schema first."),
831
+ }, zod_1.z.array(zod_1.z.string()).optional()).describe("Array of field IDs or keys to return (use describe_workflows with include: ['schema'] to see available fields). Select the fields needed for the task - use fewer fields for listings (name, status, etc.) and more fields when detailed information is required."),
444
832
  filters: zod_1.z.record(zod_1.z.object({
445
833
  operator: zod_1.z.enum([
446
- "text_search",
447
- "equals",
448
- "not_equals",
449
- "contains",
450
- "greater_than",
451
- "greater_than_or_equal",
452
- "less_than",
453
- "less_than_or_equal",
454
- "range",
455
- ]).describe("Filter operator: text_search for partial text match in field (BEST for filtering by text in relationship fields when you only have a name), equals for exact match (requires activity ID), range for date/number ranges, contains for partial text, comparison operators for numbers/dates"),
456
- value: zod_1.z.union([zod_1.z.string(), zod_1.z.number()]).optional().describe("Value to filter by - REQUIRED for text_search, equals, not_equals, contains, greater_than, less_than operators. NOT USED for range operator (use start/end instead). For text_search: use the text/name to search for. For equals: use the entity ID."),
834
+ 'text_search',
835
+ 'equals',
836
+ 'not_equals',
837
+ 'contains',
838
+ 'greater_than',
839
+ 'greater_than_or_equal',
840
+ 'less_than',
841
+ 'less_than_or_equal',
842
+ 'range',
843
+ ]).describe('Filter operator: text_search for partial text match in field (BEST for filtering by text in relationship fields when you only have a name), equals for exact match (requires activity ID), range for date/number ranges, contains for partial text, comparison operators for numbers/dates'),
844
+ value: zod_1.z.union([zod_1.z.string(), zod_1.z.number()]).optional().describe('Value to filter by - REQUIRED for text_search, equals, not_equals, contains, greater_than, less_than operators. NOT USED for range operator (use start/end instead). For text_search: use the text/name to search for. For equals: use the entity ID.'),
457
845
  start: zod_1.z.coerce.number().optional().describe("Start value - ONLY for range operator (NOT in 'value' field). Unix timestamp in milliseconds for date ranges. NOT nested in 'value'."),
458
846
  end: zod_1.z.coerce.number().optional().describe("End value - ONLY for range operator (NOT in 'value' field). Unix timestamp in milliseconds for date ranges. Example: for June 2025 date range, use end=1719791999000 directly here, NOT nested in 'value'."),
459
847
  })).optional().describe("Filter by field values. STRUCTURE: {\"fieldId\": {\"operator\": \"...\", \"value\": \"...\"}}. EXAMPLE: To find player named 'Harry Kane', use: {\"691ffdf84217e9e8434e5694\": {\"operator\": \"text_search\", \"value\": \"Harry Kane\"}}. WRONG: {\"playerName\": \"Harry Kane\"} or {\"fieldId\": \"Harry Kane\"}. Operators: text_search (partial text match), equals (exact ID match), range (use start/end instead of value)."),
460
- search: zod_1.z.string().optional().describe("Text search across activity content - USE FILTERS INSTEAD when possible for reliable results. Only use search for truly exploratory queries."),
461
- limit: zod_1.z.coerce.number().optional().default(50).describe("Maximum number of activities to return (default: 50, max: 20000)"),
462
- page: zod_1.z.coerce.number().optional().default(0).describe("Page number for pagination (0-based)"),
463
- sortBy: zod_1.z.enum(["name", "created", "updated", "priority"]).optional().default("updated").describe("Field to sort by"),
464
- sortOrder: zod_1.z.enum(["asc", "desc"]).optional().default("desc").describe("Sort direction"),
465
- includeStats: zod_1.z.coerce.boolean().optional().default(true).describe("Include total count and pagination metadata"),
848
+ search: zod_1.z.string().optional().describe('Text search across activity content - USE FILTERS INSTEAD when possible for reliable results. Only use search for truly exploratory queries.'),
849
+ limit: zod_1.z.coerce.number().int().min(1).max(200).optional().default(50).describe('Activities per page (default: 50, max: 200 — the server silently returns empty results for larger values; paginate with `page` instead)'),
850
+ page: zod_1.z.coerce.number().int().min(0).optional().default(0).describe('Page number for pagination (0-based). The response reports the total page count'),
851
+ maxRecords: zod_1.z.coerce.number().int().min(1).max(5000).optional().describe('BULK READ: fetch up to this many matching activities in ONE call — pages are pulled in parallel server-side ' +
852
+ '(sorted created asc). Overrides limit/page. Keep fields minimal (2-3): the response size cap still applies'),
853
+ sortBy: zod_1.z.enum(['name', 'created', 'updated', 'priority']).optional().default('updated').describe('Field to sort by'),
854
+ sortOrder: zod_1.z.enum(['asc', 'desc']).optional().default('desc').describe('Sort direction'),
855
+ includeStats: zod_1.z.coerce.boolean().optional().default(false).describe('Include schedule/value stats metadata (the total count is always returned regardless)'),
466
856
  }),
467
857
  async execute(args, context) {
858
+ // countOnly fast path — dispatches to the retired count_activities body (own error handling)
859
+ if (args.countOnly) {
860
+ return executeActivityCount(args.workflowId, context);
861
+ }
468
862
  try {
469
863
  const workflow = validateAndGetWorkflow(args.workflowId, context.init);
470
864
  const phaseId = await resolvePhaseForListing(workflow, args, context.init);
@@ -472,10 +866,10 @@ exports.listActivitiesTool = {
472
866
  return {
473
867
  content: [
474
868
  {
475
- type: "text",
869
+ type: 'text',
476
870
  text: `āŒ **Fields parameter required**: You must specify which fields to return to avoid huge responses.\n\n` +
477
871
  `šŸ“‹ **Next steps:**\n` +
478
- `1. Call \`get_workflow_schema\` with workflowId: "${args.workflowId}" and phaseId: "${phaseId}" to see available fields\n` +
872
+ `1. Call \`describe_workflows\` with workflowId: "${args.workflowId}" and include: ['schema'] to see available fields\n` +
479
873
  `2. Then call \`list_activities\` again with 2-3 essential field IDs\n\n` +
480
874
  `šŸ’” **Best practices:**\n` +
481
875
  `- For product listings: ["name", "price", "stock"] (3 fields)\n` +
@@ -502,10 +896,10 @@ exports.listActivitiesTool = {
502
896
  return {
503
897
  content: [
504
898
  {
505
- type: "text",
899
+ type: 'text',
506
900
  text: `āŒ **Filter Error:** ${filterErrorMessage}\n\n` +
507
901
  `šŸ’” **Valid operators:** equals, not_equals, contains, text_search, greater_than, less_than, range\n` +
508
- `šŸ“‹ Call \`get_workflow_schema\` to see available field IDs and types`,
902
+ `šŸ“‹ Call \`describe_workflows\` with include: ['schema'] to see available field IDs and types`,
509
903
  }
510
904
  ],
511
905
  };
@@ -515,6 +909,9 @@ exports.listActivitiesTool = {
515
909
  apiFilters: JSON.stringify(apiFilters)
516
910
  });
517
911
  }
912
+ if (args.maxRecords) {
913
+ return await executeBulkRead(args, workflow, phaseId, apiFilters, context);
914
+ }
518
915
  const options = {
519
916
  page: args.page,
520
917
  search: args.search,
@@ -542,12 +939,13 @@ exports.listActivitiesTool = {
542
939
  return response;
543
940
  }
544
941
  catch (error) {
545
- if (!request_logger_1.RequestLogger.getCurrent())
546
- logger.error("Failed to list activities", error);
942
+ if (!request_logger_1.RequestLogger.getCurrent()) {
943
+ logger.error('Failed to list activities', error);
944
+ }
547
945
  return {
548
946
  content: [
549
947
  {
550
- type: "text",
948
+ type: 'text',
551
949
  text: `āŒ Failed to list activities: ${(0, tool_helpers_1.extractErrorMessage)(error)}`,
552
950
  },
553
951
  ],
@@ -567,37 +965,38 @@ exports.showActivityByIdTool = {
567
965
  group: tool_registry_1.ToolGroup.READ,
568
966
  description: showActivityByIdDescription,
569
967
  schema: zod_1.z.object({
570
- activityId: zod_1.z.string().describe("Activity ID to load"),
968
+ activityId: zod_1.z.string().describe('Activity ID to load'),
571
969
  }),
572
970
  async execute(args, context) {
573
971
  // Validate: reject known non-activity ID patterns
574
972
  const id = args.activityId;
575
973
  if (!id || typeof id !== 'string' || id.length < 24) {
576
974
  return {
577
- content: [{ type: "text", text: `āŒ Invalid activity ID: "${id}". Activity IDs are 24-character hex strings from list_activities results. Do NOT use workflow IDs, field IDs, phase IDs, or discussion IDs.` }],
975
+ content: [{ type: 'text', text: `āŒ Invalid activity ID: "${id}". Activity IDs are 24-character hex strings from list_activities results. Do NOT use workflow IDs, field IDs, phase IDs, or discussion IDs.` }],
578
976
  };
579
977
  }
580
978
  try {
581
979
  const activity = await context.hailer.fetchActivityById(args.activityId);
582
- let responseText = `āœ… Loaded activity with ID "${activity._id}":\n\n${JSON.stringify(activity, null, 2)}`;
980
+ const responseText = `āœ… Loaded activity with ID "${activity._id}":\n\n${JSON.stringify(activity, null, 2)}`;
583
981
  return {
584
982
  content: [
585
983
  {
586
- type: "text",
984
+ type: 'text',
587
985
  text: responseText,
588
986
  },
589
987
  ],
590
988
  };
591
989
  }
592
990
  catch (error) {
593
- if (!request_logger_1.RequestLogger.getCurrent())
594
- logger.error("Failed to load activity", error, {
991
+ if (!request_logger_1.RequestLogger.getCurrent()) {
992
+ logger.error('Failed to load activity', error, {
595
993
  activityId: args.activityId,
596
994
  });
995
+ }
597
996
  return {
598
997
  content: [
599
998
  {
600
- type: "text",
999
+ type: 'text',
601
1000
  text: `āŒ Failed to load activity "${args.activityId}": ${(0, tool_helpers_1.extractErrorMessage)(error)}\n\nāš ļø Make sure this is an ACTIVITY ID (from list_activities or activity._id), NOT a workflow ID, field ID, phase ID, or discussion ID.`,
602
1001
  },
603
1002
  ],
@@ -610,10 +1009,10 @@ exports.showActivityByIdTool = {
610
1009
  // ============================================================================
611
1010
  const createActivityDescription = `Create a new activity (item/record/task) in a workflow.
612
1011
 
613
- **Prerequisites:** Get IDs first via:
614
- 1. \`list_workflows_minimal\` → workflowId
615
- 2. \`list_workflow_phases\` → phaseId (use isInitial=true phase)
616
- 3. \`get_workflow_schema\` → field IDs for the fields parameter
1012
+ **Prerequisites:** Get IDs first via \`describe_workflows\`:
1013
+ 1. No args → workflowId
1014
+ 2. include: ['phases'] → phaseId (use isInitial=true phase)
1015
+ 3. include: ['schema'] → field IDs for the fields parameter
617
1016
 
618
1017
  **Required:** workflowId + (name OR activities[])
619
1018
  **Recommended:** phaseId (defaults to initial phase if omitted)
@@ -633,38 +1032,38 @@ exports.createActivityTool = {
633
1032
  schema: zod_1.z.object({
634
1033
  workflowId: zod_1.z
635
1034
  .string()
636
- .describe("The workflow ID or key where to create the activity/activities. Find this in any list_* tool results"),
1035
+ .describe('The workflow ID or key where to create the activity/activities. Find this in any list_* tool results'),
637
1036
  // BULK CREATION (optional - takes precedence over single parameters)
638
1037
  activities: zod_1.z
639
1038
  .array(zod_1.z.object({
640
- name: zod_1.z.string().min(1, "Activity name cannot be empty").describe("Activity name/title"),
641
- fields: zod_1.z.union([zod_1.z.record(zod_1.z.any()), zod_1.z.string()]).optional().describe("Custom field values (field keys or IDs)"),
642
- phaseId: zod_1.z.string().optional().describe("Phase ID or key for this activity"),
643
- teamId: zod_1.z.string().optional().describe("Team ID for this activity"),
644
- discussionId: zod_1.z.string().optional().describe("Link to existing discussion"),
645
- followerIds: zod_1.z.union([zod_1.z.array(zod_1.z.string()), zod_1.z.string()]).optional().describe("User IDs to invite"),
646
- fileIds: zod_1.z.union([zod_1.z.array(zod_1.z.string()), zod_1.z.string()]).optional().describe("File IDs to attach"),
1039
+ name: zod_1.z.string().min(1, 'Activity name cannot be empty').describe('Activity name/title'),
1040
+ fields: zod_1.z.union([zod_1.z.record(zod_1.z.any()), zod_1.z.string()]).optional().describe('Custom field values (field keys or IDs)'),
1041
+ phaseId: zod_1.z.string().optional().describe('Phase ID or key for this activity'),
1042
+ teamId: zod_1.z.string().optional().describe('Team ID for this activity'),
1043
+ discussionId: zod_1.z.string().optional().describe('Link to existing discussion'),
1044
+ followerIds: zod_1.z.union([zod_1.z.array(zod_1.z.string()), zod_1.z.string()]).optional().describe('User IDs to invite'),
1045
+ fileIds: zod_1.z.union([zod_1.z.array(zod_1.z.string()), zod_1.z.string()]).optional().describe('File IDs to attach'),
647
1046
  }))
648
1047
  .optional()
649
- .describe("BULK: Array of activities. Example: [{\"name\": \"Task 1\", \"fields\": {...}}, {\"name\": \"Task 2\"}]. If provided, single parameters are ignored."),
1048
+ .describe('BULK: Array of activities. Example: [{"name": "Task 1", "fields": {...}}, {"name": "Task 2"}]. If provided, single parameters are ignored.'),
650
1049
  // SINGLE CREATION (used when 'activities' is not provided)
651
1050
  name: zod_1.z
652
1051
  .string()
653
- .min(1, "Activity name cannot be empty")
1052
+ .min(1, 'Activity name cannot be empty')
654
1053
  .optional()
655
1054
  .describe("SINGLE: The activity name/title (e.g. 'šŸ¤– AI Analysis Bot', 'Customer Research Task')"),
656
1055
  description: zod_1.z
657
1056
  .string()
658
1057
  .optional()
659
- .describe("SINGLE: Optional detailed description"),
1058
+ .describe('SINGLE: Optional detailed description'),
660
1059
  phaseId: zod_1.z
661
1060
  .string()
662
1061
  .optional()
663
- .describe("SINGLE: Optional phase/category ID or key. If not specified, uses the default phase"),
1062
+ .describe('SINGLE: Optional phase/category ID or key. If not specified, uses the default phase'),
664
1063
  teamId: zod_1.z
665
1064
  .string()
666
1065
  .optional()
667
- .describe("SINGLE: Optional team ID for team-specific activities"),
1066
+ .describe('SINGLE: Optional team ID for team-specific activities'),
668
1067
  fields: zod_1.z
669
1068
  .union([zod_1.z.record(zod_1.z.any()), zod_1.z.string()])
670
1069
  .optional()
@@ -672,20 +1071,20 @@ exports.createActivityTool = {
672
1071
  discussionId: zod_1.z
673
1072
  .string()
674
1073
  .optional()
675
- .describe("SINGLE: Optional discussion ID to link to existing conversation"),
1074
+ .describe('SINGLE: Optional discussion ID to link to existing conversation'),
676
1075
  followerIds: zod_1.z
677
1076
  .union([zod_1.z.array(zod_1.z.string()), zod_1.z.string()])
678
1077
  .optional()
679
- .describe("SINGLE: Optional array of user IDs to invite"),
1078
+ .describe('SINGLE: Optional array of user IDs to invite'),
680
1079
  fileIds: zod_1.z
681
1080
  .union([zod_1.z.array(zod_1.z.string()), zod_1.z.string()])
682
1081
  .optional()
683
- .describe("SINGLE: Optional array of file IDs to attach"),
1082
+ .describe('SINGLE: Optional array of file IDs to attach'),
684
1083
  }),
685
1084
  async execute(args, context) {
686
1085
  try {
687
1086
  // DEBUG: Log raw input to diagnose LLM tool calling issues
688
- logger.debug("create_activity called", {
1087
+ logger.debug('create_activity called', {
689
1088
  hasName: !!args.name,
690
1089
  hasActivities: !!args.activities,
691
1090
  activitiesType: typeof args.activities,
@@ -701,7 +1100,7 @@ exports.createActivityTool = {
701
1100
  };
702
1101
  if (activityData.fields) {
703
1102
  let parsedFields = activityData.fields;
704
- if (typeof activityData.fields === "string" && activityData.fields.trim() !== "") {
1103
+ if (typeof activityData.fields === 'string' && activityData.fields.trim() !== '') {
705
1104
  try {
706
1105
  parsedFields = JSON.parse(activityData.fields);
707
1106
  }
@@ -710,22 +1109,22 @@ exports.createActivityTool = {
710
1109
  }
711
1110
  }
712
1111
  if (parsedFields &&
713
- typeof parsedFields === "object" &&
1112
+ typeof parsedFields === 'object' &&
714
1113
  Object.keys(parsedFields).length > 0) {
715
1114
  autoFixDateFields(parsedFields, context);
716
1115
  activity.fields = parsedFields;
717
1116
  }
718
1117
  }
719
- if (activityData.phaseId && activityData.phaseId.trim() !== "") {
1118
+ if (activityData.phaseId && activityData.phaseId.trim() !== '') {
720
1119
  activity.phaseId = activityData.phaseId;
721
1120
  }
722
- if (activityData.teamId && activityData.teamId.trim() !== "") {
1121
+ if (activityData.teamId && activityData.teamId.trim() !== '') {
723
1122
  activity.teamId = activityData.teamId;
724
1123
  }
725
1124
  if (activityData.followerIds) {
726
1125
  let parsedFollowerIds = activityData.followerIds;
727
- if (typeof activityData.followerIds === "string" &&
728
- activityData.followerIds.trim() !== "") {
1126
+ if (typeof activityData.followerIds === 'string' &&
1127
+ activityData.followerIds.trim() !== '') {
729
1128
  try {
730
1129
  parsedFollowerIds = JSON.parse(activityData.followerIds);
731
1130
  }
@@ -744,7 +1143,7 @@ exports.createActivityTool = {
744
1143
  }
745
1144
  }
746
1145
  if (invalidUsers.length > 0) {
747
- throw new Error(`Invalid user IDs in followerIds: ${invalidUsers.join(", ")}. Use search_workspace_users to find valid user IDs.`);
1146
+ throw new Error(`Invalid user IDs in followerIds: ${invalidUsers.join(', ')}. Use search_workspace_users to find valid user IDs.`);
748
1147
  }
749
1148
  }
750
1149
  activity.followerIds = parsedFollowerIds;
@@ -752,8 +1151,8 @@ exports.createActivityTool = {
752
1151
  }
753
1152
  if (activityData.fileIds) {
754
1153
  let parsedFileIds = activityData.fileIds;
755
- if (typeof activityData.fileIds === "string" &&
756
- activityData.fileIds.trim() !== "") {
1154
+ if (typeof activityData.fileIds === 'string' &&
1155
+ activityData.fileIds.trim() !== '') {
757
1156
  try {
758
1157
  parsedFileIds = JSON.parse(activityData.fileIds);
759
1158
  }
@@ -791,7 +1190,7 @@ exports.createActivityTool = {
791
1190
  }
792
1191
  }
793
1192
  let activitiesToCreate;
794
- let options = {
1193
+ const options = {
795
1194
  returnDocument: true,
796
1195
  };
797
1196
  if (isBulk) {
@@ -810,7 +1209,7 @@ exports.createActivityTool = {
810
1209
  return activity;
811
1210
  });
812
1211
  // Check for common discussionId in bulk
813
- if (args.discussionId && args.discussionId.trim() !== "") {
1212
+ if (args.discussionId && args.discussionId.trim() !== '') {
814
1213
  options.discussionId = args.discussionId;
815
1214
  }
816
1215
  }
@@ -819,7 +1218,7 @@ exports.createActivityTool = {
819
1218
  if (!args.name) {
820
1219
  throw new Error("Either 'activities' array or 'name' parameter is required");
821
1220
  }
822
- logger.debug("Creating single activity", {
1221
+ logger.debug('Creating single activity', {
823
1222
  workflowId: args.workflowId,
824
1223
  name: args.name,
825
1224
  defaultTeamId: defaultTeamId,
@@ -830,12 +1229,29 @@ exports.createActivityTool = {
830
1229
  activity.teamId = defaultTeamId;
831
1230
  }
832
1231
  activitiesToCreate = [activity];
833
- if (args.discussionId && args.discussionId.trim() !== "") {
1232
+ if (args.discussionId && args.discussionId.trim() !== '') {
834
1233
  options.discussionId = args.discussionId;
835
1234
  }
836
1235
  }
1236
+ // Pre-validate field keys before API call — runs AFTER processActivity's
1237
+ // auto-fixups (values only, keys unchanged; see validateFieldKeys).
1238
+ // Unknown keys (e.g. field NAMES) silently no-op server-side.
1239
+ const workflow = context.init.processes?.find((proc) => proc._id === args.workflowId);
1240
+ const workflowFieldDefs = workflow?.fields;
1241
+ for (let i = 0; i < activitiesToCreate.length; i++) {
1242
+ const item = activitiesToCreate[i];
1243
+ const keyError = workflowFieldDefs && item.fields ? validateFieldKeys(item.fields, workflowFieldDefs) : undefined;
1244
+ if (keyError) {
1245
+ const itemName = item.name || `Activity ${i + 1}`;
1246
+ return {
1247
+ content: [{
1248
+ type: 'text',
1249
+ text: `āŒ Invalid field keys in "${itemName}" — nothing was created.\n\n${keyError}`,
1250
+ }],
1251
+ };
1252
+ }
1253
+ }
837
1254
  // Pre-validate required fields before API call
838
- const workflow = context.init.processes?.find((p) => p._id === args.workflowId);
839
1255
  if (workflow?.fields) {
840
1256
  const requiredFields = [];
841
1257
  for (const [fieldId, field] of Object.entries(workflow.fields)) {
@@ -864,7 +1280,7 @@ exports.createActivityTool = {
864
1280
  const fieldList = requiredFields.map(f => `- ${f.label} (key: ${f.key}, id: ${f.id})`).join('\n');
865
1281
  return {
866
1282
  content: [{
867
- type: "text",
1283
+ type: 'text',
868
1284
  text: `āŒ Missing required fields - cannot create activities.\n\n**Required fields for this workflow:**\n${fieldList}\n\n**Activities with missing fields:**\n${missingByActivity.map(m => `- ${m}`).join('\n')}\n\nšŸ’” Add the missing fields to each activity's \`fields\` object using either the field key or ID.`,
869
1285
  }],
870
1286
  };
@@ -891,7 +1307,7 @@ exports.createActivityTool = {
891
1307
  return {
892
1308
  content: [
893
1309
  {
894
- type: "text",
1310
+ type: 'text',
895
1311
  text: responseText,
896
1312
  },
897
1313
  ],
@@ -922,7 +1338,7 @@ exports.createActivityTool = {
922
1338
  return {
923
1339
  content: [
924
1340
  {
925
- type: "text",
1341
+ type: 'text',
926
1342
  text: responseText,
927
1343
  },
928
1344
  ],
@@ -930,11 +1346,12 @@ exports.createActivityTool = {
930
1346
  }
931
1347
  }
932
1348
  catch (error) {
933
- if (!request_logger_1.RequestLogger.getCurrent())
934
- logger.error("Failed to create activity/activities", error, {
1349
+ if (!request_logger_1.RequestLogger.getCurrent()) {
1350
+ logger.error('Failed to create activity/activities', error, {
935
1351
  workflowId: args.workflowId,
936
1352
  isBulk: !!(args.activities && args.activities.length > 0),
937
1353
  });
1354
+ }
938
1355
  const errorMessage = error instanceof Error
939
1356
  ? error.message
940
1357
  : (typeof error === 'object' && error !== null)
@@ -943,7 +1360,7 @@ exports.createActivityTool = {
943
1360
  return {
944
1361
  content: [
945
1362
  {
946
- type: "text",
1363
+ type: 'text',
947
1364
  text: `āŒ Error creating activity: ${errorMessage}\n\nšŸ’” Troubleshooting Tips:\n- Verify the workflowId exists and is accessible\n- Check that you have permission to create activities in this workflow\n- Ensure field IDs in the fields object match the workflow's field definitions\n- Use search_workspace_users to find valid user IDs for assignment\n- Verify user IDs in followerIds exist and are accessible`,
948
1365
  },
949
1366
  ],
@@ -956,10 +1373,11 @@ exports.createActivityTool = {
956
1373
  // ============================================================================
957
1374
  const updateActivityDescription = `Update an existing activity - change fields or move to different phase.
958
1375
 
959
- **To update fields:** Get field IDs from \`get_workflow_schema\` first, then pass them in the fields object.
960
- **To change phase:** Get phase IDs from \`list_workflow_phases\`, pass target phaseId.
1376
+ **To update fields:** Get field IDs from \`describe_workflows\` (include: ['schema']) first, then pass them in the fields object.
1377
+ **To change phase:** Get phase IDs from \`describe_workflows\` (include: ['phases']), pass target phaseId.
961
1378
 
962
1379
  **Required:** activityId (for single) OR activities[] array (for bulk)
1380
+ **Performance:** Pass \`workflowId\` whenever you know it (you usually do — it came from list_activities). It skips a per-activity server read used for field-key validation; on bulk updates that is one read per activity saved.
963
1381
 
964
1382
  **Field value formats:**
965
1383
  - Text: \`"value"\`
@@ -976,9 +1394,9 @@ exports.updateActivityTool = {
976
1394
  schema: zod_1.z.object({
977
1395
  // BULK: Array of activities to update
978
1396
  activities: zod_1.z
979
- .preprocess((val) => (typeof val === "string" ? JSON.parse(val) : val), zod_1.z
1397
+ .preprocess((val) => (typeof val === 'string' ? JSON.parse(val) : val), zod_1.z
980
1398
  .array(zod_1.z.object({
981
- _id: zod_1.z.string().min(24, "Activity ID must be at least 24 characters"),
1399
+ _id: zod_1.z.string().min(24, 'Activity ID must be at least 24 characters'),
982
1400
  name: zod_1.z.string().optional(),
983
1401
  fields: zod_1.z.record(zod_1.z.any()).optional(),
984
1402
  phaseId: zod_1.z.string().optional(),
@@ -989,10 +1407,10 @@ exports.updateActivityTool = {
989
1407
  // SINGLE: Individual activity parameters
990
1408
  activityId: zod_1.z
991
1409
  .string()
992
- .min(24, "Activity ID must be at least 24 characters")
1410
+ .min(24, 'Activity ID must be at least 24 characters')
993
1411
  .optional()
994
- .describe("SINGLE: The unique ID of the activity to update (works for any workflow)"),
995
- name: zod_1.z.string().optional().describe("SINGLE: New activity title/name"),
1412
+ .describe('SINGLE: The unique ID of the activity to update (works for any workflow)'),
1413
+ name: zod_1.z.string().optional().describe('SINGLE: New activity title/name'),
996
1414
  fields: zod_1.z
997
1415
  .union([zod_1.z.record(zod_1.z.any()), zod_1.z.string()])
998
1416
  .optional()
@@ -1000,97 +1418,24 @@ exports.updateActivityTool = {
1000
1418
  phaseId: zod_1.z
1001
1419
  .string()
1002
1420
  .optional()
1003
- .describe("SINGLE: Optional phase ID or key to move the activity to"),
1421
+ .describe('SINGLE: Optional phase ID or key to move the activity to'),
1422
+ workflowId: zod_1.z
1423
+ .string()
1424
+ .optional()
1425
+ .describe('Workflow ID or key the activities belong to (single AND bulk). Strongly recommended when known: skips one validation read per activity'),
1004
1426
  }),
1005
1427
  async execute(args, context) {
1006
1428
  try {
1007
1429
  // BULK MODE: Update multiple activities
1008
1430
  if (args.activities && Array.isArray(args.activities)) {
1009
- logger.debug("Bulk update mode", {
1010
- activityCount: args.activities.length,
1011
- activities: JSON.stringify(args.activities, null, 2)
1012
- });
1013
- // Auto-fix common parameter name mistakes
1014
- for (const activity of args.activities) {
1015
- // Fix activityId -> _id
1016
- if (!activity._id && activity.activityId) {
1017
- logger.warn("Auto-fixing: activityId -> _id", { activityId: activity.activityId });
1018
- activity._id = activity.activityId;
1019
- delete activity.activityId;
1020
- }
1021
- // Fix fieldsAndValues -> fields
1022
- if (!activity.fields && activity.fieldsAndValues) {
1023
- logger.warn("Auto-fixing: fieldsAndValues -> fields", { activityId: activity._id });
1024
- activity.fields = activity.fieldsAndValues;
1025
- delete activity.fieldsAndValues;
1026
- }
1027
- }
1028
- // Validate that all activities have _id
1029
- const invalidActivities = args.activities.filter((a) => !a._id || typeof a._id !== 'string' || a._id.length < 24);
1030
- if (invalidActivities.length > 0) {
1031
- return {
1032
- content: [{
1033
- type: "text",
1034
- text: `āŒ **Error: Invalid bulk update request**\n\nEach activity in the "activities" array MUST have a valid "_id" field (24-character activity ID).\n\n**What you sent:** ${JSON.stringify(args.activities, null, 2)}\n\n**Correct format:**\n\`\`\`json\n{\n "activities": [\n { "_id": "691ffe654217e9e8434e577c", "fields": { "fieldId": "value" } },\n { "_id": "691ffe654217e9e8434e5774", "name": "New Name" }\n ]\n}\n\`\`\`\n\n**Tip:** First use list_activities to get the activity IDs, then pass them in the _id field.`,
1035
- }],
1036
- };
1037
- }
1038
- // Build updates for each activity
1039
- const updates = args.activities.map((activity) => {
1040
- const activityUpdate = { _id: activity._id };
1041
- if (activity.name)
1042
- activityUpdate.name = activity.name;
1043
- if (activity.fields) {
1044
- // Parse fields if string
1045
- let parsedFields = typeof activity.fields === 'string'
1046
- ? JSON.parse(activity.fields)
1047
- : activity.fields;
1048
- // Auto-fix activitylink fields: if LLM passes object with _id, extract just the ID
1049
- if (parsedFields && typeof parsedFields === "object") {
1050
- for (const [fieldId, fieldValue] of Object.entries(parsedFields)) {
1051
- if (fieldValue &&
1052
- typeof fieldValue === "object" &&
1053
- !Array.isArray(fieldValue) &&
1054
- "_id" in fieldValue &&
1055
- typeof fieldValue._id === "string") {
1056
- logger.warn("Auto-fixing activitylink field in bulk mode", {
1057
- activityId: activity._id,
1058
- fieldId,
1059
- extracted: fieldValue._id,
1060
- });
1061
- parsedFields[fieldId] = fieldValue._id;
1062
- }
1063
- }
1064
- }
1065
- autoFixDateFields(parsedFields, context);
1066
- activityUpdate.fields = parsedFields;
1067
- }
1068
- return activityUpdate;
1069
- });
1070
- // Collect unique phase IDs (most activities will have the same phase)
1071
- const phaseIds = args.activities
1072
- .map((a) => a.phaseId)
1073
- .filter((p) => p);
1074
- const commonPhaseId = phaseIds.length > 0 ? phaseIds[0] : undefined;
1075
- // Call API with all updates
1076
- const options = commonPhaseId ? { phaseId: commonPhaseId } : undefined;
1077
- await context.hailer.updateActivities(updates, options);
1078
- // Format bulk response
1079
- return {
1080
- content: [
1081
- {
1082
- type: "text",
1083
- text: `šŸŽ‰ Successfully updated ${args.activities.length} activities!\n\nšŸ“Š **Bulk Update Summary:**\n- **Total Updated**: ${args.activities.length} activities\n- **Status**: All activities updated successfully\n\nāœ… All activities have been updated in your Hailer workspace!`,
1084
- },
1085
- ],
1086
- };
1431
+ return await executeBulkUpdate(args.activities, context, args.workflowId);
1087
1432
  }
1088
1433
  // SINGLE MODE: Update one activity
1089
1434
  // Validate activityId is provided for single mode
1090
1435
  if (!args.activityId || typeof args.activityId !== 'string' || args.activityId.length < 24) {
1091
1436
  return {
1092
1437
  content: [{
1093
- type: "text",
1438
+ type: 'text',
1094
1439
  text: `āŒ **Error: Missing or invalid activityId**\n\nFor single activity updates, you must provide a valid "activityId" (24-character hex string).\n\n**What you sent:** activityId = ${JSON.stringify(args.activityId)}\n\n**Correct format:**\n\`\`\`json\n{\n "activityId": "691ffe654217e9e8434e577c",\n "name": "New Name",\n "fields": { "fieldId": "value" }\n}\n\`\`\`\n\n**For bulk updates (3+ activities), use:**\n\`\`\`json\n{\n "activities": [\n { "_id": "activity-id-1", "fields": {...} },\n { "_id": "activity-id-2", "name": "New Name" }\n ]\n}\n\`\`\`\n\n**Tip:** Use list_activities or show_activity_by_id to find activity IDs first.`,
1095
1440
  }],
1096
1441
  };
@@ -1099,32 +1444,44 @@ exports.updateActivityTool = {
1099
1444
  if (!args.name && !args.fields && !args.phaseId) {
1100
1445
  return {
1101
1446
  content: [{
1102
- type: "text",
1447
+ type: 'text',
1103
1448
  text: `āŒ **Error: No update data provided**\n\nYou called update_activity with activityId="${args.activityId}" but didn't provide any data to update.\n\n**You must provide at least one of:**\n- "name" - to update the activity name\n- "fields" - to update field values\n- "phaseId" - to move to a different phase\n\n**Example:**\n\`\`\`json\n{\n "activityId": "${args.activityId}",\n "fields": {\n "fieldId123": "new value"\n }\n}\n\`\`\``,
1104
1449
  }],
1105
1450
  };
1106
1451
  }
1107
- logger.debug("Single update mode", {
1452
+ logger.debug('Single update mode', {
1108
1453
  activityId: args.activityId,
1109
1454
  name: args.name,
1110
1455
  fields: JSON.stringify(args.fields, null, 2),
1111
1456
  phaseId: args.phaseId
1112
1457
  });
1113
1458
  const updates = buildActivityUpdate(args, context);
1459
+ // Field-key validation — runs AFTER buildActivityUpdate's auto-fixups
1460
+ // (values only, keys unchanged; see validateFieldKeys), right before the
1461
+ // API call. Unknown keys (e.g. field NAMES) silently no-op server-side.
1462
+ const singleKeyError = updates.fields
1463
+ ? await validateUpdateFieldKeys(args.activityId, updates.fields, context, resolveKnownWorkflowFields(args.workflowId, context))
1464
+ : undefined;
1465
+ if (singleKeyError) {
1466
+ return {
1467
+ content: [{ type: 'text', text: singleKeyError }],
1468
+ };
1469
+ }
1114
1470
  const options = args.phaseId ? { phaseId: args.phaseId } : undefined;
1115
1471
  const result = await context.hailer.updateActivities([updates], options);
1116
1472
  return formatUpdateActivityResponse(args, result);
1117
1473
  }
1118
1474
  catch (error) {
1119
- if (!request_logger_1.RequestLogger.getCurrent())
1120
- logger.error("Failed to update activity", error, {
1475
+ if (!request_logger_1.RequestLogger.getCurrent()) {
1476
+ logger.error('Failed to update activity', error, {
1121
1477
  activityId: args.activityId || 'bulk',
1122
1478
  activityCount: args.activities?.length,
1123
1479
  });
1480
+ }
1124
1481
  return {
1125
1482
  content: [
1126
1483
  {
1127
- type: "text",
1484
+ type: 'text',
1128
1485
  text: `āŒ Error updating ${args.activities ? 'activities' : 'activity'}: ${error instanceof Error ? error.message : String(error)}`,
1129
1486
  },
1130
1487
  ],