@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.
- package/.claude/commands/tool-builder.md +37 -0
- package/.claude/commands/ws-pull.md +44 -0
- package/.claude/settings.json +8 -0
- package/.claude/settings.local.json +49 -0
- package/.claude/skills/activity-api/SKILL.md +96 -0
- package/.claude/skills/activity-api/references/activity-endpoints.md +845 -0
- package/.claude/skills/add-app-member-skill/SKILL.md +977 -0
- package/.claude/skills/agent-building/SKILL.md +243 -0
- package/.claude/skills/agent-building/references/architecture-patterns.md +446 -0
- package/.claude/skills/agent-building/references/code-examples.md +587 -0
- package/.claude/skills/agent-building/references/implementation-guide.md +619 -0
- package/.claude/skills/app-api/SKILL.md +219 -0
- package/.claude/skills/app-api/references/app-endpoints.md +759 -0
- package/.claude/skills/building-hailer-apps-skill/SKILL.md +548 -0
- package/.claude/skills/create-app-skill/SKILL.md +1101 -0
- package/.claude/skills/create-insight-skill/SKILL.md +1317 -0
- package/.claude/skills/get-insight-data-skill/SKILL.md +1053 -0
- package/.claude/skills/hailer-api/SKILL.md +283 -0
- package/.claude/skills/hailer-api/references/activities.md +620 -0
- package/.claude/skills/hailer-api/references/authentication.md +216 -0
- package/.claude/skills/hailer-api/references/datasets.md +437 -0
- package/.claude/skills/hailer-api/references/files.md +301 -0
- package/.claude/skills/hailer-api/references/insights.md +469 -0
- package/.claude/skills/hailer-api/references/workflows.md +720 -0
- package/.claude/skills/hailer-api/references/workspaces-users.md +445 -0
- package/.claude/skills/insight-api/SKILL.md +185 -0
- package/.claude/skills/insight-api/references/insight-endpoints.md +514 -0
- package/.claude/skills/install-workflow-skill/SKILL.md +1056 -0
- package/.claude/skills/list-apps-skill/SKILL.md +1010 -0
- package/.claude/skills/list-workflows-minimal-skill/SKILL.md +992 -0
- package/.claude/skills/local-first-skill/SKILL.md +570 -0
- package/.claude/skills/mcp-tools/SKILL.md +419 -0
- package/.claude/skills/mcp-tools/references/api-endpoints.md +499 -0
- package/.claude/skills/mcp-tools/references/data-structures.md +554 -0
- package/.claude/skills/mcp-tools/references/implementation-patterns.md +717 -0
- package/.claude/skills/preview-insight-skill/SKILL.md +1290 -0
- package/.claude/skills/publish-hailer-app-skill/SKILL.md +453 -0
- package/.claude/skills/remove-app-member-skill/SKILL.md +671 -0
- package/.claude/skills/remove-app-skill/SKILL.md +985 -0
- package/.claude/skills/remove-insight-skill/SKILL.md +1011 -0
- package/.claude/skills/remove-workflow-skill/SKILL.md +920 -0
- package/.claude/skills/scaffold-hailer-app-skill/SKILL.md +1034 -0
- package/.claude/skills/skill-testing/README.md +137 -0
- package/.claude/skills/skill-testing/SKILL.md +348 -0
- package/.claude/skills/skill-testing/references/test-patterns.md +705 -0
- package/.claude/skills/skill-testing/references/testing-guide.md +603 -0
- package/.claude/skills/skill-testing/references/validation-checklist.md +537 -0
- package/.claude/skills/tool-builder/SKILL.md +328 -0
- package/.claude/skills/update-app-skill/SKILL.md +970 -0
- package/.claude/skills/update-workflow-field-skill/SKILL.md +1098 -0
- package/.env.example +81 -0
- package/.mcp.json +13 -0
- package/README.md +297 -0
- package/dist/app.d.ts +4 -0
- package/dist/app.js +74 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.js +5 -0
- package/dist/client/adaptive-documentation-bot.d.ts +108 -0
- package/dist/client/adaptive-documentation-bot.js +475 -0
- package/dist/client/adaptive-documentation-types.d.ts +66 -0
- package/dist/client/adaptive-documentation-types.js +9 -0
- package/dist/client/agent-activity-bot.d.ts +51 -0
- package/dist/client/agent-activity-bot.js +166 -0
- package/dist/client/agent-tracker.d.ts +499 -0
- package/dist/client/agent-tracker.js +659 -0
- package/dist/client/description-updater.d.ts +56 -0
- package/dist/client/description-updater.js +259 -0
- package/dist/client/log-parser.d.ts +72 -0
- package/dist/client/log-parser.js +387 -0
- package/dist/client/mcp-client.d.ts +50 -0
- package/dist/client/mcp-client.js +532 -0
- package/dist/client/message-processor.d.ts +35 -0
- package/dist/client/message-processor.js +352 -0
- package/dist/client/multi-bot-manager.d.ts +24 -0
- package/dist/client/multi-bot-manager.js +74 -0
- package/dist/client/providers/anthropic-provider.d.ts +19 -0
- package/dist/client/providers/anthropic-provider.js +631 -0
- package/dist/client/providers/llm-provider.d.ts +47 -0
- package/dist/client/providers/llm-provider.js +367 -0
- package/dist/client/providers/openai-provider.d.ts +23 -0
- package/dist/client/providers/openai-provider.js +621 -0
- package/dist/client/simple-llm-caller.d.ts +19 -0
- package/dist/client/simple-llm-caller.js +100 -0
- package/dist/client/skill-generator.d.ts +81 -0
- package/dist/client/skill-generator.js +386 -0
- package/dist/client/test-adaptive-bot.d.ts +9 -0
- package/dist/client/test-adaptive-bot.js +82 -0
- package/dist/client/token-pricing.d.ts +38 -0
- package/dist/client/token-pricing.js +127 -0
- package/dist/client/token-tracker.d.ts +232 -0
- package/dist/client/token-tracker.js +457 -0
- package/dist/client/token-usage-bot.d.ts +53 -0
- package/dist/client/token-usage-bot.js +153 -0
- package/dist/client/tool-executor.d.ts +69 -0
- package/dist/client/tool-executor.js +159 -0
- package/dist/client/tool-schema-loader.d.ts +60 -0
- package/dist/client/tool-schema-loader.js +178 -0
- package/dist/client/types.d.ts +69 -0
- package/dist/client/types.js +7 -0
- package/dist/config.d.ts +162 -0
- package/dist/config.js +296 -0
- package/dist/core.d.ts +26 -0
- package/dist/core.js +147 -0
- package/dist/lib/context-manager.d.ts +111 -0
- package/dist/lib/context-manager.js +431 -0
- package/dist/lib/logger.d.ts +74 -0
- package/dist/lib/logger.js +277 -0
- package/dist/lib/materialize.d.ts +3 -0
- package/dist/lib/materialize.js +101 -0
- package/dist/lib/normalizedName.d.ts +7 -0
- package/dist/lib/normalizedName.js +48 -0
- package/dist/lib/prompt-length-manager.d.ts +81 -0
- package/dist/lib/prompt-length-manager.js +457 -0
- package/dist/lib/terminal-prompt.d.ts +9 -0
- package/dist/lib/terminal-prompt.js +108 -0
- package/dist/mcp/UserContextCache.d.ts +56 -0
- package/dist/mcp/UserContextCache.js +163 -0
- package/dist/mcp/auth.d.ts +2 -0
- package/dist/mcp/auth.js +29 -0
- package/dist/mcp/hailer-clients.d.ts +42 -0
- package/dist/mcp/hailer-clients.js +246 -0
- package/dist/mcp/signal-handler.d.ts +45 -0
- package/dist/mcp/signal-handler.js +317 -0
- package/dist/mcp/tool-registry.d.ts +100 -0
- package/dist/mcp/tool-registry.js +306 -0
- package/dist/mcp/tools/activity.d.ts +15 -0
- package/dist/mcp/tools/activity.js +955 -0
- package/dist/mcp/tools/app.d.ts +20 -0
- package/dist/mcp/tools/app.js +1488 -0
- package/dist/mcp/tools/discussion.d.ts +19 -0
- package/dist/mcp/tools/discussion.js +950 -0
- package/dist/mcp/tools/file.d.ts +15 -0
- package/dist/mcp/tools/file.js +119 -0
- package/dist/mcp/tools/insight.d.ts +17 -0
- package/dist/mcp/tools/insight.js +806 -0
- package/dist/mcp/tools/skill.d.ts +10 -0
- package/dist/mcp/tools/skill.js +279 -0
- package/dist/mcp/tools/user.d.ts +10 -0
- package/dist/mcp/tools/user.js +108 -0
- package/dist/mcp/tools/workflow-template.d.ts +19 -0
- package/dist/mcp/tools/workflow-template.js +822 -0
- package/dist/mcp/tools/workflow.d.ts +18 -0
- package/dist/mcp/tools/workflow.js +1362 -0
- package/dist/mcp/utils/api-errors.d.ts +45 -0
- package/dist/mcp/utils/api-errors.js +160 -0
- package/dist/mcp/utils/data-transformers.d.ts +102 -0
- package/dist/mcp/utils/data-transformers.js +194 -0
- package/dist/mcp/utils/file-upload.d.ts +33 -0
- package/dist/mcp/utils/file-upload.js +148 -0
- package/dist/mcp/utils/hailer-api-client.d.ts +120 -0
- package/dist/mcp/utils/hailer-api-client.js +323 -0
- package/dist/mcp/utils/index.d.ts +13 -0
- package/dist/mcp/utils/index.js +39 -0
- package/dist/mcp/utils/logger.d.ts +42 -0
- package/dist/mcp/utils/logger.js +103 -0
- package/dist/mcp/utils/types.d.ts +286 -0
- package/dist/mcp/utils/types.js +7 -0
- package/dist/mcp/workspace-cache.d.ts +42 -0
- package/dist/mcp/workspace-cache.js +97 -0
- package/dist/mcp-server.d.ts +42 -0
- package/dist/mcp-server.js +280 -0
- package/package.json +56 -0
- 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,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
|