@skillsmith/core 0.2.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (233) hide show
  1. package/README.md +233 -2
  2. package/dist/.tsbuildinfo +1 -1
  3. package/dist/src/analysis/__tests__/incremental.test.d.ts +13 -0
  4. package/dist/src/analysis/__tests__/incremental.test.d.ts.map +1 -0
  5. package/dist/src/analysis/__tests__/incremental.test.js +515 -0
  6. package/dist/src/analysis/__tests__/incremental.test.js.map +1 -0
  7. package/dist/src/analysis/__tests__/integration.test.d.ts +14 -0
  8. package/dist/src/analysis/__tests__/integration.test.d.ts.map +1 -0
  9. package/dist/src/analysis/__tests__/integration.test.js +1059 -0
  10. package/dist/src/analysis/__tests__/integration.test.js.map +1 -0
  11. package/dist/src/analysis/__tests__/metrics.test.d.ts +9 -0
  12. package/dist/src/analysis/__tests__/metrics.test.d.ts.map +1 -0
  13. package/dist/src/analysis/__tests__/metrics.test.js +369 -0
  14. package/dist/src/analysis/__tests__/metrics.test.js.map +1 -0
  15. package/dist/src/analysis/__tests__/performance.test.d.ts +15 -0
  16. package/dist/src/analysis/__tests__/performance.test.d.ts.map +1 -0
  17. package/dist/src/analysis/__tests__/performance.test.js +402 -0
  18. package/dist/src/analysis/__tests__/performance.test.js.map +1 -0
  19. package/dist/src/analysis/adapters/__tests__/go.test.d.ts +12 -0
  20. package/dist/src/analysis/adapters/__tests__/go.test.d.ts.map +1 -0
  21. package/dist/src/analysis/adapters/__tests__/go.test.js +561 -0
  22. package/dist/src/analysis/adapters/__tests__/go.test.js.map +1 -0
  23. package/dist/src/analysis/adapters/__tests__/python.test.d.ts +11 -0
  24. package/dist/src/analysis/adapters/__tests__/python.test.d.ts.map +1 -0
  25. package/dist/src/analysis/adapters/__tests__/python.test.js +669 -0
  26. package/dist/src/analysis/adapters/__tests__/python.test.js.map +1 -0
  27. package/dist/src/analysis/adapters/__tests__/rust.test.d.ts +12 -0
  28. package/dist/src/analysis/adapters/__tests__/rust.test.d.ts.map +1 -0
  29. package/dist/src/analysis/adapters/__tests__/rust.test.js +676 -0
  30. package/dist/src/analysis/adapters/__tests__/rust.test.js.map +1 -0
  31. package/dist/src/analysis/adapters/__tests__/typescript.test.d.ts +14 -0
  32. package/dist/src/analysis/adapters/__tests__/typescript.test.d.ts.map +1 -0
  33. package/dist/src/analysis/adapters/__tests__/typescript.test.js +381 -0
  34. package/dist/src/analysis/adapters/__tests__/typescript.test.js.map +1 -0
  35. package/dist/src/analysis/adapters/base.d.ts +83 -0
  36. package/dist/src/analysis/adapters/base.d.ts.map +1 -0
  37. package/dist/src/analysis/adapters/base.js +40 -0
  38. package/dist/src/analysis/adapters/base.js.map +1 -0
  39. package/dist/src/analysis/adapters/factory.d.ts +150 -0
  40. package/dist/src/analysis/adapters/factory.d.ts.map +1 -0
  41. package/dist/src/analysis/adapters/factory.js +244 -0
  42. package/dist/src/analysis/adapters/factory.js.map +1 -0
  43. package/dist/src/analysis/adapters/go.d.ts +131 -0
  44. package/dist/src/analysis/adapters/go.d.ts.map +1 -0
  45. package/dist/src/analysis/adapters/go.js +414 -0
  46. package/dist/src/analysis/adapters/go.js.map +1 -0
  47. package/dist/src/analysis/adapters/index.d.ts +20 -0
  48. package/dist/src/analysis/adapters/index.d.ts.map +1 -0
  49. package/dist/src/analysis/adapters/index.js +23 -0
  50. package/dist/src/analysis/adapters/index.js.map +1 -0
  51. package/dist/src/analysis/adapters/java.d.ts +154 -0
  52. package/dist/src/analysis/adapters/java.d.ts.map +1 -0
  53. package/dist/src/analysis/adapters/java.js +407 -0
  54. package/dist/src/analysis/adapters/java.js.map +1 -0
  55. package/dist/src/analysis/adapters/python.d.ts +165 -0
  56. package/dist/src/analysis/adapters/python.d.ts.map +1 -0
  57. package/dist/src/analysis/adapters/python.js +475 -0
  58. package/dist/src/analysis/adapters/python.js.map +1 -0
  59. package/dist/src/analysis/adapters/rust.d.ts +116 -0
  60. package/dist/src/analysis/adapters/rust.d.ts.map +1 -0
  61. package/dist/src/analysis/adapters/rust.js +476 -0
  62. package/dist/src/analysis/adapters/rust.js.map +1 -0
  63. package/dist/src/analysis/adapters/typescript.d.ts +68 -0
  64. package/dist/src/analysis/adapters/typescript.d.ts.map +1 -0
  65. package/dist/src/analysis/adapters/typescript.js +79 -0
  66. package/dist/src/analysis/adapters/typescript.js.map +1 -0
  67. package/dist/src/analysis/aggregator.d.ts +193 -0
  68. package/dist/src/analysis/aggregator.d.ts.map +1 -0
  69. package/dist/src/analysis/aggregator.js +283 -0
  70. package/dist/src/analysis/aggregator.js.map +1 -0
  71. package/dist/src/analysis/cache.d.ts +180 -0
  72. package/dist/src/analysis/cache.d.ts.map +1 -0
  73. package/dist/src/analysis/cache.js +279 -0
  74. package/dist/src/analysis/cache.js.map +1 -0
  75. package/dist/src/analysis/file-streamer.d.ts +136 -0
  76. package/dist/src/analysis/file-streamer.d.ts.map +1 -0
  77. package/dist/src/analysis/file-streamer.js +291 -0
  78. package/dist/src/analysis/file-streamer.js.map +1 -0
  79. package/dist/src/analysis/incremental-parser.d.ts +186 -0
  80. package/dist/src/analysis/incremental-parser.d.ts.map +1 -0
  81. package/dist/src/analysis/incremental-parser.js +291 -0
  82. package/dist/src/analysis/incremental-parser.js.map +1 -0
  83. package/dist/src/analysis/incremental.d.ts +186 -0
  84. package/dist/src/analysis/incremental.d.ts.map +1 -0
  85. package/dist/src/analysis/incremental.js +247 -0
  86. package/dist/src/analysis/incremental.js.map +1 -0
  87. package/dist/src/analysis/index.d.ts +25 -3
  88. package/dist/src/analysis/index.d.ts.map +1 -1
  89. package/dist/src/analysis/index.js +45 -3
  90. package/dist/src/analysis/index.js.map +1 -1
  91. package/dist/src/analysis/language-detector.d.ts +92 -0
  92. package/dist/src/analysis/language-detector.d.ts.map +1 -0
  93. package/dist/src/analysis/language-detector.js +602 -0
  94. package/dist/src/analysis/language-detector.js.map +1 -0
  95. package/dist/src/analysis/memory-monitor.d.ts +199 -0
  96. package/dist/src/analysis/memory-monitor.d.ts.map +1 -0
  97. package/dist/src/analysis/memory-monitor.js +271 -0
  98. package/dist/src/analysis/memory-monitor.js.map +1 -0
  99. package/dist/src/analysis/metrics.d.ts +300 -0
  100. package/dist/src/analysis/metrics.d.ts.map +1 -0
  101. package/dist/src/analysis/metrics.js +537 -0
  102. package/dist/src/analysis/metrics.js.map +1 -0
  103. package/dist/src/analysis/router.d.ts +264 -0
  104. package/dist/src/analysis/router.d.ts.map +1 -0
  105. package/dist/src/analysis/router.js +398 -0
  106. package/dist/src/analysis/router.js.map +1 -0
  107. package/dist/src/analysis/tree-cache.d.ts +208 -0
  108. package/dist/src/analysis/tree-cache.d.ts.map +1 -0
  109. package/dist/src/analysis/tree-cache.js +288 -0
  110. package/dist/src/analysis/tree-cache.js.map +1 -0
  111. package/dist/src/analysis/tree-sitter/manager.d.ts +141 -0
  112. package/dist/src/analysis/tree-sitter/manager.d.ts.map +1 -0
  113. package/dist/src/analysis/tree-sitter/manager.js +239 -0
  114. package/dist/src/analysis/tree-sitter/manager.js.map +1 -0
  115. package/dist/src/analysis/types.d.ts +69 -6
  116. package/dist/src/analysis/types.d.ts.map +1 -1
  117. package/dist/src/analysis/types.js +23 -2
  118. package/dist/src/analysis/types.js.map +1 -1
  119. package/dist/src/analysis/worker-pool.d.ts +141 -0
  120. package/dist/src/analysis/worker-pool.d.ts.map +1 -0
  121. package/dist/src/analysis/worker-pool.js +418 -0
  122. package/dist/src/analysis/worker-pool.js.map +1 -0
  123. package/dist/src/analytics/schema.d.ts +1 -1
  124. package/dist/src/analytics/schema.d.ts.map +1 -1
  125. package/dist/src/analytics/schema.js +72 -0
  126. package/dist/src/analytics/schema.js.map +1 -1
  127. package/dist/src/api/cache.d.ts +24 -1
  128. package/dist/src/api/cache.d.ts.map +1 -1
  129. package/dist/src/api/cache.js +50 -2
  130. package/dist/src/api/cache.js.map +1 -1
  131. package/dist/src/api/client.d.ts +132 -2
  132. package/dist/src/api/client.d.ts.map +1 -1
  133. package/dist/src/api/client.js +214 -18
  134. package/dist/src/api/client.js.map +1 -1
  135. package/dist/src/api/index.d.ts +2 -0
  136. package/dist/src/api/index.d.ts.map +1 -1
  137. package/dist/src/api/index.js +7 -0
  138. package/dist/src/api/index.js.map +1 -1
  139. package/dist/src/api/types.d.ts +251 -0
  140. package/dist/src/api/types.d.ts.map +1 -0
  141. package/dist/src/api/types.js +9 -0
  142. package/dist/src/api/types.js.map +1 -0
  143. package/dist/src/benchmarks/memory/MemoryProfiler.d.ts.map +1 -1
  144. package/dist/src/benchmarks/memory/MemoryProfiler.js.map +1 -1
  145. package/dist/src/embeddings/index.d.ts.map +1 -1
  146. package/dist/src/embeddings/index.js.map +1 -1
  147. package/dist/src/errors.d.ts +1 -0
  148. package/dist/src/errors.d.ts.map +1 -1
  149. package/dist/src/errors.js +1 -0
  150. package/dist/src/errors.js.map +1 -1
  151. package/dist/src/index.d.ts +3 -3
  152. package/dist/src/index.d.ts.map +1 -1
  153. package/dist/src/index.js +4 -4
  154. package/dist/src/index.js.map +1 -1
  155. package/dist/src/repositories/IndexerRepository.d.ts.map +1 -1
  156. package/dist/src/repositories/IndexerRepository.js +1 -0
  157. package/dist/src/repositories/IndexerRepository.js.map +1 -1
  158. package/dist/src/repositories/SkillRepository.d.ts.map +1 -1
  159. package/dist/src/repositories/SkillRepository.js +1 -0
  160. package/dist/src/repositories/SkillRepository.js.map +1 -1
  161. package/dist/src/repositories/quarantine/QuarantineRepository.d.ts.map +1 -1
  162. package/dist/src/repositories/quarantine/QuarantineRepository.js.map +1 -1
  163. package/dist/src/repositories/quarantine/query-builder.d.ts.map +1 -1
  164. package/dist/src/repositories/quarantine/query-builder.js +1 -1
  165. package/dist/src/repositories/quarantine/query-builder.js.map +1 -1
  166. package/dist/src/scripts/__tests__/scan-imported-skills.test.js +3 -3
  167. package/dist/src/scripts/__tests__/scan-imported-skills.test.js.map +1 -1
  168. package/dist/src/scripts/github-import/index.js.map +1 -1
  169. package/dist/src/scripts/import-github-skills.js +1 -1
  170. package/dist/src/scripts/import-github-skills.js.map +1 -1
  171. package/dist/src/scripts/skill-scanner/reporter.d.ts.map +1 -1
  172. package/dist/src/scripts/skill-scanner/reporter.js.map +1 -1
  173. package/dist/src/scripts/skill-scanner/scanner.d.ts.map +1 -1
  174. package/dist/src/scripts/skill-scanner/scanner.js.map +1 -1
  175. package/dist/src/scripts/skill-scanner/trust-scorer.d.ts.map +1 -1
  176. package/dist/src/scripts/skill-scanner/trust-scorer.js.map +1 -1
  177. package/dist/src/scripts/validation/index.js +1 -2
  178. package/dist/src/scripts/validation/index.js.map +1 -1
  179. package/dist/src/scripts/validation/pipeline.d.ts.map +1 -1
  180. package/dist/src/scripts/validation/pipeline.js.map +1 -1
  181. package/dist/src/scripts/validation/types.d.ts +2 -2
  182. package/dist/src/security/scanner/SecurityScanner.d.ts.map +1 -1
  183. package/dist/src/security/scanner/SecurityScanner.js.map +1 -1
  184. package/dist/src/services/SearchService.d.ts.map +1 -1
  185. package/dist/src/services/SearchService.js +1 -0
  186. package/dist/src/services/SearchService.js.map +1 -1
  187. package/dist/src/session/SessionHealthMonitor.d.ts +1 -1
  188. package/dist/src/session/SessionHealthMonitor.d.ts.map +1 -1
  189. package/dist/src/session/SessionHealthMonitor.js +1 -1
  190. package/dist/src/session/SessionHealthMonitor.js.map +1 -1
  191. package/dist/src/telemetry/index.d.ts +1 -1
  192. package/dist/src/telemetry/index.d.ts.map +1 -1
  193. package/dist/src/telemetry/index.js +2 -2
  194. package/dist/src/telemetry/index.js.map +1 -1
  195. package/dist/src/telemetry/posthog.d.ts +27 -5
  196. package/dist/src/telemetry/posthog.d.ts.map +1 -1
  197. package/dist/src/telemetry/posthog.js +20 -5
  198. package/dist/src/telemetry/posthog.js.map +1 -1
  199. package/dist/src/types/skill.d.ts +3 -0
  200. package/dist/src/types/skill.d.ts.map +1 -1
  201. package/dist/src/types.d.ts +2 -1
  202. package/dist/src/types.d.ts.map +1 -1
  203. package/dist/src/types.js +2 -2
  204. package/dist/src/types.js.map +1 -1
  205. package/dist/tests/adapters-factory.test.d.ts +13 -0
  206. package/dist/tests/adapters-factory.test.d.ts.map +1 -0
  207. package/dist/tests/adapters-factory.test.js +308 -0
  208. package/dist/tests/adapters-factory.test.js.map +1 -0
  209. package/dist/tests/adapters-java.test.d.ts +13 -0
  210. package/dist/tests/adapters-java.test.d.ts.map +1 -0
  211. package/dist/tests/adapters-java.test.js +925 -0
  212. package/dist/tests/adapters-java.test.js.map +1 -0
  213. package/dist/tests/api/client.validation.test.d.ts +7 -0
  214. package/dist/tests/api/client.validation.test.d.ts.map +1 -0
  215. package/dist/tests/api/client.validation.test.js +183 -0
  216. package/dist/tests/api/client.validation.test.js.map +1 -0
  217. package/dist/tests/language-detector.test.d.ts +13 -0
  218. package/dist/tests/language-detector.test.d.ts.map +1 -0
  219. package/dist/tests/language-detector.test.js +674 -0
  220. package/dist/tests/language-detector.test.js.map +1 -0
  221. package/dist/tests/telemetry/posthog.test.d.ts +13 -0
  222. package/dist/tests/telemetry/posthog.test.d.ts.map +1 -0
  223. package/dist/tests/telemetry/posthog.test.js +600 -0
  224. package/dist/tests/telemetry/posthog.test.js.map +1 -0
  225. package/package.json +5 -6
  226. package/dist/src/security/RateLimiter.d.ts +0 -337
  227. package/dist/src/security/RateLimiter.d.ts.map +0 -1
  228. package/dist/src/security/RateLimiter.js +0 -782
  229. package/dist/src/security/RateLimiter.js.map +0 -1
  230. package/dist/src/security/scanner.d.ts +0 -151
  231. package/dist/src/security/scanner.d.ts.map +0 -1
  232. package/dist/src/security/scanner.js +0 -599
  233. package/dist/src/security/scanner.js.map +0 -1
