swift-skills 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (247) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +410 -0
  3. package/build/cli/auth.d.ts +3 -0
  4. package/build/cli/auth.d.ts.map +1 -0
  5. package/build/cli/auth.js +44 -0
  6. package/build/cli/auth.js.map +1 -0
  7. package/build/cli/setup.d.ts +2 -0
  8. package/build/cli/setup.d.ts.map +1 -0
  9. package/build/cli/setup.js +150 -0
  10. package/build/cli/setup.js.map +1 -0
  11. package/build/cli/source-manager.d.ts +3 -0
  12. package/build/cli/source-manager.d.ts.map +1 -0
  13. package/build/cli/source-manager.js +117 -0
  14. package/build/cli/source-manager.js.map +1 -0
  15. package/build/config/creators.d.ts +11 -0
  16. package/build/config/creators.d.ts.map +1 -0
  17. package/build/config/creators.js +32 -0
  18. package/build/config/creators.js.map +1 -0
  19. package/build/config/sources.d.ts +91 -0
  20. package/build/config/sources.d.ts.map +1 -0
  21. package/build/config/sources.js +231 -0
  22. package/build/config/sources.js.map +1 -0
  23. package/build/config/sources.test.d.ts +2 -0
  24. package/build/config/sources.test.d.ts.map +1 -0
  25. package/build/config/sources.test.js +199 -0
  26. package/build/config/sources.test.js.map +1 -0
  27. package/build/config/swift-keywords.d.ts +29 -0
  28. package/build/config/swift-keywords.d.ts.map +1 -0
  29. package/build/config/swift-keywords.js +77 -0
  30. package/build/config/swift-keywords.js.map +1 -0
  31. package/build/index.d.ts +3 -0
  32. package/build/index.d.ts.map +1 -0
  33. package/build/index.js +181 -0
  34. package/build/index.js.map +1 -0
  35. package/build/integration/cache-behavior.test.d.ts +2 -0
  36. package/build/integration/cache-behavior.test.d.ts.map +1 -0
  37. package/build/integration/cache-behavior.test.js +521 -0
  38. package/build/integration/cache-behavior.test.js.map +1 -0
  39. package/build/integration/mcp-client.test.d.ts +2 -0
  40. package/build/integration/mcp-client.test.d.ts.map +1 -0
  41. package/build/integration/mcp-client.test.js +82 -0
  42. package/build/integration/mcp-client.test.js.map +1 -0
  43. package/build/integration/response-quality.test.d.ts +2 -0
  44. package/build/integration/response-quality.test.d.ts.map +1 -0
  45. package/build/integration/response-quality.test.js +230 -0
  46. package/build/integration/response-quality.test.js.map +1 -0
  47. package/build/integration/test-client.d.ts +25 -0
  48. package/build/integration/test-client.d.ts.map +1 -0
  49. package/build/integration/test-client.js +93 -0
  50. package/build/integration/test-client.js.map +1 -0
  51. package/build/sources/free/nilcoalescing.d.ts +8 -0
  52. package/build/sources/free/nilcoalescing.d.ts.map +1 -0
  53. package/build/sources/free/nilcoalescing.js +26 -0
  54. package/build/sources/free/nilcoalescing.js.map +1 -0
  55. package/build/sources/free/nilcoalescing.test.d.ts +2 -0
  56. package/build/sources/free/nilcoalescing.test.d.ts.map +1 -0
  57. package/build/sources/free/nilcoalescing.test.js +63 -0
  58. package/build/sources/free/nilcoalescing.test.js.map +1 -0
  59. package/build/sources/free/pointfree.d.ts +15 -0
  60. package/build/sources/free/pointfree.d.ts.map +1 -0
  61. package/build/sources/free/pointfree.js +175 -0
  62. package/build/sources/free/pointfree.js.map +1 -0
  63. package/build/sources/free/pointfree.test.d.ts +2 -0
  64. package/build/sources/free/pointfree.test.d.ts.map +1 -0
  65. package/build/sources/free/pointfree.test.js +86 -0
  66. package/build/sources/free/pointfree.test.js.map +1 -0
  67. package/build/sources/free/rssPatternSource.d.ts +42 -0
  68. package/build/sources/free/rssPatternSource.d.ts.map +1 -0
  69. package/build/sources/free/rssPatternSource.js +109 -0
  70. package/build/sources/free/rssPatternSource.js.map +1 -0
  71. package/build/sources/free/rssPatternSource.test.d.ts +2 -0
  72. package/build/sources/free/rssPatternSource.test.d.ts.map +1 -0
  73. package/build/sources/free/rssPatternSource.test.js +89 -0
  74. package/build/sources/free/rssPatternSource.test.js.map +1 -0
  75. package/build/sources/free/sundell.d.ts +8 -0
  76. package/build/sources/free/sundell.d.ts.map +1 -0
  77. package/build/sources/free/sundell.js +17 -0
  78. package/build/sources/free/sundell.js.map +1 -0
  79. package/build/sources/free/sundell.test.d.ts +2 -0
  80. package/build/sources/free/sundell.test.d.ts.map +1 -0
  81. package/build/sources/free/sundell.test.js +63 -0
  82. package/build/sources/free/sundell.test.js.map +1 -0
  83. package/build/sources/free/vanderlee.d.ts +8 -0
  84. package/build/sources/free/vanderlee.d.ts.map +1 -0
  85. package/build/sources/free/vanderlee.js +63 -0
  86. package/build/sources/free/vanderlee.js.map +1 -0
  87. package/build/sources/free/vanderlee.test.d.ts +2 -0
  88. package/build/sources/free/vanderlee.test.d.ts.map +1 -0
  89. package/build/sources/free/vanderlee.test.js +77 -0
  90. package/build/sources/free/vanderlee.test.js.map +1 -0
  91. package/build/sources/premium/patreon-dl.d.ts +45 -0
  92. package/build/sources/premium/patreon-dl.d.ts.map +1 -0
  93. package/build/sources/premium/patreon-dl.js +189 -0
  94. package/build/sources/premium/patreon-dl.js.map +1 -0
  95. package/build/sources/premium/patreon-fetch.d.ts +3 -0
  96. package/build/sources/premium/patreon-fetch.d.ts.map +1 -0
  97. package/build/sources/premium/patreon-fetch.js +18 -0
  98. package/build/sources/premium/patreon-fetch.js.map +1 -0
  99. package/build/sources/premium/patreon-oauth.d.ts +24 -0
  100. package/build/sources/premium/patreon-oauth.d.ts.map +1 -0
  101. package/build/sources/premium/patreon-oauth.js +208 -0
  102. package/build/sources/premium/patreon-oauth.js.map +1 -0
  103. package/build/sources/premium/patreon-zip.d.ts +17 -0
  104. package/build/sources/premium/patreon-zip.d.ts.map +1 -0
  105. package/build/sources/premium/patreon-zip.js +127 -0
  106. package/build/sources/premium/patreon-zip.js.map +1 -0
  107. package/build/sources/premium/patreon.d.ts +48 -0
  108. package/build/sources/premium/patreon.d.ts.map +1 -0
  109. package/build/sources/premium/patreon.js +221 -0
  110. package/build/sources/premium/patreon.js.map +1 -0
  111. package/build/sources/premium/youtube.d.ts +14 -0
  112. package/build/sources/premium/youtube.d.ts.map +1 -0
  113. package/build/sources/premium/youtube.js +92 -0
  114. package/build/sources/premium/youtube.js.map +1 -0
  115. package/build/tools/extract-cookie.d.ts +2 -0
  116. package/build/tools/extract-cookie.d.ts.map +1 -0
  117. package/build/tools/extract-cookie.js +40 -0
  118. package/build/tools/extract-cookie.js.map +1 -0
  119. package/build/tools/handlers/enableSource.d.ts +3 -0
  120. package/build/tools/handlers/enableSource.d.ts.map +1 -0
  121. package/build/tools/handlers/enableSource.js +25 -0
  122. package/build/tools/handlers/enableSource.js.map +1 -0
  123. package/build/tools/handlers/getPatreonPatterns.d.ts +3 -0
  124. package/build/tools/handlers/getPatreonPatterns.d.ts.map +1 -0
  125. package/build/tools/handlers/getPatreonPatterns.js +43 -0
  126. package/build/tools/handlers/getPatreonPatterns.js.map +1 -0
  127. package/build/tools/handlers/getSwiftPattern.d.ts +3 -0
  128. package/build/tools/handlers/getSwiftPattern.d.ts.map +1 -0
  129. package/build/tools/handlers/getSwiftPattern.js +72 -0
  130. package/build/tools/handlers/getSwiftPattern.js.map +1 -0
  131. package/build/tools/handlers/handlers.test.d.ts +2 -0
  132. package/build/tools/handlers/handlers.test.d.ts.map +1 -0
  133. package/build/tools/handlers/handlers.test.js +359 -0
  134. package/build/tools/handlers/handlers.test.js.map +1 -0
  135. package/build/tools/handlers/listContentSources.d.ts +3 -0
  136. package/build/tools/handlers/listContentSources.d.ts.map +1 -0
  137. package/build/tools/handlers/listContentSources.js +34 -0
  138. package/build/tools/handlers/listContentSources.js.map +1 -0
  139. package/build/tools/handlers/searchSwiftContent.d.ts +3 -0
  140. package/build/tools/handlers/searchSwiftContent.d.ts.map +1 -0
  141. package/build/tools/handlers/searchSwiftContent.js +121 -0
  142. package/build/tools/handlers/searchSwiftContent.js.map +1 -0
  143. package/build/tools/handlers/setupPatreon.d.ts +3 -0
  144. package/build/tools/handlers/setupPatreon.d.ts.map +1 -0
  145. package/build/tools/handlers/setupPatreon.js +40 -0
  146. package/build/tools/handlers/setupPatreon.js.map +1 -0
  147. package/build/tools/index.d.ts +3 -0
  148. package/build/tools/index.d.ts.map +1 -0
  149. package/build/tools/index.js +18 -0
  150. package/build/tools/index.js.map +1 -0
  151. package/build/tools/registry.d.ts +14 -0
  152. package/build/tools/registry.d.ts.map +1 -0
  153. package/build/tools/registry.js +21 -0
  154. package/build/tools/registry.js.map +1 -0
  155. package/build/tools/registry.test.d.ts +2 -0
  156. package/build/tools/registry.test.d.ts.map +1 -0
  157. package/build/tools/registry.test.js +54 -0
  158. package/build/tools/registry.test.js.map +1 -0
  159. package/build/tools/types.d.ts +67 -0
  160. package/build/tools/types.d.ts.map +1 -0
  161. package/build/tools/types.js +3 -0
  162. package/build/tools/types.js.map +1 -0
  163. package/build/utils/cache.d.ts +20 -0
  164. package/build/utils/cache.d.ts.map +1 -0
  165. package/build/utils/cache.js +186 -0
  166. package/build/utils/cache.js.map +1 -0
  167. package/build/utils/concurrency.d.ts +13 -0
  168. package/build/utils/concurrency.d.ts.map +1 -0
  169. package/build/utils/concurrency.js +33 -0
  170. package/build/utils/concurrency.js.map +1 -0
  171. package/build/utils/errors.d.ts +19 -0
  172. package/build/utils/errors.d.ts.map +1 -0
  173. package/build/utils/errors.js +35 -0
  174. package/build/utils/errors.js.map +1 -0
  175. package/build/utils/fetch.d.ts +6 -0
  176. package/build/utils/fetch.d.ts.map +1 -0
  177. package/build/utils/fetch.js +6 -0
  178. package/build/utils/fetch.js.map +1 -0
  179. package/build/utils/http.d.ts +21 -0
  180. package/build/utils/http.d.ts.map +1 -0
  181. package/build/utils/http.js +53 -0
  182. package/build/utils/http.js.map +1 -0
  183. package/build/utils/intent-cache.d.ts +94 -0
  184. package/build/utils/intent-cache.d.ts.map +1 -0
  185. package/build/utils/intent-cache.js +164 -0
  186. package/build/utils/intent-cache.js.map +1 -0
  187. package/build/utils/intent-cache.test.d.ts +2 -0
  188. package/build/utils/intent-cache.test.d.ts.map +1 -0
  189. package/build/utils/intent-cache.test.js +290 -0
  190. package/build/utils/intent-cache.test.js.map +1 -0
  191. package/build/utils/logger.d.ts +4 -0
  192. package/build/utils/logger.d.ts.map +1 -0
  193. package/build/utils/logger.js +9 -0
  194. package/build/utils/logger.js.map +1 -0
  195. package/build/utils/paths.d.ts +27 -0
  196. package/build/utils/paths.d.ts.map +1 -0
  197. package/build/utils/paths.js +43 -0
  198. package/build/utils/paths.js.map +1 -0
  199. package/build/utils/pattern-formatter.d.ts +40 -0
  200. package/build/utils/pattern-formatter.d.ts.map +1 -0
  201. package/build/utils/pattern-formatter.js +124 -0
  202. package/build/utils/pattern-formatter.js.map +1 -0
  203. package/build/utils/response-helpers.d.ts +17 -0
  204. package/build/utils/response-helpers.d.ts.map +1 -0
  205. package/build/utils/response-helpers.js +34 -0
  206. package/build/utils/response-helpers.js.map +1 -0
  207. package/build/utils/search-terms.d.ts +17 -0
  208. package/build/utils/search-terms.d.ts.map +1 -0
  209. package/build/utils/search-terms.js +71 -0
  210. package/build/utils/search-terms.js.map +1 -0
  211. package/build/utils/search-terms.test.d.ts +2 -0
  212. package/build/utils/search-terms.test.d.ts.map +1 -0
  213. package/build/utils/search-terms.test.js +107 -0
  214. package/build/utils/search-terms.test.js.map +1 -0
  215. package/build/utils/search.d.ts +48 -0
  216. package/build/utils/search.d.ts.map +1 -0
  217. package/build/utils/search.js +158 -0
  218. package/build/utils/search.js.map +1 -0
  219. package/build/utils/search.test.d.ts +2 -0
  220. package/build/utils/search.test.d.ts.map +1 -0
  221. package/build/utils/search.test.js +199 -0
  222. package/build/utils/search.test.js.map +1 -0
  223. package/build/utils/semantic-recall.d.ts +38 -0
  224. package/build/utils/semantic-recall.d.ts.map +1 -0
  225. package/build/utils/semantic-recall.js +134 -0
  226. package/build/utils/semantic-recall.js.map +1 -0
  227. package/build/utils/semantic-recall.test.d.ts +2 -0
  228. package/build/utils/semantic-recall.test.d.ts.map +1 -0
  229. package/build/utils/semantic-recall.test.js +326 -0
  230. package/build/utils/semantic-recall.test.js.map +1 -0
  231. package/build/utils/source-registry.d.ts +45 -0
  232. package/build/utils/source-registry.d.ts.map +1 -0
  233. package/build/utils/source-registry.js +113 -0
  234. package/build/utils/source-registry.js.map +1 -0
  235. package/build/utils/source-registry.test.d.ts +2 -0
  236. package/build/utils/source-registry.test.d.ts.map +1 -0
  237. package/build/utils/source-registry.test.js +206 -0
  238. package/build/utils/source-registry.test.js.map +1 -0
  239. package/build/utils/swift-analysis.d.ts +61 -0
  240. package/build/utils/swift-analysis.d.ts.map +1 -0
  241. package/build/utils/swift-analysis.js +339 -0
  242. package/build/utils/swift-analysis.js.map +1 -0
  243. package/build/utils/swift-analysis.test.d.ts +2 -0
  244. package/build/utils/swift-analysis.test.d.ts.map +1 -0
  245. package/build/utils/swift-analysis.test.js +473 -0
  246. package/build/utils/swift-analysis.test.js.map +1 -0
  247. package/package.json +85 -0
