@hailer/mcp 0.0.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 (163) hide show
  1. package/.claude/commands/tool-builder.md +37 -0
  2. package/.claude/commands/ws-pull.md +44 -0
  3. package/.claude/settings.json +8 -0
  4. package/.claude/settings.local.json +49 -0
  5. package/.claude/skills/activity-api/SKILL.md +96 -0
  6. package/.claude/skills/activity-api/references/activity-endpoints.md +845 -0
  7. package/.claude/skills/add-app-member-skill/SKILL.md +977 -0
  8. package/.claude/skills/agent-building/SKILL.md +243 -0
  9. package/.claude/skills/agent-building/references/architecture-patterns.md +446 -0
  10. package/.claude/skills/agent-building/references/code-examples.md +587 -0
  11. package/.claude/skills/agent-building/references/implementation-guide.md +619 -0
  12. package/.claude/skills/app-api/SKILL.md +219 -0
  13. package/.claude/skills/app-api/references/app-endpoints.md +759 -0
  14. package/.claude/skills/building-hailer-apps-skill/SKILL.md +548 -0
  15. package/.claude/skills/create-app-skill/SKILL.md +1101 -0
  16. package/.claude/skills/create-insight-skill/SKILL.md +1317 -0
  17. package/.claude/skills/get-insight-data-skill/SKILL.md +1053 -0
  18. package/.claude/skills/hailer-api/SKILL.md +283 -0
  19. package/.claude/skills/hailer-api/references/activities.md +620 -0
  20. package/.claude/skills/hailer-api/references/authentication.md +216 -0
  21. package/.claude/skills/hailer-api/references/datasets.md +437 -0
  22. package/.claude/skills/hailer-api/references/files.md +301 -0
  23. package/.claude/skills/hailer-api/references/insights.md +469 -0
  24. package/.claude/skills/hailer-api/references/workflows.md +720 -0
  25. package/.claude/skills/hailer-api/references/workspaces-users.md +445 -0
  26. package/.claude/skills/insight-api/SKILL.md +185 -0
  27. package/.claude/skills/insight-api/references/insight-endpoints.md +514 -0
  28. package/.claude/skills/install-workflow-skill/SKILL.md +1056 -0
  29. package/.claude/skills/list-apps-skill/SKILL.md +1010 -0
  30. package/.claude/skills/list-workflows-minimal-skill/SKILL.md +992 -0
  31. package/.claude/skills/local-first-skill/SKILL.md +570 -0
  32. package/.claude/skills/mcp-tools/SKILL.md +419 -0
  33. package/.claude/skills/mcp-tools/references/api-endpoints.md +499 -0
  34. package/.claude/skills/mcp-tools/references/data-structures.md +554 -0
  35. package/.claude/skills/mcp-tools/references/implementation-patterns.md +717 -0
  36. package/.claude/skills/preview-insight-skill/SKILL.md +1290 -0
  37. package/.claude/skills/publish-hailer-app-skill/SKILL.md +453 -0
  38. package/.claude/skills/remove-app-member-skill/SKILL.md +671 -0
  39. package/.claude/skills/remove-app-skill/SKILL.md +985 -0
  40. package/.claude/skills/remove-insight-skill/SKILL.md +1011 -0
  41. package/.claude/skills/remove-workflow-skill/SKILL.md +920 -0
  42. package/.claude/skills/scaffold-hailer-app-skill/SKILL.md +1034 -0
  43. package/.claude/skills/skill-testing/README.md +137 -0
  44. package/.claude/skills/skill-testing/SKILL.md +348 -0
  45. package/.claude/skills/skill-testing/references/test-patterns.md +705 -0
  46. package/.claude/skills/skill-testing/references/testing-guide.md +603 -0
  47. package/.claude/skills/skill-testing/references/validation-checklist.md +537 -0
  48. package/.claude/skills/tool-builder/SKILL.md +328 -0
  49. package/.claude/skills/update-app-skill/SKILL.md +970 -0
  50. package/.claude/skills/update-workflow-field-skill/SKILL.md +1098 -0
  51. package/.env.example +81 -0
  52. package/.mcp.json +13 -0
  53. package/README.md +297 -0
  54. package/dist/app.d.ts +4 -0
  55. package/dist/app.js +74 -0
  56. package/dist/cli.d.ts +3 -0
  57. package/dist/cli.js +5 -0
  58. package/dist/client/adaptive-documentation-bot.d.ts +108 -0
  59. package/dist/client/adaptive-documentation-bot.js +475 -0
  60. package/dist/client/adaptive-documentation-types.d.ts +66 -0
  61. package/dist/client/adaptive-documentation-types.js +9 -0
  62. package/dist/client/agent-activity-bot.d.ts +51 -0
  63. package/dist/client/agent-activity-bot.js +166 -0
  64. package/dist/client/agent-tracker.d.ts +499 -0
  65. package/dist/client/agent-tracker.js +659 -0
  66. package/dist/client/description-updater.d.ts +56 -0
  67. package/dist/client/description-updater.js +259 -0
  68. package/dist/client/log-parser.d.ts +72 -0
  69. package/dist/client/log-parser.js +387 -0
  70. package/dist/client/mcp-client.d.ts +50 -0
  71. package/dist/client/mcp-client.js +532 -0
  72. package/dist/client/message-processor.d.ts +35 -0
  73. package/dist/client/message-processor.js +352 -0
  74. package/dist/client/multi-bot-manager.d.ts +24 -0
  75. package/dist/client/multi-bot-manager.js +74 -0
  76. package/dist/client/providers/anthropic-provider.d.ts +19 -0
  77. package/dist/client/providers/anthropic-provider.js +631 -0
  78. package/dist/client/providers/llm-provider.d.ts +47 -0
  79. package/dist/client/providers/llm-provider.js +367 -0
  80. package/dist/client/providers/openai-provider.d.ts +23 -0
  81. package/dist/client/providers/openai-provider.js +621 -0
  82. package/dist/client/simple-llm-caller.d.ts +19 -0
  83. package/dist/client/simple-llm-caller.js +100 -0
  84. package/dist/client/skill-generator.d.ts +81 -0
  85. package/dist/client/skill-generator.js +386 -0
  86. package/dist/client/test-adaptive-bot.d.ts +9 -0
  87. package/dist/client/test-adaptive-bot.js +82 -0
  88. package/dist/client/token-pricing.d.ts +38 -0
  89. package/dist/client/token-pricing.js +127 -0
  90. package/dist/client/token-tracker.d.ts +232 -0
  91. package/dist/client/token-tracker.js +457 -0
  92. package/dist/client/token-usage-bot.d.ts +53 -0
  93. package/dist/client/token-usage-bot.js +153 -0
  94. package/dist/client/tool-executor.d.ts +69 -0
  95. package/dist/client/tool-executor.js +159 -0
  96. package/dist/client/tool-schema-loader.d.ts +60 -0
  97. package/dist/client/tool-schema-loader.js +178 -0
  98. package/dist/client/types.d.ts +69 -0
  99. package/dist/client/types.js +7 -0
  100. package/dist/config.d.ts +162 -0
  101. package/dist/config.js +296 -0
  102. package/dist/core.d.ts +26 -0
  103. package/dist/core.js +147 -0
  104. package/dist/lib/context-manager.d.ts +111 -0
  105. package/dist/lib/context-manager.js +431 -0
  106. package/dist/lib/logger.d.ts +74 -0
  107. package/dist/lib/logger.js +277 -0
  108. package/dist/lib/materialize.d.ts +3 -0
  109. package/dist/lib/materialize.js +101 -0
  110. package/dist/lib/normalizedName.d.ts +7 -0
  111. package/dist/lib/normalizedName.js +48 -0
  112. package/dist/lib/prompt-length-manager.d.ts +81 -0
  113. package/dist/lib/prompt-length-manager.js +457 -0
  114. package/dist/lib/terminal-prompt.d.ts +9 -0
  115. package/dist/lib/terminal-prompt.js +108 -0
  116. package/dist/mcp/UserContextCache.d.ts +56 -0
  117. package/dist/mcp/UserContextCache.js +163 -0
  118. package/dist/mcp/auth.d.ts +2 -0
  119. package/dist/mcp/auth.js +29 -0
  120. package/dist/mcp/hailer-clients.d.ts +42 -0
  121. package/dist/mcp/hailer-clients.js +246 -0
  122. package/dist/mcp/signal-handler.d.ts +45 -0
  123. package/dist/mcp/signal-handler.js +317 -0
  124. package/dist/mcp/tool-registry.d.ts +100 -0
  125. package/dist/mcp/tool-registry.js +306 -0
  126. package/dist/mcp/tools/activity.d.ts +15 -0
  127. package/dist/mcp/tools/activity.js +955 -0
  128. package/dist/mcp/tools/app.d.ts +20 -0
  129. package/dist/mcp/tools/app.js +1488 -0
  130. package/dist/mcp/tools/discussion.d.ts +19 -0
  131. package/dist/mcp/tools/discussion.js +950 -0
  132. package/dist/mcp/tools/file.d.ts +15 -0
  133. package/dist/mcp/tools/file.js +119 -0
  134. package/dist/mcp/tools/insight.d.ts +17 -0
  135. package/dist/mcp/tools/insight.js +806 -0
  136. package/dist/mcp/tools/skill.d.ts +10 -0
  137. package/dist/mcp/tools/skill.js +279 -0
  138. package/dist/mcp/tools/user.d.ts +10 -0
  139. package/dist/mcp/tools/user.js +108 -0
  140. package/dist/mcp/tools/workflow-template.d.ts +19 -0
  141. package/dist/mcp/tools/workflow-template.js +822 -0
  142. package/dist/mcp/tools/workflow.d.ts +18 -0
  143. package/dist/mcp/tools/workflow.js +1362 -0
  144. package/dist/mcp/utils/api-errors.d.ts +45 -0
  145. package/dist/mcp/utils/api-errors.js +160 -0
  146. package/dist/mcp/utils/data-transformers.d.ts +102 -0
  147. package/dist/mcp/utils/data-transformers.js +194 -0
  148. package/dist/mcp/utils/file-upload.d.ts +33 -0
  149. package/dist/mcp/utils/file-upload.js +148 -0
  150. package/dist/mcp/utils/hailer-api-client.d.ts +120 -0
  151. package/dist/mcp/utils/hailer-api-client.js +323 -0
  152. package/dist/mcp/utils/index.d.ts +13 -0
  153. package/dist/mcp/utils/index.js +39 -0
  154. package/dist/mcp/utils/logger.d.ts +42 -0
  155. package/dist/mcp/utils/logger.js +103 -0
  156. package/dist/mcp/utils/types.d.ts +286 -0
  157. package/dist/mcp/utils/types.js +7 -0
  158. package/dist/mcp/workspace-cache.d.ts +42 -0
  159. package/dist/mcp/workspace-cache.js +97 -0
  160. package/dist/mcp-server.d.ts +42 -0
  161. package/dist/mcp-server.js +280 -0
  162. package/package.json +56 -0
  163. package/tsconfig.json +23 -0
