@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,619 @@
1
+ # Implementation Guide: Skill-Based Agent System
2
+
3
+ This document provides step-by-step instructions for implementing a skill-based agent system in the Hailer MCP server.
4
+
5
+ ## Prerequisites
6
+
7
+ - Existing Hailer MCP server running
8
+ - Node.js and TypeScript environment
9
+ - Basic understanding of async/await patterns
10
+ - Access to `.claude/skills/` directory with existing skills
11
+
12
+ ## Implementation Overview
13
+
14
+ **Total Time**: ~1 hour
15
+ **Difficulty**: Medium
16
+ **Files to Create**: 2 new files
17
+ **Files to Modify**: 3 existing files
18
+
19
+ ## Step 1: Create Skill Loader
20
+
21
+ **File**: `server/src/client/skill-loader.ts`
22
+ **Time**: ~15 minutes
23
+ **Purpose**: Load skill files from disk and cache them
24
+
25
+ ### Implementation
26
+
27
+ ```typescript
28
+ import * as fs from 'fs/promises';
29
+ import * as path from 'path';
30
+ import { createLogger } from '../lib/logger';
31
+
32
+ export interface LoadedSkill {
33
+ name: string;
34
+ content: string;
35
+ description: string;
36
+ loadedAt: number;
37
+ }
38
+
39
+ export class SkillLoader {
40
+ private skillsPath: string;
41
+ private cache = new Map<string, LoadedSkill>();
42
+ private logger = createLogger({ component: 'skill-loader' });
43
+
44
+ constructor(skillsPath: string = '.claude/skills/') {
45
+ this.skillsPath = skillsPath;
46
+ }
47
+
48
+ /**
49
+ * Load multiple skills at once
50
+ */
51
+ async loadMultiple(skillNames: string[]): Promise<LoadedSkill[]> {
52
+ return Promise.all(skillNames.map(name => this.load(name)));
53
+ }
54
+
55
+ /**
56
+ * Load a single skill by name
57
+ */
58
+ async load(skillName: string): Promise<LoadedSkill> {
59
+ // Check cache first
60
+ if (this.cache.has(skillName)) {
61
+ this.logger.debug('Skill loaded from cache', { skillName });
62
+ return this.cache.get(skillName)!;
63
+ }
64
+
65
+ try {
66
+ const skillPath = path.join(this.skillsPath, skillName);
67
+
68
+ // Load main SKILL.md
69
+ const mainPath = path.join(skillPath, 'SKILL.md');
70
+ let content = await fs.readFile(mainPath, 'utf-8');
71
+
72
+ // Load reference files if they exist
73
+ const referencesPath = path.join(skillPath, 'references');
74
+ try {
75
+ const files = await fs.readdir(referencesPath);
76
+ for (const file of files.filter(f => f.endsWith('.md'))) {
77
+ const refContent = await fs.readFile(
78
+ path.join(referencesPath, file),
79
+ 'utf-8'
80
+ );
81
+ content += `\n\n## ${file.replace('.md', '')}\n\n${refContent}`;
82
+ }
83
+ } catch (error) {
84
+ // References directory doesn't exist or is empty - that's ok
85
+ }
86
+
87
+ const skill: LoadedSkill = {
88
+ name: skillName,
89
+ content,
90
+ description: this.extractDescription(content),
91
+ loadedAt: Date.now()
92
+ };
93
+
94
+ this.cache.set(skillName, skill);
95
+ this.logger.info('Skill loaded successfully', {
96
+ skillName,
97
+ contentLength: content.length
98
+ });
99
+
100
+ return skill;
101
+ } catch (error) {
102
+ this.logger.error('Failed to load skill', error, { skillName });
103
+ throw new Error(`Failed to load skill '${skillName}': ${error}`);
104
+ }
105
+ }
106
+
107
+ /**
108
+ * Extract description from skill content (first paragraph)
109
+ */
110
+ private extractDescription(content: string): string {
111
+ const lines = content.split('\n');
112
+ for (const line of lines) {
113
+ const trimmed = line.trim();
114
+ if (trimmed && !trimmed.startsWith('#')) {
115
+ return trimmed.slice(0, 200);
116
+ }
117
+ }
118
+ return '';
119
+ }
120
+
121
+ /**
122
+ * Clear cache for a specific skill or all skills
123
+ */
124
+ clearCache(skillName?: string): void {
125
+ if (skillName) {
126
+ this.cache.delete(skillName);
127
+ this.logger.debug('Skill cache cleared', { skillName });
128
+ } else {
129
+ this.cache.clear();
130
+ this.logger.debug('All skill caches cleared');
131
+ }
132
+ }
133
+
134
+ /**
135
+ * Get list of available skills
136
+ */
137
+ async getAvailableSkills(): Promise<string[]> {
138
+ try {
139
+ const entries = await fs.readdir(this.skillsPath, { withFileTypes: true });
140
+ return entries
141
+ .filter(entry => entry.isDirectory())
142
+ .map(entry => entry.name);
143
+ } catch (error) {
144
+ this.logger.error('Failed to list available skills', error);
145
+ return [];
146
+ }
147
+ }
148
+ }
149
+ ```
150
+
151
+ ### Testing
152
+
153
+ ```typescript
154
+ // Quick test
155
+ const loader = new SkillLoader();
156
+ const skill = await loader.load('mcp-tools');
157
+ console.log(`Loaded skill: ${skill.name}`);
158
+ console.log(`Content length: ${skill.content.length}`);
159
+ ```
160
+
161
+ ## Step 2: Create Skill Manager
162
+
163
+ **File**: `server/src/client/skill-manager.ts`
164
+ **Time**: ~20 minutes
165
+ **Purpose**: Analyze requests and select appropriate skills
166
+
167
+ ### Implementation
168
+
169
+ ```typescript
170
+ import { SkillLoader, LoadedSkill } from './skill-loader';
171
+ import { createLogger } from '../lib/logger';
172
+
173
+ export interface SkillGuidance {
174
+ skills: string[];
175
+ confidence: number;
176
+ guidance: string;
177
+ recommendedTools: string[];
178
+ skillContent?: string;
179
+ }
180
+
181
+ interface SkillMapping {
182
+ keywords: string[];
183
+ tools: string[];
184
+ priority?: number;
185
+ }
186
+
187
+ export class SkillManager {
188
+ private skillLoader: SkillLoader;
189
+ private skillMappings: Map<string, SkillMapping>;
190
+ private logger = createLogger({ component: 'skill-manager' });
191
+
192
+ constructor(skillLoader: SkillLoader) {
193
+ this.skillLoader = skillLoader;
194
+ this.skillMappings = this.buildSkillMappings();
195
+ }
196
+
197
+ /**
198
+ * Analyze a user request and determine which skills to load
199
+ */
200
+ async analyzeRequest(message: string): Promise<SkillGuidance> {
201
+ const lower = message.toLowerCase();
202
+ const scores = new Map<string, number>();
203
+
204
+ // Score each skill based on keyword matches
205
+ for (const [skillName, mapping] of this.skillMappings) {
206
+ let score = 0;
207
+ for (const keyword of mapping.keywords) {
208
+ if (lower.includes(keyword.toLowerCase())) {
209
+ score += 1;
210
+ // Bonus for exact matches
211
+ if (lower.includes(` ${keyword.toLowerCase()} `)) {
212
+ score += 0.5;
213
+ }
214
+ }
215
+ }
216
+
217
+ // Apply priority multiplier
218
+ if (mapping.priority) {
219
+ score *= mapping.priority;
220
+ }
221
+
222
+ if (score > 0) {
223
+ scores.set(skillName, score);
224
+ }
225
+ }
226
+
227
+ // Get best matching skills (up to 2)
228
+ const sortedSkills = Array.from(scores.entries())
229
+ .sort(([, a], [, b]) => b - a)
230
+ .slice(0, 2);
231
+
232
+ if (sortedSkills.length === 0) {
233
+ // No specific skill matched - use general
234
+ return await this.getDefaultGuidance();
235
+ }
236
+
237
+ const primarySkill = sortedSkills[0];
238
+ const [skillName, score] = primarySkill;
239
+ const mapping = this.skillMappings.get(skillName)!;
240
+
241
+ // Load the primary skill
242
+ const loadedSkills = await this.skillLoader.loadMultiple([skillName]);
243
+
244
+ this.logger.info('Skills selected', {
245
+ message: message.slice(0, 50),
246
+ selectedSkills: [skillName],
247
+ confidence: score
248
+ });
249
+
250
+ return {
251
+ skills: [skillName],
252
+ confidence: Math.min(score / 3, 1.0), // Normalize
253
+ guidance: this.buildGuidance(skillName, message),
254
+ recommendedTools: mapping.tools,
255
+ skillContent: loadedSkills[0]?.content
256
+ };
257
+ }
258
+
259
+ /**
260
+ * Define keyword mappings for each skill
261
+ */
262
+ private buildSkillMappings(): Map<string, SkillMapping> {
263
+ return new Map([
264
+ [
265
+ 'mcp-tools',
266
+ {
267
+ keywords: [
268
+ 'workflow', 'phase', 'field', 'schema',
269
+ 'create workflow', 'install workflow',
270
+ 'workflow template', 'workflow structure',
271
+ 'activity field', 'workflow phase'
272
+ ],
273
+ tools: [
274
+ 'install_workflow',
275
+ 'list_workflow_phases',
276
+ 'get_workflow_schema',
277
+ 'update_workflow_field'
278
+ ],
279
+ priority: 1.2
280
+ }
281
+ ],
282
+ [
283
+ 'hailer-api',
284
+ {
285
+ keywords: [
286
+ 'api', 'endpoint', 'activity', 'list activities',
287
+ 'filter', 'search', 'show activity',
288
+ 'discussion', 'message', 'fetch'
289
+ ],
290
+ tools: [
291
+ 'list_activities',
292
+ 'show_activity_by_id',
293
+ 'fetch_discussion_messages',
294
+ 'add_discussion_message'
295
+ ],
296
+ priority: 1.0
297
+ }
298
+ ],
299
+ [
300
+ 'data-analysis',
301
+ {
302
+ keywords: [
303
+ 'analyze', 'report', 'statistics', 'trends',
304
+ 'insights', 'metrics', 'summary',
305
+ 'count', 'aggregate'
306
+ ],
307
+ tools: ['list_activities'],
308
+ priority: 0.8
309
+ }
310
+ ],
311
+ [
312
+ 'agent-building',
313
+ {
314
+ keywords: [
315
+ 'build agent', 'create agent', 'agent system',
316
+ 'skill system', 'autonomous agent',
317
+ 'agent architecture', 'multi-agent'
318
+ ],
319
+ tools: [],
320
+ priority: 1.0
321
+ }
322
+ ]
323
+ ]);
324
+ }
325
+
326
+ /**
327
+ * Build guidance text for a skill
328
+ */
329
+ private buildGuidance(skillName: string, message: string): string {
330
+ const guidanceMap: Record<string, string> = {
331
+ 'mcp-tools': 'This request involves workflow/schema operations. Use the workflow management tools available.',
332
+ 'hailer-api': 'This request involves Hailer API operations. Use the appropriate API endpoints.',
333
+ 'data-analysis': 'This request involves data analysis. Gather data using list_activities and analyze it.',
334
+ 'agent-building': 'This request is about building agent systems. Reference the skill system architecture.'
335
+ };
336
+
337
+ return guidanceMap[skillName] || 'Use available tools to help the user.';
338
+ }
339
+
340
+ /**
341
+ * Get default guidance when no specific skill matches
342
+ */
343
+ private async getDefaultGuidance(): Promise<SkillGuidance> {
344
+ this.logger.debug('No specific skill matched, using default');
345
+
346
+ return {
347
+ skills: [],
348
+ confidence: 0.3,
349
+ guidance: 'General assistance request. Use available tools as needed.',
350
+ recommendedTools: [],
351
+ skillContent: undefined
352
+ };
353
+ }
354
+
355
+ /**
356
+ * Add or update a skill mapping
357
+ */
358
+ addSkillMapping(skillName: string, mapping: SkillMapping): void {
359
+ this.skillMappings.set(skillName, mapping);
360
+ this.logger.info('Skill mapping added', { skillName });
361
+ }
362
+ }
363
+ ```
364
+
365
+ ### Testing
366
+
367
+ ```typescript
368
+ // Quick test
369
+ const loader = new SkillLoader();
370
+ const manager = new SkillManager(loader);
371
+
372
+ const guidance1 = await manager.analyzeRequest("Help me create a workflow");
373
+ console.log('Guidance:', guidance1);
374
+ // Should select 'mcp-tools' skill
375
+
376
+ const guidance2 = await manager.analyzeRequest("List my activities");
377
+ console.log('Guidance:', guidance2);
378
+ // Should select 'hailer-api' skill
379
+ ```
380
+
381
+ ## Step 3: Modify Message Processor
382
+
383
+ **File**: `server/src/client/message-processor.ts`
384
+ **Time**: ~10 minutes
385
+ **Purpose**: Integrate skill manager into message flow
386
+
387
+ ### Changes Needed
388
+
389
+ 1. Import new classes
390
+ 2. Add skill manager instance
391
+ 3. Call skill manager before processing
392
+ 4. Pass skill context to provider
393
+
394
+ ### Implementation
395
+
396
+ ```typescript
397
+ // At top of file, add imports:
398
+ import { SkillLoader } from './skill-loader';
399
+ import { SkillManager } from './skill-manager';
400
+
401
+ // In class HailerMessageProcessor:
402
+ export class HailerMessageProcessor implements MessageProcessor {
403
+ // ... existing properties ...
404
+
405
+ // ADD these new properties:
406
+ private skillLoader: SkillLoader;
407
+ private skillManager: SkillManager;
408
+
409
+ constructor(
410
+ multiBotManager: MultiBotManager,
411
+ mcpAgentIds: string[],
412
+ enableDirectMessages: boolean
413
+ ) {
414
+ // ... existing constructor code ...
415
+
416
+ // ADD skill system initialization:
417
+ this.skillLoader = new SkillLoader();
418
+ this.skillManager = new SkillManager(this.skillLoader);
419
+ }
420
+
421
+ // MODIFY the processHailerMessage method:
422
+ async processHailerMessage(
423
+ signal: HailerSignal,
424
+ botClient: BotClient
425
+ ): Promise<void> {
426
+ // ... existing message extraction code ...
427
+
428
+ for (const message of messages) {
429
+ // ADD skill analysis before provider call:
430
+ const skillGuidance = await this.skillManager.analyzeRequest(
431
+ message.content
432
+ );
433
+
434
+ // Pass to provider with skill context
435
+ await this.processMessageWithProvider(
436
+ message,
437
+ botClient,
438
+ skillGuidance // NEW parameter
439
+ );
440
+ }
441
+ }
442
+
443
+ // MODIFY to accept skill guidance:
444
+ private async processMessageWithProvider(
445
+ message: ChatMessage,
446
+ botClient: BotClient,
447
+ skillGuidance: SkillGuidance // NEW parameter
448
+ ): Promise<void> {
449
+ // ... existing provider selection code ...
450
+
451
+ // Pass skill guidance to provider
452
+ await provider.processMessage(message, skillGuidance);
453
+ }
454
+ }
455
+ ```
456
+
457
+ ## Step 4: Modify LLM Providers
458
+
459
+ **Files**:
460
+ - `server/src/client/providers/openai-provider.ts`
461
+ - `server/src/client/providers/anthropic-provider.ts`
462
+
463
+ **Time**: ~15 minutes total
464
+ **Purpose**: Use skill content in system prompts
465
+
466
+ ### Changes for OpenAI Provider
467
+
468
+ ```typescript
469
+ import { SkillGuidance } from '../skill-manager';
470
+
471
+ export class OpenAIProvider extends LlmProvider {
472
+ // MODIFY processMessage to accept skill guidance:
473
+ async processMessage(
474
+ message: ChatMessage,
475
+ skillGuidance?: SkillGuidance // NEW optional parameter
476
+ ): Promise<void> {
477
+ // Build enhanced system prompt
478
+ const systemPrompt = this.buildSystemPrompt(skillGuidance);
479
+
480
+ // ... rest of existing code uses systemPrompt ...
481
+ }
482
+
483
+ // ADD method to build enhanced system prompt:
484
+ private buildSystemPrompt(skillGuidance?: SkillGuidance): string {
485
+ let prompt = `You are an AI assistant for Hailer workflow management.
486
+
487
+ You have access to MCP tools that can interact with the Hailer platform.
488
+ Use these tools to help users effectively.`;
489
+
490
+ // Add skill content if available
491
+ if (skillGuidance?.skillContent) {
492
+ prompt += `\n\n**DOMAIN EXPERTISE FOR THIS REQUEST:**
493
+ ${skillGuidance.skillContent}
494
+
495
+ **GUIDANCE:**
496
+ ${skillGuidance.guidance}`;
497
+
498
+ if (skillGuidance.recommendedTools.length > 0) {
499
+ prompt += `\n\n**RECOMMENDED TOOLS:**
500
+ ${skillGuidance.recommendedTools.join(', ')}
501
+
502
+ Consider using these tools to best address the user's request.`;
503
+ }
504
+ }
505
+
506
+ return prompt;
507
+ }
508
+ }
509
+ ```
510
+
511
+ ### Changes for Anthropic Provider
512
+
513
+ Same pattern - add `skillGuidance` parameter and build enhanced prompt.
514
+
515
+ ## Step 5: Testing
516
+
517
+ **Time**: ~10 minutes
518
+
519
+ ### Unit Tests
520
+
521
+ ```typescript
522
+ // test/skill-loader.test.ts
523
+ describe('SkillLoader', () => {
524
+ it('should load skill from disk', async () => {
525
+ const loader = new SkillLoader();
526
+ const skill = await loader.load('mcp-tools');
527
+ expect(skill.name).toBe('mcp-tools');
528
+ expect(skill.content).toContain('workflow');
529
+ });
530
+
531
+ it('should cache skills', async () => {
532
+ const loader = new SkillLoader();
533
+ const skill1 = await loader.load('mcp-tools');
534
+ const skill2 = await loader.load('mcp-tools');
535
+ expect(skill1.loadedAt).toBe(skill2.loadedAt);
536
+ });
537
+ });
538
+
539
+ // test/skill-manager.test.ts
540
+ describe('SkillManager', () => {
541
+ it('should select workflow skill for workflow requests', async () => {
542
+ const loader = new SkillLoader();
543
+ const manager = new SkillManager(loader);
544
+
545
+ const guidance = await manager.analyzeRequest("create a workflow");
546
+ expect(guidance.skills).toContain('mcp-tools');
547
+ });
548
+ });
549
+ ```
550
+
551
+ ### Integration Test
552
+
553
+ ```bash
554
+ # Start server
555
+ cd server && npm run dev
556
+
557
+ # In another terminal, test with Hailer
558
+ # Send message: "Help me create a workflow"
559
+ # Verify response includes workflow expertise
560
+ ```
561
+
562
+ ## Rollback Plan
563
+
564
+ If something goes wrong:
565
+
566
+ ```bash
567
+ # Remove new files
568
+ rm server/src/client/skill-loader.ts
569
+ rm server/src/client/skill-manager.ts
570
+
571
+ # Revert modified files
572
+ git checkout server/src/client/message-processor.ts
573
+ git checkout server/src/client/providers/
574
+
575
+ # Restart server
576
+ npm run dev
577
+ ```
578
+
579
+ ## Configuration
580
+
581
+ No configuration changes needed! The system works with existing `.env.local`.
582
+
583
+ Optional: Add skill configuration to `.env.local`:
584
+
585
+ ```bash
586
+ # Optional: Configure available skills
587
+ AVAILABLE_SKILLS=mcp-tools,hailer-api,data-analysis,agent-building
588
+ ```
589
+
590
+ ## Deployment Checklist
591
+
592
+ - [ ] SkillLoader implemented and tested
593
+ - [ ] SkillManager implemented and tested
594
+ - [ ] Message processor modified
595
+ - [ ] LLM providers modified
596
+ - [ ] Unit tests passing
597
+ - [ ] Integration tests passing
598
+ - [ ] Skills exist in `.claude/skills/` directory
599
+ - [ ] Server starts without errors
600
+ - [ ] Test messages produce skill-enhanced responses
601
+ - [ ] Performance overhead < 100ms
602
+ - [ ] No breaking changes to existing functionality
603
+
604
+ ## Next Steps After Implementation
605
+
606
+ 1. Monitor skill selection accuracy
607
+ 2. Add more keyword mappings based on usage
608
+ 3. Create additional skills as needed
609
+ 4. Implement skill usage analytics
610
+ 5. A/B test responses with/without skills
611
+
612
+ ## Support
613
+
614
+ If you encounter issues:
615
+ 1. Check logs for skill loading errors
616
+ 2. Verify skill files exist and are readable
617
+ 3. Test skill loader and manager independently
618
+ 4. Review keyword mappings
619
+ 5. Check for TypeScript compilation errors