@@ -0,0 +1,521 @@
1
+ // src/integration/cache-behavior.test.ts
2
+ // Integration tests for IntentCache behavior and performance metrics
3
+ import { describe, it, expect, beforeEach } from 'vitest';
4
+ import { intentCache } from '../utils/intent-cache.js';
5
+ // Test fixtures - known patterns with specific properties for testing
6
+ const MOCK_PATTERNS = [
7
+ {
8
+ id: 'sundell-1',
9
+ title: 'Advanced SwiftUI Patterns',
10
+ url: 'https://swiftbysundell.com/swiftui',
11
+ excerpt: 'Learn advanced SwiftUI patterns for production apps',
12
+ content: 'Full content about SwiftUI state management and views',
13
+ topics: ['swiftui', 'architecture'],
14
+ relevanceScore: 85,
15
+ hasCode: true,
16
+ publishDate: '2024-01-15T00:00:00Z',
17
+ },
18
+ {
19
+ id: 'sundell-2',
20
+ title: 'Basic Swift Tips',
21
+ url: 'https://swiftbysundell.com/tips',
22
+ excerpt: 'Simple tips for Swift developers',
23
+ content: 'Basic content without code examples',
24
+ topics: ['swift'],
25
+ relevanceScore: 55,
26
+ hasCode: false,
27
+ publishDate: '2024-01-10T00:00:00Z',
28
+ },
29
+ ];
30
+ describe('IntentCache - Cache Hit/Miss Behavior', () => {
31
+ beforeEach(() => {
32
+ // Clear cache before each test to isolate tests
33
+ intentCache.clear();
34
+ });
35
+ it('should cache miss on first call, cache hit on second identical call', async () => {
36
+ const intent = {
37
+ tool: 'get_swift_pattern',
38
+ query: 'swiftui patterns',
39
+ minQuality: 60,
40
+ sources: ['sundell', 'vanderlee'],
41
+ };
42
+ // First call - cache miss
43
+ const firstResult = await intentCache.get(intent);
44
+ expect(firstResult).toBeNull();
45
+ // Store result in cache
46
+ const cacheData = {
47
+ patternIds: MOCK_PATTERNS.map(p => p.id),
48
+ scores: Object.fromEntries(MOCK_PATTERNS.map(p => [p.id, p.relevanceScore])),
49
+ totalCount: MOCK_PATTERNS.length,
50
+ patterns: MOCK_PATTERNS,
51
+ };
52
+ await intentCache.set(intent, cacheData);
53
+ // Second call - cache hit
54
+ const secondResult = await intentCache.get(intent);
55
+ expect(secondResult).not.toBeNull();
56
+ expect(secondResult?.patternIds).toEqual(MOCK_PATTERNS.map(p => p.id));
57
+ expect(secondResult?.patterns).toEqual(MOCK_PATTERNS);
58
+ });
59
+ it('should cache miss when topic changes', async () => {
60
+ const intent1 = {
61
+ tool: 'get_swift_pattern',
62
+ query: 'swiftui',
63
+ minQuality: 60,
64
+ sources: ['sundell'],
65
+ };
66
+ const intent2 = {
67
+ tool: 'get_swift_pattern',
68
+ query: 'combine',
69
+ minQuality: 60,
70
+ sources: ['sundell'],
71
+ };
72
+ // Cache first intent
73
+ const cacheData = {
74
+ patternIds: ['sundell-1'],
75
+ scores: { 'sundell-1': 85 },
76
+ totalCount: 1,
77
+ patterns: [MOCK_PATTERNS[0]],
78
+ };
79
+ await intentCache.set(intent1, cacheData);
80
+ // Different topic should miss
81
+ const result = await intentCache.get(intent2);
82
+ expect(result).toBeNull();
83
+ });
84
+ it('should cache miss when minQuality changes', async () => {
85
+ const intent1 = {
86
+ tool: 'get_swift_pattern',
87
+ query: 'swiftui',
88
+ minQuality: 60,
89
+ sources: ['sundell'],
90
+ };
91
+ const intent2 = {
92
+ tool: 'get_swift_pattern',
93
+ query: 'swiftui',
94
+ minQuality: 70,
95
+ sources: ['sundell'],
96
+ };
97
+ // Cache first intent
98
+ const cacheData = {
99
+ patternIds: MOCK_PATTERNS.map(p => p.id),
100
+ scores: Object.fromEntries(MOCK_PATTERNS.map(p => [p.id, p.relevanceScore])),
101
+ totalCount: MOCK_PATTERNS.length,
102
+ patterns: MOCK_PATTERNS,
103
+ };
104
+ await intentCache.set(intent1, cacheData);
105
+ // Different minQuality should miss
106
+ const result = await intentCache.get(intent2);
107
+ expect(result).toBeNull();
108
+ });
109
+ it('should cache miss when requireCode changes', async () => {
110
+ const intent1 = {
111
+ tool: 'search_swift_content',
112
+ query: 'async await',
113
+ minQuality: 0,
114
+ sources: ['sundell'],
115
+ requireCode: false,
116
+ };
117
+ const intent2 = {
118
+ tool: 'search_swift_content',
119
+ query: 'async await',
120
+ minQuality: 0,
121
+ sources: ['sundell'],
122
+ requireCode: true,
123
+ };
124
+ // Cache first intent
125
+ const cacheData = {
126
+ patternIds: MOCK_PATTERNS.map(p => p.id),
127
+ scores: Object.fromEntries(MOCK_PATTERNS.map(p => [p.id, p.relevanceScore])),
128
+ totalCount: MOCK_PATTERNS.length,
129
+ patterns: MOCK_PATTERNS,
130
+ };
131
+ await intentCache.set(intent1, cacheData);
132
+ // Different requireCode should miss
133
+ const result = await intentCache.get(intent2);
134
+ expect(result).toBeNull();
135
+ });
136
+ it('should cache miss when sources change', async () => {
137
+ const intent1 = {
138
+ tool: 'get_swift_pattern',
139
+ query: 'swiftui',
140
+ minQuality: 60,
141
+ sources: ['sundell'],
142
+ };
143
+ const intent2 = {
144
+ tool: 'get_swift_pattern',
145
+ query: 'swiftui',
146
+ minQuality: 60,
147
+ sources: ['sundell', 'vanderlee'],
148
+ };
149
+ // Cache first intent
150
+ const cacheData = {
151
+ patternIds: ['sundell-1'],
152
+ scores: { 'sundell-1': 85 },
153
+ totalCount: 1,
154
+ patterns: [MOCK_PATTERNS[0]],
155
+ };
156
+ await intentCache.set(intent1, cacheData);
157
+ // Different sources should miss (source fingerprint changed)
158
+ const result = await intentCache.get(intent2);
159
+ expect(result).toBeNull();
160
+ });
161
+ it('should persist cache across multiple calls with same intent', async () => {
162
+ const intent = {
163
+ tool: 'get_swift_pattern',
164
+ query: 'swiftui',
165
+ minQuality: 60,
166
+ sources: ['sundell', 'vanderlee'],
167
+ };
168
+ // Cache the intent
169
+ const cacheData = {
170
+ patternIds: MOCK_PATTERNS.map(p => p.id),
171
+ scores: Object.fromEntries(MOCK_PATTERNS.map(p => [p.id, p.relevanceScore])),
172
+ totalCount: MOCK_PATTERNS.length,
173
+ patterns: MOCK_PATTERNS,
174
+ };
175
+ await intentCache.set(intent, cacheData);
176
+ // Multiple calls should all hit cache
177
+ const result1 = await intentCache.get(intent);
178
+ const result2 = await intentCache.get(intent);
179
+ const result3 = await intentCache.get(intent);
180
+ expect(result1).not.toBeNull();
181
+ expect(result2).not.toBeNull();
182
+ expect(result3).not.toBeNull();
183
+ expect(result1?.patternIds).toEqual(result2?.patternIds);
184
+ expect(result2?.patternIds).toEqual(result3?.patternIds);
185
+ });
186
+ });
187
+ describe('IntentCache - Cache Metrics', () => {
188
+ beforeEach(() => {
189
+ intentCache.clear();
190
+ });
191
+ it('should return 0/0 stats initially after clear', () => {
192
+ const stats = intentCache.getStats();
193
+ expect(stats.hits).toBe(0);
194
+ expect(stats.misses).toBe(0);
195
+ expect(stats.hitRate).toBe(0);
196
+ });
197
+ it('should increment miss count on cache miss', async () => {
198
+ const intent = {
199
+ tool: 'get_swift_pattern',
200
+ query: 'swiftui',
201
+ minQuality: 60,
202
+ sources: ['sundell'],
203
+ };
204
+ await intentCache.get(intent);
205
+ const stats = intentCache.getStats();
206
+ expect(stats.misses).toBe(1);
207
+ expect(stats.hits).toBe(0);
208
+ });
209
+ it('should increment hit count on cache hit', async () => {
210
+ const intent = {
211
+ tool: 'get_swift_pattern',
212
+ query: 'swiftui',
213
+ minQuality: 60,
214
+ sources: ['sundell'],
215
+ };
216
+ // Cache the intent
217
+ const cacheData = {
218
+ patternIds: ['sundell-1'],
219
+ scores: { 'sundell-1': 85 },
220
+ totalCount: 1,
221
+ patterns: [MOCK_PATTERNS[0]],
222
+ };
223
+ await intentCache.set(intent, cacheData);
224
+ // Hit the cache
225
+ await intentCache.get(intent);
226
+ const stats = intentCache.getStats();
227
+ expect(stats.hits).toBe(1);
228
+ expect(stats.misses).toBe(0);
229
+ });
230
+ it('should calculate hit rate correctly', async () => {
231
+ const intent1 = {
232
+ tool: 'get_swift_pattern',
233
+ query: 'swiftui',
234
+ minQuality: 60,
235
+ sources: ['sundell'],
236
+ };
237
+ const intent2 = {
238
+ tool: 'get_swift_pattern',
239
+ query: 'combine',
240
+ minQuality: 60,
241
+ sources: ['sundell'],
242
+ };
243
+ // Cache intent1
244
+ const cacheData = {
245
+ patternIds: ['sundell-1'],
246
+ scores: { 'sundell-1': 85 },
247
+ totalCount: 1,
248
+ patterns: [MOCK_PATTERNS[0]],
249
+ };
250
+ await intentCache.set(intent1, cacheData);
251
+ // 2 hits (intent1)
252
+ await intentCache.get(intent1);
253
+ await intentCache.get(intent1);
254
+ // 2 misses (intent2)
255
+ await intentCache.get(intent2);
256
+ await intentCache.get(intent2);
257
+ // Total: 2 hits + 2 misses = 4 requests
258
+ // Hit rate: 2/4 = 0.5
259
+ const stats = intentCache.getStats();
260
+ expect(stats.hits).toBe(2);
261
+ expect(stats.misses).toBe(2);
262
+ expect(stats.hitRate).toBe(0.5);
263
+ });
264
+ it('should reset metrics after clear', async () => {
265
+ const intent = {
266
+ tool: 'get_swift_pattern',
267
+ query: 'swiftui',
268
+ minQuality: 60,
269
+ sources: ['sundell'],
270
+ };
271
+ // Generate some cache activity
272
+ await intentCache.get(intent); // miss
273
+ const cacheData = {
274
+ patternIds: ['sundell-1'],
275
+ scores: { 'sundell-1': 85 },
276
+ totalCount: 1,
277
+ };
278
+ await intentCache.set(intent, cacheData);
279
+ await intentCache.get(intent); // hit
280
+ // Verify stats exist
281
+ let stats = intentCache.getStats();
282
+ expect(stats.hits).toBe(1);
283
+ expect(stats.misses).toBe(1);
284
+ // Clear cache
285
+ intentCache.clear();
286
+ // Verify stats reset
287
+ stats = intentCache.getStats();
288
+ expect(stats.hits).toBe(0);
289
+ expect(stats.misses).toBe(0);
290
+ expect(stats.hitRate).toBe(0);
291
+ });
292
+ it('should track metrics separately for different tools', async () => {
293
+ const getPatternIntent = {
294
+ tool: 'get_swift_pattern',
295
+ query: 'swiftui',
296
+ minQuality: 60,
297
+ sources: ['sundell'],
298
+ };
299
+ const searchIntent = {
300
+ tool: 'search_swift_content',
301
+ query: 'swiftui',
302
+ minQuality: 0,
303
+ sources: ['sundell'],
304
+ };
305
+ // Cache get_swift_pattern
306
+ const cacheData1 = {
307
+ patternIds: ['sundell-1'],
308
+ scores: { 'sundell-1': 85 },
309
+ totalCount: 1,
310
+ };
311
+ await intentCache.set(getPatternIntent, cacheData1);
312
+ // Cache search_swift_content
313
+ const cacheData2 = {
314
+ patternIds: ['sundell-1'],
315
+ scores: { 'sundell-1': 85 },
316
+ totalCount: 1,
317
+ };
318
+ await intentCache.set(searchIntent, cacheData2);
319
+ // Hit both caches
320
+ await intentCache.get(getPatternIntent); // hit
321
+ await intentCache.get(searchIntent); // hit
322
+ // Both should register as hits
323
+ const stats = intentCache.getStats();
324
+ expect(stats.hits).toBe(2);
325
+ expect(stats.misses).toBe(0);
326
+ });
327
+ });
328
+ describe('IntentCache - Cross-Handler Cache Isolation', () => {
329
+ beforeEach(() => {
330
+ intentCache.clear();
331
+ });
332
+ it('should use separate cache keys for different tools with same query', async () => {
333
+ const getPatternIntent = {
334
+ tool: 'get_swift_pattern',
335
+ query: 'swiftui',
336
+ minQuality: 60,
337
+ sources: ['sundell'],
338
+ };
339
+ const searchIntent = {
340
+ tool: 'search_swift_content',
341
+ query: 'swiftui',
342
+ minQuality: 60,
343
+ sources: ['sundell'],
344
+ };
345
+ // Cache get_swift_pattern
346
+ const cacheData = {
347
+ patternIds: ['sundell-1'],
348
+ scores: { 'sundell-1': 85 },
349
+ totalCount: 1,
350
+ patterns: [MOCK_PATTERNS[0]],
351
+ };
352
+ await intentCache.set(getPatternIntent, cacheData);
353
+ // search_swift_content with same query should miss (different tool)
354
+ const result = await intentCache.get(searchIntent);
355
+ expect(result).toBeNull();
356
+ });
357
+ it('should cache same query independently for different handlers', async () => {
358
+ const getPatternIntent = {
359
+ tool: 'get_swift_pattern',
360
+ query: 'swiftui',
361
+ minQuality: 60,
362
+ sources: ['sundell'],
363
+ };
364
+ const searchIntent = {
365
+ tool: 'search_swift_content',
366
+ query: 'swiftui',
367
+ minQuality: 0,
368
+ sources: ['sundell'],
369
+ };
370
+ // Cache for both handlers
371
+ const cacheData1 = {
372
+ patternIds: ['sundell-1'],
373
+ scores: { 'sundell-1': 85 },
374
+ totalCount: 1,
375
+ patterns: [MOCK_PATTERNS[0]],
376
+ };
377
+ await intentCache.set(getPatternIntent, cacheData1);
378
+ const cacheData2 = {
379
+ patternIds: ['sundell-1', 'sundell-2'],
380
+ scores: { 'sundell-1': 85, 'sundell-2': 55 },
381
+ totalCount: 2,
382
+ patterns: MOCK_PATTERNS,
383
+ };
384
+ await intentCache.set(searchIntent, cacheData2);
385
+ // Both should hit their respective caches
386
+ const result1 = await intentCache.get(getPatternIntent);
387
+ const result2 = await intentCache.get(searchIntent);
388
+ expect(result1).not.toBeNull();
389
+ expect(result2).not.toBeNull();
390
+ expect(result1?.totalCount).toBe(1);
391
+ expect(result2?.totalCount).toBe(2);
392
+ });
393
+ });
394
+ describe('IntentCache - Stampede Prevention', () => {
395
+ beforeEach(() => {
396
+ intentCache.clear();
397
+ });
398
+ it('should deduplicate concurrent identical requests', async () => {
399
+ const intent = {
400
+ tool: 'get_swift_pattern',
401
+ query: 'swiftui',
402
+ minQuality: 60,
403
+ sources: ['sundell'],
404
+ };
405
+ let fetchCount = 0;
406
+ const slowFetcher = async () => {
407
+ fetchCount++;
408
+ // Simulate slow fetch (50ms delay)
409
+ await new Promise(resolve => setTimeout(resolve, 50));
410
+ return {
411
+ patternIds: ['sundell-1'],
412
+ scores: { 'sundell-1': 85 },
413
+ totalCount: 1,
414
+ patterns: [MOCK_PATTERNS[0]],
415
+ };
416
+ };
417
+ // Make 5 concurrent requests
418
+ const promises = [
419
+ intentCache.getOrFetch(intent, slowFetcher),
420
+ intentCache.getOrFetch(intent, slowFetcher),
421
+ intentCache.getOrFetch(intent, slowFetcher),
422
+ intentCache.getOrFetch(intent, slowFetcher),
423
+ intentCache.getOrFetch(intent, slowFetcher),
424
+ ];
425
+ const results = await Promise.all(promises);
426
+ // Should only fetch once (stampede prevention)
427
+ expect(fetchCount).toBe(1);
428
+ // All promises should resolve to same result
429
+ expect(results).toHaveLength(5);
430
+ results.forEach(result => {
431
+ expect(result.patternIds).toEqual(['sundell-1']);
432
+ expect(result.totalCount).toBe(1);
433
+ });
434
+ });
435
+ it('should fetch separately for different intents', async () => {
436
+ const intent1 = {
437
+ tool: 'get_swift_pattern',
438
+ query: 'swiftui',
439
+ minQuality: 60,
440
+ sources: ['sundell'],
441
+ };
442
+ const intent2 = {
443
+ tool: 'get_swift_pattern',
444
+ query: 'combine',
445
+ minQuality: 60,
446
+ sources: ['sundell'],
447
+ };
448
+ const intent3 = {
449
+ tool: 'search_swift_content',
450
+ query: 'async',
451
+ minQuality: 0,
452
+ sources: ['sundell'],
453
+ };
454
+ let fetchCount = 0;
455
+ const slowFetcher = async (intentId) => {
456
+ fetchCount++;
457
+ await new Promise(resolve => setTimeout(resolve, 30));
458
+ return {
459
+ patternIds: [intentId],
460
+ scores: { [intentId]: 85 },
461
+ totalCount: 1,
462
+ };
463
+ };
464
+ // Make concurrent requests for different intents
465
+ const promises = [
466
+ intentCache.getOrFetch(intent1, () => slowFetcher('intent1')),
467
+ intentCache.getOrFetch(intent2, () => slowFetcher('intent2')),
468
+ intentCache.getOrFetch(intent3, () => slowFetcher('intent3')),
469
+ ];
470
+ const results = await Promise.all(promises);
471
+ // Should fetch once per unique intent (3 total)
472
+ expect(fetchCount).toBe(3);
473
+ // Each result should be different
474
+ expect(results[0].patternIds).toEqual(['intent1']);
475
+ expect(results[1].patternIds).toEqual(['intent2']);
476
+ expect(results[2].patternIds).toEqual(['intent3']);
477
+ });
478
+ it('should not cross-contaminate results for different intents', async () => {
479
+ const intent1 = {
480
+ tool: 'get_swift_pattern',
481
+ query: 'swiftui',
482
+ minQuality: 60,
483
+ sources: ['sundell'],
484
+ };
485
+ const intent2 = {
486
+ tool: 'get_swift_pattern',
487
+ query: 'combine',
488
+ minQuality: 60,
489
+ sources: ['sundell'],
490
+ };
491
+ const fetcher1 = async () => {
492
+ await new Promise(resolve => setTimeout(resolve, 30));
493
+ return {
494
+ patternIds: ['sundell-1'],
495
+ scores: { 'sundell-1': 85 },
496
+ totalCount: 1,
497
+ patterns: [MOCK_PATTERNS[0]],
498
+ };
499
+ };
500
+ const fetcher2 = async () => {
501
+ await new Promise(resolve => setTimeout(resolve, 30));
502
+ return {
503
+ patternIds: ['sundell-2'],
504
+ scores: { 'sundell-2': 55 },
505
+ totalCount: 1,
506
+ patterns: [MOCK_PATTERNS[1]],
507
+ };
508
+ };
509
+ // Make concurrent requests for different intents
510
+ const [result1, result2] = await Promise.all([
511
+ intentCache.getOrFetch(intent1, fetcher1),
512
+ intentCache.getOrFetch(intent2, fetcher2),
513
+ ]);
514
+ // Results should be distinct, no cross-contamination
515
+ expect(result1.patternIds).toEqual(['sundell-1']);
516
+ expect(result2.patternIds).toEqual(['sundell-2']);
517
+ expect(result1.patterns).toEqual([MOCK_PATTERNS[0]]);
518
+ expect(result2.patterns).toEqual([MOCK_PATTERNS[1]]);
519
+ });
520
+ });
521
+ //# sourceMappingURL=cache-behavior.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache-behavior.test.js","sourceRoot":"","sources":["../../src/integration/cache-behavior.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=mcp-client.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-client.test.d.ts","sourceRoot":"","sources":["../../src/integration/mcp-client.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,82 @@
1
+ // src/integration/mcp-client.test.ts
2
+ // Integration tests for MCP protocol handshake and tool invocation
3
+ // Skipped on CI due to native dependency issues (keytar)
4
+ import { describe, it, expect, beforeAll, afterAll } from 'vitest';
5
+ import { MCPTestClient, isCI } from './test-client.js';
6
+ const describeIntegration = isCI ? describe.skip : describe;
7
+ describeIntegration('MCP Server Integration', () => {
8
+ let client;
9
+ beforeAll(async () => {
10
+ client = new MCPTestClient();
11
+ await client.start();
12
+ }, 10000);
13
+ afterAll(async () => {
14
+ await client.stop();
15
+ });
16
+ describe('Protocol Handshake', () => {
17
+ it('should initialize with correct protocol version', async () => {
18
+ const response = await client.initialize();
19
+ expect(response.error).toBeUndefined();
20
+ expect(response.result).toBeDefined();
21
+ const result = response.result;
22
+ expect(result.protocolVersion).toBe('2024-11-05');
23
+ expect(result.serverInfo.name).toBe('swift-patterns-mcp');
24
+ });
25
+ it('should list available tools', async () => {
26
+ const response = await client.listTools();
27
+ expect(response.error).toBeUndefined();
28
+ const result = response.result;
29
+ expect(result.tools).toBeDefined();
30
+ expect(result.tools.length).toBeGreaterThanOrEqual(4);
31
+ const toolNames = result.tools.map(t => t.name);
32
+ expect(toolNames).toContain('get_swift_pattern');
33
+ expect(toolNames).toContain('search_swift_content');
34
+ expect(toolNames).toContain('list_content_sources');
35
+ expect(toolNames).toContain('enable_source');
36
+ });
37
+ });
38
+ describe('Tool Invocation', () => {
39
+ it('should call list_content_sources successfully', async () => {
40
+ const response = await client.callTool('list_content_sources');
41
+ expect(response.error).toBeUndefined();
42
+ const result = response.result;
43
+ expect(result.content).toBeDefined();
44
+ expect(result.content[0].type).toBe('text');
45
+ expect(result.content[0].text).toContain('Content Sources');
46
+ });
47
+ it('should call get_swift_pattern with topic', async () => {
48
+ const response = await client.callTool('get_swift_pattern', {
49
+ topic: 'swiftui',
50
+ minQuality: 70,
51
+ });
52
+ expect(response.error).toBeUndefined();
53
+ const result = response.result;
54
+ expect(result.content).toBeDefined();
55
+ expect(result.content[0].text.length).toBeGreaterThan(0);
56
+ }, 60000);
57
+ it('should handle enable_source with unknown source', async () => {
58
+ const response = await client.callTool('enable_source', {
59
+ source: 'unknown_source',
60
+ });
61
+ expect(response.error).toBeUndefined();
62
+ const result = response.result;
63
+ expect(result.content[0].text).toContain('Unknown source');
64
+ });
65
+ });
66
+ describe('Error Handling', () => {
67
+ it('should handle unknown tool gracefully', async () => {
68
+ const response = await client.callTool('nonexistent_tool');
69
+ const result = response.result;
70
+ if (result.isError) {
71
+ expect(result.content[0].text).toContain('Unknown tool');
72
+ }
73
+ });
74
+ it('should handle missing required arguments gracefully', async () => {
75
+ const response = await client.callTool('get_swift_pattern', {});
76
+ expect(response.error).toBeUndefined();
77
+ const result = response.result;
78
+ expect(result.content[0].text).toContain('Missing required argument');
79
+ }, 30000);
80
+ });
81
+ });
82
+ //# sourceMappingURL=mcp-client.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-client.test.js","sourceRoot":"","sources":["../../src/integration/mcp-client.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=response-quality.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"response-quality.test.d.ts","sourceRoot":"","sources":["../../src/integration/response-quality.test.ts"],"names":[],"mappings":""}