@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,100 @@
1
+ "use strict";
2
+ /**
3
+ * Simple LLM Caller for Adaptive Documentation Bot
4
+ *
5
+ * Provides basic LLM API calls without the full MCP provider infrastructure.
6
+ * Used for analyzing errors and generating improvements.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.SimpleLLMCaller = void 0;
10
+ const logger_1 = require("../lib/logger");
11
+ const logger = (0, logger_1.createLogger)({ component: 'SimpleLLMCaller' });
12
+ class SimpleLLMCaller {
13
+ apiKey;
14
+ model;
15
+ provider;
16
+ constructor(provider, apiKey, model) {
17
+ this.provider = provider;
18
+ this.apiKey = apiKey;
19
+ this.model = model || (provider === 'anthropic' ? 'claude-3-5-haiku-20241022' : 'gpt-4o-mini');
20
+ }
21
+ /**
22
+ * Simple LLM call for text generation
23
+ */
24
+ async generate(prompt, systemPrompt) {
25
+ if (this.provider === 'anthropic') {
26
+ return this.callAnthropic(prompt, systemPrompt);
27
+ }
28
+ else {
29
+ return this.callOpenAI(prompt, systemPrompt);
30
+ }
31
+ }
32
+ async callAnthropic(prompt, systemPrompt) {
33
+ try {
34
+ const response = await fetch('https://api.anthropic.com/v1/messages', {
35
+ method: 'POST',
36
+ headers: {
37
+ 'Content-Type': 'application/json',
38
+ 'x-api-key': this.apiKey,
39
+ 'anthropic-version': '2023-06-01'
40
+ },
41
+ body: JSON.stringify({
42
+ model: this.model,
43
+ max_tokens: 2000,
44
+ system: systemPrompt || 'You are a helpful assistant.',
45
+ messages: [
46
+ {
47
+ role: 'user',
48
+ content: prompt
49
+ }
50
+ ]
51
+ })
52
+ });
53
+ if (!response.ok) {
54
+ throw new Error(`Anthropic API error: ${response.status} ${response.statusText}`);
55
+ }
56
+ const data = await response.json();
57
+ return data.content[0].text;
58
+ }
59
+ catch (error) {
60
+ logger.error('Anthropic API call failed', error);
61
+ throw error;
62
+ }
63
+ }
64
+ async callOpenAI(prompt, systemPrompt) {
65
+ try {
66
+ const response = await fetch('https://api.openai.com/v1/chat/completions', {
67
+ method: 'POST',
68
+ headers: {
69
+ 'Content-Type': 'application/json',
70
+ 'Authorization': `Bearer ${this.apiKey}`
71
+ },
72
+ body: JSON.stringify({
73
+ model: this.model,
74
+ messages: [
75
+ {
76
+ role: 'system',
77
+ content: systemPrompt || 'You are a helpful assistant.'
78
+ },
79
+ {
80
+ role: 'user',
81
+ content: prompt
82
+ }
83
+ ],
84
+ max_tokens: 2000
85
+ })
86
+ });
87
+ if (!response.ok) {
88
+ throw new Error(`OpenAI API error: ${response.status} ${response.statusText}`);
89
+ }
90
+ const data = await response.json();
91
+ return data.choices[0].message.content;
92
+ }
93
+ catch (error) {
94
+ logger.error('OpenAI API call failed', error);
95
+ throw error;
96
+ }
97
+ }
98
+ }
99
+ exports.SimpleLLMCaller = SimpleLLMCaller;
100
+ //# sourceMappingURL=simple-llm-caller.js.map
@@ -0,0 +1,81 @@
1
+ /**
2
+ * Skill Generator for Adaptive Documentation Bot
3
+ *
4
+ * Automatically creates and updates Claude Code skill documents
5
+ * based on common LLM mistakes and error patterns.
6
+ */
7
+ import { ErrorPattern } from './adaptive-documentation-types';
8
+ export declare class SkillGenerator {
9
+ private skillsDir;
10
+ private mistakesByTool;
11
+ /**
12
+ * Update or create skill for a tool with common mistakes
13
+ */
14
+ updateOrCreateSkill(toolName: string, errorPattern: ErrorPattern, incorrectExample: any, correctExample: any): Promise<boolean>;
15
+ /**
16
+ * Load existing skill or create template
17
+ */
18
+ private loadOrCreateSkill;
19
+ /**
20
+ * Create initial skill template
21
+ */
22
+ private createSkillTemplate;
23
+ /**
24
+ * Add mistake section to skill content
25
+ */
26
+ private addMistakeToSkill;
27
+ /**
28
+ * Generate markdown section for a mistake
29
+ */
30
+ private generateMistakeSection;
31
+ /**
32
+ * Generate skill summary with statistics
33
+ */
34
+ generateSkillSummary(toolName: string): Promise<string>;
35
+ /**
36
+ * Update skill summary section
37
+ */
38
+ updateSkillSummary(toolName: string): Promise<void>;
39
+ /**
40
+ * Get list of all skills created by this generator
41
+ */
42
+ getGeneratedSkills(): Promise<string[]>;
43
+ /**
44
+ * Track mistake for statistics
45
+ */
46
+ private trackMistake;
47
+ /**
48
+ * Get mistake count for a tool
49
+ */
50
+ private getMistakeCount;
51
+ /**
52
+ * Find existing skill for a tool
53
+ * Checks for patterns like: install-workflow-skill, install_workflow-skill, etc.
54
+ */
55
+ private findExistingSkill;
56
+ /**
57
+ * Convert tool name to kebab-case for skill directory names
58
+ */
59
+ private toKebabCase;
60
+ /**
61
+ * Convert tool name to title case
62
+ */
63
+ private toTitleCase;
64
+ /**
65
+ * Ensure directory exists
66
+ */
67
+ private ensureDirectory;
68
+ /**
69
+ * Check if file exists
70
+ */
71
+ private fileExists;
72
+ /**
73
+ * Get statistics about generated skills
74
+ */
75
+ getStats(): {
76
+ totalSkills: number;
77
+ totalMistakes: number;
78
+ mistakesByTool: Record<string, number>;
79
+ };
80
+ }
81
+ //# sourceMappingURL=skill-generator.d.ts.map
@@ -0,0 +1,386 @@
1
+ "use strict";
2
+ /**
3
+ * Skill Generator for Adaptive Documentation Bot
4
+ *
5
+ * Automatically creates and updates Claude Code skill documents
6
+ * based on common LLM mistakes and error patterns.
7
+ */
8
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
9
+ if (k2 === undefined) k2 = k;
10
+ var desc = Object.getOwnPropertyDescriptor(m, k);
11
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
12
+ desc = { enumerable: true, get: function() { return m[k]; } };
13
+ }
14
+ Object.defineProperty(o, k2, desc);
15
+ }) : (function(o, m, k, k2) {
16
+ if (k2 === undefined) k2 = k;
17
+ o[k2] = m[k];
18
+ }));
19
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
20
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
21
+ }) : function(o, v) {
22
+ o["default"] = v;
23
+ });
24
+ var __importStar = (this && this.__importStar) || (function () {
25
+ var ownKeys = function(o) {
26
+ ownKeys = Object.getOwnPropertyNames || function (o) {
27
+ var ar = [];
28
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
29
+ return ar;
30
+ };
31
+ return ownKeys(o);
32
+ };
33
+ return function (mod) {
34
+ if (mod && mod.__esModule) return mod;
35
+ var result = {};
36
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
37
+ __setModuleDefault(result, mod);
38
+ return result;
39
+ };
40
+ })();
41
+ Object.defineProperty(exports, "__esModule", { value: true });
42
+ exports.SkillGenerator = void 0;
43
+ const logger_1 = require("../lib/logger");
44
+ const fs = __importStar(require("fs/promises"));
45
+ const path = __importStar(require("path"));
46
+ const logger = (0, logger_1.createLogger)({ component: 'SkillGenerator' });
47
+ class SkillGenerator {
48
+ skillsDir = '.claude/skills';
49
+ mistakesByTool = new Map();
50
+ /**
51
+ * Update or create skill for a tool with common mistakes
52
+ */
53
+ async updateOrCreateSkill(toolName, errorPattern, incorrectExample, correctExample) {
54
+ try {
55
+ // First, check if an existing skill exists for this tool
56
+ const existingSkill = await this.findExistingSkill(toolName);
57
+ let skillPath;
58
+ let skillFile;
59
+ if (existingSkill) {
60
+ // Update existing skill
61
+ skillPath = existingSkill.path;
62
+ skillFile = existingSkill.file;
63
+ logger.info('Found existing skill, will update it', {
64
+ toolName,
65
+ existingSkill: existingSkill.name
66
+ });
67
+ }
68
+ else {
69
+ // Create new -common-mistakes skill
70
+ skillPath = path.join(this.skillsDir, `${this.toKebabCase(toolName)}-common-mistakes`);
71
+ skillFile = path.join(skillPath, 'SKILL.md');
72
+ logger.info('No existing skill found, creating new one', {
73
+ toolName,
74
+ skillPath
75
+ });
76
+ }
77
+ // Ensure directory exists
78
+ await this.ensureDirectory(skillPath);
79
+ // Load or create skill content
80
+ let skillContent = await this.loadOrCreateSkill(skillFile, toolName);
81
+ // Create mistake section
82
+ const mistake = {
83
+ title: errorPattern.description,
84
+ frequency: errorPattern.count,
85
+ lastSeen: errorPattern.lastSeen,
86
+ wrongExample: incorrectExample,
87
+ correctExample: correctExample,
88
+ explanation: errorPattern.rootCause || 'Common mistake detected from LLM usage'
89
+ };
90
+ // Add mistake to the skill
91
+ skillContent = this.addMistakeToSkill(skillContent, mistake);
92
+ // Write back to file
93
+ await fs.writeFile(skillFile, skillContent, 'utf-8');
94
+ logger.info('โœ… Skill updated', {
95
+ toolName,
96
+ skillPath,
97
+ mistakeCount: this.getMistakeCount(toolName) + 1
98
+ });
99
+ // Track mistake
100
+ this.trackMistake(toolName, mistake);
101
+ return true;
102
+ }
103
+ catch (error) {
104
+ logger.error('Failed to update skill', error, { toolName });
105
+ return false;
106
+ }
107
+ }
108
+ /**
109
+ * Load existing skill or create template
110
+ */
111
+ async loadOrCreateSkill(skillFile, toolName) {
112
+ try {
113
+ const exists = await this.fileExists(skillFile);
114
+ if (exists) {
115
+ return await fs.readFile(skillFile, 'utf-8');
116
+ }
117
+ // Create new skill template
118
+ return this.createSkillTemplate(toolName);
119
+ }
120
+ catch (error) {
121
+ return this.createSkillTemplate(toolName);
122
+ }
123
+ }
124
+ /**
125
+ * Create initial skill template
126
+ */
127
+ createSkillTemplate(toolName) {
128
+ return `# ${this.toTitleCase(toolName)} - Common Mistakes
129
+
130
+ This skill document is automatically generated and updated by the Adaptive Documentation Bot.
131
+ It contains common mistakes made by LLMs when using the \`${toolName}\` tool, based on real usage errors.
132
+
133
+ ## Purpose
134
+
135
+ Help Claude Code avoid common mistakes when calling the \`${toolName}\` tool by documenting:
136
+ - Incorrect usage patterns that have caused errors
137
+ - Correct usage examples
138
+ - Why these mistakes happen
139
+ - How to avoid them
140
+
141
+ ---
142
+
143
+ ## Common Mistakes
144
+
145
+ `;
146
+ }
147
+ /**
148
+ * Add mistake section to skill content
149
+ */
150
+ addMistakeToSkill(skillContent, mistake) {
151
+ const mistakeSection = this.generateMistakeSection(mistake);
152
+ // Try to find existing "## Common Mistakes" section
153
+ const commonMistakesMarker = '## Common Mistakes';
154
+ const hasCommonMistakes = skillContent.includes(commonMistakesMarker);
155
+ if (hasCommonMistakes) {
156
+ // Insert after existing "## Common Mistakes" header
157
+ const insertMarker = commonMistakesMarker + '\n\n';
158
+ const insertIndex = skillContent.indexOf(insertMarker);
159
+ if (insertIndex !== -1) {
160
+ const beforeInsert = skillContent.substring(0, insertIndex + insertMarker.length);
161
+ const afterInsert = skillContent.substring(insertIndex + insertMarker.length);
162
+ return beforeInsert + mistakeSection + '\n' + afterInsert;
163
+ }
164
+ }
165
+ // No "## Common Mistakes" section exists - add one at the end
166
+ const newSection = `\n\n---\n\n## Common Mistakes\n\n${mistakeSection}`;
167
+ return skillContent + newSection;
168
+ }
169
+ /**
170
+ * Generate markdown section for a mistake
171
+ */
172
+ generateMistakeSection(mistake) {
173
+ const dateStr = new Date(mistake.lastSeen).toISOString().split('T')[0];
174
+ return `### โŒ ${mistake.title}
175
+
176
+ **Frequency**: Seen ${mistake.frequency} times
177
+ **Last occurrence**: ${dateStr}
178
+
179
+ **Why this happens**: ${mistake.explanation}
180
+
181
+ **โŒ Wrong:**
182
+ \`\`\`json
183
+ ${JSON.stringify(mistake.wrongExample, null, 2)}
184
+ \`\`\`
185
+
186
+ **โœ… Correct:**
187
+ \`\`\`json
188
+ ${JSON.stringify(mistake.correctExample, null, 2)}
189
+ \`\`\`
190
+
191
+ ---
192
+ `;
193
+ }
194
+ /**
195
+ * Generate skill summary with statistics
196
+ */
197
+ async generateSkillSummary(toolName) {
198
+ const mistakes = this.mistakesByTool.get(toolName) || [];
199
+ if (mistakes.length === 0) {
200
+ return `No common mistakes recorded yet for ${toolName}.`;
201
+ }
202
+ const totalFrequency = mistakes.reduce((sum, m) => sum + m.frequency, 0);
203
+ const mostRecent = Math.max(...mistakes.map(m => m.lastSeen));
204
+ return `## Summary
205
+
206
+ **Total mistake types**: ${mistakes.length}
207
+ **Total occurrences**: ${totalFrequency}
208
+ **Last updated**: ${new Date(mostRecent).toISOString().split('T')[0]}
209
+
210
+ ### Most Common Mistakes
211
+
212
+ ${mistakes
213
+ .sort((a, b) => b.frequency - a.frequency)
214
+ .slice(0, 5)
215
+ .map((m, i) => `${i + 1}. ${m.title} (${m.frequency} times)`)
216
+ .join('\n')}
217
+ `;
218
+ }
219
+ /**
220
+ * Update skill summary section
221
+ */
222
+ async updateSkillSummary(toolName) {
223
+ const skillPath = path.join(this.skillsDir, `${toolName}-common-mistakes`, 'SKILL.md');
224
+ try {
225
+ const exists = await this.fileExists(skillPath);
226
+ if (!exists)
227
+ return;
228
+ let content = await fs.readFile(skillPath, 'utf-8');
229
+ const summary = await this.generateSkillSummary(toolName);
230
+ // Replace or append summary
231
+ const summaryMarker = '## Summary';
232
+ if (content.includes(summaryMarker)) {
233
+ // Replace existing summary
234
+ content = content.replace(/## Summary[\s\S]*?(?=##|$)/, summary + '\n\n');
235
+ }
236
+ else {
237
+ // Append summary after header
238
+ const headerEnd = content.indexOf('---\n\n## Common Mistakes');
239
+ if (headerEnd !== -1) {
240
+ content = content.substring(0, headerEnd) +
241
+ '---\n\n' + summary + '\n\n## Common Mistakes' +
242
+ content.substring(headerEnd + '---\n\n## Common Mistakes'.length);
243
+ }
244
+ }
245
+ await fs.writeFile(skillPath, content, 'utf-8');
246
+ }
247
+ catch (error) {
248
+ logger.error('Failed to update skill summary', error, { toolName });
249
+ }
250
+ }
251
+ /**
252
+ * Get list of all skills created by this generator
253
+ */
254
+ async getGeneratedSkills() {
255
+ try {
256
+ const exists = await this.fileExists(this.skillsDir);
257
+ if (!exists)
258
+ return [];
259
+ const entries = await fs.readdir(this.skillsDir, { withFileTypes: true });
260
+ return entries
261
+ .filter(entry => entry.isDirectory() && entry.name.endsWith('-common-mistakes'))
262
+ .map(entry => entry.name.replace('-common-mistakes', ''));
263
+ }
264
+ catch (error) {
265
+ logger.error('Failed to get generated skills', error);
266
+ return [];
267
+ }
268
+ }
269
+ /**
270
+ * Track mistake for statistics
271
+ */
272
+ trackMistake(toolName, mistake) {
273
+ const mistakes = this.mistakesByTool.get(toolName) || [];
274
+ mistakes.push(mistake);
275
+ this.mistakesByTool.set(toolName, mistakes);
276
+ }
277
+ /**
278
+ * Get mistake count for a tool
279
+ */
280
+ getMistakeCount(toolName) {
281
+ return (this.mistakesByTool.get(toolName) || []).length;
282
+ }
283
+ /**
284
+ * Find existing skill for a tool
285
+ * Checks for patterns like: install-workflow-skill, install_workflow-skill, etc.
286
+ */
287
+ async findExistingSkill(toolName) {
288
+ try {
289
+ const exists = await this.fileExists(this.skillsDir);
290
+ if (!exists)
291
+ return null;
292
+ const entries = await fs.readdir(this.skillsDir, { withFileTypes: true });
293
+ // Convert tool name to kebab case for matching
294
+ const kebabToolName = this.toKebabCase(toolName);
295
+ // Try different naming patterns
296
+ const patterns = [
297
+ `${kebabToolName}-skill`, // install-workflow-skill
298
+ `${kebabToolName}`, // install-workflow
299
+ toolName.replace(/_/g, '-') + '-skill', // direct conversion
300
+ ];
301
+ for (const entry of entries) {
302
+ if (!entry.isDirectory())
303
+ continue;
304
+ // Check if directory name matches any pattern
305
+ for (const pattern of patterns) {
306
+ if (entry.name === pattern || entry.name.startsWith(pattern)) {
307
+ const skillPath = path.join(this.skillsDir, entry.name);
308
+ const skillFile = path.join(skillPath, 'SKILL.md');
309
+ // Verify SKILL.md exists
310
+ const skillExists = await this.fileExists(skillFile);
311
+ if (skillExists) {
312
+ return {
313
+ name: entry.name,
314
+ path: skillPath,
315
+ file: skillFile
316
+ };
317
+ }
318
+ }
319
+ }
320
+ }
321
+ return null;
322
+ }
323
+ catch (error) {
324
+ logger.error('Failed to find existing skill', error, { toolName });
325
+ return null;
326
+ }
327
+ }
328
+ /**
329
+ * Convert tool name to kebab-case for skill directory names
330
+ */
331
+ toKebabCase(str) {
332
+ return str
333
+ .replace(/_/g, '-')
334
+ .toLowerCase();
335
+ }
336
+ /**
337
+ * Convert tool name to title case
338
+ */
339
+ toTitleCase(str) {
340
+ return str
341
+ .split('_')
342
+ .map(word => word.charAt(0).toUpperCase() + word.slice(1))
343
+ .join(' ');
344
+ }
345
+ /**
346
+ * Ensure directory exists
347
+ */
348
+ async ensureDirectory(dir) {
349
+ try {
350
+ await fs.mkdir(dir, { recursive: true });
351
+ }
352
+ catch (error) {
353
+ // Directory might already exist
354
+ }
355
+ }
356
+ /**
357
+ * Check if file exists
358
+ */
359
+ async fileExists(filePath) {
360
+ try {
361
+ await fs.access(filePath);
362
+ return true;
363
+ }
364
+ catch {
365
+ return false;
366
+ }
367
+ }
368
+ /**
369
+ * Get statistics about generated skills
370
+ */
371
+ getStats() {
372
+ const mistakesByTool = {};
373
+ let totalMistakes = 0;
374
+ for (const [toolName, mistakes] of this.mistakesByTool.entries()) {
375
+ mistakesByTool[toolName] = mistakes.length;
376
+ totalMistakes += mistakes.length;
377
+ }
378
+ return {
379
+ totalSkills: this.mistakesByTool.size,
380
+ totalMistakes,
381
+ mistakesByTool
382
+ };
383
+ }
384
+ }
385
+ exports.SkillGenerator = SkillGenerator;
386
+ //# sourceMappingURL=skill-generator.js.map
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Test script for Adaptive Documentation Bot
3
+ *
4
+ * Run this to see what the bot would do without actually modifying files:
5
+ *
6
+ * npx tsx server/src/client/test-adaptive-bot.ts
7
+ */
8
+ export {};
9
+ //# sourceMappingURL=test-adaptive-bot.d.ts.map
@@ -0,0 +1,82 @@
1
+ "use strict";
2
+ /**
3
+ * Test script for Adaptive Documentation Bot
4
+ *
5
+ * Run this to see what the bot would do without actually modifying files:
6
+ *
7
+ * npx tsx server/src/client/test-adaptive-bot.ts
8
+ */
9
+ var __importDefault = (this && this.__importDefault) || function (mod) {
10
+ return (mod && mod.__esModule) ? mod : { "default": mod };
11
+ };
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ const dotenv_1 = require("dotenv");
14
+ const path_1 = __importDefault(require("path"));
15
+ const adaptive_documentation_bot_1 = require("./adaptive-documentation-bot");
16
+ // Load environment variables from server/.env.local
17
+ // When running with tsx, __dirname is the source directory, so go up to server root
18
+ (0, dotenv_1.config)({ path: path_1.default.resolve(process.cwd(), '.env.local') });
19
+ async function testAdaptiveBot() {
20
+ console.log('๐Ÿงช Testing Adaptive Documentation Bot\n');
21
+ // Check if Anthropic API key is available
22
+ if (!process.env.ANTHROPIC_API_KEY) {
23
+ console.error('โŒ ANTHROPIC_API_KEY not found in environment');
24
+ console.log('Set it in .env.local to test with LLM analysis');
25
+ process.exit(1);
26
+ }
27
+ // Create bot instance with auto-update DISABLED
28
+ const bot = new adaptive_documentation_bot_1.AdaptiveDocumentationBot(process.env.ANTHROPIC_API_KEY, 'anthropic', {
29
+ enabled: true,
30
+ autoUpdate: false, // IMPORTANT: Don't modify files during test
31
+ updateInterval: 0,
32
+ minErrorCount: 1, // Lower threshold for testing
33
+ skillGeneration: true
34
+ });
35
+ console.log('๐Ÿ“Š Analyzing recent logs...\n');
36
+ try {
37
+ const result = await bot.testRun();
38
+ console.log(`Found ${result.errors.length} errors in logs`);
39
+ console.log(`Detected ${result.patterns.length} error patterns\n`);
40
+ if (result.suggestions.length === 0) {
41
+ console.log('โœ… No improvements needed (no errors detected)');
42
+ console.log('\nTo test the bot:');
43
+ console.log('1. Trigger some tool errors (e.g., call list_activities without fields)');
44
+ console.log('2. Wait a moment for logs to be written');
45
+ console.log('3. Run this script again');
46
+ return;
47
+ }
48
+ console.log('๐Ÿ”ง Suggested Improvements:\n');
49
+ console.log('='.repeat(80));
50
+ for (const suggestion of result.suggestions) {
51
+ console.log(`\nTool: ${suggestion.toolName}`);
52
+ console.log(`Error: "${suggestion.errorMessage}"`);
53
+ console.log(`Frequency: ${suggestion.errorCount} time(s)`);
54
+ if (suggestion.existingSkill) {
55
+ console.log(`โœ… Existing skill found: ${suggestion.existingSkill}`);
56
+ console.log(` โ†’ Would UPDATE existing skill with Common Mistakes section`);
57
+ }
58
+ else {
59
+ console.log(`โŒ No existing skill found`);
60
+ console.log(` โ†’ Would CREATE new skill: ${suggestion.toolName}-common-mistakes`);
61
+ }
62
+ console.log('-'.repeat(80));
63
+ }
64
+ console.log('\n๐Ÿ“‹ Summary:');
65
+ console.log(`- Total errors: ${result.errors.length}`);
66
+ console.log(`- Unique patterns: ${result.patterns.length}`);
67
+ console.log(`- Tools needing improvement: ${result.suggestions.length}`);
68
+ console.log(`- Would update existing skills: ${result.suggestions.filter(s => s.wouldUpdateSkill).length}`);
69
+ console.log(`- Would create new skills: ${result.suggestions.filter(s => s.wouldCreateSkill).length}`);
70
+ console.log('\n๐Ÿ’ก To enable auto-improvements:');
71
+ console.log('1. Review the suggestions above');
72
+ console.log('2. Set ADAPTIVE_AUTO_UPDATE=true in .env.local');
73
+ console.log('3. Restart the MCP server');
74
+ }
75
+ catch (error) {
76
+ console.error('โŒ Test failed:', error);
77
+ process.exit(1);
78
+ }
79
+ }
80
+ // Run test
81
+ testAdaptiveBot().catch(console.error);
82
+ //# sourceMappingURL=test-adaptive-bot.js.map
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Token Pricing Utility
3
+ *
4
+ * Calculates cost estimates for LLM API usage based on token consumption.
5
+ * Pricing data is accurate as of January 2025 and should be updated periodically.
6
+ *
7
+ * Anthropic pricing: https://www.anthropic.com/pricing
8
+ * OpenAI pricing: https://openai.com/pricing
9
+ */
10
+ /**
11
+ * Token usage from API response
12
+ */
13
+ export interface TokenUsage {
14
+ input_tokens: number;
15
+ output_tokens: number;
16
+ cache_creation_input_tokens?: number;
17
+ cache_read_input_tokens?: number;
18
+ }
19
+ /**
20
+ * Calculate the cost of token usage for a specific model
21
+ *
22
+ * @param usage - Token usage from API response
23
+ * @param model - Model identifier (e.g., "claude-sonnet-4-20250514")
24
+ * @returns Estimated cost in USD
25
+ *
26
+ * @example
27
+ * ```typescript
28
+ * const usage = {
29
+ * input_tokens: 24567,
30
+ * output_tokens: 412,
31
+ * cache_read_input_tokens: 22000
32
+ * };
33
+ * const cost = calculateTokenCost(usage, 'claude-sonnet-4-20250514');
34
+ * // Returns: 0.038
35
+ * ```
36
+ */
37
+ export declare function calculateTokenCost(usage: TokenUsage, model: string): number;
38
+ //# sourceMappingURL=token-pricing.d.ts.map