@@ -0,0 +1,418 @@
1
+ /**
2
+ * SMI-1308: Worker Thread Pool for Parallel File Parsing
3
+ * SMI-1337: Added metrics integration
4
+ *
5
+ * Uses Node.js worker_threads for true parallelism,
6
+ * bypassing the single-threaded event loop limitation.
7
+ *
8
+ * @see docs/architecture/multi-language-analysis.md
9
+ * @module analysis/worker-pool
10
+ */
11
+ import { Worker, isMainThread, parentPort, workerData } from 'worker_threads';
12
+ import os from 'os';
13
+ import { EventEmitter } from 'events';
14
+ import { getAnalysisMetrics } from './metrics.js';
15
+ export class ParserWorkerPool extends EventEmitter {
16
+ workers = [];
17
+ taskQueue = [];
18
+ activeWorkers = 0;
19
+ poolSize;
20
+ minBatchForWorkers;
21
+ metrics;
22
+ disposed = false;
23
+ // SMI-1330/1331: Cache router to avoid recreation on each parseInline call
24
+ router = null;
25
+ routerPromise = null;
26
+ constructor(options = {}) {
27
+ super();
28
+ this.poolSize = options.poolSize ?? Math.max(1, os.cpus().length - 1);
29
+ this.minBatchForWorkers = options.minBatchForWorkers ?? 10;
30
+ this.metrics = options.metrics ?? getAnalysisMetrics();
31
+ }
32
+ /**
33
+ * SMI-1330/1331: Get or create shared router instance
34
+ * Lazily initializes the router on first use and caches it
35
+ */
36
+ async getRouter() {
37
+ if (this.router)
38
+ return this.router;
39
+ if (this.routerPromise)
40
+ return this.routerPromise;
41
+ this.routerPromise = this.initializeRouter();
42
+ this.router = await this.routerPromise;
43
+ return this.router;
44
+ }
45
+ /**
46
+ * SMI-1330/1331: Initialize router with all adapters
47
+ */
48
+ async initializeRouter() {
49
+ const { LanguageRouter } = await import('./router.js');
50
+ const { TypeScriptAdapter } = await import('./adapters/typescript.js');
51
+ const { PythonAdapter } = await import('./adapters/python.js');
52
+ const { GoAdapter } = await import('./adapters/go.js');
53
+ const { RustAdapter } = await import('./adapters/rust.js');
54
+ const { JavaAdapter } = await import('./adapters/java.js');
55
+ const router = new LanguageRouter();
56
+ router.registerAdapter(new TypeScriptAdapter());
57
+ router.registerAdapter(new PythonAdapter());
58
+ router.registerAdapter(new GoAdapter());
59
+ router.registerAdapter(new RustAdapter());
60
+ router.registerAdapter(new JavaAdapter());
61
+ return router;
62
+ }
63
+ /**
64
+ * Parse files in parallel using worker threads
65
+ *
66
+ * SMI-1337: Records worker pool metrics.
67
+ *
68
+ * @param tasks - Array of parse tasks
69
+ * @returns Array of worker results
70
+ * @throws Error if pool has been disposed
71
+ *
72
+ * @example
73
+ * ```typescript
74
+ * const results = await pool.parseFiles([
75
+ * { filePath: 'a.ts', content: 'export const a = 1', language: 'typescript' },
76
+ * { filePath: 'b.ts', content: 'export const b = 2', language: 'typescript' },
77
+ * ])
78
+ * ```
79
+ */
80
+ async parseFiles(tasks) {
81
+ if (this.disposed) {
82
+ throw new Error('Worker pool has been disposed');
83
+ }
84
+ if (tasks.length === 0) {
85
+ return [];
86
+ }
87
+ // SMI-1337: Update worker pool metrics
88
+ this.metrics.updateWorkerPool(this.activeWorkers, this.taskQueue.length, this.poolSize);
89
+ // For small batches, parse inline (worker overhead not worth it)
90
+ if (tasks.length < this.minBatchForWorkers) {
91
+ const results = await this.parseInline(tasks);
92
+ this.recordParseMetrics(results);
93
+ return results;
94
+ }
95
+ const results = await this.parseWithWorkers(tasks);
96
+ this.recordParseMetrics(results);
97
+ return results;
98
+ }
99
+ /**
100
+ * Record parse metrics for completed results
101
+ * SMI-1337: Helper to record metrics after parsing
102
+ */
103
+ recordParseMetrics(results) {
104
+ for (const result of results) {
105
+ if (result.error) {
106
+ this.metrics.recordError('worker_parse_error', result.filePath.split('.').pop());
107
+ }
108
+ else {
109
+ // Extract language from file extension
110
+ const ext = result.filePath.split('.').pop()?.toLowerCase();
111
+ const language = this.getLanguageFromExtension(ext);
112
+ if (language) {
113
+ this.metrics.recordFileParsed(language);
114
+ this.metrics.recordParseDuration(language, result.durationMs);
115
+ }
116
+ }
117
+ }
118
+ // Update memory usage after batch processing
119
+ this.metrics.updateMemoryUsage();
120
+ }
121
+ /**
122
+ * Get language from file extension
123
+ * SMI-1337: Helper for metrics
124
+ */
125
+ getLanguageFromExtension(ext) {
126
+ if (!ext)
127
+ return undefined;
128
+ const extensionToLanguage = {
129
+ ts: 'typescript',
130
+ tsx: 'typescript',
131
+ mts: 'typescript',
132
+ cts: 'typescript',
133
+ js: 'javascript',
134
+ jsx: 'javascript',
135
+ mjs: 'javascript',
136
+ cjs: 'javascript',
137
+ py: 'python',
138
+ pyi: 'python',
139
+ pyw: 'python',
140
+ go: 'go',
141
+ rs: 'rust',
142
+ java: 'java',
143
+ };
144
+ return extensionToLanguage[ext];
145
+ }
146
+ /**
147
+ * Parse files inline (no workers)
148
+ *
149
+ * Used for small batches where worker overhead exceeds benefit.
150
+ * SMI-1330/1331: Uses cached router to avoid recreation overhead
151
+ */
152
+ async parseInline(tasks) {
153
+ const results = [];
154
+ // SMI-1330/1331: Get shared router instance
155
+ const router = await this.getRouter();
156
+ for (const task of tasks) {
157
+ const start = performance.now();
158
+ try {
159
+ const adapter = router.tryGetAdapter(task.filePath);
160
+ if (adapter) {
161
+ const result = adapter.parseFile(task.content, task.filePath);
162
+ results.push({
163
+ filePath: task.filePath,
164
+ result,
165
+ durationMs: performance.now() - start,
166
+ });
167
+ }
168
+ else {
169
+ // Unsupported file type
170
+ results.push({
171
+ filePath: task.filePath,
172
+ result: { imports: [], exports: [], functions: [] },
173
+ durationMs: performance.now() - start,
174
+ error: `Unsupported file type: ${task.filePath}`,
175
+ });
176
+ }
177
+ }
178
+ catch (error) {
179
+ results.push({
180
+ filePath: task.filePath,
181
+ result: { imports: [], exports: [], functions: [] },
182
+ durationMs: performance.now() - start,
183
+ error: error instanceof Error ? error.message : String(error),
184
+ });
185
+ }
186
+ }
187
+ return results;
188
+ }
189
+ /**
190
+ * Parse files using worker threads
191
+ *
192
+ * Chunks tasks across available workers for parallel processing.
193
+ */
194
+ async parseWithWorkers(tasks) {
195
+ // Chunk tasks for workers
196
+ const chunkSize = Math.ceil(tasks.length / this.poolSize);
197
+ const chunks = this.chunkArray(tasks, chunkSize);
198
+ const results = await Promise.all(chunks.map((chunk) => this.dispatchToWorker(chunk)));
199
+ return results.flat();
200
+ }
201
+ /**
202
+ * Dispatch a chunk of tasks to a worker
203
+ */
204
+ async dispatchToWorker(tasks) {
205
+ return new Promise((resolve, reject) => {
206
+ // Create inline worker with basic regex-based parsing
207
+ // Full adapter-based parsing happens in main thread for accuracy
208
+ const workerCode = `
209
+ const { parentPort, workerData } = require('worker_threads');
210
+
211
+ function processTask(task) {
212
+ const start = Date.now();
213
+ try {
214
+ const result = {
215
+ imports: [],
216
+ exports: [],
217
+ functions: [],
218
+ };
219
+
220
+ const lines = task.content.split('\\n');
221
+ for (let i = 0; i < lines.length; i++) {
222
+ const line = lines[i];
223
+
224
+ // Detect imports (TypeScript/JavaScript)
225
+ if (/^import\\s/.test(line) || /^from\\s/.test(line)) {
226
+ const moduleMatch = line.match(/from\\s+['"]([^'"]+)['"]/);
227
+ result.imports.push({
228
+ module: moduleMatch ? moduleMatch[1] : line.trim(),
229
+ namedImports: [],
230
+ isTypeOnly: /^import\\s+type/.test(line),
231
+ sourceFile: task.filePath,
232
+ line: i + 1,
233
+ });
234
+ }
235
+
236
+ // Detect imports (Python)
237
+ if (/^import\\s+\\w/.test(line) || /^from\\s+\\w/.test(line)) {
238
+ const moduleMatch = line.match(/^(?:from\\s+)?(\\w+(?:\\.\\w+)*)/);
239
+ if (moduleMatch && !result.imports.some(imp => imp.line === i + 1)) {
240
+ result.imports.push({
241
+ module: moduleMatch[1],
242
+ namedImports: [],
243
+ isTypeOnly: false,
244
+ sourceFile: task.filePath,
245
+ line: i + 1,
246
+ });
247
+ }
248
+ }
249
+
250
+ // Detect imports (Go)
251
+ if (/^\\s*"[^"]+"/.test(line) || /^import\\s+/.test(line)) {
252
+ const pathMatch = line.match(/"([^"]+)"/);
253
+ if (pathMatch) {
254
+ result.imports.push({
255
+ module: pathMatch[1],
256
+ namedImports: [],
257
+ isTypeOnly: false,
258
+ sourceFile: task.filePath,
259
+ line: i + 1,
260
+ });
261
+ }
262
+ }
263
+
264
+ // Detect functions (TypeScript/JavaScript)
265
+ const tsFuncMatch = line.match(/^(export\\s+)?(async\\s+)?function\\s+(\\w+)/);
266
+ if (tsFuncMatch) {
267
+ result.functions.push({
268
+ name: tsFuncMatch[3],
269
+ parameterCount: 0,
270
+ isAsync: !!tsFuncMatch[2],
271
+ isExported: !!tsFuncMatch[1],
272
+ sourceFile: task.filePath,
273
+ line: i + 1,
274
+ });
275
+ }
276
+
277
+ // Detect functions (Python)
278
+ const pyFuncMatch = line.match(/^(async\\s+)?def\\s+(\\w+)/);
279
+ if (pyFuncMatch) {
280
+ result.functions.push({
281
+ name: pyFuncMatch[2],
282
+ parameterCount: 0,
283
+ isAsync: !!pyFuncMatch[1],
284
+ isExported: !pyFuncMatch[2].startsWith('_'),
285
+ sourceFile: task.filePath,
286
+ line: i + 1,
287
+ });
288
+ }
289
+
290
+ // Detect functions (Go)
291
+ const goFuncMatch = line.match(/^func\\s+(?:\\([^)]+\\)\\s+)?(\\w+)/);
292
+ if (goFuncMatch) {
293
+ const isExported = goFuncMatch[1][0] === goFuncMatch[1][0].toUpperCase();
294
+ result.functions.push({
295
+ name: goFuncMatch[1],
296
+ parameterCount: 0,
297
+ isAsync: false,
298
+ isExported: isExported,
299
+ sourceFile: task.filePath,
300
+ line: i + 1,
301
+ });
302
+ }
303
+
304
+ // Detect exports (TypeScript/JavaScript)
305
+ if (/^export\\s+(default\\s+)?(const|let|var|class|function|interface|type|enum)/.test(line)) {
306
+ const exportMatch = line.match(/^export\\s+(default\\s+)?(const|let|var|class|function|interface|type|enum)\\s+(\\w+)/);
307
+ if (exportMatch) {
308
+ result.exports.push({
309
+ name: exportMatch[3],
310
+ kind: exportMatch[2] === 'function' ? 'function' :
311
+ exportMatch[2] === 'class' ? 'class' :
312
+ exportMatch[2] === 'interface' ? 'interface' :
313
+ exportMatch[2] === 'type' ? 'type' :
314
+ exportMatch[2] === 'enum' ? 'enum' : 'variable',
315
+ isDefault: !!exportMatch[1],
316
+ sourceFile: task.filePath,
317
+ line: i + 1,
318
+ });
319
+ }
320
+ }
321
+ }
322
+
323
+ return {
324
+ filePath: task.filePath,
325
+ result,
326
+ durationMs: Date.now() - start,
327
+ };
328
+ } catch (error) {
329
+ return {
330
+ filePath: task.filePath,
331
+ result: { imports: [], exports: [], functions: [] },
332
+ durationMs: Date.now() - start,
333
+ error: error.message || String(error),
334
+ };
335
+ }
336
+ }
337
+
338
+ const results = workerData.tasks.map(processTask);
339
+ parentPort.postMessage(results);
340
+ `;
341
+ const worker = new Worker(workerCode, {
342
+ eval: true,
343
+ workerData: { tasks },
344
+ });
345
+ const timeout = setTimeout(() => {
346
+ worker.terminate();
347
+ reject(new Error('Worker timed out after 30 seconds'));
348
+ }, 30000);
349
+ worker.on('message', (results) => {
350
+ clearTimeout(timeout);
351
+ worker.terminate();
352
+ resolve(results);
353
+ });
354
+ worker.on('error', (error) => {
355
+ clearTimeout(timeout);
356
+ worker.terminate();
357
+ reject(error);
358
+ });
359
+ worker.on('exit', (code) => {
360
+ clearTimeout(timeout);
361
+ if (code !== 0) {
362
+ reject(new Error(`Worker exited with code ${code}`));
363
+ }
364
+ });
365
+ });
366
+ }
367
+ /**
368
+ * Chunk an array into smaller arrays
369
+ */
370
+ chunkArray(array, size) {
371
+ const chunks = [];
372
+ for (let i = 0; i < array.length; i += size) {
373
+ chunks.push(array.slice(i, i + size));
374
+ }
375
+ return chunks;
376
+ }
377
+ /**
378
+ * Get pool statistics
379
+ *
380
+ * SMI-1337: Also updates metrics.
381
+ *
382
+ * @returns Current pool statistics
383
+ */
384
+ getStats() {
385
+ const utilization = this.poolSize > 0 ? this.activeWorkers / this.poolSize : 0;
386
+ // SMI-1337: Update metrics when stats are requested
387
+ this.metrics.updateWorkerPool(this.activeWorkers, this.taskQueue.length, this.poolSize);
388
+ return {
389
+ poolSize: this.poolSize,
390
+ activeWorkers: this.activeWorkers,
391
+ queuedTasks: this.taskQueue.length,
392
+ utilization,
393
+ };
394
+ }
395
+ /**
396
+ * Dispose of worker pool
397
+ *
398
+ * Terminates all workers and clears the task queue.
399
+ * SMI-1330/1331: Also disposes cached router
400
+ */
401
+ dispose() {
402
+ this.disposed = true;
403
+ for (const worker of this.workers) {
404
+ worker.terminate();
405
+ }
406
+ this.workers = [];
407
+ this.taskQueue = [];
408
+ // SMI-1330/1331: Clean up cached router
409
+ if (this.router) {
410
+ this.router.dispose();
411
+ this.router = null;
412
+ this.routerPromise = null;
413
+ }
414
+ }
415
+ }
416
+ // Export for worker thread context detection
417
+ export { isMainThread, parentPort, workerData };
418
+ //# sourceMappingURL=worker-pool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"worker-pool.js","sourceRoot":"","sources":["../../../src/analysis/worker-pool.ts"],"names":[],"mappings":"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"}
@@ -11,7 +11,7 @@
11
11
  /**
12
12
  * Analytics schema SQL for skill usage, A/B testing, and ROI tracking
13
13
  */
