@hailer/mcp 1.1.12 → 1.1.13

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 (271) hide show
  1. package/CHANGELOG.md +0 -7
  2. package/{.claude → dist}/CLAUDE.md +2 -2
  3. package/dist/app.js +18 -5
  4. package/dist/bot/bot-config.d.ts +10 -1
  5. package/dist/bot/bot-config.js +64 -3
  6. package/dist/bot/bot-manager.d.ts +2 -0
  7. package/dist/bot/bot-manager.js +9 -2
  8. package/dist/bot/bot.d.ts +33 -0
  9. package/dist/bot/bot.js +461 -160
  10. package/dist/bot/services/message-classifier.js +17 -0
  11. package/dist/bot/services/permission-guard.d.ts +52 -0
  12. package/dist/bot/services/permission-guard.js +149 -0
  13. package/dist/bot/services/types.d.ts +5 -0
  14. package/dist/bot/services/typing-indicator.d.ts +6 -1
  15. package/dist/bot/services/typing-indicator.js +19 -3
  16. package/dist/cli.js +0 -0
  17. package/dist/config.d.ts +6 -1
  18. package/dist/config.js +43 -0
  19. package/dist/core.js +3 -6
  20. package/dist/lib/discussion-lock.d.ts +42 -0
  21. package/dist/lib/discussion-lock.js +110 -0
  22. package/dist/mcp/UserContextCache.d.ts +5 -0
  23. package/dist/mcp/UserContextCache.js +51 -19
  24. package/dist/mcp/hailer-clients.d.ts +19 -1
  25. package/dist/mcp/hailer-clients.js +158 -24
  26. package/dist/mcp/session-store.d.ts +68 -0
  27. package/dist/mcp/session-store.js +169 -0
  28. package/dist/mcp/signal-handler.js +2 -0
  29. package/dist/mcp/tool-registry.d.ts +17 -4
  30. package/dist/mcp/tool-registry.js +37 -7
  31. package/dist/mcp/tools/activity.js +99 -7
  32. package/dist/mcp/tools/app-scaffold.js +304 -336
  33. package/dist/mcp/tools/bot-config/constants.d.ts +23 -0
  34. package/dist/mcp/tools/bot-config/constants.js +94 -0
  35. package/dist/mcp/tools/bot-config/core.d.ts +253 -0
  36. package/dist/mcp/tools/bot-config/core.js +2456 -0
  37. package/dist/mcp/tools/bot-config/index.d.ts +10 -0
  38. package/dist/mcp/tools/bot-config/index.js +59 -0
  39. package/dist/mcp/tools/bot-config/tools.d.ts +7 -0
  40. package/dist/mcp/tools/bot-config/tools.js +15 -0
  41. package/dist/mcp/tools/bot-config/types.d.ts +50 -0
  42. package/dist/mcp/tools/bot-config/types.js +6 -0
  43. package/dist/mcp/tools/bug-fixer-tools.d.ts +45 -0
  44. package/dist/mcp/tools/bug-fixer-tools.js +1096 -0
  45. package/dist/mcp/tools/company.d.ts +9 -0
  46. package/dist/mcp/tools/company.js +88 -0
  47. package/dist/mcp/tools/discussion.js +68 -0
  48. package/dist/mcp/tools/document.d.ts +11 -0
  49. package/dist/mcp/tools/document.js +741 -0
  50. package/dist/mcp/tools/investigate.d.ts +9 -0
  51. package/dist/mcp/tools/investigate.js +254 -0
  52. package/dist/mcp/tools/workflow-permissions.d.ts +15 -0
  53. package/dist/mcp/tools/workflow-permissions.js +204 -0
  54. package/dist/mcp/tools/workflow.js +57 -18
  55. package/dist/mcp/utils/index.d.ts +2 -0
  56. package/dist/mcp/utils/index.js +12 -1
  57. package/dist/mcp/utils/role-utils.d.ts +74 -0
  58. package/dist/mcp/utils/role-utils.js +151 -0
  59. package/dist/mcp/utils/types.d.ts +43 -1
  60. package/dist/mcp/utils/types.js +14 -0
  61. package/dist/mcp/webhook-handler.d.ts +4 -0
  62. package/dist/mcp/webhook-handler.js +8 -0
  63. package/dist/mcp-server.d.ts +23 -2
  64. package/dist/mcp-server.js +639 -127
  65. package/dist/plugins/vipunen/client.d.ts +150 -0
  66. package/dist/plugins/vipunen/client.js +535 -0
  67. package/dist/plugins/vipunen/config/schema-config.json +19 -0
  68. package/dist/plugins/vipunen/config/schema-doc.json +22 -0
  69. package/dist/plugins/vipunen/index.d.ts +41 -0
  70. package/dist/plugins/vipunen/index.js +88 -0
  71. package/dist/plugins/vipunen/tools.d.ts +26 -0
  72. package/dist/plugins/vipunen/tools.js +501 -0
  73. package/dist/stdio-server.d.ts +14 -0
  74. package/dist/stdio-server.js +101 -0
  75. package/package.json +2 -1
  76. package/.claude/agents/agent-ada-skill-builder.md +0 -94
  77. package/.claude/agents/agent-alejandro-function-fields.md +0 -342
  78. package/.claude/agents/agent-bjorn-config-audit.md +0 -103
  79. package/.claude/agents/agent-builder-agent-creator.md +0 -130
  80. package/.claude/agents/agent-code-simplifier.md +0 -53
  81. package/.claude/agents/agent-dmitri-activity-crud.md +0 -159
  82. package/.claude/agents/agent-giuseppe-app-builder.md +0 -247
  83. package/.claude/agents/agent-gunther-mcp-tools.md +0 -39
  84. package/.claude/agents/agent-helga-workflow-config.md +0 -204
  85. package/.claude/agents/agent-igor-activity-mover-automation.md +0 -125
  86. package/.claude/agents/agent-ingrid-doc-templates.md +0 -261
  87. package/.claude/agents/agent-ivan-monolith.md +0 -154
  88. package/.claude/agents/agent-kenji-data-reader.md +0 -86
  89. package/.claude/agents/agent-lars-code-inspector.md +0 -102
  90. package/.claude/agents/agent-marco-mockup-builder.md +0 -110
  91. package/.claude/agents/agent-marcus-api-documenter.md +0 -323
  92. package/.claude/agents/agent-marketplace-publisher.md +0 -280
  93. package/.claude/agents/agent-marketplace-reviewer.md +0 -309
  94. package/.claude/agents/agent-permissions-handler.md +0 -208
  95. package/.claude/agents/agent-simple-writer.md +0 -48
  96. package/.claude/agents/agent-svetlana-code-review.md +0 -171
  97. package/.claude/agents/agent-tanya-test-runner.md +0 -333
  98. package/.claude/agents/agent-ui-designer.md +0 -100
  99. package/.claude/agents/agent-viktor-sql-insights.md +0 -212
  100. package/.claude/agents/agent-web-search.md +0 -55
  101. package/.claude/agents/agent-yevgeni-discussions.md +0 -45
  102. package/.claude/agents/agent-zara-zapier.md +0 -159
  103. package/.claude/commands/app-squad.md +0 -135
  104. package/.claude/commands/audit-squad.md +0 -158
  105. package/.claude/commands/autoplan.md +0 -563
  106. package/.claude/commands/cleanup-squad.md +0 -98
  107. package/.claude/commands/config-squad.md +0 -106
  108. package/.claude/commands/crud-squad.md +0 -87
  109. package/.claude/commands/data-squad.md +0 -97
  110. package/.claude/commands/debug-squad.md +0 -303
  111. package/.claude/commands/doc-squad.md +0 -65
  112. package/.claude/commands/handoff.md +0 -137
  113. package/.claude/commands/health.md +0 -49
  114. package/.claude/commands/help.md +0 -29
  115. package/.claude/commands/help:agents.md +0 -151
  116. package/.claude/commands/help:commands.md +0 -78
  117. package/.claude/commands/help:faq.md +0 -79
  118. package/.claude/commands/help:plugins.md +0 -50
  119. package/.claude/commands/help:skills.md +0 -93
  120. package/.claude/commands/help:tools.md +0 -75
  121. package/.claude/commands/hotfix-squad.md +0 -112
  122. package/.claude/commands/integration-squad.md +0 -82
  123. package/.claude/commands/janitor-squad.md +0 -167
  124. package/.claude/commands/learn-auto.md +0 -120
  125. package/.claude/commands/learn.md +0 -120
  126. package/.claude/commands/mcp-list.md +0 -27
  127. package/.claude/commands/onboard-squad.md +0 -140
  128. package/.claude/commands/plan-workspace.md +0 -732
  129. package/.claude/commands/prd.md +0 -130
  130. package/.claude/commands/project-status.md +0 -82
  131. package/.claude/commands/publish.md +0 -138
  132. package/.claude/commands/recap.md +0 -69
  133. package/.claude/commands/restore.md +0 -64
  134. package/.claude/commands/review-squad.md +0 -152
  135. package/.claude/commands/save.md +0 -24
  136. package/.claude/commands/stats.md +0 -19
  137. package/.claude/commands/swarm.md +0 -210
  138. package/.claude/commands/tool-builder.md +0 -39
  139. package/.claude/commands/ws-pull.md +0 -44
  140. package/.claude/hooks/_shared-memory.cjs +0 -305
  141. package/.claude/hooks/_utils.cjs +0 -108
  142. package/.claude/hooks/agent-failure-detector.cjs +0 -383
  143. package/.claude/hooks/agent-usage-logger.cjs +0 -204
  144. package/.claude/hooks/app-edit-guard.cjs +0 -494
  145. package/.claude/hooks/auto-learn.cjs +0 -304
  146. package/.claude/hooks/bash-guard.cjs +0 -272
  147. package/.claude/hooks/builder-mode-manager.cjs +0 -354
  148. package/.claude/hooks/bulk-activity-guard.cjs +0 -271
  149. package/.claude/hooks/context-watchdog.cjs +0 -230
  150. package/.claude/hooks/delegation-reminder.cjs +0 -465
  151. package/.claude/hooks/design-system-lint.cjs +0 -271
  152. package/.claude/hooks/post-scaffold-hook.cjs +0 -181
  153. package/.claude/hooks/prompt-guard.cjs +0 -354
  154. package/.claude/hooks/publish-template-guard.cjs +0 -147
  155. package/.claude/hooks/session-start.cjs +0 -35
  156. package/.claude/hooks/shared-memory-writer.cjs +0 -147
  157. package/.claude/hooks/skill-injector.cjs +0 -140
  158. package/.claude/hooks/skill-usage-logger.cjs +0 -258
  159. package/.claude/hooks/src-edit-guard.cjs +0 -240
  160. package/.claude/hooks/sync-marketplace-agents.cjs +0 -346
  161. package/.claude/settings.json +0 -257
  162. package/.claude/skills/SDK-activity-patterns/SKILL.md +0 -428
  163. package/.claude/skills/SDK-document-templates/SKILL.md +0 -1033
  164. package/.claude/skills/SDK-function-fields/SKILL.md +0 -542
  165. package/.claude/skills/SDK-generate-skill/SKILL.md +0 -92
  166. package/.claude/skills/SDK-init-skill/SKILL.md +0 -127
  167. package/.claude/skills/SDK-insight-queries/SKILL.md +0 -787
  168. package/.claude/skills/SDK-ws-config-skill/SKILL.md +0 -1139
  169. package/.claude/skills/agent-structure/SKILL.md +0 -98
  170. package/.claude/skills/api-documentation-patterns/SKILL.md +0 -474
  171. package/.claude/skills/chrome-mcp-reference/SKILL.md +0 -370
  172. package/.claude/skills/delegation-routing/SKILL.md +0 -202
  173. package/.claude/skills/frontend-design/SKILL.md +0 -254
  174. package/.claude/skills/hailer-activity-mover/SKILL.md +0 -213
  175. package/.claude/skills/hailer-api-client/SKILL.md +0 -518
  176. package/.claude/skills/hailer-app-builder/SKILL.md +0 -1434
  177. package/.claude/skills/hailer-apps-pictures/SKILL.md +0 -269
  178. package/.claude/skills/hailer-design-system/SKILL.md +0 -235
  179. package/.claude/skills/hailer-monolith-automations/SKILL.md +0 -686
  180. package/.claude/skills/hailer-permissions-system/SKILL.md +0 -121
  181. package/.claude/skills/hailer-project-protocol/SKILL.md +0 -488
  182. package/.claude/skills/hailer-rest-api/SKILL.md +0 -61
  183. package/.claude/skills/hailer-rest-api/hailer-activities.md +0 -184
  184. package/.claude/skills/hailer-rest-api/hailer-admin.md +0 -473
  185. package/.claude/skills/hailer-rest-api/hailer-calendar.md +0 -256
  186. package/.claude/skills/hailer-rest-api/hailer-feed.md +0 -249
  187. package/.claude/skills/hailer-rest-api/hailer-insights.md +0 -195
  188. package/.claude/skills/hailer-rest-api/hailer-messaging.md +0 -276
  189. package/.claude/skills/hailer-rest-api/hailer-workflows.md +0 -283
  190. package/.claude/skills/insight-join-patterns/SKILL.md +0 -174
  191. package/.claude/skills/integration-patterns/SKILL.md +0 -421
  192. package/.claude/skills/json-only-output/SKILL.md +0 -72
  193. package/.claude/skills/lsp-setup/SKILL.md +0 -160
  194. package/.claude/skills/mcp-direct-tools/SKILL.md +0 -153
  195. package/.claude/skills/optional-parameters/SKILL.md +0 -72
  196. package/.claude/skills/publish-hailer-app/SKILL.md +0 -244
  197. package/.claude/skills/testing-patterns/SKILL.md +0 -630
  198. package/.claude/skills/tool-builder/SKILL.md +0 -250
  199. package/.claude/skills/tool-parameter-usage/SKILL.md +0 -126
  200. package/.claude/skills/tool-response-verification/SKILL.md +0 -92
  201. package/.claude/skills/zapier-hailer-patterns/SKILL.md +0 -581
  202. package/.mcp.json +0 -13
  203. package/.opencode/agent/agent-ada-skill-builder.md +0 -35
  204. package/.opencode/agent/agent-alejandro-function-fields.md +0 -39
  205. package/.opencode/agent/agent-bjorn-config-audit.md +0 -36
  206. package/.opencode/agent/agent-builder-agent-creator.md +0 -39
  207. package/.opencode/agent/agent-code-simplifier.md +0 -31
  208. package/.opencode/agent/agent-dmitri-activity-crud.md +0 -40
  209. package/.opencode/agent/agent-giuseppe-app-builder.md +0 -37
  210. package/.opencode/agent/agent-gunther-mcp-tools.md +0 -39
  211. package/.opencode/agent/agent-helga-workflow-config.md +0 -203
  212. package/.opencode/agent/agent-igor-activity-mover-automation.md +0 -46
  213. package/.opencode/agent/agent-ingrid-doc-templates.md +0 -39
  214. package/.opencode/agent/agent-ivan-monolith.md +0 -46
  215. package/.opencode/agent/agent-kenji-data-reader.md +0 -53
  216. package/.opencode/agent/agent-lars-code-inspector.md +0 -28
  217. package/.opencode/agent/agent-marco-mockup-builder.md +0 -42
  218. package/.opencode/agent/agent-marcus-api-documenter.md +0 -53
  219. package/.opencode/agent/agent-marketplace-publisher.md +0 -44
  220. package/.opencode/agent/agent-marketplace-reviewer.md +0 -42
  221. package/.opencode/agent/agent-permissions-handler.md +0 -50
  222. package/.opencode/agent/agent-simple-writer.md +0 -45
  223. package/.opencode/agent/agent-svetlana-code-review.md +0 -39
  224. package/.opencode/agent/agent-tanya-test-runner.md +0 -57
  225. package/.opencode/agent/agent-ui-designer.md +0 -56
  226. package/.opencode/agent/agent-viktor-sql-insights.md +0 -34
  227. package/.opencode/agent/agent-web-search.md +0 -42
  228. package/.opencode/agent/agent-yevgeni-discussions.md +0 -37
  229. package/.opencode/agent/agent-zara-zapier.md +0 -53
  230. package/.opencode/commands/app-squad.md +0 -135
  231. package/.opencode/commands/audit-squad.md +0 -158
  232. package/.opencode/commands/autoplan.md +0 -563
  233. package/.opencode/commands/cleanup-squad.md +0 -98
  234. package/.opencode/commands/config-squad.md +0 -106
  235. package/.opencode/commands/crud-squad.md +0 -87
  236. package/.opencode/commands/data-squad.md +0 -97
  237. package/.opencode/commands/debug-squad.md +0 -303
  238. package/.opencode/commands/doc-squad.md +0 -65
  239. package/.opencode/commands/handoff.md +0 -137
  240. package/.opencode/commands/health.md +0 -49
  241. package/.opencode/commands/help-agents.md +0 -151
  242. package/.opencode/commands/help-commands.md +0 -32
  243. package/.opencode/commands/help-faq.md +0 -29
  244. package/.opencode/commands/help-plugins.md +0 -28
  245. package/.opencode/commands/help-skills.md +0 -7
  246. package/.opencode/commands/help-tools.md +0 -40
  247. package/.opencode/commands/help.md +0 -28
  248. package/.opencode/commands/hotfix-squad.md +0 -112
  249. package/.opencode/commands/integration-squad.md +0 -82
  250. package/.opencode/commands/janitor-squad.md +0 -167
  251. package/.opencode/commands/learn-auto.md +0 -120
  252. package/.opencode/commands/learn.md +0 -120
  253. package/.opencode/commands/mcp-list.md +0 -27
  254. package/.opencode/commands/onboard-squad.md +0 -140
  255. package/.opencode/commands/plan-workspace.md +0 -732
  256. package/.opencode/commands/prd.md +0 -131
  257. package/.opencode/commands/project-status.md +0 -82
  258. package/.opencode/commands/publish.md +0 -138
  259. package/.opencode/commands/recap.md +0 -69
  260. package/.opencode/commands/restore.md +0 -64
  261. package/.opencode/commands/review-squad.md +0 -152
  262. package/.opencode/commands/save.md +0 -24
  263. package/.opencode/commands/stats.md +0 -19
  264. package/.opencode/commands/swarm.md +0 -210
  265. package/.opencode/commands/tool-builder.md +0 -39
  266. package/.opencode/commands/ws-pull.md +0 -44
  267. package/.opencode/opencode.json +0 -28
  268. package/SESSION-HANDOFF.md +0 -68
  269. package/inbox/2026-03-04-bot-config-patterns.md +0 -24
  270. package/scripts/postinstall.cjs +0 -64
  271. package/scripts/test-hal-tools.ts +0 -154
