swift-skills-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/LICENSE +21 -0
- package/README.md +410 -0
- package/build/cli/auth.d.ts +3 -0
- package/build/cli/auth.d.ts.map +1 -0
- package/build/cli/auth.js +44 -0
- package/build/cli/auth.js.map +1 -0
- package/build/cli/setup.d.ts +2 -0
- package/build/cli/setup.d.ts.map +1 -0
- package/build/cli/setup.js +150 -0
- package/build/cli/setup.js.map +1 -0
- package/build/cli/source-manager.d.ts +3 -0
- package/build/cli/source-manager.d.ts.map +1 -0
- package/build/cli/source-manager.js +117 -0
- package/build/cli/source-manager.js.map +1 -0
- package/build/config/creators.d.ts +11 -0
- package/build/config/creators.d.ts.map +1 -0
- package/build/config/creators.js +32 -0
- package/build/config/creators.js.map +1 -0
- package/build/config/sources.d.ts +91 -0
- package/build/config/sources.d.ts.map +1 -0
- package/build/config/sources.js +231 -0
- package/build/config/sources.js.map +1 -0
- package/build/config/sources.test.d.ts +2 -0
- package/build/config/sources.test.d.ts.map +1 -0
- package/build/config/sources.test.js +199 -0
- package/build/config/sources.test.js.map +1 -0
- package/build/config/swift-keywords.d.ts +29 -0
- package/build/config/swift-keywords.d.ts.map +1 -0
- package/build/config/swift-keywords.js +77 -0
- package/build/config/swift-keywords.js.map +1 -0
- package/build/index.d.ts +3 -0
- package/build/index.d.ts.map +1 -0
- package/build/index.js +181 -0
- package/build/index.js.map +1 -0
- package/build/integration/cache-behavior.test.d.ts +2 -0
- package/build/integration/cache-behavior.test.d.ts.map +1 -0
- package/build/integration/cache-behavior.test.js +521 -0
- package/build/integration/cache-behavior.test.js.map +1 -0
- package/build/integration/mcp-client.test.d.ts +2 -0
- package/build/integration/mcp-client.test.d.ts.map +1 -0
- package/build/integration/mcp-client.test.js +82 -0
- package/build/integration/mcp-client.test.js.map +1 -0
- package/build/integration/response-quality.test.d.ts +2 -0
- package/build/integration/response-quality.test.d.ts.map +1 -0
- package/build/integration/response-quality.test.js +230 -0
- package/build/integration/response-quality.test.js.map +1 -0
- package/build/integration/test-client.d.ts +25 -0
- package/build/integration/test-client.d.ts.map +1 -0
- package/build/integration/test-client.js +93 -0
- package/build/integration/test-client.js.map +1 -0
- package/build/sources/free/nilcoalescing.d.ts +8 -0
- package/build/sources/free/nilcoalescing.d.ts.map +1 -0
- package/build/sources/free/nilcoalescing.js +26 -0
- package/build/sources/free/nilcoalescing.js.map +1 -0
- package/build/sources/free/nilcoalescing.test.d.ts +2 -0
- package/build/sources/free/nilcoalescing.test.d.ts.map +1 -0
- package/build/sources/free/nilcoalescing.test.js +63 -0
- package/build/sources/free/nilcoalescing.test.js.map +1 -0
- package/build/sources/free/pointfree.d.ts +15 -0
- package/build/sources/free/pointfree.d.ts.map +1 -0
- package/build/sources/free/pointfree.js +175 -0
- package/build/sources/free/pointfree.js.map +1 -0
- package/build/sources/free/pointfree.test.d.ts +2 -0
- package/build/sources/free/pointfree.test.d.ts.map +1 -0
- package/build/sources/free/pointfree.test.js +86 -0
- package/build/sources/free/pointfree.test.js.map +1 -0
- package/build/sources/free/rssPatternSource.d.ts +42 -0
- package/build/sources/free/rssPatternSource.d.ts.map +1 -0
- package/build/sources/free/rssPatternSource.js +109 -0
- package/build/sources/free/rssPatternSource.js.map +1 -0
- package/build/sources/free/rssPatternSource.test.d.ts +2 -0
- package/build/sources/free/rssPatternSource.test.d.ts.map +1 -0
- package/build/sources/free/rssPatternSource.test.js +89 -0
- package/build/sources/free/rssPatternSource.test.js.map +1 -0
- package/build/sources/free/sundell.d.ts +8 -0
- package/build/sources/free/sundell.d.ts.map +1 -0
- package/build/sources/free/sundell.js +17 -0
- package/build/sources/free/sundell.js.map +1 -0
- package/build/sources/free/sundell.test.d.ts +2 -0
- package/build/sources/free/sundell.test.d.ts.map +1 -0
- package/build/sources/free/sundell.test.js +63 -0
- package/build/sources/free/sundell.test.js.map +1 -0
- package/build/sources/free/vanderlee.d.ts +8 -0
- package/build/sources/free/vanderlee.d.ts.map +1 -0
- package/build/sources/free/vanderlee.js +63 -0
- package/build/sources/free/vanderlee.js.map +1 -0
- package/build/sources/free/vanderlee.test.d.ts +2 -0
- package/build/sources/free/vanderlee.test.d.ts.map +1 -0
- package/build/sources/free/vanderlee.test.js +77 -0
- package/build/sources/free/vanderlee.test.js.map +1 -0
- package/build/sources/premium/patreon-dl.d.ts +45 -0
- package/build/sources/premium/patreon-dl.d.ts.map +1 -0
- package/build/sources/premium/patreon-dl.js +189 -0
- package/build/sources/premium/patreon-dl.js.map +1 -0
- package/build/sources/premium/patreon-fetch.d.ts +3 -0
- package/build/sources/premium/patreon-fetch.d.ts.map +1 -0
- package/build/sources/premium/patreon-fetch.js +18 -0
- package/build/sources/premium/patreon-fetch.js.map +1 -0
- package/build/sources/premium/patreon-oauth.d.ts +24 -0
- package/build/sources/premium/patreon-oauth.d.ts.map +1 -0
- package/build/sources/premium/patreon-oauth.js +208 -0
- package/build/sources/premium/patreon-oauth.js.map +1 -0
- package/build/sources/premium/patreon-zip.d.ts +17 -0
- package/build/sources/premium/patreon-zip.d.ts.map +1 -0
- package/build/sources/premium/patreon-zip.js +127 -0
- package/build/sources/premium/patreon-zip.js.map +1 -0
- package/build/sources/premium/patreon.d.ts +48 -0
- package/build/sources/premium/patreon.d.ts.map +1 -0
- package/build/sources/premium/patreon.js +221 -0
- package/build/sources/premium/patreon.js.map +1 -0
- package/build/sources/premium/youtube.d.ts +14 -0
- package/build/sources/premium/youtube.d.ts.map +1 -0
- package/build/sources/premium/youtube.js +92 -0
- package/build/sources/premium/youtube.js.map +1 -0
- package/build/tools/extract-cookie.d.ts +2 -0
- package/build/tools/extract-cookie.d.ts.map +1 -0
- package/build/tools/extract-cookie.js +40 -0
- package/build/tools/extract-cookie.js.map +1 -0
- package/build/tools/handlers/enableSource.d.ts +3 -0
- package/build/tools/handlers/enableSource.d.ts.map +1 -0
- package/build/tools/handlers/enableSource.js +25 -0
- package/build/tools/handlers/enableSource.js.map +1 -0
- package/build/tools/handlers/getPatreonPatterns.d.ts +3 -0
- package/build/tools/handlers/getPatreonPatterns.d.ts.map +1 -0
- package/build/tools/handlers/getPatreonPatterns.js +43 -0
- package/build/tools/handlers/getPatreonPatterns.js.map +1 -0
- package/build/tools/handlers/getSwiftPattern.d.ts +3 -0
- package/build/tools/handlers/getSwiftPattern.d.ts.map +1 -0
- package/build/tools/handlers/getSwiftPattern.js +72 -0
- package/build/tools/handlers/getSwiftPattern.js.map +1 -0
- package/build/tools/handlers/handlers.test.d.ts +2 -0
- package/build/tools/handlers/handlers.test.d.ts.map +1 -0
- package/build/tools/handlers/handlers.test.js +359 -0
- package/build/tools/handlers/handlers.test.js.map +1 -0
- package/build/tools/handlers/listContentSources.d.ts +3 -0
- package/build/tools/handlers/listContentSources.d.ts.map +1 -0
- package/build/tools/handlers/listContentSources.js +34 -0
- package/build/tools/handlers/listContentSources.js.map +1 -0
- package/build/tools/handlers/searchSwiftContent.d.ts +3 -0
- package/build/tools/handlers/searchSwiftContent.d.ts.map +1 -0
- package/build/tools/handlers/searchSwiftContent.js +121 -0
- package/build/tools/handlers/searchSwiftContent.js.map +1 -0
- package/build/tools/handlers/setupPatreon.d.ts +3 -0
- package/build/tools/handlers/setupPatreon.d.ts.map +1 -0
- package/build/tools/handlers/setupPatreon.js +40 -0
- package/build/tools/handlers/setupPatreon.js.map +1 -0
- package/build/tools/index.d.ts +3 -0
- package/build/tools/index.d.ts.map +1 -0
- package/build/tools/index.js +18 -0
- package/build/tools/index.js.map +1 -0
- package/build/tools/registry.d.ts +14 -0
- package/build/tools/registry.d.ts.map +1 -0
- package/build/tools/registry.js +21 -0
- package/build/tools/registry.js.map +1 -0
- package/build/tools/registry.test.d.ts +2 -0
- package/build/tools/registry.test.d.ts.map +1 -0
- package/build/tools/registry.test.js +54 -0
- package/build/tools/registry.test.js.map +1 -0
- package/build/tools/types.d.ts +67 -0
- package/build/tools/types.d.ts.map +1 -0
- package/build/tools/types.js +3 -0
- package/build/tools/types.js.map +1 -0
- package/build/utils/cache.d.ts +20 -0
- package/build/utils/cache.d.ts.map +1 -0
- package/build/utils/cache.js +186 -0
- package/build/utils/cache.js.map +1 -0
- package/build/utils/concurrency.d.ts +13 -0
- package/build/utils/concurrency.d.ts.map +1 -0
- package/build/utils/concurrency.js +33 -0
- package/build/utils/concurrency.js.map +1 -0
- package/build/utils/errors.d.ts +19 -0
- package/build/utils/errors.d.ts.map +1 -0
- package/build/utils/errors.js +35 -0
- package/build/utils/errors.js.map +1 -0
- package/build/utils/fetch.d.ts +6 -0
- package/build/utils/fetch.d.ts.map +1 -0
- package/build/utils/fetch.js +6 -0
- package/build/utils/fetch.js.map +1 -0
- package/build/utils/http.d.ts +21 -0
- package/build/utils/http.d.ts.map +1 -0
- package/build/utils/http.js +53 -0
- package/build/utils/http.js.map +1 -0
- package/build/utils/intent-cache.d.ts +94 -0
- package/build/utils/intent-cache.d.ts.map +1 -0
- package/build/utils/intent-cache.js +164 -0
- package/build/utils/intent-cache.js.map +1 -0
- package/build/utils/intent-cache.test.d.ts +2 -0
- package/build/utils/intent-cache.test.d.ts.map +1 -0
- package/build/utils/intent-cache.test.js +290 -0
- package/build/utils/intent-cache.test.js.map +1 -0
- package/build/utils/logger.d.ts +4 -0
- package/build/utils/logger.d.ts.map +1 -0
- package/build/utils/logger.js +9 -0
- package/build/utils/logger.js.map +1 -0
- package/build/utils/paths.d.ts +27 -0
- package/build/utils/paths.d.ts.map +1 -0
- package/build/utils/paths.js +43 -0
- package/build/utils/paths.js.map +1 -0
- package/build/utils/pattern-formatter.d.ts +40 -0
- package/build/utils/pattern-formatter.d.ts.map +1 -0
- package/build/utils/pattern-formatter.js +124 -0
- package/build/utils/pattern-formatter.js.map +1 -0
- package/build/utils/response-helpers.d.ts +17 -0
- package/build/utils/response-helpers.d.ts.map +1 -0
- package/build/utils/response-helpers.js +34 -0
- package/build/utils/response-helpers.js.map +1 -0
- package/build/utils/search-terms.d.ts +17 -0
- package/build/utils/search-terms.d.ts.map +1 -0
- package/build/utils/search-terms.js +71 -0
- package/build/utils/search-terms.js.map +1 -0
- package/build/utils/search-terms.test.d.ts +2 -0
- package/build/utils/search-terms.test.d.ts.map +1 -0
- package/build/utils/search-terms.test.js +107 -0
- package/build/utils/search-terms.test.js.map +1 -0
- package/build/utils/search.d.ts +48 -0
- package/build/utils/search.d.ts.map +1 -0
- package/build/utils/search.js +158 -0
- package/build/utils/search.js.map +1 -0
- package/build/utils/search.test.d.ts +2 -0
- package/build/utils/search.test.d.ts.map +1 -0
- package/build/utils/search.test.js +199 -0
- package/build/utils/search.test.js.map +1 -0
- package/build/utils/semantic-recall.d.ts +38 -0
- package/build/utils/semantic-recall.d.ts.map +1 -0
- package/build/utils/semantic-recall.js +134 -0
- package/build/utils/semantic-recall.js.map +1 -0
- package/build/utils/semantic-recall.test.d.ts +2 -0
- package/build/utils/semantic-recall.test.d.ts.map +1 -0
- package/build/utils/semantic-recall.test.js +326 -0
- package/build/utils/semantic-recall.test.js.map +1 -0
- package/build/utils/source-registry.d.ts +45 -0
- package/build/utils/source-registry.d.ts.map +1 -0
- package/build/utils/source-registry.js +113 -0
- package/build/utils/source-registry.js.map +1 -0
- package/build/utils/source-registry.test.d.ts +2 -0
- package/build/utils/source-registry.test.d.ts.map +1 -0
- package/build/utils/source-registry.test.js +206 -0
- package/build/utils/source-registry.test.js.map +1 -0
- package/build/utils/swift-analysis.d.ts +61 -0
- package/build/utils/swift-analysis.d.ts.map +1 -0
- package/build/utils/swift-analysis.js +339 -0
- package/build/utils/swift-analysis.js.map +1 -0
- package/build/utils/swift-analysis.test.d.ts +2 -0
- package/build/utils/swift-analysis.test.d.ts.map +1 -0
- package/build/utils/swift-analysis.test.js +473 -0
- package/build/utils/swift-analysis.test.js.map +1 -0
- package/package.json +85 -0
|
@@ -0,0 +1,359 @@
|
|
|
1
|
+
// src/tools/handlers/handlers.test.ts
|
|
2
|
+
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
3
|
+
import { getSwiftPatternHandler } from './getSwiftPattern.js';
|
|
4
|
+
import { searchSwiftContentHandler } from './searchSwiftContent.js';
|
|
5
|
+
import { listContentSourcesHandler } from './listContentSources.js';
|
|
6
|
+
import { enableSourceHandler } from './enableSource.js';
|
|
7
|
+
// Test fixtures - known patterns with specific properties for testing
|
|
8
|
+
const MOCK_PATTERNS = {
|
|
9
|
+
sundell: [
|
|
10
|
+
{
|
|
11
|
+
id: 'sundell-1',
|
|
12
|
+
title: 'Advanced SwiftUI Patterns',
|
|
13
|
+
url: 'https://swiftbysundell.com/swiftui',
|
|
14
|
+
excerpt: 'Learn advanced SwiftUI patterns for production apps',
|
|
15
|
+
content: 'Full content about SwiftUI state management and views',
|
|
16
|
+
topics: ['swiftui', 'architecture'],
|
|
17
|
+
relevanceScore: 85,
|
|
18
|
+
hasCode: true,
|
|
19
|
+
publishDate: '2024-01-15T00:00:00Z',
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
id: 'sundell-2',
|
|
23
|
+
title: 'Basic Swift Tips',
|
|
24
|
+
url: 'https://swiftbysundell.com/tips',
|
|
25
|
+
excerpt: 'Simple tips for Swift developers',
|
|
26
|
+
content: 'Basic content without code examples',
|
|
27
|
+
topics: ['swift'],
|
|
28
|
+
relevanceScore: 55, // Below default minQuality of 65
|
|
29
|
+
hasCode: false,
|
|
30
|
+
publishDate: '2024-01-10T00:00:00Z',
|
|
31
|
+
},
|
|
32
|
+
],
|
|
33
|
+
vanderlee: [
|
|
34
|
+
{
|
|
35
|
+
id: 'vanderlee-1',
|
|
36
|
+
title: 'iOS Performance Optimization',
|
|
37
|
+
url: 'https://avanderlee.com/performance',
|
|
38
|
+
excerpt: 'Optimize your iOS app performance',
|
|
39
|
+
content: 'Detailed performance optimization techniques',
|
|
40
|
+
topics: ['performance', 'optimization'],
|
|
41
|
+
relevanceScore: 78,
|
|
42
|
+
hasCode: true,
|
|
43
|
+
publishDate: '2024-01-12T00:00:00Z',
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
id: 'vanderlee-2',
|
|
47
|
+
title: 'Debugging Tips',
|
|
48
|
+
url: 'https://avanderlee.com/debugging',
|
|
49
|
+
excerpt: 'Debug your iOS apps effectively',
|
|
50
|
+
content: 'Debugging techniques without code',
|
|
51
|
+
topics: ['debugging'],
|
|
52
|
+
relevanceScore: 65,
|
|
53
|
+
hasCode: false,
|
|
54
|
+
publishDate: '2024-01-08T00:00:00Z',
|
|
55
|
+
},
|
|
56
|
+
],
|
|
57
|
+
nilcoalescing: [
|
|
58
|
+
{
|
|
59
|
+
id: 'nilcoalescing-1',
|
|
60
|
+
title: 'SwiftUI Navigation Deep Dive',
|
|
61
|
+
url: 'https://nilcoalescing.com/navigation',
|
|
62
|
+
excerpt: 'Master SwiftUI navigation patterns',
|
|
63
|
+
content: 'Navigation code examples and patterns',
|
|
64
|
+
topics: ['swiftui', 'navigation'],
|
|
65
|
+
relevanceScore: 72,
|
|
66
|
+
hasCode: true,
|
|
67
|
+
publishDate: '2024-01-14T00:00:00Z',
|
|
68
|
+
},
|
|
69
|
+
],
|
|
70
|
+
pointfree: [
|
|
71
|
+
{
|
|
72
|
+
id: 'pointfree-1',
|
|
73
|
+
title: 'Composable Architecture Case Study',
|
|
74
|
+
url: 'https://github.com/pointfreeco/pointfreeco/blob/main/Sources/Models/Episodes/0001-functions.md',
|
|
75
|
+
excerpt: 'Build apps with TCA',
|
|
76
|
+
content: 'TCA reducer and store patterns',
|
|
77
|
+
topics: ['architecture', 'tca'],
|
|
78
|
+
relevanceScore: 90,
|
|
79
|
+
hasCode: true,
|
|
80
|
+
publishDate: '2024-01-16T00:00:00Z',
|
|
81
|
+
},
|
|
82
|
+
],
|
|
83
|
+
};
|
|
84
|
+
// Mock sources to return our test fixtures
|
|
85
|
+
vi.mock('../../sources/free/sundell.js', () => ({
|
|
86
|
+
default: vi.fn().mockImplementation(() => ({
|
|
87
|
+
searchPatterns: vi.fn().mockResolvedValue(MOCK_PATTERNS.sundell),
|
|
88
|
+
})),
|
|
89
|
+
}));
|
|
90
|
+
vi.mock('../../sources/free/vanderlee.js', () => ({
|
|
91
|
+
default: vi.fn().mockImplementation(() => ({
|
|
92
|
+
searchPatterns: vi.fn().mockResolvedValue(MOCK_PATTERNS.vanderlee),
|
|
93
|
+
})),
|
|
94
|
+
}));
|
|
95
|
+
vi.mock('../../sources/free/nilcoalescing.js', () => ({
|
|
96
|
+
default: vi.fn().mockImplementation(() => ({
|
|
97
|
+
searchPatterns: vi.fn().mockResolvedValue(MOCK_PATTERNS.nilcoalescing),
|
|
98
|
+
})),
|
|
99
|
+
}));
|
|
100
|
+
vi.mock('../../sources/free/pointfree.js', () => ({
|
|
101
|
+
default: vi.fn().mockImplementation(() => ({
|
|
102
|
+
searchPatterns: vi.fn().mockResolvedValue(MOCK_PATTERNS.pointfree),
|
|
103
|
+
})),
|
|
104
|
+
}));
|
|
105
|
+
// Mock SourceManager to ensure semantic recall is disabled in tests
|
|
106
|
+
vi.mock('../../config/sources.js', () => ({
|
|
107
|
+
default: vi.fn().mockImplementation(() => ({
|
|
108
|
+
getSemanticRecallConfig: vi.fn().mockReturnValue({
|
|
109
|
+
enabled: false,
|
|
110
|
+
minLexicalScore: 0.35,
|
|
111
|
+
minRelevanceScore: 70,
|
|
112
|
+
}),
|
|
113
|
+
isSemanticRecallEnabled: vi.fn().mockReturnValue(false),
|
|
114
|
+
})),
|
|
115
|
+
}));
|
|
116
|
+
// Create mock SourceManager
|
|
117
|
+
function createMockSourceManager() {
|
|
118
|
+
const sources = [
|
|
119
|
+
{ id: 'sundell', name: 'Swift by Sundell', type: 'free', requiresAuth: false, isEnabled: true, isConfigured: true, description: 'Swift articles' },
|
|
120
|
+
{ id: 'vanderlee', name: 'Antoine van der Lee', type: 'free', requiresAuth: false, isEnabled: true, isConfigured: true, description: 'iOS tips' },
|
|
121
|
+
{ id: 'nilcoalescing', name: 'Nil Coalescing', type: 'free', requiresAuth: false, isEnabled: true, isConfigured: true, description: 'SwiftUI tips' },
|
|
122
|
+
{ id: 'pointfree', name: 'Point-Free', type: 'free', requiresAuth: false, isEnabled: true, isConfigured: true, description: 'Open source patterns' },
|
|
123
|
+
{ id: 'patreon', name: 'Patreon', type: 'premium', requiresAuth: true, isEnabled: false, isConfigured: false, description: 'Premium content' },
|
|
124
|
+
];
|
|
125
|
+
return {
|
|
126
|
+
getAllSources: vi.fn().mockReturnValue(sources),
|
|
127
|
+
getSource: vi.fn((id) => sources.find(s => s.id === id)),
|
|
128
|
+
isSourceConfigured: vi.fn((id) => {
|
|
129
|
+
const source = sources.find(s => s.id === id);
|
|
130
|
+
return source?.isConfigured ?? false;
|
|
131
|
+
}),
|
|
132
|
+
enableSource: vi.fn(),
|
|
133
|
+
disableSource: vi.fn(),
|
|
134
|
+
getEnabledSources: vi.fn().mockReturnValue(sources.filter(s => s.isEnabled)),
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
describe('getSwiftPatternHandler', () => {
|
|
138
|
+
let context;
|
|
139
|
+
beforeEach(() => {
|
|
140
|
+
context = {
|
|
141
|
+
sourceManager: createMockSourceManager(),
|
|
142
|
+
patreonSource: null,
|
|
143
|
+
};
|
|
144
|
+
});
|
|
145
|
+
it('should return error when topic is missing', async () => {
|
|
146
|
+
const result = await getSwiftPatternHandler({}, context);
|
|
147
|
+
expect(result.content[0].text).toContain('Missing required argument');
|
|
148
|
+
expect(result.content[0].text).toContain('topic');
|
|
149
|
+
});
|
|
150
|
+
it('should return patterns matching the topic', async () => {
|
|
151
|
+
const result = await getSwiftPatternHandler({ topic: 'swiftui' }, context);
|
|
152
|
+
const text = result.content[0].text;
|
|
153
|
+
// Should include SwiftUI-related patterns
|
|
154
|
+
expect(text).toContain('Advanced SwiftUI Patterns');
|
|
155
|
+
expect(text).toContain('SwiftUI Navigation Deep Dive');
|
|
156
|
+
});
|
|
157
|
+
it('should filter out patterns below minQuality threshold', async () => {
|
|
158
|
+
const result = await getSwiftPatternHandler({
|
|
159
|
+
topic: 'swift',
|
|
160
|
+
minQuality: 70,
|
|
161
|
+
}, context);
|
|
162
|
+
const text = result.content[0].text;
|
|
163
|
+
// sundell-1 (85), vanderlee-1 (78), nilcoalescing-1 (72), pointfree-1 (90) should be included
|
|
164
|
+
expect(text).toContain('Advanced SwiftUI Patterns'); // score 85
|
|
165
|
+
expect(text).toContain('iOS Performance Optimization'); // score 78
|
|
166
|
+
// sundell-2 (55) and vanderlee-2 (65) should be EXCLUDED
|
|
167
|
+
expect(text).not.toContain('Basic Swift Tips'); // score 55
|
|
168
|
+
expect(text).not.toContain('Debugging Tips'); // score 65
|
|
169
|
+
});
|
|
170
|
+
it('should use default minQuality of 65 when not specified', async () => {
|
|
171
|
+
const result = await getSwiftPatternHandler({ topic: 'swift' }, context);
|
|
172
|
+
const text = result.content[0].text;
|
|
173
|
+
// sundell-2 has score 55, below default minQuality of 65
|
|
174
|
+
expect(text).not.toContain('Basic Swift Tips');
|
|
175
|
+
// vanderlee-2 has score 65, meets minQuality threshold
|
|
176
|
+
// Note: Due to maxResults=4 default, only top 4 patterns are shown
|
|
177
|
+
// So vanderlee-2 (score 65, ranked 5th) won't appear in output
|
|
178
|
+
expect(text).toContain('Found 5 results'); // 5 patterns pass the threshold
|
|
179
|
+
expect(text).toContain('Showing top 4 of 5 results'); // But only 4 are displayed
|
|
180
|
+
});
|
|
181
|
+
it('should filter by specific source when provided', async () => {
|
|
182
|
+
const result = await getSwiftPatternHandler({
|
|
183
|
+
topic: 'swift',
|
|
184
|
+
source: 'sundell',
|
|
185
|
+
}, context);
|
|
186
|
+
const text = result.content[0].text;
|
|
187
|
+
// Should only contain sundell patterns
|
|
188
|
+
expect(text).toContain('Advanced SwiftUI Patterns');
|
|
189
|
+
// Should NOT contain patterns from other sources
|
|
190
|
+
expect(text).not.toContain('iOS Performance Optimization'); // vanderlee
|
|
191
|
+
expect(text).not.toContain('SwiftUI Navigation Deep Dive'); // nilcoalescing
|
|
192
|
+
expect(text).not.toContain('Composable Architecture'); // pointfree
|
|
193
|
+
});
|
|
194
|
+
it('should sort results by relevance score (highest first)', async () => {
|
|
195
|
+
const result = await getSwiftPatternHandler({
|
|
196
|
+
topic: 'swift',
|
|
197
|
+
minQuality: 0, // Include all
|
|
198
|
+
}, context);
|
|
199
|
+
const text = result.content[0].text;
|
|
200
|
+
// pointfree-1 (90) should appear before sundell-1 (85)
|
|
201
|
+
const pointfreeIndex = text.indexOf('Composable Architecture');
|
|
202
|
+
const sundellIndex = text.indexOf('Advanced SwiftUI Patterns');
|
|
203
|
+
expect(pointfreeIndex).toBeLessThan(sundellIndex);
|
|
204
|
+
});
|
|
205
|
+
it('should include quality scores in output', async () => {
|
|
206
|
+
const result = await getSwiftPatternHandler({ topic: 'swiftui' }, context);
|
|
207
|
+
const text = result.content[0].text;
|
|
208
|
+
// Should show quality scores
|
|
209
|
+
expect(text).toMatch(/Quality.*\d+\/100/i);
|
|
210
|
+
});
|
|
211
|
+
it('should include source attribution in output', async () => {
|
|
212
|
+
const result = await getSwiftPatternHandler({ topic: 'swiftui' }, context);
|
|
213
|
+
const text = result.content[0].text;
|
|
214
|
+
expect(text).toMatch(/Source.*:/i);
|
|
215
|
+
});
|
|
216
|
+
it('should include clickable URLs in output', async () => {
|
|
217
|
+
const result = await getSwiftPatternHandler({ topic: 'swiftui' }, context);
|
|
218
|
+
const text = result.content[0].text;
|
|
219
|
+
// Should have markdown links
|
|
220
|
+
expect(text).toMatch(/\[.+\]\(https?:\/\/.+\)/);
|
|
221
|
+
});
|
|
222
|
+
it('should return helpful message when no patterns found', async () => {
|
|
223
|
+
const result = await getSwiftPatternHandler({
|
|
224
|
+
topic: 'nonexistent_topic',
|
|
225
|
+
minQuality: 100, // Filter out everything
|
|
226
|
+
}, context);
|
|
227
|
+
const text = result.content[0].text;
|
|
228
|
+
expect(text).toContain('No patterns found');
|
|
229
|
+
expect(text).toMatch(/[Tt]ry/); // Should suggest trying something else
|
|
230
|
+
});
|
|
231
|
+
});
|
|
232
|
+
describe('searchSwiftContentHandler', () => {
|
|
233
|
+
let context;
|
|
234
|
+
beforeEach(() => {
|
|
235
|
+
context = {
|
|
236
|
+
sourceManager: createMockSourceManager(),
|
|
237
|
+
patreonSource: null,
|
|
238
|
+
};
|
|
239
|
+
});
|
|
240
|
+
it('should return error when query is missing', async () => {
|
|
241
|
+
const result = await searchSwiftContentHandler({}, context);
|
|
242
|
+
expect(result.content[0].text).toContain('Missing required argument');
|
|
243
|
+
expect(result.content[0].text).toContain('query');
|
|
244
|
+
});
|
|
245
|
+
it('should return results from all sources', async () => {
|
|
246
|
+
const result = await searchSwiftContentHandler({ query: 'swift' }, context);
|
|
247
|
+
const text = result.content[0].text;
|
|
248
|
+
// Should include results from multiple sources
|
|
249
|
+
expect(text).toContain('Advanced SwiftUI Patterns'); // sundell
|
|
250
|
+
expect(text).toContain('iOS Performance Optimization'); // vanderlee
|
|
251
|
+
});
|
|
252
|
+
it('should filter by requireCode when true', async () => {
|
|
253
|
+
const result = await searchSwiftContentHandler({
|
|
254
|
+
query: 'swift',
|
|
255
|
+
requireCode: true,
|
|
256
|
+
}, context);
|
|
257
|
+
const text = result.content[0].text;
|
|
258
|
+
// Should include patterns with code
|
|
259
|
+
expect(text).toContain('Advanced SwiftUI Patterns'); // hasCode: true
|
|
260
|
+
expect(text).toContain('iOS Performance Optimization'); // hasCode: true
|
|
261
|
+
// Should EXCLUDE patterns without code
|
|
262
|
+
expect(text).not.toContain('Basic Swift Tips'); // hasCode: false
|
|
263
|
+
expect(text).not.toContain('Debugging Tips'); // hasCode: false
|
|
264
|
+
});
|
|
265
|
+
it('should include all patterns when requireCode is false', async () => {
|
|
266
|
+
const result = await searchSwiftContentHandler({
|
|
267
|
+
query: 'swift',
|
|
268
|
+
requireCode: false,
|
|
269
|
+
}, context);
|
|
270
|
+
const text = result.content[0].text;
|
|
271
|
+
// Should include patterns both with and without code
|
|
272
|
+
expect(text).toContain('Advanced SwiftUI Patterns'); // hasCode: true
|
|
273
|
+
expect(text).toContain('Basic Swift Tips'); // hasCode: false
|
|
274
|
+
});
|
|
275
|
+
it('should have search results header', async () => {
|
|
276
|
+
const result = await searchSwiftContentHandler({ query: 'swift' }, context);
|
|
277
|
+
const text = result.content[0].text;
|
|
278
|
+
expect(text).toMatch(/# Search Results/);
|
|
279
|
+
});
|
|
280
|
+
});
|
|
281
|
+
describe('listContentSourcesHandler', () => {
|
|
282
|
+
let context;
|
|
283
|
+
beforeEach(() => {
|
|
284
|
+
context = {
|
|
285
|
+
sourceManager: createMockSourceManager(),
|
|
286
|
+
patreonSource: null,
|
|
287
|
+
};
|
|
288
|
+
});
|
|
289
|
+
it('should list all sources with categories', async () => {
|
|
290
|
+
const result = await listContentSourcesHandler({}, context);
|
|
291
|
+
const text = result.content[0].text;
|
|
292
|
+
expect(text).toContain('Content Sources');
|
|
293
|
+
expect(text).toContain('Free Sources');
|
|
294
|
+
expect(text).toContain('Premium Sources');
|
|
295
|
+
});
|
|
296
|
+
it('should list all source names', async () => {
|
|
297
|
+
const result = await listContentSourcesHandler({}, context);
|
|
298
|
+
const text = result.content[0].text;
|
|
299
|
+
expect(text).toContain('Swift by Sundell');
|
|
300
|
+
expect(text).toContain('Antoine van der Lee');
|
|
301
|
+
expect(text).toContain('Nil Coalescing');
|
|
302
|
+
expect(text).toContain('Point-Free');
|
|
303
|
+
expect(text).toContain('Patreon');
|
|
304
|
+
});
|
|
305
|
+
it('should show status indicators', async () => {
|
|
306
|
+
const result = await listContentSourcesHandler({}, context);
|
|
307
|
+
const text = result.content[0].text;
|
|
308
|
+
// Should have status indicators (enabled/disabled/needs setup)
|
|
309
|
+
expect(text).toMatch(/✅|⚙️|⬜/);
|
|
310
|
+
});
|
|
311
|
+
it('should show setup instructions for premium sources', async () => {
|
|
312
|
+
const result = await listContentSourcesHandler({}, context);
|
|
313
|
+
const text = result.content[0].text;
|
|
314
|
+
expect(text).toContain('swift-patterns-mcp setup');
|
|
315
|
+
});
|
|
316
|
+
});
|
|
317
|
+
describe('enableSourceHandler', () => {
|
|
318
|
+
let context;
|
|
319
|
+
beforeEach(() => {
|
|
320
|
+
context = {
|
|
321
|
+
sourceManager: createMockSourceManager(),
|
|
322
|
+
patreonSource: null,
|
|
323
|
+
};
|
|
324
|
+
});
|
|
325
|
+
it('should return error for unknown source', async () => {
|
|
326
|
+
const result = await enableSourceHandler({ source: 'unknown_source' }, context);
|
|
327
|
+
const text = result.content[0].text;
|
|
328
|
+
expect(text).toContain('Unknown source');
|
|
329
|
+
expect(text).toContain('unknown_source');
|
|
330
|
+
});
|
|
331
|
+
it('should list available sources when source is unknown', async () => {
|
|
332
|
+
const result = await enableSourceHandler({ source: 'invalid' }, context);
|
|
333
|
+
const text = result.content[0].text;
|
|
334
|
+
expect(text).toContain('Available sources');
|
|
335
|
+
expect(text).toContain('sundell');
|
|
336
|
+
expect(text).toContain('vanderlee');
|
|
337
|
+
expect(text).toContain('nilcoalescing');
|
|
338
|
+
expect(text).toContain('pointfree');
|
|
339
|
+
});
|
|
340
|
+
it('should require setup for unconfigured premium sources', async () => {
|
|
341
|
+
const result = await enableSourceHandler({ source: 'patreon' }, context);
|
|
342
|
+
const text = result.content[0].text;
|
|
343
|
+
expect(text).toContain('requires setup');
|
|
344
|
+
expect(text).toContain('swift-patterns-mcp setup');
|
|
345
|
+
expect(text).toContain('--patreon');
|
|
346
|
+
});
|
|
347
|
+
it('should enable configured free sources', async () => {
|
|
348
|
+
const result = await enableSourceHandler({ source: 'sundell' }, context);
|
|
349
|
+
const text = result.content[0].text;
|
|
350
|
+
expect(text).toContain('enabled');
|
|
351
|
+
expect(text).toContain('Swift by Sundell');
|
|
352
|
+
expect(context.sourceManager.enableSource).toHaveBeenCalledWith('sundell');
|
|
353
|
+
});
|
|
354
|
+
it('should not call enableSource for unknown sources', async () => {
|
|
355
|
+
await enableSourceHandler({ source: 'unknown' }, context);
|
|
356
|
+
expect(context.sourceManager.enableSource).not.toHaveBeenCalled();
|
|
357
|
+
});
|
|
358
|
+
});
|
|
359
|
+
//# sourceMappingURL=handlers.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handlers.test.js","sourceRoot":"","sources":["../../../src/tools/handlers/handlers.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"listContentSources.d.ts","sourceRoot":"","sources":["../../../src/tools/handlers/listContentSources.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAG/C,eAAO,MAAM,yBAAyB,EAAE,WAiCvC,CAAC"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
// src/tools/handlers/listContentSources.ts
|
|
2
|
+
import { createTextResponse } from '../../utils/response-helpers.js';
|
|
3
|
+
export const listContentSourcesHandler = async (_args, context) => {
|
|
4
|
+
const allSources = context.sourceManager.getAllSources();
|
|
5
|
+
const freeList = allSources
|
|
6
|
+
.filter(s => s.type === 'free')
|
|
7
|
+
.map(s => `- ✅ **${s.name}** - ${s.description}`)
|
|
8
|
+
.join('\n');
|
|
9
|
+
const premiumList = allSources
|
|
10
|
+
.filter(s => s.type === 'premium')
|
|
11
|
+
.map(s => {
|
|
12
|
+
const status = s.isConfigured && s.isEnabled ? '✅' :
|
|
13
|
+
s.isConfigured ? '⚙️' : '⬜';
|
|
14
|
+
return `- ${status} **${s.name}** - ${s.description}${s.isConfigured ? '' : ' (Setup required)'}`;
|
|
15
|
+
})
|
|
16
|
+
.join('\n');
|
|
17
|
+
return createTextResponse(`# Content Sources
|
|
18
|
+
|
|
19
|
+
## Free Sources (Always Available)
|
|
20
|
+
${freeList}
|
|
21
|
+
|
|
22
|
+
## Premium Sources (Optional)
|
|
23
|
+
${premiumList}
|
|
24
|
+
|
|
25
|
+
## Legend
|
|
26
|
+
✅ Enabled | ⚙️ Configured but disabled | ⬜ Not configured
|
|
27
|
+
|
|
28
|
+
To enable premium sources:
|
|
29
|
+
\`\`\`
|
|
30
|
+
swift-patterns-mcp setup --patreon
|
|
31
|
+
\`\`\`
|
|
32
|
+
`);
|
|
33
|
+
};
|
|
34
|
+
//# sourceMappingURL=listContentSources.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"listContentSources.js","sourceRoot":"","sources":["../../../src/tools/handlers/listContentSources.ts"],"names":[],"mappings":"AAAA,2CAA2C;AAG3C,OAAO,EAAE,kBAAkB,EAAE,MAAM,iCAAiC,CAAC;AAErE,MAAM,CAAC,MAAM,yBAAyB,GAAgB,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE;IAC7E,MAAM,UAAU,GAAG,OAAO,CAAC,aAAa,CAAC,aAAa,EAAE,CAAC;IAEzD,MAAM,QAAQ,GAAG,UAAU;SACxB,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC;SAC9B,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,SAAS,CAAC,CAAC,IAAI,QAAQ,CAAC,CAAC,WAAW,EAAE,CAAC;SAChD,IAAI,CAAC,IAAI,CAAC,CAAC;IAEd,MAAM,WAAW,GAAG,UAAU;SAC3B,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC;SACjC,GAAG,CAAC,CAAC,CAAC,EAAE;QACP,MAAM,MAAM,GAAG,CAAC,CAAC,YAAY,IAAI,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;YACtC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC;QAC1C,OAAO,KAAK,MAAM,MAAM,CAAC,CAAC,IAAI,QAAQ,CAAC,CAAC,WAAW,GAAG,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,mBAAmB,EAAE,CAAC;IACpG,CAAC,CAAC;SACD,IAAI,CAAC,IAAI,CAAC,CAAC;IAEd,OAAO,kBAAkB,CAAC;;;EAG1B,QAAQ;;;EAGR,WAAW;;;;;;;;;CASZ,CAAC,CAAC;AACH,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"searchSwiftContent.d.ts","sourceRoot":"","sources":["../../../src/tools/handlers/searchSwiftContent.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAkE/C,eAAO,MAAM,yBAAyB,EAAE,WAsFvC,CAAC"}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
// src/tools/handlers/searchSwiftContent.ts
|
|
2
|
+
import { searchMultipleSources, getSourceNames, fetchAllPatterns } from '../../utils/source-registry.js';
|
|
3
|
+
import { formatSearchPatterns, COMMON_FORMAT_OPTIONS, detectCodeIntent } from '../../utils/pattern-formatter.js';
|
|
4
|
+
import { createTextResponse } from '../../utils/response-helpers.js';
|
|
5
|
+
import { intentCache } from '../../utils/intent-cache.js';
|
|
6
|
+
import { SemanticRecallIndex } from '../../utils/semantic-recall.js';
|
|
7
|
+
import SourceManager from '../../config/sources.js';
|
|
8
|
+
// Module-level singleton for semantic recall index
|
|
9
|
+
let semanticIndex = null;
|
|
10
|
+
function getSemanticIndex(config) {
|
|
11
|
+
if (!semanticIndex) {
|
|
12
|
+
semanticIndex = new SemanticRecallIndex(config);
|
|
13
|
+
}
|
|
14
|
+
return semanticIndex;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Attempt semantic recall to supplement lexical results.
|
|
18
|
+
* Returns additional patterns not in lexicalResults, or empty array on failure.
|
|
19
|
+
* Handles all errors internally - never throws.
|
|
20
|
+
*/
|
|
21
|
+
async function trySemanticRecall(options) {
|
|
22
|
+
const { query, lexicalResults, config, sourceManager, requireCode } = options;
|
|
23
|
+
try {
|
|
24
|
+
// Check if semantic recall should activate
|
|
25
|
+
const maxScore = lexicalResults.length > 0
|
|
26
|
+
? Math.max(...lexicalResults.map(p => p.relevanceScore)) / 100
|
|
27
|
+
: 0;
|
|
28
|
+
const shouldActivate = lexicalResults.length === 0 || maxScore < config.minLexicalScore;
|
|
29
|
+
if (!shouldActivate)
|
|
30
|
+
return [];
|
|
31
|
+
// Get/create index and fetch patterns from enabled sources
|
|
32
|
+
const index = getSemanticIndex(config);
|
|
33
|
+
const enabledSourceIds = sourceManager.getEnabledSources().map(s => s.id);
|
|
34
|
+
const allPatterns = await fetchAllPatterns(enabledSourceIds);
|
|
35
|
+
await index.index(allPatterns);
|
|
36
|
+
// Search and filter
|
|
37
|
+
const semanticResults = await index.search(query, 5);
|
|
38
|
+
const existingIds = new Set(lexicalResults.map(p => p.id));
|
|
39
|
+
return semanticResults.filter(p => !existingIds.has(p.id) &&
|
|
40
|
+
(!requireCode || p.hasCode) &&
|
|
41
|
+
p.relevanceScore >= config.minRelevanceScore);
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
// Semantic recall is best-effort; return empty on any failure
|
|
45
|
+
return [];
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
export const searchSwiftContentHandler = async (args) => {
|
|
49
|
+
const query = args?.query;
|
|
50
|
+
const requireCode = args?.requireCode;
|
|
51
|
+
const wantsCode = detectCodeIntent(args, query);
|
|
52
|
+
if (!query) {
|
|
53
|
+
return createTextResponse(`Missing required argument: query
|
|
54
|
+
|
|
55
|
+
Usage: search_swift_content({ query: "async await" })`);
|
|
56
|
+
}
|
|
57
|
+
// Build intent key for caching
|
|
58
|
+
// This handler always uses 'all' sources and default minQuality of 0
|
|
59
|
+
const intentKey = {
|
|
60
|
+
tool: 'search_swift_content',
|
|
61
|
+
query,
|
|
62
|
+
minQuality: 0,
|
|
63
|
+
sources: getSourceNames('all'),
|
|
64
|
+
requireCode: requireCode || false,
|
|
65
|
+
};
|
|
66
|
+
// Try to get cached result
|
|
67
|
+
const cached = await intentCache.get(intentKey);
|
|
68
|
+
let filtered;
|
|
69
|
+
// Track whether this was a cache hit (to avoid re-caching)
|
|
70
|
+
let wasCacheHit = false;
|
|
71
|
+
if (cached) {
|
|
72
|
+
// Cache hit - use cached patterns (includes any semantic results from prior search)
|
|
73
|
+
filtered = cached.patterns || [];
|
|
74
|
+
wasCacheHit = true;
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
// Cache miss - fetch from sources
|
|
78
|
+
const results = await searchMultipleSources(query);
|
|
79
|
+
// Filter by code if requested
|
|
80
|
+
filtered = requireCode
|
|
81
|
+
? results.filter(r => r.hasCode)
|
|
82
|
+
: results;
|
|
83
|
+
}
|
|
84
|
+
// Semantic recall: supplement lexical results when enabled and not cached
|
|
85
|
+
const sourceManager = new SourceManager();
|
|
86
|
+
const semanticConfig = sourceManager.getSemanticRecallConfig();
|
|
87
|
+
let finalResults = filtered;
|
|
88
|
+
if (!wasCacheHit && semanticConfig.enabled) {
|
|
89
|
+
const semanticResults = await trySemanticRecall({
|
|
90
|
+
query,
|
|
91
|
+
lexicalResults: filtered,
|
|
92
|
+
config: semanticConfig,
|
|
93
|
+
sourceManager,
|
|
94
|
+
requireCode: requireCode || false,
|
|
95
|
+
});
|
|
96
|
+
if (semanticResults.length > 0) {
|
|
97
|
+
finalResults = [...filtered, ...semanticResults]
|
|
98
|
+
.sort((a, b) => b.relevanceScore - a.relevanceScore);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
// Cache final results (after semantic merge) if this was a cache miss
|
|
102
|
+
if (!wasCacheHit && finalResults.length > 0) {
|
|
103
|
+
const cacheData = {
|
|
104
|
+
patternIds: finalResults.map(p => p.id),
|
|
105
|
+
scores: Object.fromEntries(finalResults.map(p => [p.id, p.relevanceScore])),
|
|
106
|
+
totalCount: finalResults.length,
|
|
107
|
+
patterns: finalResults,
|
|
108
|
+
};
|
|
109
|
+
await intentCache.set(intentKey, cacheData);
|
|
110
|
+
}
|
|
111
|
+
if (finalResults.length === 0) {
|
|
112
|
+
return createTextResponse(`No results found for "${query}"${requireCode ? ' with code examples' : ''}.`);
|
|
113
|
+
}
|
|
114
|
+
// Format using shared utility
|
|
115
|
+
const formatted = formatSearchPatterns(finalResults, query, {
|
|
116
|
+
...COMMON_FORMAT_OPTIONS,
|
|
117
|
+
includeCode: wantsCode,
|
|
118
|
+
});
|
|
119
|
+
return createTextResponse(formatted);
|
|
120
|
+
};
|
|
121
|
+
//# sourceMappingURL=searchSwiftContent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"searchSwiftContent.js","sourceRoot":"","sources":["../../../src/tools/handlers/searchSwiftContent.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"setupPatreon.d.ts","sourceRoot":"","sources":["../../../src/tools/handlers/setupPatreon.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAG/C,eAAO,MAAM,mBAAmB,EAAE,WAuCjC,CAAC"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
// src/tools/handlers/setupPatreon.ts
|
|
2
|
+
import { createTextResponse } from '../../utils/response-helpers.js';
|
|
3
|
+
export const setupPatreonHandler = async (args, context) => {
|
|
4
|
+
if (!context.patreonSource) {
|
|
5
|
+
return createTextResponse(`Patreon integration not available.
|
|
6
|
+
|
|
7
|
+
Please ensure:
|
|
8
|
+
1. PATREON_CLIENT_ID is set in environment
|
|
9
|
+
2. PATREON_CLIENT_SECRET is set in environment
|
|
10
|
+
|
|
11
|
+
Get credentials at: https://www.patreon.com/portal/registration/register-clients`);
|
|
12
|
+
}
|
|
13
|
+
const action = args?.action || 'start';
|
|
14
|
+
if (action === 'status') {
|
|
15
|
+
const isConfigured = context.sourceManager.isSourceConfigured('patreon');
|
|
16
|
+
return createTextResponse(isConfigured
|
|
17
|
+
? `Patreon is configured and ready to use!`
|
|
18
|
+
: `Patreon is not yet configured.
|
|
19
|
+
|
|
20
|
+
Run: swift-patterns-mcp setup --patreon`);
|
|
21
|
+
}
|
|
22
|
+
return createTextResponse(`Patreon Setup
|
|
23
|
+
|
|
24
|
+
To set up Patreon integration, run:
|
|
25
|
+
\`\`\`bash
|
|
26
|
+
swift-patterns-mcp setup --patreon
|
|
27
|
+
\`\`\`
|
|
28
|
+
|
|
29
|
+
This will:
|
|
30
|
+
1. Open your browser for Patreon OAuth
|
|
31
|
+
2. Connect your subscriptions
|
|
32
|
+
3. Analyze your content
|
|
33
|
+
4. Enable premium patterns
|
|
34
|
+
|
|
35
|
+
After setup, you'll have access to:
|
|
36
|
+
- High-quality patterns from creators you support
|
|
37
|
+
- Automatic code extraction from zips
|
|
38
|
+
- Advanced filtering and search`);
|
|
39
|
+
};
|
|
40
|
+
//# sourceMappingURL=setupPatreon.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"setupPatreon.js","sourceRoot":"","sources":["../../../src/tools/handlers/setupPatreon.ts"],"names":[],"mappings":"AAAA,qCAAqC;AAGrC,OAAO,EAAE,kBAAkB,EAAE,MAAM,iCAAiC,CAAC;AAErE,MAAM,CAAC,MAAM,mBAAmB,GAAgB,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE;IACtE,IAAI,CAAC,OAAO,CAAC,aAAa,EAAE,CAAC;QAC3B,OAAO,kBAAkB,CAAC;;;;;;iFAMmD,CAAC,CAAC;IACjF,CAAC;IAED,MAAM,MAAM,GAAI,IAAI,EAAE,MAAiB,IAAI,OAAO,CAAC;IAEnD,IAAI,MAAM,KAAK,QAAQ,EAAE,CAAC;QACxB,MAAM,YAAY,GAAG,OAAO,CAAC,aAAa,CAAC,kBAAkB,CAAC,SAAS,CAAC,CAAC;QACzE,OAAO,kBAAkB,CAAC,YAAY;YACpC,CAAC,CAAC,yCAAyC;YAC3C,CAAC,CAAC;;wCAEgC,CAAC,CAAC;IACxC,CAAC;IAED,OAAO,kBAAkB,CAAC;;;;;;;;;;;;;;;;gCAgBI,CAAC,CAAC;AAClC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAEA,cAAc,YAAY,CAAC;AAC3B,cAAc,eAAe,CAAC"}
|