14
- export declare const ANALYTICS_SCHEMA = "\n-- Skill usage events for attribution and value tracking\nCREATE TABLE IF NOT EXISTS skill_usage_events (\n id TEXT PRIMARY KEY,\n skill_id TEXT NOT NULL,\n user_id TEXT NOT NULL,\n session_id TEXT NOT NULL,\n event_type TEXT NOT NULL CHECK(event_type IN ('activation', 'invocation', 'success', 'failure')),\n context TEXT, -- JSON metadata about the usage context\n value_score REAL, -- Estimated value contribution (0-1)\n timestamp TEXT NOT NULL DEFAULT (datetime('now')),\n created_at TEXT NOT NULL DEFAULT (datetime('now'))\n);\n\n-- Indexes for usage queries\nCREATE INDEX IF NOT EXISTS idx_usage_skill_id ON skill_usage_events(skill_id);\nCREATE INDEX IF NOT EXISTS idx_usage_user_id ON skill_usage_events(user_id);\nCREATE INDEX IF NOT EXISTS idx_usage_session_id ON skill_usage_events(session_id);\nCREATE INDEX IF NOT EXISTS idx_usage_timestamp ON skill_usage_events(timestamp);\nCREATE INDEX IF NOT EXISTS idx_usage_event_type ON skill_usage_events(event_type);\n\n-- A/B testing experiments\nCREATE TABLE IF NOT EXISTS experiments (\n id TEXT PRIMARY KEY,\n name TEXT NOT NULL UNIQUE,\n description TEXT,\n hypothesis TEXT,\n status TEXT NOT NULL CHECK(status IN ('draft', 'active', 'paused', 'completed')) DEFAULT 'draft',\n variant_a TEXT NOT NULL, -- JSON config for control group\n variant_b TEXT NOT NULL, -- JSON config for treatment group\n start_date TEXT,\n end_date TEXT,\n target_sample_size INTEGER DEFAULT 100,\n created_at TEXT NOT NULL DEFAULT (datetime('now')),\n updated_at TEXT NOT NULL DEFAULT (datetime('now'))\n);\n\n-- User assignments to experiment variants\nCREATE TABLE IF NOT EXISTS experiment_assignments (\n id TEXT PRIMARY KEY,\n experiment_id TEXT NOT NULL REFERENCES experiments(id) ON DELETE CASCADE,\n user_id TEXT NOT NULL,\n variant TEXT NOT NULL CHECK(variant IN ('control', 'treatment')),\n assigned_at TEXT NOT NULL DEFAULT (datetime('now')),\n UNIQUE(experiment_id, user_id)\n);\n\n-- Experiment outcome tracking\nCREATE TABLE IF NOT EXISTS experiment_outcomes (\n id TEXT PRIMARY KEY,\n experiment_id TEXT NOT NULL REFERENCES experiments(id) ON DELETE CASCADE,\n assignment_id TEXT NOT NULL REFERENCES experiment_assignments(id) ON DELETE CASCADE,\n outcome_type TEXT NOT NULL, -- e.g., 'activation', 'usage_count', 'value_score'\n outcome_value REAL NOT NULL,\n metadata TEXT, -- JSON additional data\n measured_at TEXT NOT NULL DEFAULT (datetime('now')),\n created_at TEXT NOT NULL DEFAULT (datetime('now'))\n);\n\n-- Indexes for experiment queries\nCREATE INDEX IF NOT EXISTS idx_assignments_experiment ON experiment_assignments(experiment_id);\nCREATE INDEX IF NOT EXISTS idx_assignments_user ON experiment_assignments(user_id);\nCREATE INDEX IF NOT EXISTS idx_outcomes_experiment ON experiment_outcomes(experiment_id);\nCREATE INDEX IF NOT EXISTS idx_outcomes_assignment ON experiment_outcomes(assignment_id);\n\n-- ROI metrics aggregation (materialized view equivalent)\nCREATE TABLE IF NOT EXISTS roi_metrics (\n id TEXT PRIMARY KEY,\n metric_type TEXT NOT NULL, -- 'daily', 'weekly', 'monthly', 'user', 'skill'\n entity_id TEXT, -- user_id or skill_id for entity-level metrics\n period_start TEXT NOT NULL,\n period_end TEXT NOT NULL,\n total_activations INTEGER DEFAULT 0,\n total_invocations INTEGER DEFAULT 0,\n total_successes INTEGER DEFAULT 0,\n total_failures INTEGER DEFAULT 0,\n avg_value_score REAL DEFAULT 0.0,\n estimated_time_saved REAL DEFAULT 0.0, -- in minutes\n estimated_value_usd REAL DEFAULT 0.0, -- rough ROI estimate\n metadata TEXT, -- JSON for additional metrics\n computed_at TEXT NOT NULL DEFAULT (datetime('now')),\n created_at TEXT NOT NULL DEFAULT (datetime('now'))\n);\n\n-- Indexes for ROI queries\nCREATE INDEX IF NOT EXISTS idx_roi_type ON roi_metrics(metric_type);\nCREATE INDEX IF NOT EXISTS idx_roi_entity ON roi_metrics(entity_id);\nCREATE INDEX IF NOT EXISTS idx_roi_period ON roi_metrics(period_start, period_end);\nCREATE INDEX IF NOT EXISTS idx_roi_computed ON roi_metrics(computed_at);\n\n-- Value attribution mappings\nCREATE TABLE IF NOT EXISTS value_attributions (\n id TEXT PRIMARY KEY,\n usage_event_id TEXT NOT NULL REFERENCES skill_usage_events(id) ON DELETE CASCADE,\n skill_id TEXT NOT NULL,\n attribution_type TEXT NOT NULL, -- 'inline', 'metadata', 'session'\n value_dimension TEXT NOT NULL, -- 'time_saved', 'quality_improved', 'error_prevented'\n value_amount REAL NOT NULL,\n confidence REAL NOT NULL CHECK(confidence >= 0 AND confidence <= 1),\n metadata TEXT, -- JSON additional context\n created_at TEXT NOT NULL DEFAULT (datetime('now'))\n);\n\n-- Indexes for attribution queries\nCREATE INDEX IF NOT EXISTS idx_attributions_event ON value_attributions(usage_event_id);\nCREATE INDEX IF NOT EXISTS idx_attributions_skill ON value_attributions(skill_id);\nCREATE INDEX IF NOT EXISTS idx_attributions_type ON value_attributions(attribution_type);\n";
14
+ export declare const ANALYTICS_SCHEMA = "\n-- Skill usage events for attribution and value tracking\nCREATE TABLE IF NOT EXISTS skill_usage_events (\n id TEXT PRIMARY KEY,\n skill_id TEXT NOT NULL,\n user_id TEXT NOT NULL,\n session_id TEXT NOT NULL,\n event_type TEXT NOT NULL CHECK(event_type IN ('activation', 'invocation', 'success', 'failure')),\n context TEXT, -- JSON metadata about the usage context\n value_score REAL, -- Estimated value contribution (0-1)\n timestamp TEXT NOT NULL DEFAULT (datetime('now')),\n created_at TEXT NOT NULL DEFAULT (datetime('now'))\n);\n\n-- Indexes for usage queries\nCREATE INDEX IF NOT EXISTS idx_usage_skill_id ON skill_usage_events(skill_id);\nCREATE INDEX IF NOT EXISTS idx_usage_user_id ON skill_usage_events(user_id);\nCREATE INDEX IF NOT EXISTS idx_usage_session_id ON skill_usage_events(session_id);\nCREATE INDEX IF NOT EXISTS idx_usage_timestamp ON skill_usage_events(timestamp);\nCREATE INDEX IF NOT EXISTS idx_usage_event_type ON skill_usage_events(event_type);\n\n-- A/B testing experiments\nCREATE TABLE IF NOT EXISTS experiments (\n id TEXT PRIMARY KEY,\n name TEXT NOT NULL UNIQUE,\n description TEXT,\n hypothesis TEXT,\n status TEXT NOT NULL CHECK(status IN ('draft', 'active', 'paused', 'completed')) DEFAULT 'draft',\n variant_a TEXT NOT NULL, -- JSON config for control group\n variant_b TEXT NOT NULL, -- JSON config for treatment group\n start_date TEXT,\n end_date TEXT,\n target_sample_size INTEGER DEFAULT 100,\n created_at TEXT NOT NULL DEFAULT (datetime('now')),\n updated_at TEXT NOT NULL DEFAULT (datetime('now'))\n);\n\n-- User assignments to experiment variants\nCREATE TABLE IF NOT EXISTS experiment_assignments (\n id TEXT PRIMARY KEY,\n experiment_id TEXT NOT NULL REFERENCES experiments(id) ON DELETE CASCADE,\n user_id TEXT NOT NULL,\n variant TEXT NOT NULL CHECK(variant IN ('control', 'treatment')),\n assigned_at TEXT NOT NULL DEFAULT (datetime('now')),\n UNIQUE(experiment_id, user_id)\n);\n\n-- Experiment outcome tracking\nCREATE TABLE IF NOT EXISTS experiment_outcomes (\n id TEXT PRIMARY KEY,\n experiment_id TEXT NOT NULL REFERENCES experiments(id) ON DELETE CASCADE,\n assignment_id TEXT NOT NULL REFERENCES experiment_assignments(id) ON DELETE CASCADE,\n outcome_type TEXT NOT NULL, -- e.g., 'activation', 'usage_count', 'value_score'\n outcome_value REAL NOT NULL,\n metadata TEXT, -- JSON additional data\n measured_at TEXT NOT NULL DEFAULT (datetime('now')),\n created_at TEXT NOT NULL DEFAULT (datetime('now'))\n);\n\n-- Indexes for experiment queries\nCREATE INDEX IF NOT EXISTS idx_assignments_experiment ON experiment_assignments(experiment_id);\nCREATE INDEX IF NOT EXISTS idx_assignments_user ON experiment_assignments(user_id);\nCREATE INDEX IF NOT EXISTS idx_outcomes_experiment ON experiment_outcomes(experiment_id);\nCREATE INDEX IF NOT EXISTS idx_outcomes_assignment ON experiment_outcomes(assignment_id);\n\n-- ROI metrics aggregation (materialized view equivalent)\nCREATE TABLE IF NOT EXISTS roi_metrics (\n id TEXT PRIMARY KEY,\n metric_type TEXT NOT NULL, -- 'daily', 'weekly', 'monthly', 'user', 'skill'\n entity_id TEXT, -- user_id or skill_id for entity-level metrics\n period_start TEXT NOT NULL,\n period_end TEXT NOT NULL,\n total_activations INTEGER DEFAULT 0,\n total_invocations INTEGER DEFAULT 0,\n total_successes INTEGER DEFAULT 0,\n total_failures INTEGER DEFAULT 0,\n avg_value_score REAL DEFAULT 0.0,\n estimated_time_saved REAL DEFAULT 0.0, -- in minutes\n estimated_value_usd REAL DEFAULT 0.0, -- rough ROI estimate\n metadata TEXT, -- JSON for additional metrics\n computed_at TEXT NOT NULL DEFAULT (datetime('now')),\n created_at TEXT NOT NULL DEFAULT (datetime('now'))\n);\n\n-- Indexes for ROI queries\nCREATE INDEX IF NOT EXISTS idx_roi_type ON roi_metrics(metric_type);\nCREATE INDEX IF NOT EXISTS idx_roi_entity ON roi_metrics(entity_id);\nCREATE INDEX IF NOT EXISTS idx_roi_period ON roi_metrics(period_start, period_end);\nCREATE INDEX IF NOT EXISTS idx_roi_computed ON roi_metrics(computed_at);\n\n-- Value attribution mappings\nCREATE TABLE IF NOT EXISTS value_attributions (\n id TEXT PRIMARY KEY,\n usage_event_id TEXT NOT NULL REFERENCES skill_usage_events(id) ON DELETE CASCADE,\n skill_id TEXT NOT NULL,\n attribution_type TEXT NOT NULL, -- 'inline', 'metadata', 'session'\n value_dimension TEXT NOT NULL, -- 'time_saved', 'quality_improved', 'error_prevented'\n value_amount REAL NOT NULL,\n confidence REAL NOT NULL CHECK(confidence >= 0 AND confidence <= 1),\n metadata TEXT, -- JSON additional context\n created_at TEXT NOT NULL DEFAULT (datetime('now'))\n);\n\n-- Indexes for attribution queries\nCREATE INDEX IF NOT EXISTS idx_attributions_event ON value_attributions(usage_event_id);\nCREATE INDEX IF NOT EXISTS idx_attributions_skill ON value_attributions(skill_id);\nCREATE INDEX IF NOT EXISTS idx_attributions_type ON value_attributions(attribution_type);\n\n-- ============================================================================\n-- Quota Management Tables (SMI-XXXX)\n-- ============================================================================\n\n-- Monthly usage quotas per customer/license\n-- Tracks API call usage against tier limits\nCREATE TABLE IF NOT EXISTS usage_quotas (\n id TEXT PRIMARY KEY,\n customer_id TEXT NOT NULL,\n license_tier TEXT NOT NULL CHECK(license_tier IN ('community', 'individual', 'team', 'enterprise')),\n billing_period_start TEXT NOT NULL,\n billing_period_end TEXT NOT NULL,\n api_calls_limit INTEGER NOT NULL,\n api_calls_used INTEGER DEFAULT 0,\n last_warning_threshold INTEGER DEFAULT 0, -- 0, 80, 90, or 100\n last_warning_sent_at TEXT,\n created_at TEXT NOT NULL DEFAULT (datetime('now')),\n updated_at TEXT NOT NULL DEFAULT (datetime('now')),\n UNIQUE(customer_id, billing_period_start)\n);\n\n-- Indexes for quota queries\nCREATE INDEX IF NOT EXISTS idx_quotas_customer ON usage_quotas(customer_id);\nCREATE INDEX IF NOT EXISTS idx_quotas_period ON usage_quotas(billing_period_start, billing_period_end);\nCREATE INDEX IF NOT EXISTS idx_quotas_tier ON usage_quotas(license_tier);\n\n-- Individual API call events for detailed tracking\n-- Used for quota enforcement and analytics\nCREATE TABLE IF NOT EXISTS api_call_events (\n id TEXT PRIMARY KEY,\n customer_id TEXT NOT NULL,\n license_key_hash TEXT, -- SHA256 hash of license key for lookup\n tool_name TEXT NOT NULL,\n endpoint TEXT,\n cost INTEGER DEFAULT 1, -- Some operations may cost multiple quota units\n success INTEGER DEFAULT 1, -- 1 for success, 0 for failure\n latency_ms INTEGER,\n session_id TEXT,\n metadata TEXT, -- JSON for additional context\n timestamp TEXT NOT NULL DEFAULT (datetime('now'))\n);\n\n-- Indexes for API call queries\nCREATE INDEX IF NOT EXISTS idx_api_calls_customer ON api_call_events(customer_id);\nCREATE INDEX IF NOT EXISTS idx_api_calls_timestamp ON api_call_events(timestamp);\nCREATE INDEX IF NOT EXISTS idx_api_calls_license ON api_call_events(license_key_hash);\nCREATE INDEX IF NOT EXISTS idx_api_calls_tool ON api_call_events(tool_name);\n\n-- User subscriptions for billing integration\n-- Links customers to Stripe subscriptions\nCREATE TABLE IF NOT EXISTS user_subscriptions (\n id TEXT PRIMARY KEY,\n customer_id TEXT NOT NULL UNIQUE,\n email TEXT NOT NULL,\n tier TEXT NOT NULL CHECK(tier IN ('community', 'individual', 'team', 'enterprise')),\n stripe_customer_id TEXT,\n stripe_subscription_id TEXT,\n status TEXT NOT NULL CHECK(status IN ('active', 'past_due', 'canceled', 'trialing', 'paused')),\n current_period_start TEXT,\n current_period_end TEXT,\n last_active_at TEXT,\n created_at TEXT NOT NULL DEFAULT (datetime('now')),\n updated_at TEXT NOT NULL DEFAULT (datetime('now'))\n);\n\n-- Indexes for subscription queries\nCREATE INDEX IF NOT EXISTS idx_subs_customer ON user_subscriptions(customer_id);\nCREATE INDEX IF NOT EXISTS idx_subs_stripe ON user_subscriptions(stripe_customer_id);\nCREATE INDEX IF NOT EXISTS idx_subs_status ON user_subscriptions(status);\nCREATE INDEX IF NOT EXISTS idx_subs_tier ON user_subscriptions(tier);\nCREATE INDEX IF NOT EXISTS idx_subs_last_active ON user_subscriptions(last_active_at);\n";
15
15
  /**
16
16
  * Apply analytics schema to a database
17
17
  */
