@skillsmith/mcp-server 0.3.3 → 0.3.5
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/README.md +5 -3
- package/dist/.tsbuildinfo +1 -1
- package/dist/src/__tests__/LocalIndexer.test.d.ts +5 -0
- package/dist/src/__tests__/LocalIndexer.test.d.ts.map +1 -0
- package/dist/src/__tests__/LocalIndexer.test.js +396 -0
- package/dist/src/__tests__/LocalIndexer.test.js.map +1 -0
- package/dist/src/__tests__/context.test.d.ts +10 -0
- package/dist/src/__tests__/context.test.d.ts.map +1 -0
- package/dist/src/__tests__/context.test.js +345 -0
- package/dist/src/__tests__/context.test.js.map +1 -0
- package/dist/src/__tests__/get-skill.test.d.ts +1 -0
- package/dist/src/__tests__/get-skill.test.d.ts.map +1 -1
- package/dist/src/__tests__/get-skill.test.js +279 -0
- package/dist/src/__tests__/get-skill.test.js.map +1 -1
- package/dist/src/__tests__/index-local.test.d.ts +5 -0
- package/dist/src/__tests__/index-local.test.d.ts.map +1 -0
- package/dist/src/__tests__/index-local.test.js +203 -0
- package/dist/src/__tests__/index-local.test.js.map +1 -0
- package/dist/src/__tests__/middleware/license.test.js +180 -78
- package/dist/src/__tests__/middleware/license.test.js.map +1 -1
- package/dist/src/__tests__/recommend.test.d.ts +7 -0
- package/dist/src/__tests__/recommend.test.d.ts.map +1 -0
- package/dist/src/__tests__/recommend.test.js +277 -0
- package/dist/src/__tests__/recommend.test.js.map +1 -0
- package/dist/src/__tests__/search.test.js +140 -1
- package/dist/src/__tests__/search.test.js.map +1 -1
- package/dist/src/__tests__/utils/validation.test.d.ts +7 -0
- package/dist/src/__tests__/utils/validation.test.d.ts.map +1 -0
- package/dist/src/__tests__/utils/validation.test.js +82 -0
- package/dist/src/__tests__/utils/validation.test.js.map +1 -0
- package/dist/src/context.d.ts +22 -0
- package/dist/src/context.d.ts.map +1 -1
- package/dist/src/context.js +63 -9
- package/dist/src/context.js.map +1 -1
- package/dist/src/index.js +15 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/indexer/FrontmatterParser.d.ts +30 -0
- package/dist/src/indexer/FrontmatterParser.d.ts.map +1 -0
- package/dist/src/indexer/FrontmatterParser.js +109 -0
- package/dist/src/indexer/FrontmatterParser.js.map +1 -0
- package/dist/src/indexer/LocalIndexer.d.ts +136 -0
- package/dist/src/indexer/LocalIndexer.d.ts.map +1 -0
- package/dist/src/indexer/LocalIndexer.js +271 -0
- package/dist/src/indexer/LocalIndexer.js.map +1 -0
- package/dist/src/indexer/index.d.ts +8 -0
- package/dist/src/indexer/index.d.ts.map +1 -0
- package/dist/src/indexer/index.js +8 -0
- package/dist/src/indexer/index.js.map +1 -0
- package/dist/src/llm/failover.d.ts +210 -0
- package/dist/src/llm/failover.d.ts.map +1 -0
- package/dist/src/llm/failover.js +329 -0
- package/dist/src/llm/failover.js.map +1 -0
- package/dist/src/middleware/errorFormatter.d.ts +27 -0
- package/dist/src/middleware/errorFormatter.d.ts.map +1 -1
- package/dist/src/middleware/errorFormatter.js +95 -0
- package/dist/src/middleware/errorFormatter.js.map +1 -1
- package/dist/src/middleware/index.d.ts +1 -1
- package/dist/src/middleware/index.d.ts.map +1 -1
- package/dist/src/middleware/index.js.map +1 -1
- package/dist/src/middleware/license.d.ts +5 -0
- package/dist/src/middleware/license.d.ts.map +1 -1
- package/dist/src/middleware/license.js +2 -1
- package/dist/src/middleware/license.js.map +1 -1
- package/dist/src/middleware/quota-helpers.d.ts +40 -0
- package/dist/src/middleware/quota-helpers.d.ts.map +1 -0
- package/dist/src/middleware/quota-helpers.js +90 -0
- package/dist/src/middleware/quota-helpers.js.map +1 -0
- package/dist/src/middleware/quota-types.d.ts +105 -0
- package/dist/src/middleware/quota-types.d.ts.map +1 -0
- package/dist/src/middleware/quota-types.js +4 -0
- package/dist/src/middleware/quota-types.js.map +1 -0
- package/dist/src/middleware/quota.d.ts +3 -97
- package/dist/src/middleware/quota.d.ts.map +1 -1
- package/dist/src/middleware/quota.js +2 -87
- package/dist/src/middleware/quota.js.map +1 -1
- package/dist/src/tools/LocalSkillSearch.d.ts +32 -0
- package/dist/src/tools/LocalSkillSearch.d.ts.map +1 -0
- package/dist/src/tools/LocalSkillSearch.js +74 -0
- package/dist/src/tools/LocalSkillSearch.js.map +1 -0
- package/dist/src/tools/compare.d.ts +3 -102
- package/dist/src/tools/compare.d.ts.map +1 -1
- package/dist/src/tools/compare.helpers.d.ts +36 -0
- package/dist/src/tools/compare.helpers.d.ts.map +1 -0
- package/dist/src/tools/compare.helpers.js +252 -0
- package/dist/src/tools/compare.helpers.js.map +1 -0
- package/dist/src/tools/compare.js +6 -288
- package/dist/src/tools/compare.js.map +1 -1
- package/dist/src/tools/compare.types.d.ts +134 -0
- package/dist/src/tools/compare.types.d.ts.map +1 -0
- package/dist/src/tools/compare.types.js +47 -0
- package/dist/src/tools/compare.types.js.map +1 -0
- package/dist/src/tools/get-skill.d.ts.map +1 -1
- package/dist/src/tools/get-skill.js +38 -2
- package/dist/src/tools/get-skill.js.map +1 -1
- package/dist/src/tools/index-local.d.ts +117 -0
- package/dist/src/tools/index-local.d.ts.map +1 -0
- package/dist/src/tools/index-local.js +126 -0
- package/dist/src/tools/index-local.js.map +1 -0
- package/dist/src/tools/index.d.ts +2 -0
- package/dist/src/tools/index.d.ts.map +1 -1
- package/dist/src/tools/index.js +2 -0
- package/dist/src/tools/index.js.map +1 -1
- package/dist/src/tools/install.conflict-helpers.d.ts +64 -0
- package/dist/src/tools/install.conflict-helpers.d.ts.map +1 -0
- package/dist/src/tools/install.conflict-helpers.js +165 -0
- package/dist/src/tools/install.conflict-helpers.js.map +1 -0
- package/dist/src/tools/install.conflict-helpers.test.d.ts +15 -0
- package/dist/src/tools/install.conflict-helpers.test.d.ts.map +1 -0
- package/dist/src/tools/install.conflict-helpers.test.js +243 -0
- package/dist/src/tools/install.conflict-helpers.test.js.map +1 -0
- package/dist/src/tools/install.conflict.d.ts +58 -0
- package/dist/src/tools/install.conflict.d.ts.map +1 -0
- package/dist/src/tools/install.conflict.js +160 -0
- package/dist/src/tools/install.conflict.js.map +1 -0
- package/dist/src/tools/install.conflict.test.d.ts +15 -0
- package/dist/src/tools/install.conflict.test.d.ts.map +1 -0
- package/dist/src/tools/install.conflict.test.js +354 -0
- package/dist/src/tools/install.conflict.test.js.map +1 -0
- package/dist/src/tools/install.d.ts +11 -60
- package/dist/src/tools/install.d.ts.map +1 -1
- package/dist/src/tools/install.helpers.d.ts +83 -0
- package/dist/src/tools/install.helpers.d.ts.map +1 -0
- package/dist/src/tools/install.helpers.js +333 -0
- package/dist/src/tools/install.helpers.js.map +1 -0
- package/dist/src/tools/install.js +199 -255
- package/dist/src/tools/install.js.map +1 -1
- package/dist/src/tools/install.types.d.ts +178 -0
- package/dist/src/tools/install.types.d.ts.map +1 -0
- package/dist/src/tools/install.types.js +105 -0
- package/dist/src/tools/install.types.js.map +1 -0
- package/dist/src/tools/merge.d.ts +53 -0
- package/dist/src/tools/merge.d.ts.map +1 -0
- package/dist/src/tools/merge.js +276 -0
- package/dist/src/tools/merge.js.map +1 -0
- package/dist/src/tools/merge.test.d.ts +11 -0
- package/dist/src/tools/merge.test.d.ts.map +1 -0
- package/dist/src/tools/merge.test.js +224 -0
- package/dist/src/tools/merge.test.js.map +1 -0
- package/dist/src/tools/recommend.d.ts +3 -148
- package/dist/src/tools/recommend.d.ts.map +1 -1
- package/dist/src/tools/recommend.helpers.d.ts +42 -0
- package/dist/src/tools/recommend.helpers.d.ts.map +1 -0
- package/dist/src/tools/recommend.helpers.js +155 -0
- package/dist/src/tools/recommend.helpers.js.map +1 -0
- package/dist/src/tools/recommend.js +216 -154
- package/dist/src/tools/recommend.js.map +1 -1
- package/dist/src/tools/recommend.types.d.ts +164 -0
- package/dist/src/tools/recommend.types.d.ts.map +1 -0
- package/dist/src/tools/recommend.types.js +87 -0
- package/dist/src/tools/recommend.types.js.map +1 -0
- package/dist/src/tools/search.d.ts +18 -4
- package/dist/src/tools/search.d.ts.map +1 -1
- package/dist/src/tools/search.js +91 -16
- package/dist/src/tools/search.js.map +1 -1
- package/dist/src/tools/validate.d.ts +3 -70
- package/dist/src/tools/validate.d.ts.map +1 -1
- package/dist/src/tools/validate.helpers.d.ts +22 -0
- package/dist/src/tools/validate.helpers.d.ts.map +1 -0
- package/dist/src/tools/validate.helpers.js +276 -0
- package/dist/src/tools/validate.helpers.js.map +1 -0
- package/dist/src/tools/validate.js +4 -337
- package/dist/src/tools/validate.js.map +1 -1
- package/dist/src/tools/validate.types.d.ts +96 -0
- package/dist/src/tools/validate.types.d.ts.map +1 -0
- package/dist/src/tools/validate.types.js +71 -0
- package/dist/src/tools/validate.types.js.map +1 -0
- package/dist/src/utils/validation.d.ts +6 -2
- package/dist/src/utils/validation.d.ts.map +1 -1
- package/dist/src/utils/validation.js +11 -2
- package/dist/src/utils/validation.js.map +1 -1
- package/dist/src/webhooks/index.d.ts +1 -0
- package/dist/src/webhooks/index.d.ts.map +1 -1
- package/dist/src/webhooks/index.js +2 -0
- package/dist/src/webhooks/index.js.map +1 -1
- package/dist/src/webhooks/stripe-webhook-endpoint.d.ts +68 -0
- package/dist/src/webhooks/stripe-webhook-endpoint.d.ts.map +1 -0
- package/dist/src/webhooks/stripe-webhook-endpoint.js +213 -0
- package/dist/src/webhooks/stripe-webhook-endpoint.js.map +1 -0
- package/dist/src/webhooks/webhook-endpoint.d.ts +4 -49
- package/dist/src/webhooks/webhook-endpoint.d.ts.map +1 -1
- package/dist/src/webhooks/webhook-endpoint.js +3 -125
- package/dist/src/webhooks/webhook-endpoint.js.map +1 -1
- package/dist/src/webhooks/webhook-helpers.d.ts +69 -0
- package/dist/src/webhooks/webhook-helpers.d.ts.map +1 -0
- package/dist/src/webhooks/webhook-helpers.js +146 -0
- package/dist/src/webhooks/webhook-helpers.js.map +1 -0
- package/dist/tests/e2e/conflict-resolution.e2e.test.d.ts +12 -0
- package/dist/tests/e2e/conflict-resolution.e2e.test.d.ts.map +1 -0
- package/dist/tests/e2e/conflict-resolution.e2e.test.js +343 -0
- package/dist/tests/e2e/conflict-resolution.e2e.test.js.map +1 -0
- package/dist/tests/integration/fixtures/development-skills.d.ts +22 -0
- package/dist/tests/integration/fixtures/development-skills.d.ts.map +1 -0
- package/dist/tests/integration/fixtures/development-skills.js +165 -0
- package/dist/tests/integration/fixtures/development-skills.js.map +1 -0
- package/dist/tests/integration/fixtures/devops-skills.d.ts +10 -0
- package/dist/tests/integration/fixtures/devops-skills.d.ts.map +1 -0
- package/dist/tests/integration/fixtures/devops-skills.js +70 -0
- package/dist/tests/integration/fixtures/devops-skills.js.map +1 -0
- package/dist/tests/integration/fixtures/experimental-skills.d.ts +14 -0
- package/dist/tests/integration/fixtures/experimental-skills.d.ts.map +1 -0
- package/dist/tests/integration/fixtures/experimental-skills.js +255 -0
- package/dist/tests/integration/fixtures/experimental-skills.js.map +1 -0
- package/dist/tests/integration/fixtures/skill-types.d.ts +18 -0
- package/dist/tests/integration/fixtures/skill-types.d.ts.map +1 -0
- package/dist/tests/integration/fixtures/skill-types.js +6 -0
- package/dist/tests/integration/fixtures/skill-types.js.map +1 -0
- package/dist/tests/integration/fixtures/test-skills.d.ts +10 -14
- package/dist/tests/integration/fixtures/test-skills.d.ts.map +1 -1
- package/dist/tests/integration/fixtures/test-skills.js +23 -590
- package/dist/tests/integration/fixtures/test-skills.js.map +1 -1
- package/dist/tests/integration/fixtures/testing-skills.d.ts +10 -0
- package/dist/tests/integration/fixtures/testing-skills.d.ts.map +1 -0
- package/dist/tests/integration/fixtures/testing-skills.js +70 -0
- package/dist/tests/integration/fixtures/testing-skills.js.map +1 -0
- package/dist/tests/integration/fixtures/verified-skills.d.ts +11 -0
- package/dist/tests/integration/fixtures/verified-skills.d.ts.map +1 -0
- package/dist/tests/integration/fixtures/verified-skills.js +91 -0
- package/dist/tests/integration/fixtures/verified-skills.js.map +1 -0
- package/dist/tests/integration/install-conflict.integration.test.d.ts +8 -0
- package/dist/tests/integration/install-conflict.integration.test.d.ts.map +1 -0
- package/dist/tests/integration/install-conflict.integration.test.js +384 -0
- package/dist/tests/integration/install-conflict.integration.test.js.map +1 -0
- package/dist/tests/integration/install-trust-parsing.integration.test.d.ts +13 -0
- package/dist/tests/integration/install-trust-parsing.integration.test.d.ts.map +1 -0
- package/dist/tests/integration/install-trust-parsing.integration.test.js +290 -0
- package/dist/tests/integration/install-trust-parsing.integration.test.js.map +1 -0
- package/dist/tests/integration/install.integration.test.js +151 -1
- package/dist/tests/integration/install.integration.test.js.map +1 -1
- package/dist/tests/integration/recommend.integration.test.js +2 -1
- package/dist/tests/integration/recommend.integration.test.js.map +1 -1
- package/dist/tests/llm/failover.test.d.ts +13 -0
- package/dist/tests/llm/failover.test.d.ts.map +1 -0
- package/dist/tests/llm/failover.test.js +250 -0
- package/dist/tests/llm/failover.test.js.map +1 -0
- package/dist/tests/recommend.test.js +133 -1
- package/dist/tests/recommend.test.js.map +1 -1
- package/dist/tests/tools.test.d.ts +1 -0
- package/dist/tests/tools.test.d.ts.map +1 -1
- package/dist/tests/tools.test.js +59 -1
- package/dist/tests/tools.test.js.map +1 -1
- package/dist/tests/unit/compare-helpers.test.d.ts +8 -0
- package/dist/tests/unit/compare-helpers.test.d.ts.map +1 -0
- package/dist/tests/unit/compare-helpers.test.js +224 -0
- package/dist/tests/unit/compare-helpers.test.js.map +1 -0
- package/dist/tests/unit/install-helpers.test.d.ts +8 -0
- package/dist/tests/unit/install-helpers.test.d.ts.map +1 -0
- package/dist/tests/unit/install-helpers.test.js +460 -0
- package/dist/tests/unit/install-helpers.test.js.map +1 -0
- package/dist/tests/unit/recommend-helpers.test.d.ts +8 -0
- package/dist/tests/unit/recommend-helpers.test.d.ts.map +1 -0
- package/dist/tests/unit/recommend-helpers.test.js +117 -0
- package/dist/tests/unit/recommend-helpers.test.js.map +1 -0
- package/dist/tests/unit/validate-helpers.test.d.ts +8 -0
- package/dist/tests/unit/validate-helpers.test.d.ts.map +1 -0
- package/dist/tests/unit/validate-helpers.test.js +243 -0
- package/dist/tests/unit/validate-helpers.test.js.map +1 -0
- package/package.json +7 -6
- package/src/assets/docs/USER_GUIDE.md +0 -220
- package/src/assets/skills/skillsmith/docs/QUOTAS.md +0 -182
- package/src/assets/skills/skillsmith/docs/SECURITY.md +0 -174
- package/src/assets/skills/skillsmith/docs/TRUST_TIERS.md +0 -142
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for SMI-1837: Include Local Skills in Recommendations
|
|
3
|
+
* Verifies that local skills are searched in parallel with the API,
|
|
4
|
+
* not just as a fallback.
|
|
5
|
+
*/
|
|
6
|
+
import { describe, it, expect, beforeAll, afterAll, vi, beforeEach, afterEach } from 'vitest';
|
|
7
|
+
import { executeRecommend, formatRecommendations } from '../tools/recommend.js';
|
|
8
|
+
import { createSeededTestContext } from './test-utils.js';
|
|
9
|
+
import * as LocalSkillSearchModule from '../tools/LocalSkillSearch.js';
|
|
10
|
+
let context;
|
|
11
|
+
beforeAll(() => {
|
|
12
|
+
context = createSeededTestContext();
|
|
13
|
+
});
|
|
14
|
+
afterAll(() => {
|
|
15
|
+
context.db.close();
|
|
16
|
+
});
|
|
17
|
+
describe('Recommend Tool', () => {
|
|
18
|
+
describe('executeRecommend - basic functionality', () => {
|
|
19
|
+
it('should return recommendations for project context', async () => {
|
|
20
|
+
const result = await executeRecommend({
|
|
21
|
+
project_context: 'React frontend with testing',
|
|
22
|
+
limit: 5,
|
|
23
|
+
}, context);
|
|
24
|
+
expect(result.recommendations).toBeDefined();
|
|
25
|
+
expect(Array.isArray(result.recommendations)).toBe(true);
|
|
26
|
+
expect(result.context.has_project_context).toBe(true);
|
|
27
|
+
expect(result.timing.totalMs).toBeGreaterThanOrEqual(0);
|
|
28
|
+
});
|
|
29
|
+
it('should return recommendations with installed skills', async () => {
|
|
30
|
+
const result = await executeRecommend({
|
|
31
|
+
installed_skills: ['anthropic/commit'],
|
|
32
|
+
limit: 5,
|
|
33
|
+
}, context);
|
|
34
|
+
expect(result.recommendations).toBeDefined();
|
|
35
|
+
expect(result.context.installed_count).toBe(1);
|
|
36
|
+
// Should not recommend the already installed skill
|
|
37
|
+
const hasInstalledSkill = result.recommendations.some((r) => r.skill_id === 'anthropic/commit');
|
|
38
|
+
expect(hasInstalledSkill).toBe(false);
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
describe('formatRecommendations', () => {
|
|
42
|
+
it('should format results for terminal display', async () => {
|
|
43
|
+
const result = await executeRecommend({
|
|
44
|
+
project_context: 'testing',
|
|
45
|
+
limit: 3,
|
|
46
|
+
}, context);
|
|
47
|
+
const formatted = formatRecommendations(result);
|
|
48
|
+
expect(formatted).toContain('Skill Recommendations');
|
|
49
|
+
});
|
|
50
|
+
it('should show helpful message when no results', async () => {
|
|
51
|
+
const emptyResult = {
|
|
52
|
+
recommendations: [],
|
|
53
|
+
candidates_considered: 0,
|
|
54
|
+
overlap_filtered: 0,
|
|
55
|
+
role_filtered: 0,
|
|
56
|
+
context: {
|
|
57
|
+
installed_count: 0,
|
|
58
|
+
has_project_context: false,
|
|
59
|
+
using_semantic_matching: true,
|
|
60
|
+
auto_detected: false,
|
|
61
|
+
},
|
|
62
|
+
timing: { totalMs: 10 },
|
|
63
|
+
};
|
|
64
|
+
const formatted = formatRecommendations(emptyResult);
|
|
65
|
+
expect(formatted).toContain('No recommendations found');
|
|
66
|
+
expect(formatted).toContain('Suggestions:');
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
/**
|
|
71
|
+
* SMI-1837: Tests for parallel local skill search integration
|
|
72
|
+
*/
|
|
73
|
+
describe('Recommend Tool - Local Skill Integration (SMI-1837)', () => {
|
|
74
|
+
let branchContext;
|
|
75
|
+
// Mock local skills for testing
|
|
76
|
+
const mockLocalSkills = [
|
|
77
|
+
{
|
|
78
|
+
id: 'local/my-commit-helper',
|
|
79
|
+
name: 'my-commit-helper',
|
|
80
|
+
description: 'Personal commit message helper',
|
|
81
|
+
author: 'local',
|
|
82
|
+
tags: ['git', 'commit', 'personal'],
|
|
83
|
+
qualityScore: 75,
|
|
84
|
+
trustTier: 'local',
|
|
85
|
+
source: 'local',
|
|
86
|
+
path: '/home/user/.claude/skills/my-commit-helper',
|
|
87
|
+
hasSkillMd: true,
|
|
88
|
+
lastModified: new Date().toISOString(),
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
id: 'local/react-patterns',
|
|
92
|
+
name: 'react-patterns',
|
|
93
|
+
description: 'React component patterns and best practices',
|
|
94
|
+
author: 'local',
|
|
95
|
+
tags: ['react', 'patterns', 'components'],
|
|
96
|
+
qualityScore: 80,
|
|
97
|
+
trustTier: 'local',
|
|
98
|
+
source: 'local',
|
|
99
|
+
path: '/home/user/.claude/skills/react-patterns',
|
|
100
|
+
hasSkillMd: true,
|
|
101
|
+
lastModified: new Date().toISOString(),
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
id: 'local/testing-utils',
|
|
105
|
+
name: 'testing-utils',
|
|
106
|
+
description: 'Testing utilities and helpers',
|
|
107
|
+
author: 'local',
|
|
108
|
+
tags: ['testing', 'jest', 'vitest'],
|
|
109
|
+
qualityScore: 70,
|
|
110
|
+
trustTier: 'local',
|
|
111
|
+
source: 'local',
|
|
112
|
+
path: '/home/user/.claude/skills/testing-utils',
|
|
113
|
+
hasSkillMd: true,
|
|
114
|
+
lastModified: new Date().toISOString(),
|
|
115
|
+
},
|
|
116
|
+
];
|
|
117
|
+
beforeAll(() => {
|
|
118
|
+
branchContext = createSeededTestContext();
|
|
119
|
+
});
|
|
120
|
+
afterAll(() => {
|
|
121
|
+
branchContext.db.close();
|
|
122
|
+
});
|
|
123
|
+
beforeEach(() => {
|
|
124
|
+
// Mock the local indexer to return controlled test data
|
|
125
|
+
vi.spyOn(LocalSkillSearchModule, 'getLocalIndexer').mockReturnValue({
|
|
126
|
+
index: vi.fn().mockResolvedValue(mockLocalSkills),
|
|
127
|
+
indexSync: vi.fn().mockReturnValue(mockLocalSkills),
|
|
128
|
+
search: vi.fn((query, skills) => {
|
|
129
|
+
const lowerQuery = query.toLowerCase();
|
|
130
|
+
return skills.filter((s) => s.name.toLowerCase().includes(lowerQuery) ||
|
|
131
|
+
s.description?.toLowerCase().includes(lowerQuery) ||
|
|
132
|
+
s.tags.some((t) => t.toLowerCase().includes(lowerQuery)));
|
|
133
|
+
}),
|
|
134
|
+
clearCache: vi.fn(),
|
|
135
|
+
getSkillsDir: vi.fn().mockReturnValue('/home/user/.claude/skills'),
|
|
136
|
+
calculateQualityScore: vi.fn().mockReturnValue(75),
|
|
137
|
+
indexSkillDir: vi.fn(),
|
|
138
|
+
});
|
|
139
|
+
});
|
|
140
|
+
afterEach(() => {
|
|
141
|
+
vi.restoreAllMocks();
|
|
142
|
+
});
|
|
143
|
+
describe('parallel local search', () => {
|
|
144
|
+
it('should include local skills in recommendations when API is offline', async () => {
|
|
145
|
+
// Context is created with offline mode, so it will use local matching
|
|
146
|
+
const result = await executeRecommend({
|
|
147
|
+
project_context: 'React testing project',
|
|
148
|
+
limit: 10,
|
|
149
|
+
}, branchContext);
|
|
150
|
+
expect(result.recommendations).toBeDefined();
|
|
151
|
+
expect(result.timing.totalMs).toBeGreaterThanOrEqual(0);
|
|
152
|
+
expect(result.timing.totalMs).toBeLessThan(500); // Performance requirement
|
|
153
|
+
});
|
|
154
|
+
it('should not have duplicate skills in results', async () => {
|
|
155
|
+
const result = await executeRecommend({
|
|
156
|
+
project_context: 'commit automation',
|
|
157
|
+
limit: 10,
|
|
158
|
+
}, branchContext);
|
|
159
|
+
// Check for duplicate skill_ids
|
|
160
|
+
const skillIds = result.recommendations.map((r) => r.skill_id);
|
|
161
|
+
const uniqueIds = new Set(skillIds);
|
|
162
|
+
expect(skillIds.length).toBe(uniqueIds.size);
|
|
163
|
+
});
|
|
164
|
+
it('should complete within performance target (<500ms)', async () => {
|
|
165
|
+
const startTime = performance.now();
|
|
166
|
+
await executeRecommend({
|
|
167
|
+
project_context: 'JavaScript development',
|
|
168
|
+
installed_skills: ['anthropic/commit'],
|
|
169
|
+
limit: 10,
|
|
170
|
+
}, branchContext);
|
|
171
|
+
const endTime = performance.now();
|
|
172
|
+
const duration = endTime - startTime;
|
|
173
|
+
expect(duration).toBeLessThan(500);
|
|
174
|
+
});
|
|
175
|
+
it('should handle empty local skills gracefully', async () => {
|
|
176
|
+
// Mock empty local skills
|
|
177
|
+
vi.spyOn(LocalSkillSearchModule, 'getLocalIndexer').mockReturnValue({
|
|
178
|
+
index: vi.fn().mockResolvedValue([]),
|
|
179
|
+
indexSync: vi.fn().mockReturnValue([]),
|
|
180
|
+
search: vi.fn().mockReturnValue([]),
|
|
181
|
+
clearCache: vi.fn(),
|
|
182
|
+
getSkillsDir: vi.fn().mockReturnValue('/home/user/.claude/skills'),
|
|
183
|
+
calculateQualityScore: vi.fn().mockReturnValue(0),
|
|
184
|
+
indexSkillDir: vi.fn(),
|
|
185
|
+
});
|
|
186
|
+
const result = await executeRecommend({
|
|
187
|
+
project_context: 'testing',
|
|
188
|
+
limit: 5,
|
|
189
|
+
}, branchContext);
|
|
190
|
+
// Should still return database results
|
|
191
|
+
expect(result.recommendations).toBeDefined();
|
|
192
|
+
expect(Array.isArray(result.recommendations)).toBe(true);
|
|
193
|
+
});
|
|
194
|
+
it('should handle local indexer errors gracefully', async () => {
|
|
195
|
+
// Mock indexer that throws an error
|
|
196
|
+
vi.spyOn(LocalSkillSearchModule, 'getLocalIndexer').mockReturnValue({
|
|
197
|
+
index: vi.fn().mockRejectedValue(new Error('Indexer failed')),
|
|
198
|
+
indexSync: vi.fn().mockImplementation(() => {
|
|
199
|
+
throw new Error('Indexer failed');
|
|
200
|
+
}),
|
|
201
|
+
search: vi.fn().mockReturnValue([]),
|
|
202
|
+
clearCache: vi.fn(),
|
|
203
|
+
getSkillsDir: vi.fn().mockReturnValue('/home/user/.claude/skills'),
|
|
204
|
+
calculateQualityScore: vi.fn().mockReturnValue(0),
|
|
205
|
+
indexSkillDir: vi.fn(),
|
|
206
|
+
});
|
|
207
|
+
// Should not throw, should fall back gracefully
|
|
208
|
+
const result = await executeRecommend({
|
|
209
|
+
project_context: 'testing',
|
|
210
|
+
limit: 5,
|
|
211
|
+
}, branchContext);
|
|
212
|
+
expect(result.recommendations).toBeDefined();
|
|
213
|
+
});
|
|
214
|
+
});
|
|
215
|
+
describe('deduplication logic', () => {
|
|
216
|
+
it('should prefer registry skills over local skills with same name', async () => {
|
|
217
|
+
// Create a local skill with same name as registry skill
|
|
218
|
+
const duplicateMockSkills = [
|
|
219
|
+
{
|
|
220
|
+
id: 'local/commit',
|
|
221
|
+
name: 'commit',
|
|
222
|
+
description: 'Local commit helper (duplicate of anthropic/commit)',
|
|
223
|
+
author: 'local',
|
|
224
|
+
tags: ['git', 'commit'],
|
|
225
|
+
qualityScore: 60,
|
|
226
|
+
trustTier: 'local',
|
|
227
|
+
source: 'local',
|
|
228
|
+
path: '/home/user/.claude/skills/commit',
|
|
229
|
+
hasSkillMd: true,
|
|
230
|
+
lastModified: new Date().toISOString(),
|
|
231
|
+
},
|
|
232
|
+
];
|
|
233
|
+
vi.spyOn(LocalSkillSearchModule, 'getLocalIndexer').mockReturnValue({
|
|
234
|
+
index: vi.fn().mockResolvedValue(duplicateMockSkills),
|
|
235
|
+
indexSync: vi.fn().mockReturnValue(duplicateMockSkills),
|
|
236
|
+
search: vi.fn().mockReturnValue(duplicateMockSkills),
|
|
237
|
+
clearCache: vi.fn(),
|
|
238
|
+
getSkillsDir: vi.fn().mockReturnValue('/home/user/.claude/skills'),
|
|
239
|
+
calculateQualityScore: vi.fn().mockReturnValue(60),
|
|
240
|
+
indexSkillDir: vi.fn(),
|
|
241
|
+
});
|
|
242
|
+
const result = await executeRecommend({
|
|
243
|
+
project_context: 'git workflow',
|
|
244
|
+
limit: 10,
|
|
245
|
+
}, branchContext);
|
|
246
|
+
// Should not have both 'anthropic/commit' and 'local/commit'
|
|
247
|
+
const commitSkills = result.recommendations.filter((r) => r.name === 'commit' || r.skill_id.includes('commit'));
|
|
248
|
+
// If there's a commit skill, registry should take precedence
|
|
249
|
+
if (commitSkills.length > 0) {
|
|
250
|
+
const hasRegistryCommit = commitSkills.some((s) => s.skill_id === 'anthropic/commit');
|
|
251
|
+
const hasLocalCommit = commitSkills.some((s) => s.skill_id === 'local/commit');
|
|
252
|
+
// Should not have local duplicate if registry version exists
|
|
253
|
+
if (hasRegistryCommit) {
|
|
254
|
+
expect(hasLocalCommit).toBe(false);
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
});
|
|
258
|
+
});
|
|
259
|
+
describe('role filtering with local skills', () => {
|
|
260
|
+
it('should apply role filter to local skills', async () => {
|
|
261
|
+
const result = await executeRecommend({
|
|
262
|
+
project_context: 'testing project',
|
|
263
|
+
role: 'testing',
|
|
264
|
+
limit: 10,
|
|
265
|
+
}, branchContext);
|
|
266
|
+
// All results should have testing role if role filter is applied
|
|
267
|
+
if (result.recommendations.length > 0 && result.context.role_filter) {
|
|
268
|
+
result.recommendations.forEach((rec) => {
|
|
269
|
+
if (rec.roles) {
|
|
270
|
+
expect(rec.roles).toContain('testing');
|
|
271
|
+
}
|
|
272
|
+
});
|
|
273
|
+
}
|
|
274
|
+
});
|
|
275
|
+
});
|
|
276
|
+
});
|
|
277
|
+
//# sourceMappingURL=recommend.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recommend.test.js","sourceRoot":"","sources":["../../../src/__tests__/recommend.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -61,8 +61,9 @@ describe('Search Tool', () => {
|
|
|
61
61
|
it('should throw error for empty query', async () => {
|
|
62
62
|
await expect(executeSearch({ query: '' }, context)).rejects.toThrow(SkillsmithError);
|
|
63
63
|
});
|
|
64
|
-
it('should throw error for query less than
|
|
64
|
+
it('should throw error for query less than 3 characters', async () => {
|
|
65
65
|
await expect(executeSearch({ query: 'a' }, context)).rejects.toThrow(SkillsmithError);
|
|
66
|
+
await expect(executeSearch({ query: 'ab' }, context)).rejects.toThrow(SkillsmithError);
|
|
66
67
|
});
|
|
67
68
|
it('should throw error for invalid min_score', async () => {
|
|
68
69
|
await expect(executeSearch({ query: 'test', min_score: 150 }, context)).rejects.toThrow(SkillsmithError);
|
|
@@ -83,4 +84,142 @@ describe('Search Tool', () => {
|
|
|
83
84
|
});
|
|
84
85
|
});
|
|
85
86
|
});
|
|
87
|
+
/**
|
|
88
|
+
* SMI-1785: Additional tests for search.ts branch coverage
|
|
89
|
+
* Covers validation errors, filter combinations, and edge cases
|
|
90
|
+
*/
|
|
91
|
+
describe('Search Tool branch coverage', () => {
|
|
92
|
+
let branchContext;
|
|
93
|
+
beforeAll(() => {
|
|
94
|
+
branchContext = createSeededTestContext();
|
|
95
|
+
});
|
|
96
|
+
afterAll(() => {
|
|
97
|
+
branchContext.db.close();
|
|
98
|
+
});
|
|
99
|
+
describe('validation errors', () => {
|
|
100
|
+
it('should throw error for negative min_score', async () => {
|
|
101
|
+
await expect(executeSearch({ query: 'test', min_score: -10 }, branchContext)).rejects.toThrow(SkillsmithError);
|
|
102
|
+
});
|
|
103
|
+
it('should throw error for invalid trust_tier', async () => {
|
|
104
|
+
try {
|
|
105
|
+
await executeSearch({ query: 'test', trust_tier: 'invalid_tier' }, branchContext);
|
|
106
|
+
expect.fail('Should have thrown an error');
|
|
107
|
+
}
|
|
108
|
+
catch (error) {
|
|
109
|
+
expect(error).toBeInstanceOf(SkillsmithError);
|
|
110
|
+
expect(error.message).toContain('Invalid trust_tier');
|
|
111
|
+
expect(error.message).toContain('invalid_tier');
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
it('should throw error for negative max_risk', async () => {
|
|
115
|
+
try {
|
|
116
|
+
await executeSearch({ query: 'test', max_risk: -5 }, branchContext);
|
|
117
|
+
expect.fail('Should have thrown an error');
|
|
118
|
+
}
|
|
119
|
+
catch (error) {
|
|
120
|
+
expect(error).toBeInstanceOf(SkillsmithError);
|
|
121
|
+
expect(error.message).toContain('max_risk must be between 0 and 100');
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
it('should throw error for max_risk over 100', async () => {
|
|
125
|
+
try {
|
|
126
|
+
await executeSearch({ query: 'test', max_risk: 150 }, branchContext);
|
|
127
|
+
expect.fail('Should have thrown an error');
|
|
128
|
+
}
|
|
129
|
+
catch (error) {
|
|
130
|
+
expect(error).toBeInstanceOf(SkillsmithError);
|
|
131
|
+
expect(error.message).toContain('max_risk must be between 0 and 100');
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
});
|
|
135
|
+
describe('security filters', () => {
|
|
136
|
+
it('should accept safe_only filter', async () => {
|
|
137
|
+
const result = await executeSearch({
|
|
138
|
+
query: 'commit',
|
|
139
|
+
safe_only: true,
|
|
140
|
+
}, branchContext);
|
|
141
|
+
expect(result.results).toBeDefined();
|
|
142
|
+
expect(result.filters.safeOnly).toBe(true);
|
|
143
|
+
});
|
|
144
|
+
it('should accept max_risk filter', async () => {
|
|
145
|
+
const result = await executeSearch({
|
|
146
|
+
query: 'commit',
|
|
147
|
+
max_risk: 50,
|
|
148
|
+
}, branchContext);
|
|
149
|
+
expect(result.results).toBeDefined();
|
|
150
|
+
expect(result.filters.maxRiskScore).toBe(50);
|
|
151
|
+
});
|
|
152
|
+
});
|
|
153
|
+
describe('filter-only search (no query)', () => {
|
|
154
|
+
it('should allow search with only category filter', async () => {
|
|
155
|
+
const result = await executeSearch({
|
|
156
|
+
category: 'testing',
|
|
157
|
+
}, branchContext);
|
|
158
|
+
expect(result.results).toBeDefined();
|
|
159
|
+
expect(result.query).toBe('');
|
|
160
|
+
expect(result.filters.category).toBe('testing');
|
|
161
|
+
});
|
|
162
|
+
it('should allow search with only trust_tier filter', async () => {
|
|
163
|
+
const result = await executeSearch({
|
|
164
|
+
trust_tier: 'verified',
|
|
165
|
+
}, branchContext);
|
|
166
|
+
expect(result.results).toBeDefined();
|
|
167
|
+
expect(result.query).toBe('');
|
|
168
|
+
expect(result.filters.trustTier).toBe('verified');
|
|
169
|
+
});
|
|
170
|
+
it('should allow search with only min_score filter', async () => {
|
|
171
|
+
const result = await executeSearch({
|
|
172
|
+
min_score: 90,
|
|
173
|
+
}, branchContext);
|
|
174
|
+
expect(result.results).toBeDefined();
|
|
175
|
+
expect(result.query).toBe('');
|
|
176
|
+
});
|
|
177
|
+
it('should allow search with only safe_only filter', async () => {
|
|
178
|
+
const result = await executeSearch({
|
|
179
|
+
safe_only: true,
|
|
180
|
+
}, branchContext);
|
|
181
|
+
expect(result.results).toBeDefined();
|
|
182
|
+
expect(result.query).toBe('');
|
|
183
|
+
expect(result.filters.safeOnly).toBe(true);
|
|
184
|
+
});
|
|
185
|
+
it('should allow search with only max_risk filter', async () => {
|
|
186
|
+
const result = await executeSearch({
|
|
187
|
+
max_risk: 30,
|
|
188
|
+
}, branchContext);
|
|
189
|
+
expect(result.results).toBeDefined();
|
|
190
|
+
expect(result.query).toBe('');
|
|
191
|
+
expect(result.filters.maxRiskScore).toBe(30);
|
|
192
|
+
});
|
|
193
|
+
it('should allow search with multiple filters (no query)', async () => {
|
|
194
|
+
const result = await executeSearch({
|
|
195
|
+
category: 'testing',
|
|
196
|
+
trust_tier: 'community',
|
|
197
|
+
min_score: 70,
|
|
198
|
+
safe_only: true,
|
|
199
|
+
}, branchContext);
|
|
200
|
+
expect(result.results).toBeDefined();
|
|
201
|
+
expect(result.query).toBe('');
|
|
202
|
+
expect(result.filters.category).toBe('testing');
|
|
203
|
+
expect(result.filters.trustTier).toBe('community');
|
|
204
|
+
expect(result.filters.safeOnly).toBe(true);
|
|
205
|
+
});
|
|
206
|
+
});
|
|
207
|
+
describe('combined query and filters', () => {
|
|
208
|
+
it('should accept all filters together', async () => {
|
|
209
|
+
const result = await executeSearch({
|
|
210
|
+
query: 'test',
|
|
211
|
+
category: 'testing',
|
|
212
|
+
trust_tier: 'community',
|
|
213
|
+
min_score: 70,
|
|
214
|
+
safe_only: true,
|
|
215
|
+
max_risk: 40,
|
|
216
|
+
}, branchContext);
|
|
217
|
+
expect(result.results).toBeDefined();
|
|
218
|
+
expect(result.filters.category).toBe('testing');
|
|
219
|
+
expect(result.filters.trustTier).toBe('community');
|
|
220
|
+
expect(result.filters.safeOnly).toBe(true);
|
|
221
|
+
expect(result.filters.maxRiskScore).toBe(40);
|
|
222
|
+
});
|
|
223
|
+
});
|
|
224
|
+
});
|
|
86
225
|
//# sourceMappingURL=search.test.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"search.test.js","sourceRoot":"","sources":["../../../src/__tests__/search.test.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"search.test.js","sourceRoot":"","sources":["../../../src/__tests__/search.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validation.test.d.ts","sourceRoot":"","sources":["../../../../src/__tests__/utils/validation.test.ts"],"names":[],"mappings":"AAAA;;;;GAIG"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SMI-1602: Validation utility tests
|
|
3
|
+
*
|
|
4
|
+
* Tests for validation functions to increase branch coverage.
|
|
5
|
+
*/
|
|
6
|
+
import { describe, it, expect } from 'vitest';
|
|
7
|
+
import { parseSkillId, mapTrustTierToDb, mapTrustTierFromDb, extractCategoryFromTags, } from '../../utils/validation.js';
|
|
8
|
+
describe('Validation Utilities', () => {
|
|
9
|
+
describe('parseSkillId', () => {
|
|
10
|
+
it('should parse 2-part skill ID (author/name)', () => {
|
|
11
|
+
const result = parseSkillId('anthropic/commit');
|
|
12
|
+
expect(result).toEqual({ author: 'anthropic', name: 'commit' });
|
|
13
|
+
});
|
|
14
|
+
it('should parse 3-part skill ID (source/author/name)', () => {
|
|
15
|
+
const result = parseSkillId('github/cyanheads/git-mcp-server');
|
|
16
|
+
expect(result).toEqual({
|
|
17
|
+
source: 'github',
|
|
18
|
+
author: 'cyanheads',
|
|
19
|
+
name: 'git-mcp-server',
|
|
20
|
+
});
|
|
21
|
+
});
|
|
22
|
+
it('should return null for invalid skill ID', () => {
|
|
23
|
+
expect(parseSkillId('invalid')).toBeNull();
|
|
24
|
+
expect(parseSkillId('')).toBeNull();
|
|
25
|
+
expect(parseSkillId('too/many/parts/here')).toBeNull();
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
describe('mapTrustTierToDb', () => {
|
|
29
|
+
it('should map verified tier', () => {
|
|
30
|
+
expect(mapTrustTierToDb('verified')).toBe('verified');
|
|
31
|
+
});
|
|
32
|
+
it('should map community tier', () => {
|
|
33
|
+
expect(mapTrustTierToDb('community')).toBe('community');
|
|
34
|
+
});
|
|
35
|
+
it('should map experimental tier', () => {
|
|
36
|
+
expect(mapTrustTierToDb('experimental')).toBe('experimental');
|
|
37
|
+
});
|
|
38
|
+
it('should map unknown tier', () => {
|
|
39
|
+
expect(mapTrustTierToDb('unknown')).toBe('unknown');
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
describe('mapTrustTierFromDb', () => {
|
|
43
|
+
it('should map verified tier', () => {
|
|
44
|
+
expect(mapTrustTierFromDb('verified')).toBe('verified');
|
|
45
|
+
});
|
|
46
|
+
it('should map community tier', () => {
|
|
47
|
+
expect(mapTrustTierFromDb('community')).toBe('community');
|
|
48
|
+
});
|
|
49
|
+
it('should map experimental tier', () => {
|
|
50
|
+
expect(mapTrustTierFromDb('experimental')).toBe('experimental');
|
|
51
|
+
});
|
|
52
|
+
it('should map unknown tier', () => {
|
|
53
|
+
expect(mapTrustTierFromDb('unknown')).toBe('unknown');
|
|
54
|
+
});
|
|
55
|
+
it('should return unknown for unrecognized string', () => {
|
|
56
|
+
// The function accepts string input and handles invalid values gracefully
|
|
57
|
+
const invalidValue = 'invalid';
|
|
58
|
+
expect(mapTrustTierFromDb(invalidValue)).toBe('unknown');
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
describe('extractCategoryFromTags', () => {
|
|
62
|
+
it('should return "other" for null tags', () => {
|
|
63
|
+
expect(extractCategoryFromTags(null)).toBe('other');
|
|
64
|
+
});
|
|
65
|
+
it('should return "other" for undefined tags', () => {
|
|
66
|
+
expect(extractCategoryFromTags(undefined)).toBe('other');
|
|
67
|
+
});
|
|
68
|
+
it('should return "other" for empty tags array', () => {
|
|
69
|
+
expect(extractCategoryFromTags([])).toBe('other');
|
|
70
|
+
});
|
|
71
|
+
it('should extract testing category', () => {
|
|
72
|
+
expect(extractCategoryFromTags(['testing', 'jest'])).toBe('testing');
|
|
73
|
+
});
|
|
74
|
+
it('should extract development category', () => {
|
|
75
|
+
expect(extractCategoryFromTags(['development', 'react'])).toBe('development');
|
|
76
|
+
});
|
|
77
|
+
it('should return "other" for unrecognized tags', () => {
|
|
78
|
+
expect(extractCategoryFromTags(['random', 'tags'])).toBe('other');
|
|
79
|
+
});
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
//# sourceMappingURL=validation.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validation.test.js","sourceRoot":"","sources":["../../../../src/__tests__/utils/validation.test.ts"],"names":[],"mappings":"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"}
|
package/dist/src/context.d.ts
CHANGED
|
@@ -19,10 +19,12 @@
|
|
|
19
19
|
*/
|
|
20
20
|
import type { Database as DatabaseType } from 'better-sqlite3';
|
|
21
21
|
import { SearchService, SkillRepository, SkillsmithApiClient, BackgroundSyncService, type ApiClientConfig } from '@skillsmith/core';
|
|
22
|
+
import { LLMFailoverChain, type LLMFailoverConfig } from './llm/failover.js';
|
|
22
23
|
/**
|
|
23
24
|
* Shared context for MCP tool handlers
|
|
24
25
|
* SMI-1183: Added apiClient for live API access with local fallback
|
|
25
26
|
* SMI-1184: Added distinctId for telemetry tracking
|
|
27
|
+
* SMI-1524: Added llmFailover for multi-LLM support with circuit breaker
|
|
26
28
|
*/
|
|
27
29
|
export interface ToolContext {
|
|
28
30
|
/** SQLite database connection */
|
|
@@ -37,6 +39,13 @@ export interface ToolContext {
|
|
|
37
39
|
distinctId?: string;
|
|
38
40
|
/** Background sync service (if enabled) */
|
|
39
41
|
backgroundSync?: BackgroundSyncService;
|
|
42
|
+
/** LLM failover chain for multi-provider support (SMI-1524) */
|
|
43
|
+
llmFailover?: LLMFailoverChain;
|
|
44
|
+
/** Internal: Signal handlers for cleanup (prevents memory leaks) */
|
|
45
|
+
_signalHandlers?: Array<{
|
|
46
|
+
signal: NodeJS.Signals;
|
|
47
|
+
handler: () => void;
|
|
48
|
+
}>;
|
|
40
49
|
}
|
|
41
50
|
/**
|
|
42
51
|
* Telemetry configuration for PostHog (SMI-1184)
|
|
@@ -83,6 +92,12 @@ export interface ToolContextOptions {
|
|
|
83
92
|
searchCacheTtl?: number;
|
|
84
93
|
/** API client configuration (SMI-1183) */
|
|
85
94
|
apiClientConfig?: ApiClientConfig;
|
|
95
|
+
/**
|
|
96
|
+
* API key for authenticated requests
|
|
97
|
+
* Can also be set via SKILLSMITH_API_KEY env var
|
|
98
|
+
* SMI-XXXX: API Key Authentication
|
|
99
|
+
*/
|
|
100
|
+
apiKey?: string;
|
|
86
101
|
/**
|
|
87
102
|
* Telemetry configuration (SMI-1184)
|
|
88
103
|
* Privacy-first: telemetry is OPT-IN and disabled by default
|
|
@@ -93,6 +108,12 @@ export interface ToolContextOptions {
|
|
|
93
108
|
* Enables automatic registry sync during MCP server sessions
|
|
94
109
|
*/
|
|
95
110
|
backgroundSyncConfig?: BackgroundSyncConfig;
|
|
111
|
+
/**
|
|
112
|
+
* LLM failover chain configuration (SMI-1524)
|
|
113
|
+
* Enables multi-provider LLM support with automatic failover
|
|
114
|
+
* Disabled by default - set enabled: true to activate
|
|
115
|
+
*/
|
|
116
|
+
llmFailoverConfig?: LLMFailoverConfig;
|
|
96
117
|
}
|
|
97
118
|
/**
|
|
98
119
|
* Get the default database path
|
|
@@ -134,6 +155,7 @@ export declare function createToolContext(options?: ToolContextOptions): ToolCon
|
|
|
134
155
|
/**
|
|
135
156
|
* Close the tool context and release resources
|
|
136
157
|
* SMI-1184: Also shuts down PostHog telemetry if initialized
|
|
158
|
+
* SMI-1524: Also closes LLM failover chain
|
|
137
159
|
*
|
|
138
160
|
* @param context - Tool context to close
|
|
139
161
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/context.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAKH,OAAO,KAAK,EAAE,QAAQ,IAAI,YAAY,EAAE,MAAM,gBAAgB,CAAA;AAC9D,OAAO,
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/context.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAKH,OAAO,KAAK,EAAE,QAAQ,IAAI,YAAY,EAAE,MAAM,gBAAgB,CAAA;AAC9D,OAAO,EAGL,aAAa,EACb,eAAe,EAEf,mBAAmB,EAOnB,qBAAqB,EAErB,KAAK,eAAe,EAErB,MAAM,kBAAkB,CAAA;AACzB,OAAO,EAAE,gBAAgB,EAAE,KAAK,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AAE5E;;;;;GAKG;AACH,MAAM,WAAW,WAAW;IAC1B,iCAAiC;IACjC,EAAE,EAAE,YAAY,CAAA;IAChB,+CAA+C;IAC/C,aAAa,EAAE,aAAa,CAAA;IAC5B,sDAAsD;IACtD,eAAe,EAAE,eAAe,CAAA;IAChC,iDAAiD;IACjD,SAAS,EAAE,mBAAmB,CAAA;IAC9B,wEAAwE;IACxE,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,2CAA2C;IAC3C,cAAc,CAAC,EAAE,qBAAqB,CAAA;IACtC,+DAA+D;IAC/D,WAAW,CAAC,EAAE,gBAAgB,CAAA;IAC9B,oEAAoE;IACpE,eAAe,CAAC,EAAE,KAAK,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC,OAAO,CAAC;QAAC,OAAO,EAAE,MAAM,IAAI,CAAA;KAAE,CAAC,CAAA;CACzE;AAED;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC9B;;;OAGG;IACH,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC;;;;OAIG;IACH,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB;;OAEG;IACH,KAAK,CAAC,EAAE,OAAO,CAAA;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,iEAAiE;IACjE,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,iDAAiD;IACjD,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,0CAA0C;IAC1C,eAAe,CAAC,EAAE,eAAe,CAAA;IACjC;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,CAAA;IACf;;;OAGG;IACH,eAAe,CAAC,EAAE,eAAe,CAAA;IACjC;;;OAGG;IACH,oBAAoB,CAAC,EAAE,oBAAoB,CAAA;IAC3C;;;;OAIG;IACH,iBAAiB,CAAC,EAAE,iBAAiB,CAAA;CACtC;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,gBAAgB,IAAI,MAAM,CAqBzC;AAeD;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,GAAE,kBAAuB,GAAG,WAAW,CA+K/E;AAED;;;;;;GAMG;AACH,wBAAsB,gBAAgB,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAyB1E;AAKD;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAAC,OAAO,CAAC,EAAE,kBAAkB,GAAG,WAAW,CAUxE;AAED;;;GAGG;AACH,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC,CAKtD"}
|