@@ -0,0 +1,532 @@
1
+ "use strict";
2
+ /**
3
+ * Main MCP Client
4
+ * Orchestrates signal handling, message processing, and LLM provider interaction
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.McpClient = void 0;
8
+ const message_processor_1 = require("./message-processor");
9
+ const openai_provider_1 = require("./providers/openai-provider");
10
+ const anthropic_provider_1 = require("./providers/anthropic-provider");
11
+ const multi_bot_manager_1 = require("./multi-bot-manager");
12
+ const agent_tracker_1 = require("./agent-tracker");
13
+ const token_tracker_1 = require("./token-tracker");
14
+ const token_usage_bot_1 = require("./token-usage-bot");
15
+ const agent_activity_bot_1 = require("./agent-activity-bot");
16
+ const adaptive_documentation_bot_1 = require("./adaptive-documentation-bot");
17
+ const config_1 = require("../config");
18
+ class McpClient {
19
+ multiBotManager;
20
+ messageProcessor;
21
+ providers = new Map();
22
+ config;
23
+ isActive = false;
24
+ processedMessages = new Set(); // Global message deduplication
25
+ activeSubscriptions = new Set(); // Track active subscriptions
26
+ agentTracker = (0, agent_tracker_1.createAgentTracker)();
27
+ tokenTracker = (0, token_tracker_1.createTokenTracker)();
28
+ tokenUsageBot;
29
+ agentActivityBot;
30
+ adaptiveDocBot;
31
+ constructor(config) {
32
+ this.config = config;
33
+ this.multiBotManager = new multi_bot_manager_1.MultiBotManager(config.botConfigs);
34
+ this.messageProcessor = new message_processor_1.HailerMessageProcessor(this.multiBotManager, config.mcpAgentIds, config.enableDirectMessages);
35
+ // Initialize Token Usage Bot
36
+ this.tokenUsageBot = (0, token_usage_bot_1.createTokenUsageBot)(this.tokenTracker, this.agentTracker, {
37
+ enabled: config.tokenUsageBotEnabled,
38
+ postSummaryAfterConversation: config.tokenUsageBotEnabled,
39
+ minCostThreshold: 0, // Post summary for every conversation
40
+ });
41
+ // Initialize Agent Activity Bot
42
+ this.agentActivityBot = (0, agent_activity_bot_1.createAgentActivityBot)(this.agentTracker, {
43
+ enabled: config.agentActivityBotEnabled,
44
+ postSummaryAfterConversation: config.agentActivityBotEnabled,
45
+ minDurationThreshold: 1000, // Only post if duration > 1s
46
+ });
47
+ // Initialize Adaptive Documentation Bot
48
+ const appConfig = (0, config_1.createApplicationConfig)();
49
+ if (appConfig.adaptiveDocumentation.enabled && this.config.providers.length > 0) {
50
+ // Use the first available provider's API key for the adaptive bot
51
+ const firstProviderConfig = this.config.providers[0];
52
+ if (firstProviderConfig.apiKey) {
53
+ this.adaptiveDocBot = new adaptive_documentation_bot_1.AdaptiveDocumentationBot(firstProviderConfig.apiKey, firstProviderConfig.type === 'openai' ? 'openai' : 'anthropic', {
54
+ enabled: appConfig.adaptiveDocumentation.enabled,
55
+ autoUpdate: appConfig.adaptiveDocumentation.autoUpdate,
56
+ updateInterval: appConfig.adaptiveDocumentation.updateInterval,
57
+ minErrorCount: appConfig.adaptiveDocumentation.minErrorCount,
58
+ skillGeneration: appConfig.adaptiveDocumentation.skillGeneration,
59
+ });
60
+ console.log('🔧 Adaptive Documentation Bot initialized');
61
+ }
62
+ }
63
+ // Initialize providers after adaptive bot
64
+ this.initializeProviders();
65
+ }
66
+ async initialize() {
67
+ await this.multiBotManager.initializeAllHailerClientsFromConfig();
68
+ // Update agent IDs with the actual user IDs retrieved from authentication
69
+ const actualAgentIds = this.multiBotManager.getBotIds();
70
+ if (actualAgentIds.length > 0) {
71
+ console.log(`🤖 Updated MCP Agent IDs: ${actualAgentIds.join(", ")}`);
72
+ // Update the message processor with the actual agent IDs
73
+ this.messageProcessor = new message_processor_1.HailerMessageProcessor(this.multiBotManager, actualAgentIds, this.config.enableDirectMessages);
74
+ // Log successful initialization
75
+ this.agentTracker.logSystem({
76
+ success: true,
77
+ message: "MCP Client Initialized",
78
+ details: `Successfully initialized with ${actualAgentIds.length} bot agent(s): ${actualAgentIds.map((id) => id.substring(0, 8)).join(", ")}`,
79
+ });
80
+ }
81
+ else {
82
+ // Log failed initialization
83
+ this.agentTracker.logSystem({
84
+ success: false,
85
+ message: "MCP Client Initialization Failed",
86
+ error: "No bot agents configured or authentication failed",
87
+ });
88
+ }
89
+ // Start adaptive documentation monitoring
90
+ if (this.adaptiveDocBot) {
91
+ this.adaptiveDocBot.startMonitoring();
92
+ }
93
+ }
94
+ initializeProviders() {
95
+ for (const providerConfig of this.config.providers) {
96
+ try {
97
+ let provider;
98
+ switch (providerConfig.type) {
99
+ case "openai":
100
+ provider = new openai_provider_1.OpenAIProvider(providerConfig);
101
+ break;
102
+ case "anthropic":
103
+ provider = new anthropic_provider_1.AnthropicProvider(providerConfig);
104
+ break;
105
+ case "gemini":
106
+ // TODO: Implement GeminiProvider
107
+ console.warn(`⚠️ Provider type ${providerConfig.type} not yet implemented`);
108
+ continue;
109
+ default:
110
+ console.warn(`⚠️ Unknown provider type: ${providerConfig.type}`);
111
+ continue;
112
+ }
113
+ if (provider.isEnabled()) {
114
+ this.providers.set(providerConfig.name, provider);
115
+ }
116
+ else {
117
+ console.warn(`⚠️ Provider "${providerConfig.name}" is disabled or missing API key`);
118
+ }
119
+ }
120
+ catch (error) {
121
+ console.error(`❌ Failed to initialize provider "${providerConfig.name}":`, error);
122
+ }
123
+ }
124
+ }
125
+ start() {
126
+ if (this.isActive) {
127
+ console.log("🤖 MCP Client already active, skipping start");
128
+ return;
129
+ }
130
+ // Subscribe to signals from ALL bot clients since each bot has access to different discussions
131
+ const botClients = this.multiBotManager.getAllBotClients();
132
+ if (botClients.length === 0) {
133
+ console.error("❌ No bot clients available for signal subscription");
134
+ return;
135
+ }
136
+ // Subscribe to signals from each bot client
137
+ for (const botClient of botClients) {
138
+ const subscriptionId = `mcp-client-${botClient.userId}`;
139
+ botClient.signalHandler.subscribe(subscriptionId, ["messenger.new"], this.handleSignal.bind(this));
140
+ this.activeSubscriptions.add(subscriptionId);
141
+ console.log(`🤖 Subscribed to signals for bot: ${botClient.config.email} (${botClient.userId})`);
142
+ }
143
+ this.isActive = true;
144
+ console.log(`🤖 MCP Client started with ${botClients.length} bot signal handlers (direct messages: enabled)`);
145
+ }
146
+ /**
147
+ * Get adaptive documentation bot instance (for error reporting)
148
+ */
149
+ getAdaptiveBot() {
150
+ return this.adaptiveDocBot;
151
+ }
152
+ stop() {
153
+ if (!this.isActive) {
154
+ return;
155
+ }
156
+ console.log("🤖 Stopping MCP Client...");
157
+ // Unsubscribe from all bot signal handlers
158
+ const botClients = this.multiBotManager.getAllBotClients();
159
+ for (const botClient of botClients) {
160
+ const subscriptionId = `mcp-client-${botClient.userId}`;
161
+ if (this.activeSubscriptions.has(subscriptionId)) {
162
+ botClient.signalHandler.unsubscribe(subscriptionId);
163
+ this.activeSubscriptions.delete(subscriptionId);
164
+ console.log(`🤖 Unsubscribed from signals for bot: ${botClient.config.email}`);
165
+ }
166
+ }
167
+ // Stop adaptive documentation monitoring
168
+ if (this.adaptiveDocBot) {
169
+ this.adaptiveDocBot.stopMonitoring();
170
+ }
171
+ this.isActive = false;
172
+ console.log("🤖 MCP Client stopped");
173
+ }
174
+ async handleSignal(signal) {
175
+ let requestId = null;
176
+ const startTime = Date.now();
177
+ try {
178
+ // Early deduplication check - prevent race conditions from multiple bot subscriptions
179
+ const msgId = signal.data?.msg_id;
180
+ if (msgId) {
181
+ if (this.processedMessages.has(msgId)) {
182
+ console.log(`🔄 MCP Client: Message ${msgId} already being processed, skipping`);
183
+ return;
184
+ }
185
+ // Mark as processing immediately to prevent race conditions
186
+ this.processedMessages.add(msgId);
187
+ // Clean up old processed message IDs (keep only last 1000)
188
+ if (this.processedMessages.size > 1000) {
189
+ const entries = Array.from(this.processedMessages);
190
+ this.processedMessages.clear();
191
+ entries.slice(-500).forEach((id) => this.processedMessages.add(id)); // Keep last 500
192
+ }
193
+ }
194
+ const messages = await this.messageProcessor.extractMessage(signal);
195
+ if (!messages || messages.length === 0) {
196
+ // If message extraction failed, remove from processed set
197
+ if (msgId) {
198
+ this.processedMessages.delete(msgId);
199
+ }
200
+ return; // Signal doesn't contain a valid MCP agent message
201
+ }
202
+ // Process each message (one per mentioned bot)
203
+ const processingPromises = messages.map(async (message) => {
204
+ // Ensure we have a mentioned bot
205
+ if (!message.mentionedOrDirectMessagedBotId) {
206
+ console.warn(`⚠️ MCP Client: No bot mentioned in message, skipping processing`);
207
+ return;
208
+ }
209
+ // Double-check that the mentioned bot exists
210
+ const mentionedBot = this.multiBotManager.getBotClient(message.mentionedOrDirectMessagedBotId);
211
+ if (!mentionedBot) {
212
+ console.error(`❌ MCP Client: Mentioned bot ${message.mentionedOrDirectMessagedBotId} not found`);
213
+ return;
214
+ }
215
+ // LOG TRIGGER EVENT - Bot was successfully triggered (only for the first message to avoid duplicate logs)
216
+ let messageRequestId = null;
217
+ if (!requestId) {
218
+ requestId = this.agentTracker.logTrigger({
219
+ triggerType: this.determineTriggerType(message.content),
220
+ discussionId: message.discussionId,
221
+ userId: message.userId,
222
+ userName: message.userName,
223
+ botId: message.mentionedOrDirectMessagedBotId,
224
+ messageContent: message.content,
225
+ workspaceId: message.workspaceId,
226
+ });
227
+ messageRequestId = requestId;
228
+ }
229
+ else {
230
+ // Log additional triggers for multiple bots
231
+ messageRequestId = this.agentTracker.logTrigger({
232
+ triggerType: this.determineTriggerType(message.content),
233
+ discussionId: message.discussionId,
234
+ userId: message.userId,
235
+ userName: message.userName,
236
+ botId: message.mentionedOrDirectMessagedBotId,
237
+ messageContent: message.content,
238
+ workspaceId: message.workspaceId,
239
+ });
240
+ }
241
+ // Process with the first enabled provider (can be enhanced to support multiple or selection)
242
+ const provider = this.getFirstEnabledProvider();
243
+ if (!provider) {
244
+ console.error(`❌ MCP Client: No LLM providers are available`);
245
+ // Log completion failure
246
+ if (messageRequestId) {
247
+ this.agentTracker.logCompletion({
248
+ requestId: messageRequestId,
249
+ success: false,
250
+ duration: Date.now() - startTime,
251
+ error: "No LLM providers are available",
252
+ });
253
+ }
254
+ await this.messageProcessor.postErrorMessage(message.discussionId, "No LLM providers are available", message.workspaceId, message.mentionedOrDirectMessagedBotId);
255
+ return;
256
+ }
257
+ console.log(`🤖 Processing request from ${message.userName} with ${provider.name} (Bot: ${message.mentionedOrDirectMessagedBotId})`);
258
+ // Check if Token Bot is mentioned with a token usage query - handle directly without LLM
259
+ // For other bots (like Manager Bot), they'll use LLM + tools to invite Token Bot
260
+ const tokenBotUserId = '691c07ad702e78dc33797c97';
261
+ if (this.config.tokenUsageBotEnabled &&
262
+ this.tokenUsageBot.isTokenQuery(message.content) &&
263
+ message.mentionedOrDirectMessagedBotId === tokenBotUserId) {
264
+ console.log('📊 Token Bot query detected - generating report with direct JSON access');
265
+ const detailedReport = this.tokenUsageBot.generateDetailedReport(message.discussionId);
266
+ await this.messageProcessor.postMessage(message.discussionId, detailedReport, message.workspaceId, message.mentionedOrDirectMessagedBotId);
267
+ // Token Bot leaves the discussion after posting report
268
+ const tokenBotClient = this.multiBotManager.getBotClient(message.mentionedOrDirectMessagedBotId);
269
+ if (tokenBotClient) {
270
+ try {
271
+ await tokenBotClient.client.socket.request('messenger.leave_discussion', [message.discussionId]);
272
+ console.log('👋 Token Bot left the discussion after posting report');
273
+ }
274
+ catch (error) {
275
+ console.error('❌ Failed to leave discussion:', error);
276
+ }
277
+ }
278
+ // Log completion for token query
279
+ if (messageRequestId) {
280
+ this.agentTracker.logCompletion({
281
+ requestId: messageRequestId,
282
+ success: true,
283
+ provider: 'token-usage-bot',
284
+ toolsCalled: ['generate_detailed_report', 'leave_discussion'],
285
+ responseContent: 'Token usage report generated and left discussion',
286
+ duration: Date.now() - startTime,
287
+ });
288
+ }
289
+ return; // Skip LLM processing
290
+ }
291
+ // Check if this is an agent activity query - handle directly without LLM (only if bot is enabled)
292
+ if (this.config.agentActivityBotEnabled && this.agentActivityBot.isActivityQuery(message.content)) {
293
+ console.log('🤖 Agent activity query detected - generating report');
294
+ const detailedReport = this.agentActivityBot.generateDetailedReport(message.discussionId);
295
+ await this.messageProcessor.postMessage(message.discussionId, detailedReport, message.workspaceId, message.mentionedOrDirectMessagedBotId);
296
+ // Log completion for activity query
297
+ if (messageRequestId) {
298
+ this.agentTracker.logCompletion({
299
+ requestId: messageRequestId,
300
+ success: true,
301
+ provider: 'agent-activity-bot',
302
+ toolsCalled: ['generate_detailed_report'],
303
+ responseContent: 'Agent activity report generated',
304
+ duration: Date.now() - startTime,
305
+ });
306
+ }
307
+ return; // Skip LLM processing
308
+ }
309
+ // Generate and post personalized confirmation message
310
+ const confirmationMessage = await provider.generateConfirmationMessage(message);
311
+ await this.messageProcessor.postMessage(message.discussionId, confirmationMessage, message.workspaceId, message.mentionedOrDirectMessagedBotId);
312
+ const response = await this.processMessage(message, provider);
313
+ await this.handleResponse(message, response);
314
+ // LOG COMPLETION EVENT - Bot finished processing
315
+ if (messageRequestId) {
316
+ const duration = Date.now() - startTime;
317
+ this.agentTracker.logCompletion({
318
+ requestId: messageRequestId,
319
+ success: response.success,
320
+ provider: provider.name,
321
+ toolsCalled: response.toolCalls?.map((tc) => tc.toolName) || [],
322
+ responseContent: response.response,
323
+ duration: duration,
324
+ error: response.error,
325
+ });
326
+ // ANALYZE LOGS - Check for tool call errors after conversation completes
327
+ if (this.adaptiveDocBot) {
328
+ this.adaptiveDocBot.analyzeAfterConversation().catch(error => {
329
+ console.error('❌ Failed to analyze conversation errors:', error);
330
+ });
331
+ }
332
+ // POST AGENT ACTIVITY SUMMARY - Automatically post summary if duration threshold met
333
+ if (this.agentActivityBot.shouldPostSummary(message.discussionId, duration)) {
334
+ try {
335
+ const summary = this.agentActivityBot.generateSummary(messageRequestId, message.discussionId, duration, response.toolCalls?.map((tc) => tc.toolName) || []);
336
+ await this.messageProcessor.postMessage(message.discussionId, summary, message.workspaceId, message.mentionedOrDirectMessagedBotId);
337
+ this.agentActivityBot.markPosted(message.discussionId);
338
+ console.log('🤖 Agent activity summary posted to discussion');
339
+ }
340
+ catch (error) {
341
+ console.error('❌ Failed to post agent activity summary:', error);
342
+ }
343
+ }
344
+ // LOG TOKEN USAGE - Track costs and usage for optimization
345
+ if (response.tokens && response.tokens.cost !== undefined && response.success) {
346
+ this.tokenTracker.logUsage({
347
+ botId: message.mentionedOrDirectMessagedBotId,
348
+ botName: mentionedBot.config.email, // Use email as bot name
349
+ provider: provider.name,
350
+ conversationId: message.discussionId,
351
+ toolsCalled: response.toolCalls?.map((tc) => tc.toolName) || [],
352
+ tokens: {
353
+ input: response.tokens.input,
354
+ output: response.tokens.output,
355
+ total: response.tokens.total,
356
+ cacheCreation: response.tokens.cacheCreation,
357
+ cacheRead: response.tokens.cacheRead,
358
+ cost: response.tokens.cost,
359
+ },
360
+ duration: Date.now() - startTime,
361
+ success: true,
362
+ });
363
+ // POST TOKEN USAGE SUMMARY - Automatically post summary if cost threshold met
364
+ if (this.tokenUsageBot.shouldPostSummary(message.discussionId, response.tokens.cost)) {
365
+ try {
366
+ const summary = await this.tokenUsageBot.generateSummary(message.discussionId, response.tokens.cost, response.tokens.total);
367
+ await this.messageProcessor.postMessage(message.discussionId, summary, message.workspaceId, message.mentionedOrDirectMessagedBotId);
368
+ this.tokenUsageBot.markPosted(message.discussionId);
369
+ console.log('💰 Token usage summary posted to discussion');
370
+ }
371
+ catch (error) {
372
+ console.error('❌ Failed to post token usage summary:', error);
373
+ }
374
+ }
375
+ }
376
+ }
377
+ });
378
+ // Wait for all bot processing to complete
379
+ await Promise.all(processingPromises);
380
+ }
381
+ catch (error) {
382
+ console.error("❌ MCP Client: Error handling signal:", error);
383
+ // Log completion failure
384
+ if (requestId) {
385
+ this.agentTracker.logCompletion({
386
+ requestId,
387
+ success: false,
388
+ duration: Date.now() - startTime,
389
+ error: error instanceof Error ? error.message : String(error),
390
+ });
391
+ }
392
+ // Remove from processed set on error
393
+ const msgId = signal.data?.msg_id;
394
+ if (msgId) {
395
+ this.processedMessages.delete(msgId);
396
+ }
397
+ }
398
+ }
399
+ getFirstEnabledProvider() {
400
+ for (const provider of this.providers.values()) {
401
+ if (provider.isEnabled()) {
402
+ return provider;
403
+ }
404
+ }
405
+ return null;
406
+ }
407
+ determineTriggerType(messageContent) {
408
+ // Check if message contains hailerTag mentions
409
+ const hailerTagPattern = /\[hailerTag\|[^\]]+\]\(([^)]+)\)/g;
410
+ if (hailerTagPattern.test(messageContent)) {
411
+ return "mention";
412
+ }
413
+ // Check for old @mcp-agent format (fallback)
414
+ if (messageContent.toLowerCase().includes("@mcp-agent")) {
415
+ return "mention";
416
+ }
417
+ // Otherwise it's a direct message
418
+ return "direct";
419
+ }
420
+ async processMessage(message, provider) {
421
+ try {
422
+ const botClient = this.multiBotManager.getBotClient(message.mentionedOrDirectMessagedBotId);
423
+ if (!botClient) {
424
+ throw new Error(`Bot client not found for mentionedOrDirectMessagedBotId '${message.mentionedOrDirectMessagedBotId}'`);
425
+ }
426
+ const result = await provider.processMessage(message, this.config.mcpServerUrl, botClient.config.mcpServerApiKey, botClient.config.email);
427
+ return result;
428
+ }
429
+ catch (error) {
430
+ console.error(`❌ MCP Client: Provider "${provider.name}" failed to process message:`, error);
431
+ return {
432
+ success: false,
433
+ error: `Processing failed: ${error instanceof Error ? error.message : String(error)}`,
434
+ };
435
+ }
436
+ }
437
+ async handleResponse(message, response) {
438
+ // Build complete message with tool usage info and main response
439
+ let combinedMessage = "";
440
+ // Add tool usage information if any tools were called
441
+ // COMMENTED OUT FOR SALES DEMO - uncomment to re-enable tool logs for developmen/debugging
442
+ // if (response.toolCalls && response.toolCalls.length > 0) {
443
+ // const toolSummary = this.buildToolUsageSummary(response.toolCalls);
444
+ // if (toolSummary) {
445
+ // combinedMessage += `${toolSummary}\n\n`;
446
+ // }
447
+ // }
448
+ // Add main response or error
449
+ if (response.success && response.response) {
450
+ combinedMessage += response.response;
451
+ await this.postSuccessResponse(message, combinedMessage.trim());
452
+ }
453
+ else if (!response.success && response.error) {
454
+ combinedMessage += `❌ Error: ${response.error}`;
455
+ await this.postErrorResponse(message, combinedMessage.trim());
456
+ }
457
+ else {
458
+ console.log(`❌Unhandled case while handling the message, response.success: ${response.success}; response.error: ${response.error}`);
459
+ }
460
+ }
461
+ async postSuccessResponse(message, content) {
462
+ await this.messageProcessor.postMessage(message.discussionId, content, message.workspaceId, message.mentionedOrDirectMessagedBotId);
463
+ }
464
+ buildToolUsageSummary(toolCalls) {
465
+ if (!toolCalls || toolCalls.length === 0) {
466
+ return "";
467
+ }
468
+ const successfulTools = toolCalls.filter((tc) => !tc.error);
469
+ const failedTools = toolCalls.filter((tc) => tc.error);
470
+ let summary = "";
471
+ if (successfulTools.length > 0) {
472
+ successfulTools.forEach((tc, index) => {
473
+ if (index > 0)
474
+ summary += "\n\n";
475
+ summary += `🔧 Using tool: **${tc.toolName}**`;
476
+ if (tc.args && Object.keys(tc.args).length > 0) {
477
+ summary += `\n\`\`\`json\n${JSON.stringify(tc.args, null, 2)}\n\`\`\``;
478
+ }
479
+ });
480
+ }
481
+ if (failedTools.length > 0) {
482
+ if (summary)
483
+ summary += "\n\n";
484
+ failedTools.forEach((tc, index) => {
485
+ if (index > 0)
486
+ summary += "\n\n";
487
+ summary += `❌ Tool **${tc.toolName}** failed: ${tc.error}`;
488
+ if (tc.args && Object.keys(tc.args).length > 0) {
489
+ summary += `\nArguments:\n\`\`\`json\n${JSON.stringify(tc.args, null, 2)}\n\`\`\``;
490
+ }
491
+ });
492
+ }
493
+ return summary;
494
+ }
495
+ async postErrorResponse(message, error) {
496
+ try {
497
+ await this.messageProcessor.postErrorMessage(message.discussionId, error, message.workspaceId, message.mentionedOrDirectMessagedBotId);
498
+ }
499
+ catch (postError) {
500
+ console.error(`❌ MCP Client: Failed to post error response:`, postError);
501
+ }
502
+ }
503
+ /** Shutdown the dependency: MultiBotManager */
504
+ async shutdownMultiBotManager() {
505
+ await this.multiBotManager.shutdown();
506
+ }
507
+ /** Shutdown the McpClient and MultiBotManager */
508
+ async shutdown() {
509
+ console.log('Shutting down MCP Client');
510
+ this.stop();
511
+ await this.shutdownMultiBotManager();
512
+ console.log('MCP Client shut down successfully');
513
+ }
514
+ getStatus() {
515
+ const enabledProviders = [];
516
+ for (const [name, provider] of this.providers) {
517
+ if (provider.isEnabled()) {
518
+ enabledProviders.push(name);
519
+ }
520
+ }
521
+ return {
522
+ active: this.isActive,
523
+ providersCount: this.providers.size,
524
+ enabledProviders,
525
+ activeSubscriptions: this.activeSubscriptions.size,
526
+ botClientsCount: this.multiBotManager.getAllBotClients().length,
527
+ directMessagesEnabled: this.config.enableDirectMessages,
528
+ };
529
+ }
530
+ }
531
+ exports.McpClient = McpClient;
532
+ //# sourceMappingURL=mcp-client.js.map
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Message Processor for MCP Client
3
+ * Handles incoming socket.io signals and processes messages that mention MCP agents
4
+ * or are sent directly in one-on-one conversations with MCP agents
5
+ */
6
+ import { HailerSignal } from "../mcp/signal-handler";
7
+ import { ChatMessage, MessageProcessor } from "./types";
8
+ import { MultiBotManager } from "./multi-bot-manager";
9
+ export declare class HailerMessageProcessor implements MessageProcessor {
10
+ private multiBotManager;
11
+ private mcpAgentIds;
12
+ private enableDirectMessages;
13
+ constructor(multiBotManager: MultiBotManager, mcpAgentIds?: string[], enableDirectMessages?: boolean);
14
+ shouldProcess(signal: HailerSignal): boolean;
15
+ private containsMcpAgentMention;
16
+ /**
17
+ * Fetch discussion participants to determine if it's a one-on-one conversation
18
+ * Uses messenger.load_discussions API to get actual member count
19
+ */
20
+ private fetchDiscussionParticipants;
21
+ /**
22
+ * Check if a discussion is a one-on-one conversation with a specific MCP agent
23
+ * @param discussionId - The discussion to check
24
+ * @param senderId - The user who sent the message
25
+ * @param botIdToCheck - The specific bot ID to check for direct message
26
+ * @returns The bot ID if it's a 1:1 conversation with that bot, null otherwise
27
+ */
28
+ private isDirectMessageToBot;
29
+ extractMessage(signal: HailerSignal): Promise<ChatMessage[]>;
30
+ private extractFromMessengerNew;
31
+ postMessage(discussionId: string, content: string, workspaceId?: string, botId?: string): Promise<boolean>;
32
+ postInfoMessage(discussionId: string, toolName: string, args: any, workspaceId?: string, botId?: string): Promise<boolean>;
33
+ postErrorMessage(discussionId: string, error: string, workspaceId?: string, botId?: string): Promise<boolean>;
34
+ }
35
+ //# sourceMappingURL=message-processor.d.ts.map