@@ -0,0 +1,741 @@
1
+ "use strict";
2
+ /**
3
+ * Document Tools - PDF/CSV Generation
4
+ *
5
+ * Tools for generating documents from templates:
6
+ * - List document templates (READ)
7
+ * - Generate PDF documents from activities (WRITE)
8
+ */
9
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ var desc = Object.getOwnPropertyDescriptor(m, k);
12
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
13
+ desc = { enumerable: true, get: function() { return m[k]; } };
14
+ }
15
+ Object.defineProperty(o, k2, desc);
16
+ }) : (function(o, m, k, k2) {
17
+ if (k2 === undefined) k2 = k;
18
+ o[k2] = m[k];
19
+ }));
20
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
21
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
22
+ }) : function(o, v) {
23
+ o["default"] = v;
24
+ });
25
+ var __importStar = (this && this.__importStar) || (function () {
26
+ var ownKeys = function(o) {
27
+ ownKeys = Object.getOwnPropertyNames || function (o) {
28
+ var ar = [];
29
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
30
+ return ar;
31
+ };
32
+ return ownKeys(o);
33
+ };
34
+ return function (mod) {
35
+ if (mod && mod.__esModule) return mod;
36
+ var result = {};
37
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
38
+ __setModuleDefault(result, mod);
39
+ return result;
40
+ };
41
+ })();
42
+ Object.defineProperty(exports, "__esModule", { value: true });
43
+ exports.generateDocumentTool = exports.listDocumentTemplatesTool = void 0;
44
+ const zod_1 = require("zod");
45
+ const tool_registry_1 = require("../tool-registry");
46
+ const index_1 = require("../utils/index");
47
+ const request_logger_1 = require("../../lib/request-logger");
48
+ const fs = __importStar(require("fs"));
49
+ const path = __importStar(require("path"));
50
+ const os = __importStar(require("os"));
51
+ const logger = (0, index_1.createLogger)({ component: 'document-tools' });
52
+ // Helper: extract error message from various error types
53
+ function extractErrorMessage(error) {
54
+ if (error instanceof Error) {
55
+ return error.message;
56
+ }
57
+ else if (error && typeof error === 'object') {
58
+ if ('message' in error)
59
+ return String(error.message);
60
+ if ('error' in error) {
61
+ const e = error.error;
62
+ return typeof e === 'string' ? e : JSON.stringify(e);
63
+ }
64
+ try {
65
+ return JSON.stringify(error);
66
+ }
67
+ catch {
68
+ return '[Complex error object]';
69
+ }
70
+ }
71
+ return String(error);
72
+ }
73
+ function convertFiltersToApiFormat(mcpFilters) {
74
+ const apiFilters = { and: [] };
75
+ for (const [fieldId, filter] of Object.entries(mcpFilters)) {
76
+ switch (filter.operator) {
77
+ case 'text_search':
78
+ if (filter.value !== undefined) {
79
+ apiFilters.and.push({ [fieldId]: { textSearch: filter.value } });
80
+ }
81
+ break;
82
+ case 'equals':
83
+ if (filter.value !== undefined) {
84
+ apiFilters.and.push({ [fieldId]: { equalTo: filter.value } });
85
+ }
86
+ break;
87
+ case 'not_equals':
88
+ if (filter.value !== undefined) {
89
+ apiFilters.and.push({ [fieldId]: { notEqualTo: filter.value } });
90
+ }
91
+ break;
92
+ case 'contains':
93
+ if (filter.value !== undefined) {
94
+ apiFilters.and.push({ [fieldId]: { contains: filter.value } });
95
+ }
96
+ break;
97
+ case 'greater_than':
98
+ if (filter.value !== undefined && typeof filter.value === 'number') {
99
+ apiFilters.and.push({ [fieldId]: { greaterThan: filter.value } });
100
+ }
101
+ break;
102
+ case 'less_than':
103
+ if (filter.value !== undefined && typeof filter.value === 'number') {
104
+ apiFilters.and.push({ [fieldId]: { lessThan: filter.value } });
105
+ }
106
+ break;
107
+ case 'range':
108
+ if (filter.start !== undefined && filter.end !== undefined) {
109
+ apiFilters.and.push({ [fieldId]: { between: [String(filter.start), String(filter.end)] } });
110
+ }
111
+ break;
112
+ default:
113
+ // Unknown operator, try text_search as fallback
114
+ if (filter.value !== undefined) {
115
+ apiFilters.and.push({ [fieldId]: { textSearch: filter.value } });
116
+ }
117
+ }
118
+ }
119
+ return apiFilters;
120
+ }
121
+ // Helper: delay for rate limiting and retry backoff
122
+ const delay = (ms) => new Promise(resolve => setTimeout(resolve, ms));
123
+ // Retry configuration
124
+ const RETRY_CONFIG = {
125
+ maxRetries: 3,
126
+ baseDelayMs: 1000, // 1 second base delay
127
+ batchDelayMs: 500, // 500ms between batches
128
+ retryableCodes: [502, 503, 504, 429] // Gateway errors and rate limits
129
+ };
130
+ // ============================================================================
131
+ // TOOL 1: LIST DOCUMENT TEMPLATES
132
+ // ============================================================================
133
+ const listDocumentTemplatesDescription = `List available document templates for PDF/CSV generation
134
+
135
+ **Returns**: Template IDs, names, types, and associated workflow IDs
136
+
137
+ **Example**:
138
+ \`\`\`javascript
139
+ list_document_templates({ workflowId: "691ffdf84217e9e8434e5694" })
140
+ \`\`\``;
141
+ exports.listDocumentTemplatesTool = {
142
+ name: 'list_document_templates',
143
+ group: tool_registry_1.ToolGroup.READ,
144
+ description: listDocumentTemplatesDescription,
145
+ schema: zod_1.z.object({
146
+ workflowId: zod_1.z
147
+ .string()
148
+ .optional()
149
+ .describe("Optional workflow ID to filter templates for a specific workflow")
150
+ }),
151
+ async execute(args, context) {
152
+ logger.debug('Listing document templates', {
153
+ workflowId: args.workflowId,
154
+ apiKey: context.apiKey.substring(0, 8) + '...'
155
+ });
156
+ try {
157
+ const rawInit = context.init;
158
+ let templates = [];
159
+ // Method 1: Check workspace-level templates
160
+ if (rawInit.templates) {
161
+ const workspaceTemplates = Array.isArray(rawInit.templates)
162
+ ? rawInit.templates
163
+ : Object.values(rawInit.templates);
164
+ templates.push(...workspaceTemplates);
165
+ }
166
+ if (rawInit.documentTemplates) {
167
+ const docTemplates = Array.isArray(rawInit.documentTemplates)
168
+ ? rawInit.documentTemplates
169
+ : Object.values(rawInit.documentTemplates);
170
+ templates.push(...docTemplates);
171
+ }
172
+ // Method 2: Check per-workflow templates (in processes)
173
+ if (rawInit.processes) {
174
+ const processes = Array.isArray(rawInit.processes)
175
+ ? rawInit.processes
176
+ : Object.values(rawInit.processes);
177
+ for (const process of processes) {
178
+ // Check templates in process
179
+ if (process.templates) {
180
+ const procTemplates = Array.isArray(process.templates)
181
+ ? process.templates
182
+ : Object.values(process.templates);
183
+ // Add workflowId to each template
184
+ for (const t of procTemplates) {
185
+ templates.push({ ...t, workflowId: process._id, workflowName: process.name });
186
+ }
187
+ }
188
+ // Check documentTemplates in process
189
+ if (process.documentTemplates) {
190
+ const procDocTemplates = Array.isArray(process.documentTemplates)
191
+ ? process.documentTemplates
192
+ : Object.values(process.documentTemplates);
193
+ for (const t of procDocTemplates) {
194
+ templates.push({ ...t, workflowId: process._id, workflowName: process.name });
195
+ }
196
+ }
197
+ // Check printTemplates in process
198
+ if (process.printTemplates) {
199
+ const printTemplates = Array.isArray(process.printTemplates)
200
+ ? process.printTemplates
201
+ : Object.values(process.printTemplates);
202
+ for (const t of printTemplates) {
203
+ templates.push({ ...t, workflowId: process._id, workflowName: process.name });
204
+ }
205
+ }
206
+ }
207
+ }
208
+ // Method 3: Try dedicated API call if no templates found
209
+ if (templates.length === 0) {
210
+ try {
211
+ // Try v3.template.list or similar
212
+ const apiTemplates = await context.hailer.request('v3.documentTemplate.list', []);
213
+ if (Array.isArray(apiTemplates)) {
214
+ templates.push(...apiTemplates);
215
+ }
216
+ else if (apiTemplates?.templates) {
217
+ templates.push(...apiTemplates.templates);
218
+ }
219
+ }
220
+ catch (apiError) {
221
+ logger.debug('v3.documentTemplate.list not available', { error: apiError });
222
+ }
223
+ }
224
+ logger.debug('Template discovery results', {
225
+ initKeys: Object.keys(rawInit),
226
+ processCount: rawInit.processes ? Object.keys(rawInit.processes).length : 0,
227
+ templatesFound: templates.length
228
+ });
229
+ // Filter by workflow if provided
230
+ if (args.workflowId) {
231
+ templates = templates.filter((t) => t.workflowId === args.workflowId ||
232
+ t.processId === args.workflowId ||
233
+ t.pid === args.workflowId);
234
+ }
235
+ if (templates.length === 0) {
236
+ // Return diagnostic info to help debug
237
+ const processInfo = rawInit.processes
238
+ ? Object.entries(rawInit.processes).slice(0, 3).map(([id, p]) => ({
239
+ id,
240
+ name: p.name,
241
+ hasTemplates: !!p.templates,
242
+ hasDocumentTemplates: !!p.documentTemplates,
243
+ hasPrintTemplates: !!p.printTemplates,
244
+ keys: Object.keys(p).filter(k => k.toLowerCase().includes('template'))
245
+ }))
246
+ : [];
247
+ return {
248
+ content: [{
249
+ type: "text",
250
+ text: `šŸ“„ No document templates found${args.workflowId ? ` for workflow ${args.workflowId}` : ''}.\n\n` +
251
+ `**Init data keys**: ${Object.keys(rawInit).join(', ')}\n\n` +
252
+ `**Process sample** (first 3):\n${JSON.stringify(processInfo, null, 2)}\n\n` +
253
+ `šŸ’” Document templates may need to be created in Hailer UI first.`
254
+ }]
255
+ };
256
+ }
257
+ let responseText = `šŸ“„ **Document Templates** (${templates.length} total):\n\n`;
258
+ templates.forEach((template, index) => {
259
+ // Get template ID from various possible fields
260
+ const templateId = template._id || template.id || template.templateId || template.key || Object.keys(template)[0];
261
+ const templateName = template.name || template.label || template.title || 'Untitled';
262
+ responseText += `${index + 1}. **${templateName}**\n`;
263
+ responseText += ` - Template ID: \`${templateId}\`\n`;
264
+ if (template.type)
265
+ responseText += ` - Type: ${template.type}\n`;
266
+ if (template.workflowId || template.processId) {
267
+ responseText += ` - Workflow: ${template.workflowName || ''} (\`${template.workflowId || template.processId}\`)\n`;
268
+ }
269
+ responseText += `\n`;
270
+ });
271
+ responseText += `\nšŸ’” **Usage**: Use \`generate_document\` with a template ID and activity IDs to create PDF documents.`;
272
+ return {
273
+ content: [{
274
+ type: "text",
275
+ text: responseText
276
+ }]
277
+ };
278
+ }
279
+ catch (error) {
280
+ if (!request_logger_1.RequestLogger.getCurrent())
281
+ logger.error("Failed to list document templates", error);
282
+ return {
283
+ content: [{
284
+ type: "text",
285
+ text: `āŒ Failed to list document templates: ${error instanceof Error ? error.message : String(error)}\n\n` +
286
+ `šŸ’” Document templates may not be available in this workspace.`
287
+ }]
288
+ };
289
+ }
290
+ }
291
+ };
292
+ // ============================================================================
293
+ // TOOL 2: GENERATE DOCUMENT
294
+ // ============================================================================
295
+ const generateDocumentDescription = `Generate PDF document from template and activities, upload to Hailer
296
+
297
+ **Two modes:**
298
+ 1. **Direct IDs**: Pass \`activityIds\` array directly
299
+ 2. **Filter-based**: Pass \`workflowId\` + optional filters (fetches IDs internally - saves context!)
300
+
301
+ **Auto-batching**: For large activity lists (>50), automatically splits into batches to avoid timeouts.
302
+
303
+ **Parameters**:
304
+ - \`templateId\`: Document template ID (from list_document_templates)
305
+ - \`activityIds\`: Array of activity IDs (OR use workflowId + filters)
306
+ - \`workflowId\`: Workflow to fetch activities from (alternative to activityIds)
307
+ - \`phaseId\`: Optional phase filter (used with workflowId)
308
+ - \`filters\`: Optional field filters, same format as list_activities
309
+ - \`limit\`: Max activities to process (default: 1000)
310
+ - \`discussionId\`: Optional - post PDF(s) to this discussion
311
+ - \`batchSize\`: Optional - activities per PDF (default: 50)
312
+
313
+ **Example with filters (recommended for large datasets):**
314
+ \`\`\`javascript
315
+ generate_document({
316
+ templateId: "abc123",
317
+ workflowId: "workflow-id",
318
+ phaseId: "phase-id",
319
+ filters: { "fieldId": { "operator": "equals", "value": "Defender" }},
320
+ discussionId: "discussion-id"
321
+ })
322
+ \`\`\`
323
+
324
+ **Example with direct IDs:**
325
+ \`\`\`javascript
326
+ generate_document({
327
+ templateId: "abc123",
328
+ activityIds: ["id1", "id2"],
329
+ discussionId: "discussion-id"
330
+ })
331
+ \`\`\``;
332
+ exports.generateDocumentTool = {
333
+ name: 'generate_document',
334
+ group: tool_registry_1.ToolGroup.WRITE,
335
+ description: generateDocumentDescription,
336
+ schema: zod_1.z.object({
337
+ templateId: zod_1.z
338
+ .string()
339
+ .min(1, "Template ID is required")
340
+ .describe("Document template ID (use list_document_templates to find available templates)"),
341
+ // Option 1: Direct activity IDs
342
+ activityIds: zod_1.z
343
+ .preprocess((val) => {
344
+ if (typeof val === 'string') {
345
+ try {
346
+ return JSON.parse(val);
347
+ }
348
+ catch {
349
+ return val.split(',').map(id => id.trim()).filter(Boolean);
350
+ }
351
+ }
352
+ return val;
353
+ }, zod_1.z.array(zod_1.z.string()))
354
+ .optional()
355
+ .describe("Array of activity IDs (OR use workflowId + filters instead)"),
356
+ // Option 2: Filter-based (fetches IDs internally)
357
+ workflowId: zod_1.z
358
+ .string()
359
+ .optional()
360
+ .describe("Workflow ID to fetch activities from (alternative to activityIds)"),
361
+ phaseId: zod_1.z
362
+ .string()
363
+ .optional()
364
+ .describe("Optional phase ID filter (used with workflowId)"),
365
+ filters: zod_1.z
366
+ .any()
367
+ .optional()
368
+ .describe("Field filters, same format as list_activities: { fieldId: { operator, value }}"),
369
+ limit: zod_1.z
370
+ .number()
371
+ .optional()
372
+ .default(1000)
373
+ .describe("Max activities to fetch when using workflowId (default: 1000)"),
374
+ // Common options
375
+ discussionId: zod_1.z
376
+ .string()
377
+ .optional()
378
+ .describe("Optional discussion ID - if provided, the PDF(s) will be posted to this discussion"),
379
+ timeZone: zod_1.z
380
+ .string()
381
+ .optional()
382
+ .default("Europe/Helsinki")
383
+ .describe("Timezone for date formatting in document (default: Europe/Helsinki)"),
384
+ batchSize: zod_1.z
385
+ .number()
386
+ .optional()
387
+ .default(50)
388
+ .describe("Activities per PDF batch (default: 50). Large lists are auto-batched to avoid timeouts.")
389
+ }),
390
+ async execute(args, context) {
391
+ const batchSize = args.batchSize || 50;
392
+ const limit = args.limit || 1000;
393
+ let activityIds = args.activityIds || [];
394
+ // Validate: need either activityIds or workflowId
395
+ if (activityIds.length === 0 && !args.workflowId) {
396
+ return {
397
+ content: [{
398
+ type: "text",
399
+ text: `āŒ Missing required parameter: provide either \`activityIds\` or \`workflowId\`.\n\n` +
400
+ `**Option 1 - Direct IDs:**\n` +
401
+ `\`\`\`json\n{ "templateId": "...", "activityIds": ["id1", "id2"] }\n\`\`\`\n\n` +
402
+ `**Option 2 - Filter-based (recommended for large datasets):**\n` +
403
+ `\`\`\`json\n{ "templateId": "...", "workflowId": "...", "phaseId": "...", "filters": {...} }\n\`\`\``
404
+ }]
405
+ };
406
+ }
407
+ // If workflowId provided, fetch activity IDs internally
408
+ if (args.workflowId && activityIds.length === 0) {
409
+ logger.debug('Fetching activities via filters', {
410
+ workflowId: args.workflowId,
411
+ phaseId: args.phaseId,
412
+ hasFilters: !!args.filters,
413
+ limit
414
+ });
415
+ try {
416
+ // Get phases if phaseId not provided - we need at least one phase
417
+ let phaseIds = [];
418
+ if (args.phaseId) {
419
+ phaseIds = [args.phaseId];
420
+ }
421
+ else {
422
+ // Get all phases for this workflow
423
+ const workflow = context.init.processes.find((p) => p._id === args.workflowId);
424
+ if (workflow?.phases) {
425
+ phaseIds = Object.keys(workflow.phases);
426
+ }
427
+ if (phaseIds.length === 0) {
428
+ throw new Error(`No phases found for workflow ${args.workflowId}`);
429
+ }
430
+ }
431
+ // Convert filters to API format if provided
432
+ let apiFilters;
433
+ if (args.filters && typeof args.filters === 'object') {
434
+ apiFilters = convertFiltersToApiFormat(args.filters);
435
+ logger.debug('Converted filters to API format', {
436
+ original: args.filters,
437
+ converted: apiFilters
438
+ });
439
+ }
440
+ // Fetch activities from each phase with pagination
441
+ const allIds = [];
442
+ const PAGE_SIZE = 200; // Fetch in pages of 200
443
+ for (const phaseId of phaseIds) {
444
+ if (allIds.length >= limit)
445
+ break;
446
+ let page = 0;
447
+ let hasMore = true;
448
+ // Paginate through all results for this phase
449
+ while (hasMore && allIds.length < limit) {
450
+ const remaining = limit - allIds.length;
451
+ const result = await context.hailer.fetchActivityList(args.workflowId, phaseId, Math.min(remaining, PAGE_SIZE), {
452
+ page,
453
+ filters: apiFilters,
454
+ returnFlat: true,
455
+ includeStats: true
456
+ // Don't pass fields - API returns _id by default
457
+ });
458
+ // Extract IDs from result
459
+ const activities = result?.activities || result?.list || result?.data || [];
460
+ const metadata = result?.metadata || {};
461
+ for (const activity of activities) {
462
+ if (allIds.length >= limit)
463
+ break;
464
+ if (activity._id) {
465
+ allIds.push(activity._id);
466
+ }
467
+ }
468
+ logger.debug(`Fetched page ${page + 1} from phase ${phaseId}`, {
469
+ phaseId,
470
+ page: page + 1,
471
+ fetched: activities.length,
472
+ totalInPhase: metadata.totalCount,
473
+ totalSoFar: allIds.length
474
+ });
475
+ // Check if there are more pages
476
+ const totalInPhase = metadata.totalCount || 0;
477
+ const fetchedSoFarInPhase = (page + 1) * PAGE_SIZE;
478
+ hasMore = activities.length === PAGE_SIZE && fetchedSoFarInPhase < totalInPhase;
479
+ page++;
480
+ // Safety: max 50 pages (10,000 activities per phase)
481
+ if (page >= 50) {
482
+ logger.warn('Hit pagination safety limit', { phaseId, page });
483
+ break;
484
+ }
485
+ }
486
+ }
487
+ activityIds = allIds;
488
+ if (activityIds.length === 0) {
489
+ return {
490
+ content: [{
491
+ type: "text",
492
+ text: `šŸ“„ No activities found matching the filters.\n\n` +
493
+ `**Workflow:** ${args.workflowId}\n` +
494
+ `**Phase:** ${args.phaseId || 'all phases'}\n` +
495
+ `**Filters:** ${args.filters ? JSON.stringify(args.filters) : 'none'}\n\n` +
496
+ `šŸ’” Try adjusting your filters or check that activities exist in this workflow.`
497
+ }]
498
+ };
499
+ }
500
+ logger.debug('Activity IDs fetched via filters', {
501
+ count: activityIds.length,
502
+ limit,
503
+ phaseCount: phaseIds.length
504
+ });
505
+ }
506
+ catch (fetchError) {
507
+ const errorMsg = extractErrorMessage(fetchError);
508
+ logger.error('Failed to fetch activities via filters', { error: errorMsg });
509
+ return {
510
+ content: [{
511
+ type: "text",
512
+ text: `āŒ Failed to fetch activities: ${errorMsg}\n\n` +
513
+ `**Workflow:** ${args.workflowId}\n` +
514
+ `**Phase:** ${args.phaseId || 'all phases'}\n` +
515
+ `**Filters:** ${args.filters ? JSON.stringify(args.filters) : 'none'}\n\n` +
516
+ `šŸ’” Check that:\n` +
517
+ `- Workflow and phase IDs are correct\n` +
518
+ `- Filter field IDs exist in the workflow\n` +
519
+ `- Filter format is correct: { "fieldId": { "operator": "text_search", "value": "..." }}`
520
+ }]
521
+ };
522
+ }
523
+ }
524
+ const totalActivities = activityIds.length;
525
+ logger.debug('Generating document', {
526
+ templateId: args.templateId,
527
+ activityCount: totalActivities,
528
+ batchSize,
529
+ batchCount: Math.ceil(totalActivities / batchSize),
530
+ hasDiscussionId: !!args.discussionId,
531
+ timeZone: args.timeZone,
532
+ mode: args.workflowId ? 'filter-based' : 'direct-ids'
533
+ });
534
+ try {
535
+ // Split activities into batches
536
+ const batches = [];
537
+ for (let i = 0; i < activityIds.length; i += batchSize) {
538
+ batches.push(activityIds.slice(i, i + batchSize));
539
+ }
540
+ const results = [];
541
+ const errors = [];
542
+ // Process each batch with retry logic and delays
543
+ for (let batchNum = 0; batchNum < batches.length; batchNum++) {
544
+ const batch = batches[batchNum];
545
+ // Add delay between batches (except first one)
546
+ if (batchNum > 0) {
547
+ await delay(RETRY_CONFIG.batchDelayMs);
548
+ }
549
+ logger.debug(`Processing batch ${batchNum + 1}/${batches.length}`, {
550
+ batchNum: batchNum + 1,
551
+ activityCount: batch.length
552
+ });
553
+ let lastError = '';
554
+ let success = false;
555
+ // Retry loop for this batch
556
+ for (let attempt = 0; attempt < RETRY_CONFIG.maxRetries && !success; attempt++) {
557
+ if (attempt > 0) {
558
+ // Exponential backoff: 1s, 2s, 4s
559
+ const backoffMs = RETRY_CONFIG.baseDelayMs * Math.pow(2, attempt - 1);
560
+ logger.debug(`Retry attempt ${attempt + 1} for batch ${batchNum + 1} after ${backoffMs}ms`);
561
+ await delay(backoffMs);
562
+ }
563
+ try {
564
+ // Build templateMap for this batch
565
+ const templateMap = { [args.templateId]: batch };
566
+ const requestBody = {
567
+ templateMap,
568
+ timeZone: args.timeZone || "Europe/Helsinki",
569
+ save: 0
570
+ };
571
+ // Call REST API to generate PDF (binary response)
572
+ const pdfBuffer = await context.hailer.callRest({
573
+ operation: 'generate_document',
574
+ endpoint: '/documentgenerator',
575
+ method: 'POST',
576
+ body: requestBody,
577
+ timeout: 120000, // 2 minutes per batch
578
+ responseType: 'binary'
579
+ });
580
+ // Convert buffer to Buffer instance if needed
581
+ let buffer;
582
+ if (typeof pdfBuffer === 'string') {
583
+ buffer = Buffer.from(pdfBuffer, 'base64');
584
+ }
585
+ else if (Buffer.isBuffer(pdfBuffer)) {
586
+ buffer = pdfBuffer;
587
+ }
588
+ else if (pdfBuffer instanceof ArrayBuffer) {
589
+ buffer = Buffer.from(pdfBuffer);
590
+ }
591
+ else {
592
+ throw new Error('Unexpected PDF response format');
593
+ }
594
+ // Save to temporary file
595
+ const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
596
+ const filename = batches.length > 1
597
+ ? `document-batch${batchNum + 1}-${timestamp}.pdf`
598
+ : `document-${timestamp}.pdf`;
599
+ const tempDir = os.tmpdir();
600
+ const tempPath = path.join(tempDir, filename);
601
+ fs.writeFileSync(tempPath, buffer);
602
+ // Upload PDF to Hailer (also with retry for upload failures)
603
+ let uploadResult;
604
+ for (let uploadAttempt = 0; uploadAttempt < RETRY_CONFIG.maxRetries; uploadAttempt++) {
605
+ if (uploadAttempt > 0) {
606
+ const backoffMs = RETRY_CONFIG.baseDelayMs * Math.pow(2, uploadAttempt - 1);
607
+ logger.debug(`Retry upload attempt ${uploadAttempt + 1} after ${backoffMs}ms`);
608
+ await delay(backoffMs);
609
+ }
610
+ uploadResult = await context.hailer.uploadFile({
611
+ path: tempPath,
612
+ filename
613
+ });
614
+ if (uploadResult.success)
615
+ break;
616
+ // Check if error is retryable
617
+ const isRetryable = RETRY_CONFIG.retryableCodes.some(code => uploadResult.error?.includes(String(code)));
618
+ if (!isRetryable)
619
+ break;
620
+ }
621
+ // Clean up temp file
622
+ try {
623
+ fs.unlinkSync(tempPath);
624
+ }
625
+ catch { /* ignore */ }
626
+ if (!uploadResult.success) {
627
+ throw new Error(`PDF upload failed: ${uploadResult.error}`);
628
+ }
629
+ results.push({
630
+ fileId: uploadResult.fileId || '',
631
+ sizeKB: uploadResult.sizeKB || '',
632
+ activityCount: batch.length,
633
+ batchNum: batchNum + 1
634
+ });
635
+ logger.debug(`Batch ${batchNum + 1} complete`, {
636
+ fileId: uploadResult.fileId,
637
+ sizeKB: uploadResult.sizeKB,
638
+ attempts: attempt + 1
639
+ });
640
+ success = true;
641
+ }
642
+ catch (batchError) {
643
+ lastError = batchError instanceof Error ? batchError.message : String(batchError);
644
+ // Check if error is retryable (502, 503, 504, 429)
645
+ const isRetryable = RETRY_CONFIG.retryableCodes.some(code => lastError.includes(String(code)));
646
+ if (!isRetryable) {
647
+ logger.debug(`Non-retryable error for batch ${batchNum + 1}: ${lastError}`);
648
+ break; // Don't retry non-retryable errors
649
+ }
650
+ logger.debug(`Retryable error for batch ${batchNum + 1} (attempt ${attempt + 1}): ${lastError}`);
651
+ }
652
+ }
653
+ if (!success) {
654
+ errors.push({ batchNum: batchNum + 1, error: lastError });
655
+ logger.error(`Batch ${batchNum + 1} failed after ${RETRY_CONFIG.maxRetries} attempts`, { error: lastError });
656
+ }
657
+ }
658
+ // Check if all batches failed
659
+ if (results.length === 0) {
660
+ throw new Error(`All ${batches.length} batches failed. First error: ${errors[0]?.error || 'Unknown'}`);
661
+ }
662
+ // Post to discussion if requested
663
+ if (args.discussionId && results.length > 0) {
664
+ const fileIds = results.map(r => r.fileId);
665
+ const message = batches.length > 1
666
+ ? `šŸ“„ Generated ${results.length} PDFs from ${totalActivities} activities (${batches.length} batches)`
667
+ : `šŸ“„ Generated document from ${totalActivities} ${totalActivities === 1 ? 'activity' : 'activities'}`;
668
+ await context.hailer.sendDiscussionMessage(args.discussionId, message, fileIds);
669
+ logger.debug('Posted PDFs to discussion', {
670
+ discussionId: args.discussionId,
671
+ fileCount: fileIds.length
672
+ });
673
+ }
674
+ // Build response
675
+ const totalSizeKB = results.reduce((sum, r) => sum + parseFloat(r.sizeKB || '0'), 0).toFixed(2);
676
+ if (batches.length === 1) {
677
+ // Single batch response
678
+ const r = results[0];
679
+ let responseText = `āœ… **Document generated successfully!**\n\n` +
680
+ `šŸ“„ **File Details:**\n` +
681
+ `- File ID: \`${r.fileId}\`\n` +
682
+ `- Size: ${r.sizeKB} KB\n` +
683
+ `- Activities: ${totalActivities}\n`;
684
+ if (args.discussionId) {
685
+ responseText += `\nšŸ’¬ **Posted to discussion**: ${args.discussionId}`;
686
+ }
687
+ else {
688
+ responseText += `\nšŸ’” **Next Steps:**\n` +
689
+ `- Download: \`download_file({ fileId: "${r.fileId}" })\`\n` +
690
+ `- Post to discussion: \`add_discussion_message({ discussionId: "...", fileIds: ["${r.fileId}"] })\``;
691
+ }
692
+ return { content: [{ type: "text", text: responseText }] };
693
+ }
694
+ // Multi-batch response
695
+ let responseText = `āœ… **Documents generated successfully!**\n\n` +
696
+ `šŸ“Š **Summary:**\n` +
697
+ `- Total activities: ${totalActivities}\n` +
698
+ `- Batches: ${batches.length} (${batchSize} per batch)\n` +
699
+ `- PDFs generated: ${results.length}\n` +
700
+ `- Total size: ${totalSizeKB} KB\n`;
701
+ if (errors.length > 0) {
702
+ responseText += `- Failed batches: ${errors.length}\n`;
703
+ }
704
+ responseText += `\nšŸ“„ **Generated Files:**\n`;
705
+ results.forEach(r => {
706
+ responseText += `- Batch ${r.batchNum}: \`${r.fileId}\` (${r.activityCount} activities, ${r.sizeKB} KB)\n`;
707
+ });
708
+ if (errors.length > 0) {
709
+ responseText += `\nāš ļø **Failed Batches:**\n`;
710
+ errors.forEach(e => {
711
+ responseText += `- Batch ${e.batchNum}: ${e.error}\n`;
712
+ });
713
+ }
714
+ if (args.discussionId) {
715
+ responseText += `\nšŸ’¬ **Posted to discussion**: ${args.discussionId}`;
716
+ }
717
+ return { content: [{ type: "text", text: responseText }] };
718
+ }
719
+ catch (error) {
720
+ if (!request_logger_1.RequestLogger.getCurrent())
721
+ logger.error("Failed to generate document", error);
722
+ const errorMessage = error instanceof Error
723
+ ? error.message
724
+ : (typeof error === 'object' && error !== null)
725
+ ? JSON.stringify(error, null, 2)
726
+ : String(error);
727
+ return {
728
+ content: [{
729
+ type: "text",
730
+ text: `āŒ Document generation failed: ${errorMessage}\n\n` +
731
+ `šŸ’” **Troubleshooting:**\n` +
732
+ `- Verify the template ID is correct (use list_document_templates)\n` +
733
+ `- Ensure all activity IDs are valid and accessible\n` +
734
+ `- For large batches, try reducing batchSize\n` +
735
+ `- Check that the template is compatible with the provided activities`
736
+ }]
737
+ };
738
+ }
739
+ }
740
+ };
741
+ //# sourceMappingURL=document.js.map