@@ -1 +1 @@
1
- {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../../src/analytics/schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH;;GAEG;AACH,eAAO,MAAM,gBAAgB,o0JA2G5B,CAAA;AAED;;GAEG;AACH,OAAO,KAAK,EAAE,QAAQ,IAAI,YAAY,EAAE,MAAM,gBAAgB,CAAA;AAE9D,wBAAgB,yBAAyB,CAAC,EAAE,EAAE,YAAY,GAAG,IAAI,CAEhE"}
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../../src/analytics/schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH;;GAEG;AACH,eAAO,MAAM,gBAAgB,4gQAmL5B,CAAA;AAED;;GAEG;AACH,OAAO,KAAK,EAAE,QAAQ,IAAI,YAAY,EAAE,MAAM,gBAAgB,CAAA;AAE9D,wBAAgB,yBAAyB,CAAC,EAAE,EAAE,YAAY,GAAG,IAAI,CAEhE"}
@@ -118,6 +118,78 @@ CREATE TABLE IF NOT EXISTS value_attributions (
118
118
  CREATE INDEX IF NOT EXISTS idx_attributions_event ON value_attributions(usage_event_id);
119
119
  CREATE INDEX IF NOT EXISTS idx_attributions_skill ON value_attributions(skill_id);
120
120
  CREATE INDEX IF NOT EXISTS idx_attributions_type ON value_attributions(attribution_type);
121
+
122
+ -- ============================================================================
123
+ -- Quota Management Tables (SMI-XXXX)
124
+ -- ============================================================================
125
+
126
+ -- Monthly usage quotas per customer/license
127
+ -- Tracks API call usage against tier limits
128
+ CREATE TABLE IF NOT EXISTS usage_quotas (
129
+ id TEXT PRIMARY KEY,
130
+ customer_id TEXT NOT NULL,
131
+ license_tier TEXT NOT NULL CHECK(license_tier IN ('community', 'individual', 'team', 'enterprise')),
132
+ billing_period_start TEXT NOT NULL,
133
+ billing_period_end TEXT NOT NULL,
134
+ api_calls_limit INTEGER NOT NULL,
135
+ api_calls_used INTEGER DEFAULT 0,
136
+ last_warning_threshold INTEGER DEFAULT 0, -- 0, 80, 90, or 100
137
+ last_warning_sent_at TEXT,
138
+ created_at TEXT NOT NULL DEFAULT (datetime('now')),
139
+ updated_at TEXT NOT NULL DEFAULT (datetime('now')),
140
+ UNIQUE(customer_id, billing_period_start)
141
+ );
142
+
143
+ -- Indexes for quota queries
144
+ CREATE INDEX IF NOT EXISTS idx_quotas_customer ON usage_quotas(customer_id);
145
+ CREATE INDEX IF NOT EXISTS idx_quotas_period ON usage_quotas(billing_period_start, billing_period_end);
146
+ CREATE INDEX IF NOT EXISTS idx_quotas_tier ON usage_quotas(license_tier);
147
+
148
+ -- Individual API call events for detailed tracking
149
+ -- Used for quota enforcement and analytics
150
+ CREATE TABLE IF NOT EXISTS api_call_events (
151
+ id TEXT PRIMARY KEY,
152
+ customer_id TEXT NOT NULL,
153
+ license_key_hash TEXT, -- SHA256 hash of license key for lookup
154
+ tool_name TEXT NOT NULL,
155
+ endpoint TEXT,
156
+ cost INTEGER DEFAULT 1, -- Some operations may cost multiple quota units
157
+ success INTEGER DEFAULT 1, -- 1 for success, 0 for failure
158
+ latency_ms INTEGER,
159
+ session_id TEXT,
160
+ metadata TEXT, -- JSON for additional context
161
+ timestamp TEXT NOT NULL DEFAULT (datetime('now'))
162
+ );
163
+
164
+ -- Indexes for API call queries
165
+ CREATE INDEX IF NOT EXISTS idx_api_calls_customer ON api_call_events(customer_id);
166
+ CREATE INDEX IF NOT EXISTS idx_api_calls_timestamp ON api_call_events(timestamp);
167
+ CREATE INDEX IF NOT EXISTS idx_api_calls_license ON api_call_events(license_key_hash);
168
+ CREATE INDEX IF NOT EXISTS idx_api_calls_tool ON api_call_events(tool_name);
169
+
170
+ -- User subscriptions for billing integration
171
+ -- Links customers to Stripe subscriptions
172
+ CREATE TABLE IF NOT EXISTS user_subscriptions (
173
+ id TEXT PRIMARY KEY,
174
+ customer_id TEXT NOT NULL UNIQUE,
175
+ email TEXT NOT NULL,
176
+ tier TEXT NOT NULL CHECK(tier IN ('community', 'individual', 'team', 'enterprise')),
177
+ stripe_customer_id TEXT,
178
+ stripe_subscription_id TEXT,
179
+ status TEXT NOT NULL CHECK(status IN ('active', 'past_due', 'canceled', 'trialing', 'paused')),
180
+ current_period_start TEXT,
181
+ current_period_end TEXT,
182
+ last_active_at TEXT,
183
+ created_at TEXT NOT NULL DEFAULT (datetime('now')),
184
+ updated_at TEXT NOT NULL DEFAULT (datetime('now'))
185
+ );
186
+
187
+ -- Indexes for subscription queries
188
+ CREATE INDEX IF NOT EXISTS idx_subs_customer ON user_subscriptions(customer_id);
189
+ CREATE INDEX IF NOT EXISTS idx_subs_stripe ON user_subscriptions(stripe_customer_id);
190
+ CREATE INDEX IF NOT EXISTS idx_subs_status ON user_subscriptions(status);
191
+ CREATE INDEX IF NOT EXISTS idx_subs_tier ON user_subscriptions(tier);
192
+ CREATE INDEX IF NOT EXISTS idx_subs_last_active ON user_subscriptions(last_active_at);
121
193
  `;
122
194
  export function initializeAnalyticsSchema(db) {
123
195
  db.exec(ANALYTICS_SCHEMA);
@@ -1 +1 @@
1
- {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../../src/analytics/schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH;;GAEG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2G/B,CAAA;AAOD,MAAM,UAAU,yBAAyB,CAAC,EAAgB;IACxD,EAAE,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAA;AAC3B,CAAC"}
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../../src/analytics/schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH;;GAEG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAmL/B,CAAA;AAOD,MAAM,UAAU,yBAAyB,CAAC,EAAgB;IACxD,EAAE,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAA;AAC3B,CAAC"}
@@ -54,6 +54,8 @@ export declare class ApiCache {
54
54
  private hits;
55
55
  private misses;
56
56
  private evictions;
57
+ private operationCount;
58
+ private readonly PRUNE_INTERVAL;
57
59
  constructor(config?: CacheConfig);
58
60
  /**
59
61
  * Generate cache key from endpoint and parameters
@@ -84,13 +86,34 @@ export declare class ApiCache {
84
86
  */
85
87
  prune(): number;
86
88
  /**
87
- * Invalidate entries matching a pattern
89
+ * Invalidate entries matching a pattern.
90
+ *
91
+ * When a string is provided, it is treated as a literal string and
92
+ * special RegExp characters are escaped to prevent RegExp injection.
93
+ * To use regex patterns, pass a RegExp object directly.
94
+ *
95
+ * @param pattern - Literal string to match or RegExp for pattern matching
96
+ * @returns Number of entries invalidated
97
+ *
98
+ * @example
99
+ * ```typescript
100
+ * // Literal string matching (special chars are escaped)
101
+ * cache.invalidatePattern('search:user.name') // Matches exactly 'search:user.name'
102
+ *
103
+ * // RegExp for pattern matching
104
+ * cache.invalidatePattern(/^search:/) // Matches all keys starting with 'search:'
105
+ * ```
88
106
  */
89
107
  invalidatePattern(pattern: string | RegExp): number;
90
108
  /**
91
109
  * Get cache statistics
92
110
  */
93
111
  getStats(): CacheStats;
112
+ /**
113
+ * Automatically prune expired entries every PRUNE_INTERVAL operations.
114
+ * SMI-1262: Prevents expired entries from accumulating until maxEntries is reached.
115
+ */
116
+ private maybeAutoPrune;
94
117
  /**
95
118
  * Evict least recently used entries
96
119
  */
@@ -1 +1 @@
1
- {"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../../src/api/cache.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAcH;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,oDAAoD;IACpD,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,2CAA2C;IAC3C,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,+CAA+C;IAC/C,WAAW,CAAC,EAAE,OAAO,CAAA;CACtB;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,EAAE,MAAM,CAAA;IACf,SAAS,EAAE,MAAM,CAAA;IACjB,OAAO,EAAE,MAAM,CAAA;CAChB;AAED;;GAEG;AACH,eAAO,MAAM,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAI9C,CAAA;AAED;;;;;;;;;;;;;GAaG;AACH,qBAAa,QAAQ;IACnB,OAAO,CAAC,KAAK,CAAkC;IAC/C,OAAO,CAAC,UAAU,CAAQ;IAC1B,OAAO,CAAC,UAAU,CAAQ;IAC1B,OAAO,CAAC,WAAW,CAAS;IAG5B,OAAO,CAAC,IAAI,CAAI;IAChB,OAAO,CAAC,MAAM,CAAI;IAClB,OAAO,CAAC,SAAS,CAAI;gBAET,MAAM,GAAE,WAAgB;IAOpC;;OAEG;IACH,MAAM,CAAC,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM;IAa5E;;OAEG;IACH,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,GAAG,SAAS;IAsBlC;;OAEG;IACH,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,EAAE,YAAY,CAAC,EAAE,MAAM,OAAO,WAAW,GAAG,IAAI;IAiB3E;;OAEG;IACH,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAUzB;;OAEG;IACH,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAI5B;;OAEG;IACH,KAAK,IAAI,IAAI;IAOb;;OAEG;IACH,KAAK,IAAI,MAAM;IAcf;;OAEG;IACH,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM;IAcnD;;OAEG;IACH,QAAQ,IAAI,UAAU;IAWtB;;OAEG;IACH,OAAO,CAAC,cAAc;CAwBvB;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,QAAQ,CAE1D;AAOD;;GAEG;AACH,wBAAgB,cAAc,IAAI,QAAQ,CAKzC;AAED,eAAe,QAAQ,CAAA"}
1
+ {"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../../src/api/cache.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAiCH;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,oDAAoD;IACpD,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,2CAA2C;IAC3C,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,+CAA+C;IAC/C,WAAW,CAAC,EAAE,OAAO,CAAA;CACtB;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,EAAE,MAAM,CAAA;IACf,SAAS,EAAE,MAAM,CAAA;IACjB,OAAO,EAAE,MAAM,CAAA;CAChB;AAED;;GAEG;AACH,eAAO,MAAM,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAI9C,CAAA;AAED;;;;;;;;;;;;;GAaG;AACH,qBAAa,QAAQ;IACnB,OAAO,CAAC,KAAK,CAAkC;IAC/C,OAAO,CAAC,UAAU,CAAQ;IAC1B,OAAO,CAAC,UAAU,CAAQ;IAC1B,OAAO,CAAC,WAAW,CAAS;IAG5B,OAAO,CAAC,IAAI,CAAI;IAChB,OAAO,CAAC,MAAM,CAAI;IAClB,OAAO,CAAC,SAAS,CAAI;IAGrB,OAAO,CAAC,cAAc,CAAI;IAC1B,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAM;gBAEzB,MAAM,GAAE,WAAgB;IAOpC;;OAEG;IACH,MAAM,CAAC,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM;IAa5E;;OAEG;IACH,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,GAAG,SAAS;IAuBlC;;OAEG;IACH,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,EAAE,YAAY,CAAC,EAAE,MAAM,OAAO,WAAW,GAAG,IAAI;IAmB3E;;OAEG;IACH,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAUzB;;OAEG;IACH,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAI5B;;OAEG;IACH,KAAK,IAAI,IAAI;IAOb;;OAEG;IACH,KAAK,IAAI,MAAM;IAcf;;;;;;;;;;;;;;;;;;OAkBG;IACH,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM;IAcnD;;OAEG;IACH,QAAQ,IAAI,UAAU;IAWtB;;;OAGG;IACH,OAAO,CAAC,cAAc;IAMtB;;OAEG;IACH,OAAO,CAAC,cAAc;CAwBvB;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,QAAQ,CAE1D;AAOD;;GAEG;AACH,wBAAgB,cAAc,IAAI,QAAQ,CAKzC;AAED,eAAe,QAAQ,CAAA"}