@hailer/mcp 0.0.6 โ†’ 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (122) hide show
  1. package/.claude/agents/ada.md +127 -0
  2. package/.claude/agents/agent-builder.md +151 -0
  3. package/.claude/agents/alejandro.md +66 -0
  4. package/.claude/agents/bjorn.md +305 -0
  5. package/.claude/agents/dmitri.md +61 -0
  6. package/.claude/agents/giuseppe.md +66 -0
  7. package/.claude/agents/gunther.md +355 -0
  8. package/.claude/agents/helga.md +68 -0
  9. package/.claude/agents/ingrid.md +108 -0
  10. package/.claude/agents/kenji.md +58 -0
  11. package/.claude/agents/svetlana.md +394 -0
  12. package/.claude/agents/viktor.md +63 -0
  13. package/.claude/agents/yevgeni.md +60 -0
  14. package/.claude/hooks/agent-failure-detector.cjs +286 -0
  15. package/.claude/hooks/app-edit-guard.cjs +462 -0
  16. package/.claude/hooks/interactive-mode.cjs +59 -0
  17. package/.claude/hooks/mcp-server-guard.cjs +92 -0
  18. package/.claude/hooks/post-scaffold-hook.cjs +31 -0
  19. package/.claude/hooks/sdk-delete-guard.cjs +2 -0
  20. package/.claude/hooks/src-edit-guard.cjs +208 -0
  21. package/.claude/settings.json +47 -2
  22. package/.claude/skills/insight-join-patterns/SKILL.md +209 -0
  23. package/.env.example +13 -1
  24. package/CLAUDE.md +135 -0
  25. package/dist/app.js +4 -3
  26. package/dist/cli.js +0 -0
  27. package/dist/client/adaptive-documentation-bot.d.ts +0 -2
  28. package/dist/client/adaptive-documentation-bot.js +5 -16
  29. package/dist/client/message-processor.js +5 -0
  30. package/dist/client/providers/anthropic-provider.js +21 -7
  31. package/dist/mcp/UserContextCache.d.ts +14 -0
  32. package/dist/mcp/UserContextCache.js +49 -24
  33. package/dist/mcp/auth.d.ts +7 -0
  34. package/dist/mcp/auth.js +13 -5
  35. package/dist/mcp/hailer-clients.d.ts +5 -2
  36. package/dist/mcp/signal-handler.d.ts +28 -2
  37. package/dist/mcp/signal-handler.js +4 -2
  38. package/dist/mcp/tool-registry.d.ts +55 -2
  39. package/dist/mcp/tool-registry.js +197 -2
  40. package/dist/mcp/tools/app-core.d.ts +15 -0
  41. package/dist/mcp/tools/app-core.js +609 -0
  42. package/dist/mcp/tools/app-marketplace.d.ts +21 -0
  43. package/dist/mcp/tools/app-marketplace.js +1284 -0
  44. package/dist/mcp/tools/app-member.d.ts +11 -0
  45. package/dist/mcp/tools/app-member.js +258 -0
  46. package/dist/mcp/tools/app-scaffold.d.ts +11 -0
  47. package/dist/mcp/tools/app-scaffold.js +743 -0
  48. package/dist/mcp/tools/app.d.ts +13 -22
  49. package/dist/mcp/tools/app.js +17 -2466
  50. package/dist/mcp/tools/file.js +6 -6
  51. package/dist/mcp/tools/insight.d.ts +1 -0
  52. package/dist/mcp/tools/insight.js +203 -64
  53. package/dist/mcp/tools/user.js +3 -9
  54. package/dist/mcp/tools/workflow.js +49 -38
  55. package/dist/mcp/utils/hailer-api-client.js +4 -13
  56. package/dist/mcp/utils/tool-helpers.d.ts +102 -0
  57. package/dist/mcp/utils/tool-helpers.js +179 -0
  58. package/dist/mcp/utils/types.d.ts +6 -0
  59. package/dist/mcp/workspace-cache.d.ts +5 -5
  60. package/dist/mcp/workspace-cache.js +4 -3
  61. package/package.json +1 -1
  62. package/.claude/hooks/PreToolUse.sh +0 -52
  63. package/.claude/hooks/prompt-skill-loader.cjs +0 -553
  64. package/.claude/hooks/skill-loader.cjs +0 -142
  65. package/.claude/settings.local.json +0 -49
  66. package/.claude/skills/MCP-add-app-member-skill/SKILL.md +0 -977
  67. package/.claude/skills/MCP-build-data-app-skill/SKILL.md +0 -372
  68. package/.claude/skills/MCP-create-app-skill/SKILL.md +0 -1101
  69. package/.claude/skills/MCP-create-insight-skill/SKILL.md +0 -1317
  70. package/.claude/skills/MCP-get-insight-data-skill/SKILL.md +0 -1053
  71. package/.claude/skills/MCP-insight-api/SKILL.md +0 -185
  72. package/.claude/skills/MCP-insight-api/references/insight-endpoints.md +0 -514
  73. package/.claude/skills/MCP-install-workflow-skill/SKILL.md +0 -1056
  74. package/.claude/skills/MCP-list-apps-skill/SKILL.md +0 -1010
  75. package/.claude/skills/MCP-list-workflows-minimal-skill/SKILL.md +0 -992
  76. package/.claude/skills/MCP-local-first-skill/SKILL.md +0 -570
  77. package/.claude/skills/MCP-populate-workflow-data-skill/SKILL.md +0 -395
  78. package/.claude/skills/MCP-preview-insight-skill/SKILL.md +0 -1290
  79. package/.claude/skills/MCP-publish-hailer-app-skill/SKILL.md +0 -453
  80. package/.claude/skills/MCP-publish-template-skill/SKILL.md +0 -278
  81. package/.claude/skills/MCP-remove-app-member-skill/SKILL.md +0 -671
  82. package/.claude/skills/MCP-remove-app-skill/SKILL.md +0 -985
  83. package/.claude/skills/MCP-remove-insight-skill/SKILL.md +0 -1011
  84. package/.claude/skills/MCP-remove-workflow-skill/SKILL.md +0 -920
  85. package/.claude/skills/MCP-scaffold-hailer-app-skill/SKILL.md +0 -1314
  86. package/.claude/skills/MCP-update-app-skill/SKILL.md +0 -970
  87. package/.claude/skills/MCP-update-workflow-field-skill/SKILL.md +0 -1098
  88. package/.claude/skills/SDK-create-function-field-skill/SKILL.md +0 -313
  89. package/.claude/skills/SDK-generate-skill/SKILL.md +0 -223
  90. package/.claude/skills/SDK-init-skill/SKILL.md +0 -177
  91. package/.claude/skills/SDK-workspace-setup-skill/SKILL.md +0 -605
  92. package/.claude/skills/SDK-ws-config-skill/SKILL.md +0 -435
  93. package/.claude/skills/activity-api/SKILL.md +0 -96
  94. package/.claude/skills/activity-api/references/activity-endpoints.md +0 -845
  95. package/.claude/skills/agent-building/SKILL.md +0 -243
  96. package/.claude/skills/agent-building/references/architecture-patterns.md +0 -446
  97. package/.claude/skills/agent-building/references/code-examples.md +0 -587
  98. package/.claude/skills/agent-building/references/implementation-guide.md +0 -619
  99. package/.claude/skills/app-api/SKILL.md +0 -219
  100. package/.claude/skills/app-api/references/app-endpoints.md +0 -759
  101. package/.claude/skills/building-hailer-apps-skill/SKILL.md +0 -813
  102. package/.claude/skills/hailer-api/SKILL.md +0 -283
  103. package/.claude/skills/hailer-api/references/activities.md +0 -620
  104. package/.claude/skills/hailer-api/references/authentication.md +0 -216
  105. package/.claude/skills/hailer-api/references/datasets.md +0 -437
  106. package/.claude/skills/hailer-api/references/files.md +0 -301
  107. package/.claude/skills/hailer-api/references/insights.md +0 -469
  108. package/.claude/skills/hailer-api/references/workflows.md +0 -720
  109. package/.claude/skills/hailer-api/references/workspaces-users.md +0 -445
  110. package/.claude/skills/hailer-app-builder/SKILL.md +0 -340
  111. package/.claude/skills/mcp-tools/SKILL.md +0 -419
  112. package/.claude/skills/mcp-tools/references/api-endpoints.md +0 -499
  113. package/.claude/skills/mcp-tools/references/data-structures.md +0 -554
  114. package/.claude/skills/mcp-tools/references/implementation-patterns.md +0 -717
  115. package/.claude/skills/skill-testing/README.md +0 -137
  116. package/.claude/skills/skill-testing/SKILL.md +0 -348
  117. package/.claude/skills/skill-testing/references/test-patterns.md +0 -705
  118. package/.claude/skills/skill-testing/references/testing-guide.md +0 -603
  119. package/.claude/skills/skill-testing/references/validation-checklist.md +0 -537
  120. package/.claude/skills/spawn-app-builder/SKILL.md +0 -366
  121. package/.claude/skills/tool-builder/SKILL.md +0 -328
  122. package/tsconfig.json +0 -23
