@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,120 @@
1
+ /**
2
+ * Hailer API Client
3
+ * Provides separate socket and REST API methods for flexible endpoint usage
4
+ */
5
+ import { HailerClient } from '../hailer-clients';
6
+ import { LogContext } from '../../lib/logger';
7
+ import { FileSpec, UploadResult } from './file-upload';
8
+ export interface RestCallConfig {
9
+ operation: string;
10
+ endpoint: string;
11
+ body?: any;
12
+ method?: string;
13
+ timeout?: number;
14
+ context?: LogContext;
15
+ }
16
+ export declare class HailerApiClient {
17
+ private clients;
18
+ private logger;
19
+ constructor(clients: HailerClient);
20
+ /**
21
+ * Makes a socket API call - thin wrapper around clients.socket.request
22
+ */
23
+ request<T>(method: string, args?: any[]): Promise<T>;
24
+ /**
25
+ * Makes a REST API call
26
+ */
27
+ callRest<T>(config: RestCallConfig): Promise<T>;
28
+ /**
29
+ * Get workflow schema - uses Socket API to get field definitions
30
+ */
31
+ getWorkflowSchema(workflowId: string, phaseId: string): Promise<any>;
32
+ /**
33
+ * Fetch activity list - uses v3 Socket API with enhanced pagination and filtering
34
+ */
35
+ fetchActivityList(workflowId: string, phaseId?: string, limit?: number, options?: {
36
+ page?: number;
37
+ search?: string;
38
+ sortBy?: string;
39
+ sortOrder?: string;
40
+ includeStats?: boolean;
41
+ returnFlat?: boolean;
42
+ filters?: any;
43
+ }): Promise<any>;
44
+ /**
45
+ * Create activities - uses Socket API
46
+ */
47
+ createActivities(workflowId: string, activities: any[], options?: any): Promise<any>;
48
+ /**
49
+ * Update activities - uses Socket API
50
+ */
51
+ updateActivities(updates: any[], options?: any): Promise<any>;
52
+ /**
53
+ * Fetch discussion messages - uses Socket API, load messages from specified discussion
54
+ * @param discussionId - The discussion ID to fetch messages from
55
+ * @param limit - Number of messages to fetch (client-side limiting if API doesn't support it)
56
+ */
57
+ fetchDiscussionMessages(discussionId: string, limit?: number): Promise<any>;
58
+ /**
59
+ * Fetch previous discussion messages - uses Socket API for pagination
60
+ * @param oldestMessageId - The ID of the oldest message from previous fetch
61
+ * @param batches - Number of previous batches to fetch (default: 1)
62
+ */
63
+ fetchPreviousDiscussionMessages(oldestMessageId: string, batches?: number): Promise<any>;
64
+ /**
65
+ * Fetch activity by ID - uses Socket API
66
+ */
67
+ fetchActivityById(activityId: string): Promise<any>;
68
+ /**
69
+ * Send discussion message - uses Socket API
70
+ */
71
+ sendDiscussionMessage(discussionId: string, content: string, fileIds?: string[]): Promise<any>;
72
+ /**
73
+ * Join an activity's discussion by following the activity - uses Socket API
74
+ * This is the recommended way to join activity discussions.
75
+ * Returns true if now following, false if was already following and toggled off.
76
+ */
77
+ joinActivityDiscussion(activityId: string): Promise<boolean>;
78
+ /**
79
+ * Leave an activity's discussion by unfollowing the activity - uses Socket API
80
+ * Returns true if successfully unfollowed, false if was already not following.
81
+ */
82
+ leaveActivityDiscussion(activityId: string): Promise<boolean>;
83
+ /**
84
+ * Leave a discussion directly - uses Socket API
85
+ * This works for any discussion type. For activity discussions, prefer leaveActivityDiscussion().
86
+ */
87
+ leaveDiscussion(discussionId: string): Promise<void>;
88
+ /**
89
+ * Join a discussion directly - uses Socket API
90
+ * Note: There's no generic join endpoint. For activity discussions, use joinActivityDiscussion().
91
+ * For other discussion types, you may need to use invite mechanisms.
92
+ * This method attempts to fetch the discussion to check if user needs to join.
93
+ */
94
+ joinDiscussion(discussionId: string): Promise<{
95
+ success: boolean;
96
+ message: string;
97
+ method?: string;
98
+ }>;
99
+ /**
100
+ * Fetch workspace initialization data - uses Socket API
101
+ */
102
+ fetchInit(): Promise<any>;
103
+ /**
104
+ * Global search across workspace - uses Socket API
105
+ */
106
+ globalSearch(query: string, sections?: string[]): Promise<any>;
107
+ /**
108
+ * Upload a file from URL or filesystem path
109
+ */
110
+ uploadFile(fileSpec: FileSpec): Promise<UploadResult>;
111
+ /**
112
+ * Helper method to create MCP tool responses
113
+ */
114
+ createMcpResponse(data: any, operation: string, summary?: string): any;
115
+ /**
116
+ * Helper method to create MCP error responses
117
+ */
118
+ createMcpError(error: unknown, operation: string): any;
119
+ }
120
+ //# sourceMappingURL=hailer-api-client.d.ts.map
@@ -0,0 +1,323 @@
1
+ "use strict";
2
+ /**
3
+ * Hailer API Client
4
+ * Provides separate socket and REST API methods for flexible endpoint usage
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.HailerApiClient = void 0;
8
+ const logger_1 = require("../../lib/logger");
9
+ const api_errors_1 = require("./api-errors");
10
+ const file_upload_1 = require("./file-upload");
11
+ class HailerApiClient {
12
+ clients;
13
+ logger = (0, logger_1.createLogger)({ component: 'HailerApiClient' });
14
+ constructor(clients) {
15
+ this.clients = clients;
16
+ }
17
+ /**
18
+ * Makes a socket API call - thin wrapper around clients.socket.request
19
+ */
20
+ async request(method, args) {
21
+ if (!this.clients.socket) {
22
+ throw new Error(`Socket client not available for method: ${method}`);
23
+ }
24
+ this.logger.debug('Socket API call', { method, args });
25
+ try {
26
+ const result = await this.clients.socket.request(method, args || []);
27
+ this.logger.debug('Socket API success', { method });
28
+ return result;
29
+ }
30
+ catch (error) {
31
+ // Log with detailed context for debugging
32
+ this.logger.error('Socket API error', error, {
33
+ method,
34
+ args: JSON.stringify(args || []),
35
+ apiBaseUrl: this.clients.socket.host
36
+ });
37
+ throw error;
38
+ }
39
+ }
40
+ /**
41
+ * Makes a REST API call
42
+ */
43
+ async callRest(config) {
44
+ const url = `${this.clients.socket.host}${config.endpoint}`;
45
+ return await (0, api_errors_1.makeApiCall)(url, {
46
+ operation: config.operation,
47
+ endpoint: config.endpoint,
48
+ method: config.method || 'POST',
49
+ body: config.body,
50
+ timeout: config.timeout,
51
+ context: config.context,
52
+ headers: {
53
+ 'hlrkey': this.clients.sessionKey,
54
+ },
55
+ });
56
+ }
57
+ /**
58
+ * Get workflow schema - uses Socket API to get field definitions
59
+ */
60
+ async getWorkflowSchema(workflowId, phaseId) {
61
+ return await this.request('v3.activity.template.create', [workflowId, phaseId]);
62
+ }
63
+ /**
64
+ * Fetch activity list - uses v3 Socket API with enhanced pagination and filtering
65
+ */
66
+ async fetchActivityList(workflowId, phaseId, limit = 50, options) {
67
+ // V3 API uses processId and phaseId (not process/phase)
68
+ const workflowFilter = { processId: workflowId };
69
+ if (phaseId)
70
+ workflowFilter.phaseId = phaseId;
71
+ const requestOptions = {
72
+ filters: options?.filters,
73
+ limit,
74
+ search: options?.search || null,
75
+ page: options?.page ? options.page + 1 : 1, // v3 uses 1-based page numbering
76
+ sortBy: options?.sortBy || "updated",
77
+ sortOrder: options?.sortOrder || "desc",
78
+ includeStats: options?.includeStats !== undefined ? options?.includeStats : true,
79
+ returnFlat: options?.returnFlat !== undefined ? options?.returnFlat : true,
80
+ };
81
+ this.logger.debug('📋 V3 Activity List API Call', {
82
+ endpoint: 'v3.activity.list',
83
+ workflowId,
84
+ phaseId,
85
+ limit,
86
+ hasFilters: !!options?.filters,
87
+ filterCount: options?.filters?.and?.length || 0,
88
+ });
89
+ // Use Format B (simple array) - confirmed working
90
+ return await this.request('v3.activity.list', [workflowFilter, requestOptions]);
91
+ }
92
+ /**
93
+ * Create activities - uses Socket API
94
+ */
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
+ try {
108
+ const result = await this.request('v3.activity.createMany', [workflowId, activities, options || {}]);
109
+ console.log('✅ CREATE ACTIVITIES SUCCESS');
110
+ return result;
111
+ }
112
+ catch (error) {
113
+ console.error('❌ CREATE ACTIVITIES FAILED');
114
+ throw error;
115
+ }
116
+ }
117
+ /**
118
+ * Update activities - uses Socket API
119
+ */
120
+ async updateActivities(updates, options) {
121
+ const args = options ? [updates, options] : [updates];
122
+ return await this.request('v3.activity.updateMany', args);
123
+ }
124
+ /**
125
+ * Fetch discussion messages - uses Socket API, load messages from specified discussion
126
+ * @param discussionId - The discussion ID to fetch messages from
127
+ * @param limit - Number of messages to fetch (client-side limiting if API doesn't support it)
128
+ */
129
+ async fetchDiscussionMessages(discussionId, limit = 50) {
130
+ const result = await this.request('v3.discussion.message.latest', [discussionId]);
131
+ // If API returned messages and we need to limit them, slice the array
132
+ if (result?.messages && Array.isArray(result.messages) && result.messages.length > limit) {
133
+ return {
134
+ ...result,
135
+ messages: result.messages.slice(0, limit),
136
+ // Add metadata to indicate truncation
137
+ truncated: true,
138
+ originalCount: result.messages.length,
139
+ requestedLimit: limit
140
+ };
141
+ }
142
+ return result;
143
+ }
144
+ /**
145
+ * Fetch previous discussion messages - uses Socket API for pagination
146
+ * @param oldestMessageId - The ID of the oldest message from previous fetch
147
+ * @param batches - Number of previous batches to fetch (default: 1)
148
+ */
149
+ async fetchPreviousDiscussionMessages(oldestMessageId, batches = 1) {
150
+ const allMessages = [];
151
+ let currentMessageId = oldestMessageId;
152
+ let totalFetched = 0;
153
+ this.logger.debug('Starting previous message fetch', {
154
+ oldestMessageId,
155
+ batches,
156
+ totalRequests: batches
157
+ });
158
+ for (let i = 0; i < batches; i++) {
159
+ try {
160
+ this.logger.debug(`Fetching batch ${i + 1}/${batches}`, {
161
+ currentMessageId,
162
+ batchNumber: i + 1
163
+ });
164
+ const result = await this.request('v3.discussion.message.previous', [currentMessageId]);
165
+ this.logger.debug(`Batch ${i + 1} API response`, {
166
+ hasMessages: !!(result?.messages),
167
+ messageCount: result?.messages?.length || 0,
168
+ resultKeys: Object.keys(result || {})
169
+ });
170
+ if (result?.messages && Array.isArray(result.messages) && result.messages.length > 0) {
171
+ allMessages.push(...result.messages);
172
+ totalFetched += result.messages.length;
173
+ // Update currentMessageId to the oldest message from this batch for next iteration
174
+ const oldestInBatch = result.messages[result.messages.length - 1];
175
+ currentMessageId = oldestInBatch._id;
176
+ this.logger.debug(`Batch ${i + 1}/${batches} fetched successfully`, {
177
+ messagesInBatch: result.messages.length,
178
+ totalSoFar: totalFetched,
179
+ nextMessageId: currentMessageId
180
+ });
181
+ }
182
+ else {
183
+ // No more messages available
184
+ this.logger.debug(`No more messages available at batch ${i + 1}`, {
185
+ totalFetched,
186
+ completedBatches: i,
187
+ resultStructure: result
188
+ });
189
+ break;
190
+ }
191
+ }
192
+ catch (error) {
193
+ this.logger.error(`Error fetching batch ${i + 1}`, {
194
+ error: error,
195
+ currentMessageId,
196
+ batchNumber: i + 1
197
+ });
198
+ break;
199
+ }
200
+ }
201
+ const finalResult = {
202
+ messages: allMessages,
203
+ totalFetched,
204
+ batchesCompleted: Math.min(batches, Math.ceil(totalFetched / 50)),
205
+ oldestMessageId: allMessages.length > 0 ? allMessages[allMessages.length - 1]._id : oldestMessageId,
206
+ hasMore: totalFetched > 0 // Assume there might be more if we got any messages
207
+ };
208
+ this.logger.debug('Previous message fetch completed', finalResult);
209
+ return finalResult;
210
+ }
211
+ /**
212
+ * Fetch activity by ID - uses Socket API
213
+ */
214
+ async fetchActivityById(activityId) {
215
+ return await this.request('activities.load', [activityId]);
216
+ }
217
+ /**
218
+ * Send discussion message - uses Socket API
219
+ */
220
+ async sendDiscussionMessage(discussionId, content, fileIds) {
221
+ const messageData = { msg: content };
222
+ if (fileIds && fileIds.length > 0) {
223
+ messageData.files = fileIds;
224
+ }
225
+ return await this.request('messenger.send', [messageData, discussionId]);
226
+ }
227
+ /**
228
+ * Join an activity's discussion by following the activity - uses Socket API
229
+ * This is the recommended way to join activity discussions.
230
+ * Returns true if now following, false if was already following and toggled off.
231
+ */
232
+ async joinActivityDiscussion(activityId) {
233
+ // activities.follow toggles the state, but we need to check current state first
234
+ const activity = await this.fetchActivityById(activityId);
235
+ // If not already following, call activities.follow to join
236
+ const result = await this.request('activities.follow', [activityId]);
237
+ return result; // true if now following, false if unfollowed
238
+ }
239
+ /**
240
+ * Leave an activity's discussion by unfollowing the activity - uses Socket API
241
+ * Returns true if successfully unfollowed, false if was already not following.
242
+ */
243
+ async leaveActivityDiscussion(activityId) {
244
+ // activities.follow toggles the state
245
+ const activity = await this.fetchActivityById(activityId);
246
+ // If already following, call activities.follow to unfollow
247
+ const result = await this.request('activities.follow', [activityId]);
248
+ return !result; // Inverse: true if now unfollowed, false if followed
249
+ }
250
+ /**
251
+ * Leave a discussion directly - uses Socket API
252
+ * This works for any discussion type. For activity discussions, prefer leaveActivityDiscussion().
253
+ */
254
+ async leaveDiscussion(discussionId) {
255
+ return await this.request('messenger.leave_discussion', [discussionId]);
256
+ }
257
+ /**
258
+ * Join a discussion directly - uses Socket API
259
+ * Note: There's no generic join endpoint. For activity discussions, use joinActivityDiscussion().
260
+ * For other discussion types, you may need to use invite mechanisms.
261
+ * This method attempts to fetch the discussion to check if user needs to join.
262
+ */
263
+ async joinDiscussion(discussionId) {
264
+ // Try to fetch messages to check if already a member
265
+ try {
266
+ await this.request('v3.discussion.message.latest', [discussionId]);
267
+ return {
268
+ success: true,
269
+ message: 'Already a member of this discussion or successfully accessed it',
270
+ method: 'direct_access'
271
+ };
272
+ }
273
+ catch (error) {
274
+ // Check if error indicates permission/access issue
275
+ const errorMsg = error?.message || String(error);
276
+ if (errorMsg.toLowerCase().includes('permission') ||
277
+ errorMsg.toLowerCase().includes('access') ||
278
+ errorMsg.toLowerCase().includes('not found')) {
279
+ // This is likely an activity discussion - we need the activity ID
280
+ throw new Error('Cannot join this discussion directly. If this is an activity discussion, ' +
281
+ 'please use join_activity_discussion tool with the activity ID instead. ' +
282
+ 'For other discussion types, you may need an invitation.');
283
+ }
284
+ throw error;
285
+ }
286
+ }
287
+ /**
288
+ * Fetch workspace initialization data - uses Socket API
289
+ */
290
+ async fetchInit() {
291
+ return await this.request('v2.core.init', [{}]);
292
+ }
293
+ /**
294
+ * Global search across workspace - uses Socket API
295
+ */
296
+ async globalSearch(query, sections) {
297
+ const searchOptions = { search: query };
298
+ if (sections) {
299
+ searchOptions.sections = sections;
300
+ }
301
+ return await this.request('v2.search.global', [searchOptions]);
302
+ }
303
+ /**
304
+ * Upload a file from URL or filesystem path
305
+ */
306
+ async uploadFile(fileSpec) {
307
+ return await (0, file_upload_1.uploadSingleFile)(fileSpec, this.clients);
308
+ }
309
+ /**
310
+ * Helper method to create MCP tool responses
311
+ */
312
+ createMcpResponse(data, operation, summary) {
313
+ return (0, api_errors_1.createSuccessResponse)(data, operation, summary);
314
+ }
315
+ /**
316
+ * Helper method to create MCP error responses
317
+ */
318
+ createMcpError(error, operation) {
319
+ return (0, api_errors_1.createErrorResponse)(error, operation);
320
+ }
321
+ }
322
+ exports.HailerApiClient = HailerApiClient;
323
+ //# sourceMappingURL=hailer-api-client.js.map
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Utility exports for Hailer MCP Server
3
+ * Provides centralized access to all utility functions and types
4
+ */
5
+ export { createLogger, getDefaultLogger as logger, LogLevel, LogTag } from '../../lib/logger';
6
+ export type { LogContext } from '../../lib/logger';
7
+ export { HailerApiError, makeApiCall, handleApiResponse, createErrorResponse, createSuccessResponse } from './api-errors';
8
+ export type { ApiCallOptions } from './api-errors';
9
+ export { HailerApiClient } from './hailer-api-client';
10
+ export type { RestCallConfig } from './hailer-api-client';
11
+ export { transformActivity, transformActivities, transformFields, transformFieldValue, findFieldByKey, transformWorkflow, transformPhases, transformWorkflowFields, formatTimestamp, formatUserName, getFirstPhaseId, formatActivityListResponse, transformActivityForSearch, } from './data-transformers';
12
+ export type * from './types';
13
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+ /**
3
+ * Utility exports for Hailer MCP Server
4
+ * Provides centralized access to all utility functions and types
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.transformActivityForSearch = exports.formatActivityListResponse = exports.getFirstPhaseId = exports.formatUserName = exports.formatTimestamp = exports.transformWorkflowFields = exports.transformPhases = exports.transformWorkflow = exports.findFieldByKey = exports.transformFieldValue = exports.transformFields = exports.transformActivities = exports.transformActivity = exports.HailerApiClient = exports.createSuccessResponse = exports.createErrorResponse = exports.handleApiResponse = exports.makeApiCall = exports.HailerApiError = exports.LogTag = exports.LogLevel = exports.logger = exports.createLogger = void 0;
8
+ // Logging utilities
9
+ var logger_1 = require("../../lib/logger");
10
+ Object.defineProperty(exports, "createLogger", { enumerable: true, get: function () { return logger_1.createLogger; } });
11
+ Object.defineProperty(exports, "logger", { enumerable: true, get: function () { return logger_1.getDefaultLogger; } });
12
+ Object.defineProperty(exports, "LogLevel", { enumerable: true, get: function () { return logger_1.LogLevel; } });
13
+ Object.defineProperty(exports, "LogTag", { enumerable: true, get: function () { return logger_1.LogTag; } });
14
+ // Error handling utilities
15
+ var api_errors_1 = require("./api-errors");
16
+ Object.defineProperty(exports, "HailerApiError", { enumerable: true, get: function () { return api_errors_1.HailerApiError; } });
17
+ Object.defineProperty(exports, "makeApiCall", { enumerable: true, get: function () { return api_errors_1.makeApiCall; } });
18
+ Object.defineProperty(exports, "handleApiResponse", { enumerable: true, get: function () { return api_errors_1.handleApiResponse; } });
19
+ Object.defineProperty(exports, "createErrorResponse", { enumerable: true, get: function () { return api_errors_1.createErrorResponse; } });
20
+ Object.defineProperty(exports, "createSuccessResponse", { enumerable: true, get: function () { return api_errors_1.createSuccessResponse; } });
21
+ // API client
22
+ var hailer_api_client_1 = require("./hailer-api-client");
23
+ Object.defineProperty(exports, "HailerApiClient", { enumerable: true, get: function () { return hailer_api_client_1.HailerApiClient; } });
24
+ // Data transformers
25
+ var data_transformers_1 = require("./data-transformers");
26
+ Object.defineProperty(exports, "transformActivity", { enumerable: true, get: function () { return data_transformers_1.transformActivity; } });
27
+ Object.defineProperty(exports, "transformActivities", { enumerable: true, get: function () { return data_transformers_1.transformActivities; } });
28
+ Object.defineProperty(exports, "transformFields", { enumerable: true, get: function () { return data_transformers_1.transformFields; } });
29
+ Object.defineProperty(exports, "transformFieldValue", { enumerable: true, get: function () { return data_transformers_1.transformFieldValue; } });
30
+ Object.defineProperty(exports, "findFieldByKey", { enumerable: true, get: function () { return data_transformers_1.findFieldByKey; } });
31
+ Object.defineProperty(exports, "transformWorkflow", { enumerable: true, get: function () { return data_transformers_1.transformWorkflow; } });
32
+ Object.defineProperty(exports, "transformPhases", { enumerable: true, get: function () { return data_transformers_1.transformPhases; } });
33
+ Object.defineProperty(exports, "transformWorkflowFields", { enumerable: true, get: function () { return data_transformers_1.transformWorkflowFields; } });
34
+ Object.defineProperty(exports, "formatTimestamp", { enumerable: true, get: function () { return data_transformers_1.formatTimestamp; } });
35
+ Object.defineProperty(exports, "formatUserName", { enumerable: true, get: function () { return data_transformers_1.formatUserName; } });
36
+ Object.defineProperty(exports, "getFirstPhaseId", { enumerable: true, get: function () { return data_transformers_1.getFirstPhaseId; } });
37
+ Object.defineProperty(exports, "formatActivityListResponse", { enumerable: true, get: function () { return data_transformers_1.formatActivityListResponse; } });
38
+ Object.defineProperty(exports, "transformActivityForSearch", { enumerable: true, get: function () { return data_transformers_1.transformActivityForSearch; } });
39
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Structured logging utility for Hailer MCP Server
3
+ * Provides consistent logging across the application with configurable levels
4
+ */
5
+ export declare enum LogLevel {
6
+ DEBUG = 0,
7
+ INFO = 1,
8
+ WARN = 2,
9
+ ERROR = 3
10
+ }
11
+ export interface LogContext {
12
+ operation?: string;
13
+ endpoint?: string;
14
+ activityId?: string;
15
+ workflowId?: string;
16
+ discussionId?: string;
17
+ userId?: string;
18
+ duration?: number;
19
+ [key: string]: any;
20
+ }
21
+ declare class Logger {
22
+ private level;
23
+ private context;
24
+ setLevel(level: LogLevel): void;
25
+ setContext(context: LogContext): Logger;
26
+ private withContext;
27
+ private shouldLog;
28
+ private formatMessage;
29
+ private getEmoji;
30
+ debug(message: string, context?: LogContext): void;
31
+ info(message: string, context?: LogContext): void;
32
+ warn(message: string, context?: LogContext): void;
33
+ error(message: string, error?: Error | unknown, context?: LogContext): void;
34
+ apiCall(operation: string, endpoint: string, params?: any): void;
35
+ apiSuccess(operation: string, endpoint: string, duration?: number): void;
36
+ apiError(operation: string, endpoint: string, error: Error | unknown, duration?: number): void;
37
+ socketFallback(operation: string, reason: string): void;
38
+ }
39
+ export declare const logger: Logger;
40
+ export declare function createLogger(context: LogContext): Logger;
41
+ export {};
42
+ //# sourceMappingURL=logger.d.ts.map
@@ -0,0 +1,103 @@
1
+ "use strict";
2
+ /**
3
+ * Structured logging utility for Hailer MCP Server
4
+ * Provides consistent logging across the application with configurable levels
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.logger = exports.LogLevel = void 0;
8
+ exports.createLogger = createLogger;
9
+ var LogLevel;
10
+ (function (LogLevel) {
11
+ LogLevel[LogLevel["DEBUG"] = 0] = "DEBUG";
12
+ LogLevel[LogLevel["INFO"] = 1] = "INFO";
13
+ LogLevel[LogLevel["WARN"] = 2] = "WARN";
14
+ LogLevel[LogLevel["ERROR"] = 3] = "ERROR";
15
+ })(LogLevel || (exports.LogLevel = LogLevel = {}));
16
+ class Logger {
17
+ level = LogLevel.DEBUG;
18
+ context = {};
19
+ setLevel(level) {
20
+ this.level = level;
21
+ }
22
+ setContext(context) {
23
+ return new Logger().withContext({ ...this.context, ...context });
24
+ }
25
+ withContext(context) {
26
+ const newLogger = new Logger();
27
+ newLogger.level = this.level;
28
+ newLogger.context = context;
29
+ return newLogger;
30
+ }
31
+ shouldLog(level) {
32
+ return level >= this.level;
33
+ }
34
+ formatMessage(level, message, context) {
35
+ const emoji = this.getEmoji(level);
36
+ const levelName = LogLevel[level];
37
+ const fullContext = { ...this.context, ...context };
38
+ let contextStr = '';
39
+ if (Object.keys(fullContext).length > 0) {
40
+ const contextParts = Object.entries(fullContext)
41
+ .filter(([_, value]) => value !== undefined && value !== null)
42
+ .map(([key, value]) => `${key}=${value}`);
43
+ if (contextParts.length > 0) {
44
+ contextStr = ` [${contextParts.join(', ')}]`;
45
+ }
46
+ }
47
+ return `${emoji} ${levelName}: ${message}${contextStr}`;
48
+ }
49
+ getEmoji(level) {
50
+ switch (level) {
51
+ case LogLevel.DEBUG: return '🔍';
52
+ case LogLevel.INFO: return '📡';
53
+ case LogLevel.WARN: return '⚠️';
54
+ case LogLevel.ERROR: return '❌';
55
+ default: return '📝';
56
+ }
57
+ }
58
+ debug(message, context) {
59
+ if (this.shouldLog(LogLevel.DEBUG)) {
60
+ console.log(this.formatMessage(LogLevel.DEBUG, message, context));
61
+ }
62
+ }
63
+ info(message, context) {
64
+ if (this.shouldLog(LogLevel.INFO)) {
65
+ console.log(this.formatMessage(LogLevel.INFO, message, context));
66
+ }
67
+ }
68
+ warn(message, context) {
69
+ if (this.shouldLog(LogLevel.WARN)) {
70
+ console.warn(this.formatMessage(LogLevel.WARN, message, context));
71
+ }
72
+ }
73
+ error(message, error, context) {
74
+ if (this.shouldLog(LogLevel.ERROR)) {
75
+ const errorMsg = error instanceof Error ? error.message : String(error);
76
+ const fullMessage = error ? `${message}: ${errorMsg}` : message;
77
+ console.error(this.formatMessage(LogLevel.ERROR, fullMessage, context));
78
+ if (error instanceof Error && error.stack) {
79
+ console.error(error.stack);
80
+ }
81
+ }
82
+ }
83
+ // Convenience methods for common operations
84
+ apiCall(operation, endpoint, params) {
85
+ this.debug(`API call: ${operation}`, { operation, endpoint, params: params ? JSON.stringify(params) : undefined });
86
+ }
87
+ apiSuccess(operation, endpoint, duration) {
88
+ this.info(`API success: ${operation}`, { operation, endpoint, duration });
89
+ }
90
+ apiError(operation, endpoint, error, duration) {
91
+ this.error(`API error: ${operation}`, error, { operation, endpoint, duration });
92
+ }
93
+ socketFallback(operation, reason) {
94
+ this.warn(`Socket fallback: ${operation} - ${reason}`, { operation });
95
+ }
96
+ }
97
+ // Export singleton instance
98
+ exports.logger = new Logger();
99
+ // Export factory function for creating loggers with specific context
100
+ function createLogger(context) {
101
+ return exports.logger.setContext(context);
102
+ }
103
+ //# sourceMappingURL=logger.js.map