@skillsmith/mcp-server 0.1.0
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/dist/.tsbuildinfo +1 -0
- package/dist/src/__tests__/get-skill.test.d.ts +6 -0
- package/dist/src/__tests__/get-skill.test.d.ts.map +1 -0
- package/dist/src/__tests__/get-skill.test.js +88 -0
- package/dist/src/__tests__/get-skill.test.js.map +1 -0
- package/dist/src/__tests__/middleware/errorFormatter.test.d.ts +7 -0
- package/dist/src/__tests__/middleware/errorFormatter.test.d.ts.map +1 -0
- package/dist/src/__tests__/middleware/errorFormatter.test.js +304 -0
- package/dist/src/__tests__/middleware/errorFormatter.test.js.map +1 -0
- package/dist/src/__tests__/middleware/license.test.d.ts +7 -0
- package/dist/src/__tests__/middleware/license.test.d.ts.map +1 -0
- package/dist/src/__tests__/middleware/license.test.js +500 -0
- package/dist/src/__tests__/middleware/license.test.js.map +1 -0
- package/dist/src/__tests__/search.test.d.ts +6 -0
- package/dist/src/__tests__/search.test.d.ts.map +1 -0
- package/dist/src/__tests__/search.test.js +86 -0
- package/dist/src/__tests__/search.test.js.map +1 -0
- package/dist/src/__tests__/test-utils.d.ts +19 -0
- package/dist/src/__tests__/test-utils.d.ts.map +1 -0
- package/dist/src/__tests__/test-utils.js +87 -0
- package/dist/src/__tests__/test-utils.js.map +1 -0
- package/dist/src/context/index.d.ts +19 -0
- package/dist/src/context/index.d.ts.map +1 -0
- package/dist/src/context/index.js +25 -0
- package/dist/src/context/index.js.map +1 -0
- package/dist/src/context/project-detector.d.ts +145 -0
- package/dist/src/context/project-detector.d.ts.map +1 -0
- package/dist/src/context/project-detector.js +321 -0
- package/dist/src/context/project-detector.js.map +1 -0
- package/dist/src/context.d.ts +100 -0
- package/dist/src/context.d.ts.map +1 -0
- package/dist/src/context.js +157 -0
- package/dist/src/context.js.map +1 -0
- package/dist/src/core-shim.d.ts +7 -0
- package/dist/src/core-shim.d.ts.map +1 -0
- package/dist/src/core-shim.js +9 -0
- package/dist/src/core-shim.js.map +1 -0
- package/dist/src/health/healthCheck.d.ts +88 -0
- package/dist/src/health/healthCheck.d.ts.map +1 -0
- package/dist/src/health/healthCheck.js +117 -0
- package/dist/src/health/healthCheck.js.map +1 -0
- package/dist/src/health/index.d.ts +21 -0
- package/dist/src/health/index.d.ts.map +1 -0
- package/dist/src/health/index.js +21 -0
- package/dist/src/health/index.js.map +1 -0
- package/dist/src/health/readinessCheck.d.ts +139 -0
- package/dist/src/health/readinessCheck.d.ts.map +1 -0
- package/dist/src/health/readinessCheck.js +266 -0
- package/dist/src/health/readinessCheck.js.map +1 -0
- package/dist/src/index.d.ts +8 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +178 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/index.test.d.ts +2 -0
- package/dist/src/index.test.d.ts.map +1 -0
- package/dist/src/index.test.js +43 -0
- package/dist/src/index.test.js.map +1 -0
- package/dist/src/logger.d.ts +26 -0
- package/dist/src/logger.d.ts.map +1 -0
- package/dist/src/logger.js +179 -0
- package/dist/src/logger.js.map +1 -0
- package/dist/src/middleware/__tests__/csp.test.d.ts +2 -0
- package/dist/src/middleware/__tests__/csp.test.d.ts.map +1 -0
- package/dist/src/middleware/__tests__/csp.test.js +389 -0
- package/dist/src/middleware/__tests__/csp.test.js.map +1 -0
- package/dist/src/middleware/csp.d.ts +87 -0
- package/dist/src/middleware/csp.d.ts.map +1 -0
- package/dist/src/middleware/csp.js +273 -0
- package/dist/src/middleware/csp.js.map +1 -0
- package/dist/src/middleware/degradation.d.ts +99 -0
- package/dist/src/middleware/degradation.d.ts.map +1 -0
- package/dist/src/middleware/degradation.js +315 -0
- package/dist/src/middleware/degradation.js.map +1 -0
- package/dist/src/middleware/errorFormatter.d.ts +119 -0
- package/dist/src/middleware/errorFormatter.d.ts.map +1 -0
- package/dist/src/middleware/errorFormatter.js +294 -0
- package/dist/src/middleware/errorFormatter.js.map +1 -0
- package/dist/src/middleware/index.d.ts +10 -0
- package/dist/src/middleware/index.d.ts.map +1 -0
- package/dist/src/middleware/index.js +14 -0
- package/dist/src/middleware/index.js.map +1 -0
- package/dist/src/middleware/license.d.ts +161 -0
- package/dist/src/middleware/license.d.ts.map +1 -0
- package/dist/src/middleware/license.js +281 -0
- package/dist/src/middleware/license.js.map +1 -0
- package/dist/src/middleware/toolFeatureMapping.d.ts +36 -0
- package/dist/src/middleware/toolFeatureMapping.d.ts.map +1 -0
- package/dist/src/middleware/toolFeatureMapping.js +90 -0
- package/dist/src/middleware/toolFeatureMapping.js.map +1 -0
- package/dist/src/onboarding/first-run.d.ts +64 -0
- package/dist/src/onboarding/first-run.d.ts.map +1 -0
- package/dist/src/onboarding/first-run.js +77 -0
- package/dist/src/onboarding/first-run.js.map +1 -0
- package/dist/src/onboarding/index.d.ts +7 -0
- package/dist/src/onboarding/index.d.ts.map +1 -0
- package/dist/src/onboarding/index.js +7 -0
- package/dist/src/onboarding/index.js.map +1 -0
- package/dist/src/suggestions/index.d.ts +21 -0
- package/dist/src/suggestions/index.d.ts.map +1 -0
- package/dist/src/suggestions/index.js +20 -0
- package/dist/src/suggestions/index.js.map +1 -0
- package/dist/src/suggestions/suggestion-engine.d.ts +185 -0
- package/dist/src/suggestions/suggestion-engine.d.ts.map +1 -0
- package/dist/src/suggestions/suggestion-engine.js +352 -0
- package/dist/src/suggestions/suggestion-engine.js.map +1 -0
- package/dist/src/suggestions/types.d.ts +88 -0
- package/dist/src/suggestions/types.d.ts.map +1 -0
- package/dist/src/suggestions/types.js +21 -0
- package/dist/src/suggestions/types.js.map +1 -0
- package/dist/src/tools/analyze.d.ts +151 -0
- package/dist/src/tools/analyze.d.ts.map +1 -0
- package/dist/src/tools/analyze.js +205 -0
- package/dist/src/tools/analyze.js.map +1 -0
- package/dist/src/tools/compare.d.ts +149 -0
- package/dist/src/tools/compare.d.ts.map +1 -0
- package/dist/src/tools/compare.js +464 -0
- package/dist/src/tools/compare.js.map +1 -0
- package/dist/src/tools/get-skill.d.ts +116 -0
- package/dist/src/tools/get-skill.d.ts.map +1 -0
- package/dist/src/tools/get-skill.js +224 -0
- package/dist/src/tools/get-skill.js.map +1 -0
- package/dist/src/tools/index.d.ts +20 -0
- package/dist/src/tools/index.d.ts.map +1 -0
- package/dist/src/tools/index.js +20 -0
- package/dist/src/tools/index.js.map +1 -0
- package/dist/src/tools/install.d.ts +122 -0
- package/dist/src/tools/install.d.ts.map +1 -0
- package/dist/src/tools/install.js +314 -0
- package/dist/src/tools/install.js.map +1 -0
- package/dist/src/tools/recommend.d.ts +171 -0
- package/dist/src/tools/recommend.d.ts.map +1 -0
- package/dist/src/tools/recommend.js +325 -0
- package/dist/src/tools/recommend.js.map +1 -0
- package/dist/src/tools/search.d.ts +121 -0
- package/dist/src/tools/search.d.ts.map +1 -0
- package/dist/src/tools/search.js +249 -0
- package/dist/src/tools/search.js.map +1 -0
- package/dist/src/tools/suggest.d.ts +181 -0
- package/dist/src/tools/suggest.d.ts.map +1 -0
- package/dist/src/tools/suggest.js +342 -0
- package/dist/src/tools/suggest.js.map +1 -0
- package/dist/src/tools/uninstall.d.ts +123 -0
- package/dist/src/tools/uninstall.d.ts.map +1 -0
- package/dist/src/tools/uninstall.js +250 -0
- package/dist/src/tools/uninstall.js.map +1 -0
- package/dist/src/tools/validate.d.ts +122 -0
- package/dist/src/tools/validate.d.ts.map +1 -0
- package/dist/src/tools/validate.js +497 -0
- package/dist/src/tools/validate.js.map +1 -0
- package/dist/src/utils/installed-skills.d.ts +101 -0
- package/dist/src/utils/installed-skills.d.ts.map +1 -0
- package/dist/src/utils/installed-skills.js +220 -0
- package/dist/src/utils/installed-skills.js.map +1 -0
- package/dist/src/utils/validation.d.ts +76 -0
- package/dist/src/utils/validation.d.ts.map +1 -0
- package/dist/src/utils/validation.js +153 -0
- package/dist/src/utils/validation.js.map +1 -0
- package/dist/src/webhooks/index.d.ts +8 -0
- package/dist/src/webhooks/index.d.ts.map +1 -0
- package/dist/src/webhooks/index.js +9 -0
- package/dist/src/webhooks/index.js.map +1 -0
- package/dist/src/webhooks/webhook-endpoint.d.ts +149 -0
- package/dist/src/webhooks/webhook-endpoint.d.ts.map +1 -0
- package/dist/src/webhooks/webhook-endpoint.js +339 -0
- package/dist/src/webhooks/webhook-endpoint.js.map +1 -0
- package/dist/tests/compare.test.d.ts +6 -0
- package/dist/tests/compare.test.d.ts.map +1 -0
- package/dist/tests/compare.test.js +225 -0
- package/dist/tests/compare.test.js.map +1 -0
- package/dist/tests/context/project-detector.test.d.ts +6 -0
- package/dist/tests/context/project-detector.test.d.ts.map +1 -0
- package/dist/tests/context/project-detector.test.js +719 -0
- package/dist/tests/context/project-detector.test.js.map +1 -0
- package/dist/tests/e2e/compare.e2e.test.d.ts +10 -0
- package/dist/tests/e2e/compare.e2e.test.d.ts.map +1 -0
- package/dist/tests/e2e/compare.e2e.test.js +286 -0
- package/dist/tests/e2e/compare.e2e.test.js.map +1 -0
- package/dist/tests/e2e/install-flow.e2e.test.d.ts +10 -0
- package/dist/tests/e2e/install-flow.e2e.test.d.ts.map +1 -0
- package/dist/tests/e2e/install-flow.e2e.test.js +209 -0
- package/dist/tests/e2e/install-flow.e2e.test.js.map +1 -0
- package/dist/tests/e2e/recommend.e2e.test.d.ts +12 -0
- package/dist/tests/e2e/recommend.e2e.test.d.ts.map +1 -0
- package/dist/tests/e2e/recommend.e2e.test.js +347 -0
- package/dist/tests/e2e/recommend.e2e.test.js.map +1 -0
- package/dist/tests/e2e/skill-flow.e2e.test.d.ts +10 -0
- package/dist/tests/e2e/skill-flow.e2e.test.d.ts.map +1 -0
- package/dist/tests/e2e/skill-flow.e2e.test.js +280 -0
- package/dist/tests/e2e/skill-flow.e2e.test.js.map +1 -0
- package/dist/tests/e2e/suggest.e2e.test.d.ts +13 -0
- package/dist/tests/e2e/suggest.e2e.test.d.ts.map +1 -0
- package/dist/tests/e2e/suggest.e2e.test.js +347 -0
- package/dist/tests/e2e/suggest.e2e.test.js.map +1 -0
- package/dist/tests/e2e/utils/baseline-collector.d.ts +107 -0
- package/dist/tests/e2e/utils/baseline-collector.d.ts.map +1 -0
- package/dist/tests/e2e/utils/baseline-collector.js +211 -0
- package/dist/tests/e2e/utils/baseline-collector.js.map +1 -0
- package/dist/tests/e2e/utils/hardcoded-detector.d.ts +46 -0
- package/dist/tests/e2e/utils/hardcoded-detector.d.ts.map +1 -0
- package/dist/tests/e2e/utils/hardcoded-detector.js +255 -0
- package/dist/tests/e2e/utils/hardcoded-detector.js.map +1 -0
- package/dist/tests/e2e/utils/index.d.ts +7 -0
- package/dist/tests/e2e/utils/index.d.ts.map +1 -0
- package/dist/tests/e2e/utils/index.js +7 -0
- package/dist/tests/e2e/utils/index.js.map +1 -0
- package/dist/tests/e2e/utils/linear-reporter.d.ts +60 -0
- package/dist/tests/e2e/utils/linear-reporter.d.ts.map +1 -0
- package/dist/tests/e2e/utils/linear-reporter.js +232 -0
- package/dist/tests/e2e/utils/linear-reporter.js.map +1 -0
- package/dist/tests/health.test.d.ts +9 -0
- package/dist/tests/health.test.d.ts.map +1 -0
- package/dist/tests/health.test.js +308 -0
- package/dist/tests/health.test.js.map +1 -0
- package/dist/tests/integration/analyze.integration.test.d.ts +2 -0
- package/dist/tests/integration/analyze.integration.test.d.ts.map +1 -0
- package/dist/tests/integration/analyze.integration.test.js +244 -0
- package/dist/tests/integration/analyze.integration.test.js.map +1 -0
- package/dist/tests/integration/compare.integration.test.d.ts +2 -0
- package/dist/tests/integration/compare.integration.test.d.ts.map +1 -0
- package/dist/tests/integration/compare.integration.test.js +120 -0
- package/dist/tests/integration/compare.integration.test.js.map +1 -0
- package/dist/tests/integration/fixtures/test-skills.d.ts +62 -0
- package/dist/tests/integration/fixtures/test-skills.d.ts.map +1 -0
- package/dist/tests/integration/fixtures/test-skills.js +644 -0
- package/dist/tests/integration/fixtures/test-skills.js.map +1 -0
- package/dist/tests/integration/get-skill.integration.test.d.ts +6 -0
- package/dist/tests/integration/get-skill.integration.test.d.ts.map +1 -0
- package/dist/tests/integration/get-skill.integration.test.js +203 -0
- package/dist/tests/integration/get-skill.integration.test.js.map +1 -0
- package/dist/tests/integration/github-api.integration.test.d.ts +14 -0
- package/dist/tests/integration/github-api.integration.test.d.ts.map +1 -0
- package/dist/tests/integration/github-api.integration.test.js +190 -0
- package/dist/tests/integration/github-api.integration.test.js.map +1 -0
- package/dist/tests/integration/install.integration.test.d.ts +6 -0
- package/dist/tests/integration/install.integration.test.d.ts.map +1 -0
- package/dist/tests/integration/install.integration.test.js +282 -0
- package/dist/tests/integration/install.integration.test.js.map +1 -0
- package/dist/tests/integration/recommend.integration.test.d.ts +2 -0
- package/dist/tests/integration/recommend.integration.test.d.ts.map +1 -0
- package/dist/tests/integration/recommend.integration.test.js +215 -0
- package/dist/tests/integration/recommend.integration.test.js.map +1 -0
- package/dist/tests/integration/search.integration.test.d.ts +6 -0
- package/dist/tests/integration/search.integration.test.d.ts.map +1 -0
- package/dist/tests/integration/search.integration.test.js +229 -0
- package/dist/tests/integration/search.integration.test.js.map +1 -0
- package/dist/tests/integration/setup.d.ts +71 -0
- package/dist/tests/integration/setup.d.ts.map +1 -0
- package/dist/tests/integration/setup.js +124 -0
- package/dist/tests/integration/setup.js.map +1 -0
- package/dist/tests/integration/uninstall.integration.test.d.ts +6 -0
- package/dist/tests/integration/uninstall.integration.test.d.ts.map +1 -0
- package/dist/tests/integration/uninstall.integration.test.js +296 -0
- package/dist/tests/integration/uninstall.integration.test.js.map +1 -0
- package/dist/tests/integration/validate.integration.test.d.ts +2 -0
- package/dist/tests/integration/validate.integration.test.d.ts.map +1 -0
- package/dist/tests/integration/validate.integration.test.js +181 -0
- package/dist/tests/integration/validate.integration.test.js.map +1 -0
- package/dist/tests/onboarding/first-run.test.d.ts +7 -0
- package/dist/tests/onboarding/first-run.test.d.ts.map +1 -0
- package/dist/tests/onboarding/first-run.test.js +258 -0
- package/dist/tests/onboarding/first-run.test.js.map +1 -0
- package/dist/tests/performance/search-performance.test.d.ts +10 -0
- package/dist/tests/performance/search-performance.test.d.ts.map +1 -0
- package/dist/tests/performance/search-performance.test.js +218 -0
- package/dist/tests/performance/search-performance.test.js.map +1 -0
- package/dist/tests/recommend.test.d.ts +6 -0
- package/dist/tests/recommend.test.d.ts.map +1 -0
- package/dist/tests/recommend.test.js +208 -0
- package/dist/tests/recommend.test.js.map +1 -0
- package/dist/tests/suggestions/suggestion-engine.test.d.ts +6 -0
- package/dist/tests/suggestions/suggestion-engine.test.d.ts.map +1 -0
- package/dist/tests/suggestions/suggestion-engine.test.js +448 -0
- package/dist/tests/suggestions/suggestion-engine.test.js.map +1 -0
- package/dist/tests/test-utils.d.ts +74 -0
- package/dist/tests/test-utils.d.ts.map +1 -0
- package/dist/tests/test-utils.js +98 -0
- package/dist/tests/test-utils.js.map +1 -0
- package/dist/tests/tools.test.d.ts +5 -0
- package/dist/tests/tools.test.d.ts.map +1 -0
- package/dist/tests/tools.test.js +138 -0
- package/dist/tests/tools.test.js.map +1 -0
- package/dist/tests/unit/installed-skills.test.d.ts +6 -0
- package/dist/tests/unit/installed-skills.test.d.ts.map +1 -0
- package/dist/tests/unit/installed-skills.test.js +285 -0
- package/dist/tests/unit/installed-skills.test.js.map +1 -0
- package/dist/tests/unit/logger.test.d.ts +6 -0
- package/dist/tests/unit/logger.test.d.ts.map +1 -0
- package/dist/tests/unit/logger.test.js +281 -0
- package/dist/tests/unit/logger.test.js.map +1 -0
- package/dist/tests/validate.test.d.ts +5 -0
- package/dist/tests/validate.test.d.ts.map +1 -0
- package/dist/tests/validate.test.js +303 -0
- package/dist/tests/validate.test.js.map +1 -0
- package/dist/tests/webhooks/proxy-trust.security.test.d.ts +8 -0
- package/dist/tests/webhooks/proxy-trust.security.test.d.ts.map +1 -0
- package/dist/tests/webhooks/proxy-trust.security.test.js +145 -0
- package/dist/tests/webhooks/proxy-trust.security.test.js.map +1 -0
- package/dist/tests/webhooks/rate-limiter.security.test.d.ts +8 -0
- package/dist/tests/webhooks/rate-limiter.security.test.d.ts.map +1 -0
- package/dist/tests/webhooks/rate-limiter.security.test.js +122 -0
- package/dist/tests/webhooks/rate-limiter.security.test.js.map +1 -0
- package/dist/vitest.config.d.ts +6 -0
- package/dist/vitest.config.d.ts.map +1 -0
- package/dist/vitest.config.js +13 -0
- package/dist/vitest.config.js.map +1 -0
- package/package.json +63 -0
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Utility for auto-detecting installed skills from ~/.claude/skills/
|
|
3
|
+
* @module @skillsmith/mcp-server/utils/installed-skills
|
|
4
|
+
* @see SMI-906: Auto-detect installed skills from ~/.claude/skills/
|
|
5
|
+
*
|
|
6
|
+
* Scans the user's skills directory and extracts skill IDs from SKILL.md files.
|
|
7
|
+
* Falls back to folder name if no SKILL.md or no ID found in frontmatter.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* const skills = await getInstalledSkills();
|
|
11
|
+
* // Returns: ["docker", "linear", "varlock"]
|
|
12
|
+
*/
|
|
13
|
+
import * as fs from 'node:fs';
|
|
14
|
+
import * as path from 'node:path';
|
|
15
|
+
import * as os from 'node:os';
|
|
16
|
+
/**
|
|
17
|
+
* Default skills directory path
|
|
18
|
+
*/
|
|
19
|
+
const DEFAULT_SKILLS_DIR = path.join(os.homedir(), '.claude', 'skills');
|
|
20
|
+
/**
|
|
21
|
+
* Parse SKILL.md frontmatter to extract skill metadata.
|
|
22
|
+
*
|
|
23
|
+
* Extracts the `name` field from YAML frontmatter in SKILL.md files.
|
|
24
|
+
* Frontmatter is delimited by `---` lines at the start of the file.
|
|
25
|
+
*
|
|
26
|
+
* @param content - Content of the SKILL.md file
|
|
27
|
+
* @returns Parsed skill metadata, or null values if parsing fails
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* const content = `---
|
|
31
|
+
* name: docker
|
|
32
|
+
* description: Docker skill
|
|
33
|
+
* ---
|
|
34
|
+
* # Docker Skill`;
|
|
35
|
+
* parseSkillMd(content); // { id: "docker", name: "docker", description: "Docker skill" }
|
|
36
|
+
*/
|
|
37
|
+
export function parseSkillMd(content) {
|
|
38
|
+
const result = {
|
|
39
|
+
id: null,
|
|
40
|
+
name: null,
|
|
41
|
+
description: null,
|
|
42
|
+
};
|
|
43
|
+
// Check for frontmatter (starts with ---)
|
|
44
|
+
if (!content.startsWith('---')) {
|
|
45
|
+
return result;
|
|
46
|
+
}
|
|
47
|
+
// Find the closing --- delimiter
|
|
48
|
+
const secondDelimiterIndex = content.indexOf('---', 3);
|
|
49
|
+
if (secondDelimiterIndex === -1) {
|
|
50
|
+
return result;
|
|
51
|
+
}
|
|
52
|
+
// Extract frontmatter content
|
|
53
|
+
const frontmatter = content.substring(3, secondDelimiterIndex).trim();
|
|
54
|
+
// Parse YAML-like frontmatter (simple key: value parsing)
|
|
55
|
+
const lines = frontmatter.split('\n');
|
|
56
|
+
for (const line of lines) {
|
|
57
|
+
const colonIndex = line.indexOf(':');
|
|
58
|
+
if (colonIndex === -1)
|
|
59
|
+
continue;
|
|
60
|
+
const key = line.substring(0, colonIndex).trim().toLowerCase();
|
|
61
|
+
const value = line.substring(colonIndex + 1).trim();
|
|
62
|
+
if (key === 'name' && value) {
|
|
63
|
+
result.name = value;
|
|
64
|
+
result.id = value; // Use name as the skill ID
|
|
65
|
+
}
|
|
66
|
+
else if (key === 'description' && value) {
|
|
67
|
+
result.description = value;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return result;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Get the skill ID from a skill directory.
|
|
74
|
+
*
|
|
75
|
+
* Looks for SKILL.md in the directory and extracts the ID from frontmatter.
|
|
76
|
+
* Falls back to the directory name if no SKILL.md or no ID found.
|
|
77
|
+
*
|
|
78
|
+
* @param skillDir - Path to the skill directory
|
|
79
|
+
* @param dirName - Name of the directory (used as fallback)
|
|
80
|
+
* @returns Skill ID
|
|
81
|
+
*/
|
|
82
|
+
export function getSkillIdFromDir(skillDir, dirName) {
|
|
83
|
+
const skillMdPath = path.join(skillDir, 'SKILL.md');
|
|
84
|
+
try {
|
|
85
|
+
if (fs.existsSync(skillMdPath)) {
|
|
86
|
+
const content = fs.readFileSync(skillMdPath, 'utf-8');
|
|
87
|
+
const parsed = parseSkillMd(content);
|
|
88
|
+
if (parsed.id) {
|
|
89
|
+
return parsed.id;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
catch (error) {
|
|
94
|
+
console.warn('[installed-skills] Failed to parse SKILL.md:', skillMdPath, error instanceof Error ? error.message : String(error));
|
|
95
|
+
}
|
|
96
|
+
return dirName;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Auto-detect installed skills from ~/.claude/skills/ directory.
|
|
100
|
+
*
|
|
101
|
+
* Scans the skills directory for subdirectories containing SKILL.md files.
|
|
102
|
+
* Extracts the skill ID from the `name` field in SKILL.md frontmatter.
|
|
103
|
+
* Falls back to directory name if no SKILL.md or no name field found.
|
|
104
|
+
*
|
|
105
|
+
* @param skillsDir - Optional custom skills directory path (defaults to ~/.claude/skills/)
|
|
106
|
+
* @returns Promise resolving to array of skill IDs
|
|
107
|
+
*
|
|
108
|
+
* @example
|
|
109
|
+
* const skills = await getInstalledSkills();
|
|
110
|
+
* // Returns: ["docker", "linear", "varlock"]
|
|
111
|
+
*
|
|
112
|
+
* @example
|
|
113
|
+
* // With custom directory
|
|
114
|
+
* const skills = await getInstalledSkills('/path/to/custom/skills');
|
|
115
|
+
*/
|
|
116
|
+
export async function getInstalledSkills(skillsDir) {
|
|
117
|
+
const dir = skillsDir || DEFAULT_SKILLS_DIR;
|
|
118
|
+
// Check if directory exists
|
|
119
|
+
if (!fs.existsSync(dir)) {
|
|
120
|
+
return [];
|
|
121
|
+
}
|
|
122
|
+
try {
|
|
123
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
124
|
+
const skillIds = [];
|
|
125
|
+
for (const entry of entries) {
|
|
126
|
+
// Skip non-directories and hidden directories
|
|
127
|
+
if (!entry.isDirectory() || entry.name.startsWith('.')) {
|
|
128
|
+
continue;
|
|
129
|
+
}
|
|
130
|
+
const skillDir = path.join(dir, entry.name);
|
|
131
|
+
const skillId = getSkillIdFromDir(skillDir, entry.name);
|
|
132
|
+
skillIds.push(skillId);
|
|
133
|
+
}
|
|
134
|
+
return skillIds.sort();
|
|
135
|
+
}
|
|
136
|
+
catch (error) {
|
|
137
|
+
console.warn('[installed-skills] Failed to read skills directory:', dir, error instanceof Error ? error.message : String(error));
|
|
138
|
+
return [];
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Synchronous version of getInstalledSkills for use in non-async contexts.
|
|
143
|
+
*
|
|
144
|
+
* @param skillsDir - Optional custom skills directory path (defaults to ~/.claude/skills/)
|
|
145
|
+
* @returns Array of skill IDs
|
|
146
|
+
*/
|
|
147
|
+
export function getInstalledSkillsSync(skillsDir) {
|
|
148
|
+
const dir = skillsDir || DEFAULT_SKILLS_DIR;
|
|
149
|
+
// Check if directory exists
|
|
150
|
+
if (!fs.existsSync(dir)) {
|
|
151
|
+
return [];
|
|
152
|
+
}
|
|
153
|
+
try {
|
|
154
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
155
|
+
const skillIds = [];
|
|
156
|
+
for (const entry of entries) {
|
|
157
|
+
// Skip non-directories and hidden directories
|
|
158
|
+
if (!entry.isDirectory() || entry.name.startsWith('.')) {
|
|
159
|
+
continue;
|
|
160
|
+
}
|
|
161
|
+
const skillDir = path.join(dir, entry.name);
|
|
162
|
+
const skillId = getSkillIdFromDir(skillDir, entry.name);
|
|
163
|
+
skillIds.push(skillId);
|
|
164
|
+
}
|
|
165
|
+
return skillIds.sort();
|
|
166
|
+
}
|
|
167
|
+
catch (error) {
|
|
168
|
+
console.warn('[installed-skills] Failed to read skills directory:', dir, error instanceof Error ? error.message : String(error));
|
|
169
|
+
return [];
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
export async function getInstalledSkillsDetailed(skillsDir) {
|
|
173
|
+
const dir = skillsDir || DEFAULT_SKILLS_DIR;
|
|
174
|
+
// Check if directory exists
|
|
175
|
+
if (!fs.existsSync(dir)) {
|
|
176
|
+
return [];
|
|
177
|
+
}
|
|
178
|
+
try {
|
|
179
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
180
|
+
const skills = [];
|
|
181
|
+
for (const entry of entries) {
|
|
182
|
+
// Skip non-directories and hidden directories
|
|
183
|
+
if (!entry.isDirectory() || entry.name.startsWith('.')) {
|
|
184
|
+
continue;
|
|
185
|
+
}
|
|
186
|
+
const skillDir = path.join(dir, entry.name);
|
|
187
|
+
const skillMdPath = path.join(skillDir, 'SKILL.md');
|
|
188
|
+
let hasSkillMd = false;
|
|
189
|
+
let description = null;
|
|
190
|
+
let id = entry.name;
|
|
191
|
+
try {
|
|
192
|
+
if (fs.existsSync(skillMdPath)) {
|
|
193
|
+
hasSkillMd = true;
|
|
194
|
+
const content = fs.readFileSync(skillMdPath, 'utf-8');
|
|
195
|
+
const parsed = parseSkillMd(content);
|
|
196
|
+
if (parsed.id) {
|
|
197
|
+
id = parsed.id;
|
|
198
|
+
}
|
|
199
|
+
description = parsed.description;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
catch (error) {
|
|
203
|
+
console.warn('[installed-skills] Failed to parse SKILL.md for detailed info:', skillMdPath, error instanceof Error ? error.message : String(error));
|
|
204
|
+
}
|
|
205
|
+
skills.push({
|
|
206
|
+
id,
|
|
207
|
+
directory: entry.name,
|
|
208
|
+
path: skillDir,
|
|
209
|
+
hasSkillMd,
|
|
210
|
+
description,
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
return skills.sort((a, b) => a.id.localeCompare(b.id));
|
|
214
|
+
}
|
|
215
|
+
catch (error) {
|
|
216
|
+
console.warn('[installed-skills] Failed to get detailed skills:', dir, error instanceof Error ? error.message : String(error));
|
|
217
|
+
return [];
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
//# sourceMappingURL=installed-skills.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"installed-skills.js","sourceRoot":"","sources":["../../../src/utils/installed-skills.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Shared validation utilities for MCP tools
|
|
3
|
+
* @module @skillsmith/mcp-server/utils/validation
|
|
4
|
+
* @see SMI-810: Create shared validation utility
|
|
5
|
+
*
|
|
6
|
+
* Provides common validation functions used across MCP tools:
|
|
7
|
+
* - Skill ID format validation
|
|
8
|
+
* - Skill ID parsing
|
|
9
|
+
* - Trust tier mapping between MCP and database types
|
|
10
|
+
*/
|
|
11
|
+
import type { TrustTier as DBTrustTier, MCPTrustTier, SkillCategory } from '@skillsmith/core';
|
|
12
|
+
/**
|
|
13
|
+
* Validate skill ID format.
|
|
14
|
+
*
|
|
15
|
+
* Accepts two formats:
|
|
16
|
+
* - Author/name format: `anthropic/commit`, `community/jest-helper`
|
|
17
|
+
* - UUID format: `550e8400-e29b-41d4-a716-446655440000`
|
|
18
|
+
*
|
|
19
|
+
* @param id - Skill ID to validate
|
|
20
|
+
* @returns True if ID matches valid format
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* isValidSkillId('anthropic/commit') // true
|
|
24
|
+
* isValidSkillId('invalid-format') // false
|
|
25
|
+
*/
|
|
26
|
+
export declare function isValidSkillId(id: string): boolean;
|
|
27
|
+
/**
|
|
28
|
+
* Parse a skill ID into author and name components.
|
|
29
|
+
*
|
|
30
|
+
* @param id - Skill ID in author/name format
|
|
31
|
+
* @returns Object with author and name, or null if invalid format
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* parseSkillId('anthropic/commit') // { author: 'anthropic', name: 'commit' }
|
|
35
|
+
* parseSkillId('invalid') // null
|
|
36
|
+
*/
|
|
37
|
+
export declare function parseSkillId(id: string): {
|
|
38
|
+
author: string;
|
|
39
|
+
name: string;
|
|
40
|
+
} | null;
|
|
41
|
+
/**
|
|
42
|
+
* Map MCP trust tier to database trust tier.
|
|
43
|
+
*
|
|
44
|
+
* MCP types: verified, community, standard, unverified
|
|
45
|
+
* DB types: verified, community, experimental, unknown
|
|
46
|
+
*
|
|
47
|
+
* @param mcpTier - MCP trust tier
|
|
48
|
+
* @returns Database trust tier
|
|
49
|
+
*/
|
|
50
|
+
export declare function mapTrustTierToDb(mcpTier: MCPTrustTier): DBTrustTier;
|
|
51
|
+
/**
|
|
52
|
+
* Map database trust tier to MCP trust tier.
|
|
53
|
+
*
|
|
54
|
+
* DB types: verified, community, experimental, unknown
|
|
55
|
+
* MCP types: verified, community, standard, unverified
|
|
56
|
+
*
|
|
57
|
+
* @param dbTier - Database trust tier
|
|
58
|
+
* @returns MCP trust tier
|
|
59
|
+
*/
|
|
60
|
+
export declare function mapTrustTierFromDb(dbTier: DBTrustTier): MCPTrustTier;
|
|
61
|
+
/**
|
|
62
|
+
* Extract skill category from tags array.
|
|
63
|
+
*
|
|
64
|
+
* Searches through tags to find the first valid category match.
|
|
65
|
+
* Handles case-insensitive matching and common aliases.
|
|
66
|
+
*
|
|
67
|
+
* @param tags - Array of skill tags
|
|
68
|
+
* @returns Valid SkillCategory, defaults to 'other' if no match
|
|
69
|
+
*
|
|
70
|
+
* @example
|
|
71
|
+
* extractCategoryFromTags(['git', 'testing', 'jest']) // 'testing'
|
|
72
|
+
* extractCategoryFromTags(['react', 'frontend']) // 'development'
|
|
73
|
+
* extractCategoryFromTags(['random', 'tags']) // 'other'
|
|
74
|
+
*/
|
|
75
|
+
export declare function extractCategoryFromTags(tags: string[] | undefined | null): SkillCategory;
|
|
76
|
+
//# sourceMappingURL=validation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../../../src/utils/validation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,SAAS,IAAI,WAAW,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAA;AAkB7F;;;;;;;;;;;;;GAaG;AACH,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAMlD;AAED;;;;;;;;;GASG;AACH,wBAAgB,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAMhF;AAED;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,YAAY,GAAG,WAAW,CAWnE;AAED;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,WAAW,GAAG,YAAY,CAWpE;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,SAAS,GAAG,IAAI,GAAG,aAAa,CAsCxF"}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Shared validation utilities for MCP tools
|
|
3
|
+
* @module @skillsmith/mcp-server/utils/validation
|
|
4
|
+
* @see SMI-810: Create shared validation utility
|
|
5
|
+
*
|
|
6
|
+
* Provides common validation functions used across MCP tools:
|
|
7
|
+
* - Skill ID format validation
|
|
8
|
+
* - Skill ID parsing
|
|
9
|
+
* - Trust tier mapping between MCP and database types
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* Valid skill categories for mapping
|
|
13
|
+
*/
|
|
14
|
+
const VALID_CATEGORIES = [
|
|
15
|
+
'development',
|
|
16
|
+
'testing',
|
|
17
|
+
'documentation',
|
|
18
|
+
'devops',
|
|
19
|
+
'database',
|
|
20
|
+
'security',
|
|
21
|
+
'productivity',
|
|
22
|
+
'integration',
|
|
23
|
+
'ai-ml',
|
|
24
|
+
'other',
|
|
25
|
+
];
|
|
26
|
+
/**
|
|
27
|
+
* Validate skill ID format.
|
|
28
|
+
*
|
|
29
|
+
* Accepts two formats:
|
|
30
|
+
* - Author/name format: `anthropic/commit`, `community/jest-helper`
|
|
31
|
+
* - UUID format: `550e8400-e29b-41d4-a716-446655440000`
|
|
32
|
+
*
|
|
33
|
+
* @param id - Skill ID to validate
|
|
34
|
+
* @returns True if ID matches valid format
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* isValidSkillId('anthropic/commit') // true
|
|
38
|
+
* isValidSkillId('invalid-format') // false
|
|
39
|
+
*/
|
|
40
|
+
export function isValidSkillId(id) {
|
|
41
|
+
// Format: author/skill-name or UUID
|
|
42
|
+
const authorSlashName = /^[a-z0-9-]+\/[a-z0-9-]+$/i;
|
|
43
|
+
const uuid = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
44
|
+
return authorSlashName.test(id) || uuid.test(id);
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Parse a skill ID into author and name components.
|
|
48
|
+
*
|
|
49
|
+
* @param id - Skill ID in author/name format
|
|
50
|
+
* @returns Object with author and name, or null if invalid format
|
|
51
|
+
*
|
|
52
|
+
* @example
|
|
53
|
+
* parseSkillId('anthropic/commit') // { author: 'anthropic', name: 'commit' }
|
|
54
|
+
* parseSkillId('invalid') // null
|
|
55
|
+
*/
|
|
56
|
+
export function parseSkillId(id) {
|
|
57
|
+
const parts = id.split('/');
|
|
58
|
+
if (parts.length !== 2) {
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
return { author: parts[0], name: parts[1] };
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Map MCP trust tier to database trust tier.
|
|
65
|
+
*
|
|
66
|
+
* MCP types: verified, community, standard, unverified
|
|
67
|
+
* DB types: verified, community, experimental, unknown
|
|
68
|
+
*
|
|
69
|
+
* @param mcpTier - MCP trust tier
|
|
70
|
+
* @returns Database trust tier
|
|
71
|
+
*/
|
|
72
|
+
export function mapTrustTierToDb(mcpTier) {
|
|
73
|
+
switch (mcpTier) {
|
|
74
|
+
case 'verified':
|
|
75
|
+
return 'verified';
|
|
76
|
+
case 'community':
|
|
77
|
+
return 'community';
|
|
78
|
+
case 'standard':
|
|
79
|
+
return 'experimental';
|
|
80
|
+
case 'unverified':
|
|
81
|
+
return 'unknown';
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Map database trust tier to MCP trust tier.
|
|
86
|
+
*
|
|
87
|
+
* DB types: verified, community, experimental, unknown
|
|
88
|
+
* MCP types: verified, community, standard, unverified
|
|
89
|
+
*
|
|
90
|
+
* @param dbTier - Database trust tier
|
|
91
|
+
* @returns MCP trust tier
|
|
92
|
+
*/
|
|
93
|
+
export function mapTrustTierFromDb(dbTier) {
|
|
94
|
+
switch (dbTier) {
|
|
95
|
+
case 'verified':
|
|
96
|
+
return 'verified';
|
|
97
|
+
case 'community':
|
|
98
|
+
return 'community';
|
|
99
|
+
case 'experimental':
|
|
100
|
+
return 'standard';
|
|
101
|
+
case 'unknown':
|
|
102
|
+
return 'unverified';
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Extract skill category from tags array.
|
|
107
|
+
*
|
|
108
|
+
* Searches through tags to find the first valid category match.
|
|
109
|
+
* Handles case-insensitive matching and common aliases.
|
|
110
|
+
*
|
|
111
|
+
* @param tags - Array of skill tags
|
|
112
|
+
* @returns Valid SkillCategory, defaults to 'other' if no match
|
|
113
|
+
*
|
|
114
|
+
* @example
|
|
115
|
+
* extractCategoryFromTags(['git', 'testing', 'jest']) // 'testing'
|
|
116
|
+
* extractCategoryFromTags(['react', 'frontend']) // 'development'
|
|
117
|
+
* extractCategoryFromTags(['random', 'tags']) // 'other'
|
|
118
|
+
*/
|
|
119
|
+
export function extractCategoryFromTags(tags) {
|
|
120
|
+
if (!tags || tags.length === 0) {
|
|
121
|
+
return 'other';
|
|
122
|
+
}
|
|
123
|
+
// Normalize tags to lowercase for matching
|
|
124
|
+
const normalizedTags = tags.map((tag) => tag.toLowerCase());
|
|
125
|
+
// First pass: direct category match
|
|
126
|
+
for (const tag of normalizedTags) {
|
|
127
|
+
if (VALID_CATEGORIES.includes(tag)) {
|
|
128
|
+
return tag;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
// Second pass: keyword-based category inference
|
|
132
|
+
const categoryKeywords = {
|
|
133
|
+
development: ['dev', 'code', 'coding', 'programming', 'frontend', 'backend', 'fullstack'],
|
|
134
|
+
testing: ['test', 'tests', 'jest', 'vitest', 'mocha', 'cypress', 'playwright', 'e2e', 'unit'],
|
|
135
|
+
documentation: ['docs', 'doc', 'readme', 'markdown', 'jsdoc', 'typedoc'],
|
|
136
|
+
devops: ['ci', 'cd', 'cicd', 'docker', 'kubernetes', 'k8s', 'deploy', 'deployment', 'infra'],
|
|
137
|
+
database: ['db', 'sql', 'postgres', 'mysql', 'mongodb', 'redis', 'sqlite'],
|
|
138
|
+
security: ['auth', 'authentication', 'authorization', 'oauth', 'jwt', 'encryption'],
|
|
139
|
+
productivity: ['workflow', 'automation', 'tools', 'utility', 'helper'],
|
|
140
|
+
integration: ['api', 'rest', 'graphql', 'webhook', 'sync'],
|
|
141
|
+
'ai-ml': ['ai', 'ml', 'machine-learning', 'llm', 'gpt', 'claude', 'openai', 'neural'],
|
|
142
|
+
other: [],
|
|
143
|
+
};
|
|
144
|
+
for (const tag of normalizedTags) {
|
|
145
|
+
for (const [category, keywords] of Object.entries(categoryKeywords)) {
|
|
146
|
+
if (keywords.includes(tag)) {
|
|
147
|
+
return category;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
return 'other';
|
|
152
|
+
}
|
|
153
|
+
//# sourceMappingURL=validation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validation.js","sourceRoot":"","sources":["../../../src/utils/validation.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SMI-645: Webhook module for MCP server
|
|
3
|
+
*
|
|
4
|
+
* Re-exports webhook functionality from core and provides HTTP server integration.
|
|
5
|
+
*/
|
|
6
|
+
export { createWebhookServer, startWebhookServer, stopWebhookServer, type WebhookServerOptions, type ServerStartOptions, type WebhookServer, } from './webhook-endpoint.js';
|
|
7
|
+
export { WebhookHandler, WebhookQueue, isSkillFile, extractSkillChanges, parseWebhookPayload, type WebhookEventType, type SkillFileChange, type WebhookHandleResult, type WebhookQueueItem, type QueueStats, } from '@skillsmith/core';
|
|
8
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/webhooks/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EACL,mBAAmB,EACnB,kBAAkB,EAClB,iBAAiB,EACjB,KAAK,oBAAoB,EACzB,KAAK,kBAAkB,EACvB,KAAK,aAAa,GACnB,MAAM,uBAAuB,CAAA;AAG9B,OAAO,EACL,cAAc,EACd,YAAY,EACZ,WAAW,EACX,mBAAmB,EACnB,mBAAmB,EACnB,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACpB,KAAK,mBAAmB,EACxB,KAAK,gBAAgB,EACrB,KAAK,UAAU,GAChB,MAAM,kBAAkB,CAAA"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SMI-645: Webhook module for MCP server
|
|
3
|
+
*
|
|
4
|
+
* Re-exports webhook functionality from core and provides HTTP server integration.
|
|
5
|
+
*/
|
|
6
|
+
export { createWebhookServer, startWebhookServer, stopWebhookServer, } from './webhook-endpoint.js';
|
|
7
|
+
// Re-export core webhook types for convenience
|
|
8
|
+
export { WebhookHandler, WebhookQueue, isSkillFile, extractSkillChanges, parseWebhookPayload, } from '@skillsmith/core';
|
|
9
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/webhooks/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EACL,mBAAmB,EACnB,kBAAkB,EAClB,iBAAiB,GAIlB,MAAM,uBAAuB,CAAA;AAE9B,+CAA+C;AAC/C,OAAO,EACL,cAAc,EACd,YAAY,EACZ,WAAW,EACX,mBAAmB,EACnB,mBAAmB,GAMpB,MAAM,kBAAkB,CAAA"}
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SMI-645: Webhook Endpoint - HTTP server for GitHub webhooks
|
|
3
|
+
*
|
|
4
|
+
* Provides:
|
|
5
|
+
* - Express/Node.js HTTP server for receiving webhooks
|
|
6
|
+
* - Signature validation middleware
|
|
7
|
+
* - Rate limiting for security
|
|
8
|
+
* - Event routing to WebhookHandler
|
|
9
|
+
*
|
|
10
|
+
* Usage:
|
|
11
|
+
* import { createWebhookServer, startWebhookServer } from './webhooks/webhook-endpoint.js';
|
|
12
|
+
*
|
|
13
|
+
* const server = createWebhookServer({
|
|
14
|
+
* secret: process.env.GITHUB_WEBHOOK_SECRET,
|
|
15
|
+
* onIndexUpdate: (repoUrl, filePath) => { ... },
|
|
16
|
+
* });
|
|
17
|
+
*
|
|
18
|
+
* startWebhookServer(server, { port: 3000 });
|
|
19
|
+
*/
|
|
20
|
+
import { IncomingMessage, Server } from 'http';
|
|
21
|
+
import { WebhookHandler, WebhookQueue, type WebhookQueueItem } from '@skillsmith/core';
|
|
22
|
+
/**
|
|
23
|
+
* Webhook server configuration (SMI-682: Added trust proxy options)
|
|
24
|
+
*/
|
|
25
|
+
export interface WebhookServerConfig {
|
|
26
|
+
/**
|
|
27
|
+
* GitHub webhook secret for signature verification
|
|
28
|
+
*/
|
|
29
|
+
secret: string;
|
|
30
|
+
/**
|
|
31
|
+
* Whether to trust X-Forwarded-For headers (default: false)
|
|
32
|
+
* SMI-682: Must be explicitly enabled for security
|
|
33
|
+
*/
|
|
34
|
+
trustProxy?: boolean;
|
|
35
|
+
/**
|
|
36
|
+
* List of trusted proxy IPs (optional, for enhanced security)
|
|
37
|
+
* SMI-682: When set, X-Forwarded-For is only trusted from these IPs
|
|
38
|
+
*/
|
|
39
|
+
trustedProxies?: string[];
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Webhook server options
|
|
43
|
+
*/
|
|
44
|
+
export interface WebhookServerOptions extends WebhookServerConfig {
|
|
45
|
+
/**
|
|
46
|
+
* Maximum request body size in bytes (default: 1MB)
|
|
47
|
+
*/
|
|
48
|
+
maxBodySize?: number;
|
|
49
|
+
/**
|
|
50
|
+
* Rate limit: max requests per window (default: 100)
|
|
51
|
+
*/
|
|
52
|
+
rateLimit?: number;
|
|
53
|
+
/**
|
|
54
|
+
* Rate limit window in ms (default: 60000 = 1 minute)
|
|
55
|
+
*/
|
|
56
|
+
rateLimitWindow?: number;
|
|
57
|
+
/**
|
|
58
|
+
* Callback when a skill needs to be indexed/updated
|
|
59
|
+
*/
|
|
60
|
+
onIndexUpdate?: (item: WebhookQueueItem) => Promise<void>;
|
|
61
|
+
/**
|
|
62
|
+
* Callback for logging
|
|
63
|
+
*/
|
|
64
|
+
onLog?: (level: 'info' | 'warn' | 'error', message: string, data?: unknown) => void;
|
|
65
|
+
/**
|
|
66
|
+
* Queue options for debouncing and retry
|
|
67
|
+
*/
|
|
68
|
+
queueOptions?: {
|
|
69
|
+
debounceMs?: number;
|
|
70
|
+
maxRetries?: number;
|
|
71
|
+
retryDelayMs?: number;
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Server startup options
|
|
76
|
+
*/
|
|
77
|
+
export interface ServerStartOptions {
|
|
78
|
+
/**
|
|
79
|
+
* Port to listen on (default: 3000)
|
|
80
|
+
*/
|
|
81
|
+
port?: number;
|
|
82
|
+
/**
|
|
83
|
+
* Host to bind to (default: '0.0.0.0')
|
|
84
|
+
*/
|
|
85
|
+
host?: string;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Rate limiter state (SMI-681: Added cleanup timer for memory leak prevention)
|
|
89
|
+
*/
|
|
90
|
+
export interface RateLimiterState {
|
|
91
|
+
requests: Map<string, number[]>;
|
|
92
|
+
limit: number;
|
|
93
|
+
window: number;
|
|
94
|
+
cleanupTimer?: ReturnType<typeof setInterval>;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Create rate limiter with automatic cleanup (SMI-681)
|
|
98
|
+
* @param limit - Maximum requests per window
|
|
99
|
+
* @param windowMs - Window duration in milliseconds
|
|
100
|
+
*/
|
|
101
|
+
export declare function createRateLimiter(limit: number, windowMs: number): RateLimiterState;
|
|
102
|
+
/**
|
|
103
|
+
* Destroy rate limiter and clean up resources (SMI-681)
|
|
104
|
+
*/
|
|
105
|
+
export declare function destroyRateLimiter(state: RateLimiterState): void;
|
|
106
|
+
/**
|
|
107
|
+
* Check if request is rate limited
|
|
108
|
+
*/
|
|
109
|
+
export declare function isRateLimited(limiter: RateLimiterState, ip: string): boolean;
|
|
110
|
+
/**
|
|
111
|
+
* Get client IP from request (SMI-682: Added trusted proxy validation)
|
|
112
|
+
* @param req - Incoming HTTP request
|
|
113
|
+
* @param config - Server configuration with trust proxy settings
|
|
114
|
+
*/
|
|
115
|
+
export declare function getClientIp(req: IncomingMessage, config: WebhookServerConfig): string;
|
|
116
|
+
/**
|
|
117
|
+
* Webhook server instance
|
|
118
|
+
*/
|
|
119
|
+
export interface WebhookServer {
|
|
120
|
+
/**
|
|
121
|
+
* The underlying HTTP server
|
|
122
|
+
*/
|
|
123
|
+
server: Server;
|
|
124
|
+
/**
|
|
125
|
+
* The webhook handler
|
|
126
|
+
*/
|
|
127
|
+
handler: WebhookHandler;
|
|
128
|
+
/**
|
|
129
|
+
* The webhook queue
|
|
130
|
+
*/
|
|
131
|
+
queue: WebhookQueue;
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Create a webhook server
|
|
135
|
+
*/
|
|
136
|
+
export declare function createWebhookServer(options: WebhookServerOptions): WebhookServer;
|
|
137
|
+
/**
|
|
138
|
+
* Start the webhook server
|
|
139
|
+
*/
|
|
140
|
+
export declare function startWebhookServer(webhookServer: WebhookServer, options?: ServerStartOptions): Promise<void>;
|
|
141
|
+
/**
|
|
142
|
+
* Stop the webhook server
|
|
143
|
+
*/
|
|
144
|
+
export declare function stopWebhookServer(webhookServer: WebhookServer): Promise<void>;
|
|
145
|
+
/**
|
|
146
|
+
* Main entry point for standalone webhook server
|
|
147
|
+
*/
|
|
148
|
+
export declare function main(): Promise<void>;
|
|
149
|
+
//# sourceMappingURL=webhook-endpoint.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"webhook-endpoint.d.ts","sourceRoot":"","sources":["../../../src/webhooks/webhook-endpoint.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAAgB,eAAe,EAAkB,MAAM,EAAE,MAAM,MAAM,CAAA;AAC5E,OAAO,EACL,cAAc,EACd,YAAY,EACZ,KAAK,gBAAgB,EAEtB,MAAM,kBAAkB,CAAA;AAEzB;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC;;OAEG;IACH,MAAM,EAAE,MAAM,CAAA;IAEd;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAA;IAEpB;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,EAAE,CAAA;CAC1B;AAED;;GAEG;AACH,MAAM,WAAW,oBAAqB,SAAQ,mBAAmB;IAC/D;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,CAAA;IAEpB;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;IAElB;;OAEG;IACH,eAAe,CAAC,EAAE,MAAM,CAAA;IAExB;;OAEG;IACH,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,gBAAgB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IAEzD;;OAEG;IACH,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,KAAK,IAAI,CAAA;IAEnF;;OAEG;IACH,YAAY,CAAC,EAAE;QACb,UAAU,CAAC,EAAE,MAAM,CAAA;QACnB,UAAU,CAAC,EAAE,MAAM,CAAA;QACnB,YAAY,CAAC,EAAE,MAAM,CAAA;KACtB,CAAA;CACF;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,CAAA;IAEb;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,CAAA;CACd;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAA;IAC/B,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;IACd,YAAY,CAAC,EAAE,UAAU,CAAC,OAAO,WAAW,CAAC,CAAA;CAC9C;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,gBAAgB,CA4BnF;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,gBAAgB,GAAG,IAAI,CAMhE;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,gBAAgB,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAoB5E;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,eAAe,EAAE,MAAM,EAAE,mBAAmB,GAAG,MAAM,CAmCrF;AAoCD;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B;;OAEG;IACH,MAAM,EAAE,MAAM,CAAA;IAEd;;OAEG;IACH,OAAO,EAAE,cAAc,CAAA;IAEvB;;OAEG;IACH,KAAK,EAAE,YAAY,CAAA;CACpB;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,oBAAoB,GAAG,aAAa,CA0IhF;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAChC,aAAa,EAAE,aAAa,EAC5B,OAAO,GAAE,kBAAuB,GAC/B,OAAO,CAAC,IAAI,CAAC,CAUf;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,aAAa,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAW7E;AAED;;GAEG;AACH,wBAAsB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAuC1C"}
|