@@ -17,7 +17,7 @@ const logger = (0, logger_1.createLogger)({ component: 'upload-files-tool' });
17
17
  /**
18
18
  * Tool description - extracted for clarity
19
19
  */
20
- const description = `๐Ÿงช [PLAYGROUND] Upload files: \`{ "files": [{ "path": "/path/to/file" }] }\` or \`{ "files": [{ "url": "https://..." }] }\`.
20
+ const uploadFilesDescription = `๐Ÿงช [PLAYGROUND] Upload files: \`{ "files": [{ "path": "/path/to/file" }] }\` or \`{ "files": [{ "url": "https://..." }] }\`.
21
21
 
22
22
  Max 100MB per file. Returns file IDs for activities.`;
23
23
  /**
@@ -26,14 +26,14 @@ Max 100MB per file. Returns file IDs for activities.`;
26
26
  exports.uploadFilesTool = {
27
27
  name: 'upload_files',
28
28
  group: tool_registry_1.ToolGroup.PLAYGROUND,
29
- description,
29
+ description: uploadFilesDescription,
30
30
  schema: zod_1.z.object({
31
31
  files: zod_1.z.union([
32
32
  zod_1.z.array(zod_1.z.object({
33
- url: zod_1.z.string().optional(),
34
- path: zod_1.z.string().optional(),
35
- filename: zod_1.z.string().optional(),
36
- isPublic: zod_1.z.boolean().optional()
33
+ url: zod_1.z.string().optional().describe("URL to download file from (e.g., https://example.com/file.pdf)"),
34
+ path: zod_1.z.string().optional().describe("Local file path to upload (e.g., /home/user/document.pdf)"),
35
+ filename: zod_1.z.string().optional().describe("Override filename for the uploaded file"),
36
+ isPublic: zod_1.z.boolean().optional().describe("Whether the file should be publicly accessible")
37
37
  })),
38
38
  zod_1.z.string()
39
39
  ]).describe("Array of files to upload (or JSON string). Each file must have either 'url' or 'path'")
@@ -12,6 +12,7 @@ import { Tool } from '../tool-registry';
12
12
  export declare const createInsightTool: Tool;
13
13
  export declare const previewInsightTool: Tool;
14
14
  export declare const getInsightDataTool: Tool;
15
+ export declare const updateInsightTool: Tool;
15
16
  export declare const removeInsightTool: Tool;
16
17
  export declare const listInsightsTool: Tool;
17
18
  //# sourceMappingURL=insight.d.ts.map
@@ -10,11 +10,11 @@
10
10
  * All 4 insight management tools in one file for cohesion.
11
11
  */
12
12
  Object.defineProperty(exports, "__esModule", { value: true });
13
- exports.listInsightsTool = exports.removeInsightTool = exports.getInsightDataTool = exports.previewInsightTool = exports.createInsightTool = void 0;
13
+ exports.listInsightsTool = exports.removeInsightTool = exports.updateInsightTool = exports.getInsightDataTool = exports.previewInsightTool = exports.createInsightTool = void 0;
14
14
  const zod_1 = require("zod");
15
15
  const tool_registry_1 = require("../tool-registry");
16
- const workspace_cache_1 = require("../workspace-cache");
17
16
  const logger_1 = require("../../lib/logger");
17
+ const tool_helpers_1 = require("../utils/tool-helpers");
18
18
  const logger = (0, logger_1.createLogger)({ component: 'insight-tools' });
19
19
  // ============================================================================
20
20
  // SHARED TYPES & SCHEMAS
@@ -108,25 +108,10 @@ exports.createInsightTool = {
108
108
  apiKey: context.apiKey.substring(0, 8) + '...'
109
109
  });
110
110
  try {
111
- if (!context.workspaceCache) {
112
- return {
113
- content: [{
114
- type: "text",
115
- text: "โŒ Workspace cache not available",
116
- }],
117
- };
118
- }
119
- // Resolve workspace ID
120
- const workspaceId = args.workspaceId
121
- ? (0, workspace_cache_1.resolveWorkspaceId)(context.workspaceCache, args.workspaceId)
122
- : context.workspaceCache.currentWorkspace._id;
111
+ // Resolve workspace ID (returns undefined if cache unavailable)
112
+ const workspaceId = (0, tool_helpers_1.getResolvedWorkspaceId)(args, context);
123
113
  if (!workspaceId) {
124
- return {
125
- content: [{
126
- type: "text",
127
- text: `โŒ Could not resolve workspace: ${args.workspaceId}`,
128
- }],
129
- };
114
+ return (0, tool_helpers_1.missingWorkspaceCacheResponse)();
130
115
  }
131
116
  logger.debug('Calling v3.insight.create', {
132
117
  workspaceId,
@@ -293,25 +278,10 @@ exports.previewInsightTool = {
293
278
  apiKey: context.apiKey.substring(0, 8) + '...'
294
279
  });
295
280
  try {
296
- if (!context.workspaceCache) {
297
- return {
298
- content: [{
299
- type: "text",
300
- text: "โŒ Workspace cache not available",
301
- }],
302
- };
303
- }
304
- // Resolve workspace ID
305
- const workspaceId = args.workspaceId
306
- ? (0, workspace_cache_1.resolveWorkspaceId)(context.workspaceCache, args.workspaceId)
307
- : context.workspaceCache.currentWorkspace._id;
281
+ // Resolve workspace ID (returns undefined if cache unavailable)
282
+ const workspaceId = (0, tool_helpers_1.getResolvedWorkspaceId)(args, context);
308
283
  if (!workspaceId) {
309
- return {
310
- content: [{
311
- type: "text",
312
- text: `โŒ Could not resolve workspace: ${args.workspaceId}`,
313
- }],
314
- };
284
+ return (0, tool_helpers_1.missingWorkspaceCacheResponse)();
315
285
  }
316
286
  logger.debug('Calling v3.insight.preview', {
317
287
  workspaceId,
@@ -512,6 +482,194 @@ exports.getInsightDataTool = {
512
482
  }
513
483
  };
514
484
  // ============================================================================
485
+ // UPDATE INSIGHT TOOL
486
+ // ============================================================================
487
+ const updateInsightDescription = `๐Ÿงช [PLAYGROUND] Update Insight - Modify existing insight properties
488
+
489
+ **What it does:**
490
+ Updates an existing insight's properties (name, query, sources, visibility).
491
+
492
+ **Required Parameters:**
493
+ - insightId - The insight ID to update
494
+
495
+ **Optional Parameters (include only what you want to change):**
496
+ - name - New insight name
497
+ - public - Change visibility (true/false)
498
+ - sources - Updated workflow sources
499
+ - query - Updated SQL query
500
+
501
+ **Example - Update name only:**
502
+ \`\`\`javascript
503
+ update_insight({
504
+ insightId: '<insight-id>',
505
+ name: 'New Insight Name'
506
+ })
507
+ \`\`\`
508
+
509
+ **Example - Update query:**
510
+ \`\`\`javascript
511
+ update_insight({
512
+ insightId: '<insight-id>',
513
+ query: 'SELECT * FROM players WHERE position = "Forward"'
514
+ })
515
+ \`\`\`
516
+
517
+ **Example - Full update:**
518
+ \`\`\`javascript
519
+ update_insight({
520
+ insightId: '<insight-id>',
521
+ name: 'Updated Insight',
522
+ public: true,
523
+ sources: [{ name: 'p', workflowId: 'xxx', fields: [...] }],
524
+ query: 'SELECT * FROM p'
525
+ })
526
+ \`\`\`
527
+
528
+ **Tips:**
529
+ - Use \`preview_insight\` to test query changes before updating
530
+ - Use \`list_insights\` to find insight IDs
531
+ - Only include fields you want to change`;
532
+ exports.updateInsightTool = {
533
+ name: 'update_insight',
534
+ group: tool_registry_1.ToolGroup.PLAYGROUND,
535
+ description: updateInsightDescription,
536
+ schema: zod_1.z.object({
537
+ insightId: zod_1.z
538
+ .string()
539
+ .describe("Insight ID to update (24 characters)"),
540
+ name: zod_1.z
541
+ .string()
542
+ .optional()
543
+ .describe("New insight name"),
544
+ public: zod_1.z
545
+ .coerce.boolean()
546
+ .optional()
547
+ .describe("Whether insight is publicly accessible"),
548
+ sources: zod_1.z
549
+ .preprocess((val) => typeof val === 'string' ? JSON.parse(val) : val, zod_1.z.array(sourceSchema).optional())
550
+ .describe("Updated workflow sources (like SQL table references)"),
551
+ query: zod_1.z
552
+ .string()
553
+ .optional()
554
+ .describe("Updated SQL query"),
555
+ }),
556
+ async execute(args, context) {
557
+ logger.debug('Updating insight', {
558
+ insightId: args.insightId,
559
+ hasName: !!args.name,
560
+ hasQuery: !!args.query,
561
+ hasSources: !!args.sources,
562
+ hasPublic: args.public !== undefined,
563
+ apiKey: context.apiKey.substring(0, 8) + '...'
564
+ });
565
+ try {
566
+ // Build update payload - only include provided fields
567
+ const updateData = {};
568
+ if (args.name !== undefined) {
569
+ updateData.name = args.name;
570
+ }
571
+ if (args.public !== undefined) {
572
+ updateData.public = args.public;
573
+ }
574
+ if (args.sources !== undefined) {
575
+ updateData.sources = args.sources;
576
+ }
577
+ if (args.query !== undefined) {
578
+ updateData.query = args.query;
579
+ }
580
+ // Validate at least one field is being updated
581
+ if (Object.keys(updateData).length === 0) {
582
+ return {
583
+ content: [{
584
+ type: "text",
585
+ text: `โŒ **No updates provided**\n\nYou must provide at least one field to update:\n- name\n- public\n- sources\n- query\n\nExample:\n\`\`\`javascript\nupdate_insight({\n insightId: "${args.insightId}",\n name: "New Name"\n})\n\`\`\``,
586
+ }],
587
+ };
588
+ }
589
+ logger.debug('Calling v3.insight.update', {
590
+ insightId: args.insightId,
591
+ updateFields: Object.keys(updateData)
592
+ });
593
+ // Call v3.insight.update endpoint
594
+ // API expects: [insightId, updateData]
595
+ const result = await context.hailer.request('v3.insight.update', [
596
+ args.insightId,
597
+ updateData
598
+ ]);
599
+ logger.debug('Insight update successful', {
600
+ insightId: args.insightId,
601
+ result: JSON.stringify(result)
602
+ });
603
+ // Build success response
604
+ let responseText = `โœ… **Insight Updated Successfully**\n\n`;
605
+ responseText += `**Insight ID:** \`${args.insightId}\`\n`;
606
+ responseText += `**Updated Fields:**\n`;
607
+ if (args.name !== undefined) {
608
+ responseText += `- Name: ${args.name}\n`;
609
+ }
610
+ if (args.public !== undefined) {
611
+ responseText += `- Public: ${args.public ? 'Yes' : 'No'}\n`;
612
+ }
613
+ if (args.sources !== undefined) {
614
+ responseText += `- Sources: ${args.sources.length} workflow(s)\n`;
615
+ }
616
+ if (args.query !== undefined) {
617
+ responseText += `- Query: Updated\n`;
618
+ }
619
+ if (args.query) {
620
+ responseText += `\n**New SQL Query:**\n\`\`\`sql\n${args.query}\n\`\`\`\n`;
621
+ }
622
+ responseText += `\n๐Ÿ’ก **Next Steps:**\n`;
623
+ responseText += `- Use \`get_insight_data\` with \`update: true\` to see fresh results\n`;
624
+ responseText += `- Use \`preview_insight\` to test if you made query changes\n`;
625
+ responseText += `- Use \`list_insights\` to see all insights\n`;
626
+ return {
627
+ content: [{
628
+ type: "text",
629
+ text: responseText,
630
+ }],
631
+ };
632
+ }
633
+ catch (error) {
634
+ logger.error("Error updating insight", error);
635
+ const errorMessage = (0, tool_helpers_1.extractErrorMessage)(error);
636
+ // Handle SQL syntax errors
637
+ if (errorMessage.toLowerCase().includes('sql') || errorMessage.toLowerCase().includes('syntax')) {
638
+ return {
639
+ content: [{
640
+ type: "text",
641
+ text: `โŒ **SQL Query Error**\n\nThere's a problem with your SQL query.\n\n**Error:** ${errorMessage}\n\n**Tips:**\n- Check column names match field names in sources\n- Check table names match source names\n- Use \`preview_insight\` to test queries before updating\n- Make sure field IDs are correct (use \`get_workflow_schema\`)`,
642
+ }],
643
+ };
644
+ }
645
+ // Handle permission errors
646
+ if (errorMessage.includes('permission') || errorMessage.includes('PermissionDenied')) {
647
+ return {
648
+ content: [{
649
+ type: "text",
650
+ text: `โŒ **Permission Denied**\n\nYou may not have permission to update this insight.\n\n**Error:** ${errorMessage}`,
651
+ }],
652
+ };
653
+ }
654
+ // Handle not found errors
655
+ if (errorMessage.includes('not found') || errorMessage.includes('NotFound')) {
656
+ return {
657
+ content: [{
658
+ type: "text",
659
+ text: `โŒ **Insight Not Found**\n\nInsight ID \`${args.insightId}\` does not exist.\n\n**Error:** ${errorMessage}\n\n**Tips:**\n- Use \`list_insights\` to find valid insight IDs\n- Check for typos in the insight ID`,
660
+ }],
661
+ };
662
+ }
663
+ return {
664
+ content: [{
665
+ type: "text",
666
+ text: `โŒ **Error updating insight**\n\n**Error:** ${errorMessage}\n\n**Common Issues:**\n- Insight ID not found\n- SQL query syntax errors\n- Invalid field IDs or workflow IDs\n- Permission issues\n- Use \`list_insights\` to verify insight ID\n- Use \`preview_insight\` to test query changes first`,
667
+ }],
668
+ };
669
+ }
670
+ }
671
+ };
672
+ // ============================================================================
515
673
  // REMOVE INSIGHT TOOL
516
674
  // ============================================================================
517
675
  const removeInsightDescription = `๐Ÿงช [PLAYGROUND] Remove Insight - โš ๏ธ DANGER: Permanently deletes insight and all its data
@@ -579,15 +737,11 @@ exports.removeInsightTool = {
579
737
  apiKey: context.apiKey.substring(0, 8) + '...'
580
738
  });
581
739
  try {
582
- if (!context.workspaceCache) {
583
- return {
584
- content: [{
585
- type: "text",
586
- text: "โŒ Workspace cache not available",
587
- }],
588
- };
740
+ // Resolve workspace ID (returns undefined if cache unavailable)
741
+ const workspaceId = (0, tool_helpers_1.getResolvedWorkspaceId)({}, context);
742
+ if (!workspaceId) {
743
+ return (0, tool_helpers_1.missingWorkspaceCacheResponse)();
589
744
  }
590
- const workspaceId = context.workspaceCache.currentWorkspace._id;
591
745
  // Fetch insight info and workspace info
592
746
  const [insightListResult, initData] = await Promise.all([
593
747
  context.hailer.request('v3.insight.list', [workspaceId]),
@@ -721,25 +875,10 @@ exports.listInsightsTool = {
721
875
  apiKey: context.apiKey.substring(0, 8) + '...'
722
876
  });
723
877
  try {
724
- if (!context.workspaceCache) {
725
- return {
726
- content: [{
727
- type: "text",
728
- text: "โŒ Workspace cache not available",
729
- }],
730
- };
731
- }
732
- // Resolve workspace ID
733
- const workspaceId = args.workspaceId
734
- ? (0, workspace_cache_1.resolveWorkspaceId)(context.workspaceCache, args.workspaceId)
735
- : context.workspaceCache.currentWorkspace._id;
878
+ // Resolve workspace ID (returns undefined if cache unavailable)
879
+ const workspaceId = (0, tool_helpers_1.getResolvedWorkspaceId)(args, context);
736
880
  if (!workspaceId) {
737
- return {
738
- content: [{
739
- type: "text",
740
- text: `โŒ Could not resolve workspace: ${args.workspaceId}`,
741
- }],
742
- };
881
+ return (0, tool_helpers_1.missingWorkspaceCacheResponse)();
743
882
  }
744
883
  logger.debug('Calling v3.insight.list', { workspaceId });
745
884
  // Call v3.insight.list endpoint
@@ -11,6 +11,7 @@ exports.searchWorkspaceUsersTool = void 0;
11
11
  const zod_1 = require("zod");
12
12
  const tool_registry_1 = require("../tool-registry");
13
13
  const index_1 = require("../utils/index");
14
+ const tool_helpers_1 = require("../utils/tool-helpers");
14
15
  const logger = (0, index_1.createLogger)({ component: 'user-tools' });
15
16
  // ============================================================================
16
17
  // TOOL 1: SEARCH WORKSPACE USERS
@@ -38,14 +39,7 @@ exports.searchWorkspaceUsersTool = {
38
39
  });
39
40
  try {
40
41
  if (!context.workspaceCache) {
41
- return {
42
- content: [
43
- {
44
- type: "text",
45
- text: "โŒ Workspace cache not available for user search. You must report it to user that there is a problem with MCP Server that must be forwarded to development team",
46
- },
47
- ],
48
- };
42
+ return (0, tool_helpers_1.missingWorkspaceCacheResponse)();
49
43
  }
50
44
  const query = args.query.toLowerCase().trim();
51
45
  const exactMatch = args.exactMatch;
@@ -98,7 +92,7 @@ exports.searchWorkspaceUsersTool = {
98
92
  content: [
99
93
  {
100
94
  type: "text",
101
- text: `โŒ Error searching users: ${error instanceof Error ? error.message : String(error)}`,
95
+ text: `โŒ Error searching users: ${(0, tool_helpers_1.extractErrorMessage)(error)}`,
102
96
  },
103
97
  ],
104
98
  };
@@ -63,9 +63,8 @@ exports.getWorkflowSchemaTool = {
63
63
  }),
64
64
  async execute(args, context) {
65
65
  try {
66
- // Fetch complete workflow definition from API (includes field keys)
67
- const initData = await context.hailer.request('v2.core.init', [['processes']]);
68
- const workflow = initData.processes?.find(p => p._id === args.workflowId);
66
+ // Use cached workflow data from context.init (already fetched during initialization)
67
+ const workflow = context.init.processes?.find(p => p._id === args.workflowId);
69
68
  if (!workflow) {
70
69
  return {
71
70
  content: [{
@@ -162,9 +161,8 @@ exports.listWorkflowPhasesTool = {
162
161
  }),
163
162
  async execute(args, context) {
164
163
  try {
165
- // Fetch workflow definition directly from API
166
- const initData = await context.hailer.request('v2.core.init', [["processes"]]);
167
- const workflowData = initData.processes?.find(p => p._id === args.workflowId);
164
+ // Use cached workflow data from context.init (already fetched during initialization)
165
+ const workflowData = context.init.processes?.find(p => p._id === args.workflowId);
168
166
  if (!workflowData) {
169
167
  return {
170
168
  content: [{
@@ -245,9 +243,8 @@ exports.listWorkflowsTool = {
245
243
  apiKey: context.apiKey.substring(0, 8) + '...'
246
244
  });
247
245
  try {
248
- // Fetch workflows directly from API
249
- const initData = await context.hailer.request('v2.core.init', [["processes"]]);
250
- let workflows = initData.processes || [];
246
+ // Use cached workflows from context.init (already fetched during initialization)
247
+ let workflows = context.init.processes || [];
251
248
  if (args.workspace) {
252
249
  // Filter by workspace ID or name
253
250
  const workspaceFilter = args.workspace;
@@ -442,11 +439,10 @@ exports.installWorkflowTool = {
442
439
  apiKey: context.apiKey.substring(0, 8) + '...'
443
440
  });
444
441
  try {
445
- // Get current workspace from API if not specified
442
+ // Get current workspace from cached init data
446
443
  let workspaceId = args.workspaceId;
447
444
  if (!workspaceId) {
448
- const initData = await context.hailer.request('v2.core.init', [["network"]]);
449
- workspaceId = initData.network?._id;
445
+ workspaceId = context.init.network?._id;
450
446
  }
451
447
  if (!workspaceId) {
452
448
  return {
@@ -590,9 +586,8 @@ exports.removeWorkflowTool = {
590
586
  apiKey: context.apiKey.substring(0, 8) + '...'
591
587
  });
592
588
  try {
593
- // Fetch workflow info from API to get name
594
- const initData = await context.hailer.request('v2.core.init', [["processes", "network"]]);
595
- const workflow = initData.processes?.find(p => p._id === args.workflowId);
589
+ // Get workflow info from cached init data
590
+ const workflow = context.init.processes?.find(p => p._id === args.workflowId);
596
591
  if (!workflow) {
597
592
  return {
598
593
  content: [{
@@ -602,8 +597,8 @@ exports.removeWorkflowTool = {
602
597
  };
603
598
  }
604
599
  const workflowName = workflow.name;
605
- const workspaceId = args.workspaceId || initData.network?._id;
606
- const workspaceName = initData.network?.name || 'Unknown';
600
+ const workspaceId = args.workspaceId || context.init.network?._id;
601
+ const workspaceName = context.init.network?.name || 'Unknown';
607
602
  // SAFETY CHECK: Require double confirmation
608
603
  if (!args.confirmed || !args.secondConfirmed) {
609
604
  let warningText = `โš ๏ธ **DESTRUCTIVE OPERATION - CONFIRMATION REQUIRED**\n\n`;
@@ -768,11 +763,10 @@ exports.updateWorkflowFieldTool = {
768
763
  apiKey: context.apiKey.substring(0, 8) + '...'
769
764
  });
770
765
  try {
771
- // Get current workspace from API if not specified
766
+ // Get current workspace from cached init data
772
767
  let workspaceId = args.workspaceId;
773
768
  if (!workspaceId) {
774
- const initData = await context.hailer.request('v2.core.init', [["network"]]);
775
- workspaceId = initData.network?._id;
769
+ workspaceId = context.init.network?._id;
776
770
  }
777
771
  // Process field data - auto-generate key from label if requested
778
772
  const fieldData = { ...args.fieldData };
@@ -910,9 +904,8 @@ exports.testFunctionFieldTool = {
910
904
  }],
911
905
  };
912
906
  }
913
- // Get workflow field definition from API
914
- const initData = await context.hailer.request('v2.core.init', [["processes"]]);
915
- const workflow = initData.processes?.find(p => p._id === activity.process);
907
+ // Get workflow field definition from cached data
908
+ const workflow = context.init.processes?.find(p => p._id === activity.process);
916
909
  const field = workflow?.fields?.[args.fieldId];
917
910
  if (!field) {
918
911
  return {
@@ -1047,7 +1040,23 @@ ${errorMessage}
1047
1040
  // ============================================================================
1048
1041
  // TOOL 5: LIST WORKFLOWS MINIMAL
1049
1042
  // ============================================================================
1050
- const listWorkflowsMinimalDescription = `๐Ÿงช [PLAYGROUND] List workflows with minimal output - Returns only id and name to avoid token limits`;
1043
+ const listWorkflowsMinimalDescription = `๐Ÿงช [PLAYGROUND] List workflows with minimal output - Returns only id and name to avoid token limits
1044
+
1045
+ **โšก PERFORMANCE ADVANTAGE:**
1046
+ - Uses cached data from init (v2.core.init) - **ZERO extra API calls**
1047
+ - Returns activity counts for ALL workflows in one call
1048
+ - **Preferred method for getting bulk workflow counts**
1049
+ - Much faster and more efficient than calling \`count_activities\` for each workflow
1050
+
1051
+ **When to use this vs count_activities:**
1052
+ - โœ… Use \`list_workflows_minimal\` for: Bulk counts, workflow discovery, listing all workflows with counts
1053
+ - โŒ Use \`count_activities\` for: Phase-level breakdown, real-time count for single workflow
1054
+
1055
+ **Response includes**:
1056
+ - Workflow ID and name
1057
+ - Activity count (from cached init data)
1058
+ - Starred status
1059
+ - Workspace ID`;
1051
1060
  const listWorkflowsMinimalSchema = zod_1.z.object({
1052
1061
  workspace: zod_1.z.string().optional().describe("Optional workspace ID or name"),
1053
1062
  limit: zod_1.z.coerce.number().optional().describe("Maximum number of workflows to return"),
@@ -1065,9 +1074,8 @@ exports.listWorkflowsMinimalTool = {
1065
1074
  apiKey: context.apiKey.substring(0, 8) + '...'
1066
1075
  });
1067
1076
  try {
1068
- // Fetch workflows directly from API
1069
- const initData = await context.hailer.request('v2.core.init', [["processes"]]);
1070
- let workflows = initData.processes || [];
1077
+ // Use cached workflows from context.init (already fetched during initialization)
1078
+ let workflows = context.init.processes || [];
1071
1079
  // Filter by workspace if specified
1072
1080
  if (args.workspace) {
1073
1081
  workflows = workflows.filter(w => w.cid === args.workspace);
@@ -1142,6 +1150,11 @@ const countActivitiesDescription = `๐Ÿ”ข Count Activities - Get total count of a
1142
1150
 
1143
1151
  **Purpose**: Returns the total number of activities in a specific workflow. Useful for analytics, reporting, and understanding workflow size.
1144
1152
 
1153
+ **โš ๏ธ PERFORMANCE NOTICE:**
1154
+ - This makes a separate API call per workflow (v3.activity.count)
1155
+ - Use \`list_workflows_minimal\` instead for bulk workflow counts (uses cached data from init, zero extra API calls)
1156
+ - Only use \`count_activities\` when you need phase-level breakdown or real-time count
1157
+
1145
1158
  **Example**:
1146
1159
  \`\`\`javascript
1147
1160
  count_activities({
@@ -1152,13 +1165,13 @@ count_activities({
1152
1165
  **Response**: Returns count in details object
1153
1166
 
1154
1167
  **Use Cases**:
1155
- - Analytics and reporting
1156
- - Workflow size estimation
1157
- - Data migration planning
1158
- - Performance monitoring
1168
+ - Single workflow activity count
1169
+ - Phase-by-phase breakdown (returned data shows counts per phase)
1170
+ - Real-time activity count (bypasses cache)
1159
1171
 
1160
1172
  **Tips**:
1161
- - Much faster than list_activities for just getting count
1173
+ - For bulk counts of ALL workflows, use \`list_workflows_minimal\` (free, no API calls)
1174
+ - This tool makes 1 API call per workflow
1162
1175
  - Use list_workflows to get workflow IDs`;
1163
1176
  const countActivitiesSchema = zod_1.z.object({
1164
1177
  workflowId: zod_1.z.string().describe("Workflow ID to count activities from (24 characters)"),
@@ -1174,9 +1187,8 @@ exports.countActivitiesTool = {
1174
1187
  apiKey: context.apiKey.substring(0, 8) + '...'
1175
1188
  });
1176
1189
  try {
1177
- // Get workflow name for better response
1178
- const initData = await context.hailer.request('v2.core.init', [["processes"]]);
1179
- const workflow = initData.processes?.find(p => p._id === args.workflowId);
1190
+ // Get workflow name from cached data
1191
+ const workflow = context.init.processes?.find(p => p._id === args.workflowId);
1180
1192
  if (!workflow) {
1181
1193
  return {
1182
1194
  content: [{
@@ -1279,11 +1291,10 @@ exports.updateWorkflowPhaseTool = {
1279
1291
  apiKey: context.apiKey.substring(0, 8) + '...'
1280
1292
  });
1281
1293
  try {
1282
- // Get current workspace from API if not specified
1294
+ // Get current workspace from cached init data
1283
1295
  let workspaceId = args.workspaceId;
1284
1296
  if (!workspaceId) {
1285
- const initData = await context.hailer.request('v2.core.init', [["network"]]);
1286
- workspaceId = initData.network?._id;
1297
+ workspaceId = context.init.network?._id;
1287
1298
  }
1288
1299
  const phaseData = args.phaseData;
1289
1300
  const language = 'en'; // Default language
@@ -93,24 +93,15 @@ class HailerApiClient {
93
93
  * Create activities - uses Socket API
94
94
  */
95
95
  async createActivities(workflowId, activities, options) {
96
- console.log('๐Ÿญ CREATE ACTIVITIES API CALL');
97
- console.log('๐Ÿ“‹ Workflow ID:', workflowId);
98
- console.log('๐Ÿ“Š Activities Count:', activities.length);
99
- console.log('๐ŸŽฏ Activities Array:', JSON.stringify(activities, null, 2));
100
- console.log('โš™๏ธ Options:', JSON.stringify(options || {}, null, 2));
101
- this.logger.debug('createActivities called with:', {
102
- workflowId,
103
- activities: JSON.stringify(activities),
104
- options: JSON.stringify(options || {})
105
- });
106
- console.log('๐Ÿ”Œ Calling socket API: v3.activity.createMany');
107
96
  try {
108
97
  const result = await this.request('v3.activity.createMany', [workflowId, activities, options || {}]);
109
- console.log('โœ… CREATE ACTIVITIES SUCCESS');
110
98
  return result;
111
99
  }
112
100
  catch (error) {
113
- console.error('โŒ CREATE ACTIVITIES FAILED');
101
+ this.logger.error('createActivities failed', error, {
102
+ workflowId,
103
+ activitiesCount: activities.length
104
+ });
114
105
  throw error;
115
106
  }
116
107
  }