@milo4jo/contextkit 0.5.0 → 0.5.6

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 (59) hide show
  1. package/README.md +59 -1
  2. package/dist/commands/cache.d.ts +3 -0
  3. package/dist/commands/cache.d.ts.map +1 -0
  4. package/dist/commands/cache.js +50 -0
  5. package/dist/commands/cache.js.map +1 -0
  6. package/dist/commands/doctor.d.ts +3 -0
  7. package/dist/commands/doctor.d.ts.map +1 -0
  8. package/dist/commands/doctor.js +254 -0
  9. package/dist/commands/doctor.js.map +1 -0
  10. package/dist/commands/graph.d.ts +10 -0
  11. package/dist/commands/graph.d.ts.map +1 -0
  12. package/dist/commands/graph.js +289 -0
  13. package/dist/commands/graph.js.map +1 -0
  14. package/dist/commands/select.d.ts.map +1 -1
  15. package/dist/commands/select.js +11 -0
  16. package/dist/commands/select.js.map +1 -1
  17. package/dist/commands/symbol.d.ts +9 -0
  18. package/dist/commands/symbol.d.ts.map +1 -0
  19. package/dist/commands/symbol.js +420 -0
  20. package/dist/commands/symbol.js.map +1 -0
  21. package/dist/db/index.d.ts +48 -0
  22. package/dist/db/index.d.ts.map +1 -1
  23. package/dist/db/index.js +99 -0
  24. package/dist/db/index.js.map +1 -1
  25. package/dist/index.js +12 -0
  26. package/dist/index.js.map +1 -1
  27. package/dist/indexer/chunker.d.ts +25 -3
  28. package/dist/indexer/chunker.d.ts.map +1 -1
  29. package/dist/indexer/chunker.js +344 -4
  30. package/dist/indexer/chunker.js.map +1 -1
  31. package/dist/indexer/index.d.ts.map +1 -1
  32. package/dist/indexer/index.js +3 -2
  33. package/dist/indexer/index.js.map +1 -1
  34. package/dist/mcp-server.js +0 -0
  35. package/dist/parsers/index.d.ts +65 -0
  36. package/dist/parsers/index.d.ts.map +1 -0
  37. package/dist/parsers/index.js +130 -0
  38. package/dist/parsers/index.js.map +1 -0
  39. package/dist/parsers/markdown.d.ts +29 -0
  40. package/dist/parsers/markdown.d.ts.map +1 -0
  41. package/dist/parsers/markdown.js +142 -0
  42. package/dist/parsers/markdown.js.map +1 -0
  43. package/dist/parsers/tree-sitter.d.ts +32 -0
  44. package/dist/parsers/tree-sitter.d.ts.map +1 -0
  45. package/dist/parsers/tree-sitter.js +356 -0
  46. package/dist/parsers/tree-sitter.js.map +1 -0
  47. package/dist/parsers/typescript.d.ts +43 -0
  48. package/dist/parsers/typescript.d.ts.map +1 -0
  49. package/dist/parsers/typescript.js +306 -0
  50. package/dist/parsers/typescript.js.map +1 -0
  51. package/dist/selector/formatter.d.ts +4 -1
  52. package/dist/selector/formatter.d.ts.map +1 -1
  53. package/dist/selector/formatter.js +214 -6
  54. package/dist/selector/formatter.js.map +1 -1
  55. package/dist/selector/index.d.ts +8 -0
  56. package/dist/selector/index.d.ts.map +1 -1
  57. package/dist/selector/index.js +37 -2
  58. package/dist/selector/index.js.map +1 -1
  59. package/package.json +6 -1
@@ -0,0 +1,420 @@
1
+ /**
2
+ * Symbol Search Command
3
+ *
4
+ * Find code by symbol name (exact/fuzzy match).
5
+ * Faster than semantic search when you know the name.
6
+ */
7
+ import { Command } from 'commander';
8
+ import { ensureInitialized } from '../config/index.js';
9
+ import { openDatabase } from '../db/index.js';
10
+ import { writeData, writeMessage } from '../utils/streams.js';
11
+ import { formatDim } from '../utils/format.js';
12
+ import { getGlobalOpts } from '../utils/cli.js';
13
+ /** Extract symbols from chunk content */
14
+ function extractSymbols(content, filePath) {
15
+ const symbols = [];
16
+ const lines = content.split('\n');
17
+ const ext = filePath.split('.').pop()?.toLowerCase();
18
+ for (let i = 0; i < lines.length; i++) {
19
+ const line = lines[i];
20
+ const trimmed = line.trim();
21
+ const lineNum = i + 1;
22
+ // TypeScript/JavaScript patterns
23
+ if (ext === 'ts' || ext === 'tsx' || ext === 'js' || ext === 'jsx') {
24
+ // Function declaration
25
+ const funcMatch = trimmed.match(/^(export\s+)?(async\s+)?function\s+(\w+)/);
26
+ if (funcMatch) {
27
+ symbols.push({
28
+ filePath,
29
+ symbolName: funcMatch[3],
30
+ symbolType: 'function',
31
+ startLine: lineNum,
32
+ endLine: findBlockEnd(lines, i),
33
+ signature: extractSignatureLine(trimmed),
34
+ content: '',
35
+ });
36
+ continue;
37
+ }
38
+ // Class declaration
39
+ const classMatch = trimmed.match(/^(export\s+)?(abstract\s+)?class\s+(\w+)/);
40
+ if (classMatch) {
41
+ symbols.push({
42
+ filePath,
43
+ symbolName: classMatch[3],
44
+ symbolType: 'class',
45
+ startLine: lineNum,
46
+ endLine: findBlockEnd(lines, i),
47
+ signature: extractSignatureLine(trimmed),
48
+ content: '',
49
+ });
50
+ continue;
51
+ }
52
+ // Interface declaration
53
+ const interfaceMatch = trimmed.match(/^(export\s+)?interface\s+(\w+)/);
54
+ if (interfaceMatch) {
55
+ symbols.push({
56
+ filePath,
57
+ symbolName: interfaceMatch[2],
58
+ symbolType: 'interface',
59
+ startLine: lineNum,
60
+ endLine: findBlockEnd(lines, i),
61
+ signature: extractSignatureLine(trimmed),
62
+ content: '',
63
+ });
64
+ continue;
65
+ }
66
+ // Type alias
67
+ const typeMatch = trimmed.match(/^(export\s+)?type\s+(\w+)/);
68
+ if (typeMatch) {
69
+ symbols.push({
70
+ filePath,
71
+ symbolName: typeMatch[2],
72
+ symbolType: 'type',
73
+ startLine: lineNum,
74
+ endLine: findTypeEnd(lines, i),
75
+ signature: trimmed,
76
+ content: '',
77
+ });
78
+ continue;
79
+ }
80
+ // Const/let/var with arrow function or value
81
+ const constMatch = trimmed.match(/^(export\s+)?(const|let|var)\s+(\w+)/);
82
+ if (constMatch) {
83
+ const isFunction = trimmed.includes('=>') || trimmed.includes('function');
84
+ symbols.push({
85
+ filePath,
86
+ symbolName: constMatch[3],
87
+ symbolType: isFunction ? 'function' : 'constant',
88
+ startLine: lineNum,
89
+ endLine: findStatementEnd(lines, i),
90
+ signature: extractSignatureLine(trimmed),
91
+ content: '',
92
+ });
93
+ continue;
94
+ }
95
+ }
96
+ // Python patterns
97
+ if (ext === 'py') {
98
+ // Function/method definition
99
+ const pyFuncMatch = trimmed.match(/^(async\s+)?def\s+(\w+)/);
100
+ if (pyFuncMatch) {
101
+ symbols.push({
102
+ filePath,
103
+ symbolName: pyFuncMatch[2],
104
+ symbolType: 'function',
105
+ startLine: lineNum,
106
+ endLine: findPythonBlockEnd(lines, i),
107
+ signature: trimmed.replace(/:$/, ''),
108
+ content: '',
109
+ });
110
+ continue;
111
+ }
112
+ // Class definition
113
+ const pyClassMatch = trimmed.match(/^class\s+(\w+)/);
114
+ if (pyClassMatch) {
115
+ symbols.push({
116
+ filePath,
117
+ symbolName: pyClassMatch[1],
118
+ symbolType: 'class',
119
+ startLine: lineNum,
120
+ endLine: findPythonBlockEnd(lines, i),
121
+ signature: trimmed.replace(/:$/, ''),
122
+ content: '',
123
+ });
124
+ continue;
125
+ }
126
+ }
127
+ // Go patterns
128
+ if (ext === 'go') {
129
+ // Function declaration
130
+ const goFuncMatch = trimmed.match(/^func\s+(\w+)/);
131
+ if (goFuncMatch) {
132
+ symbols.push({
133
+ filePath,
134
+ symbolName: goFuncMatch[1],
135
+ symbolType: 'function',
136
+ startLine: lineNum,
137
+ endLine: findBlockEnd(lines, i),
138
+ signature: trimmed.replace(/\s*\{$/, ''),
139
+ content: '',
140
+ });
141
+ continue;
142
+ }
143
+ // Method declaration (func (r Receiver) Name)
144
+ const goMethodMatch = trimmed.match(/^func\s+\([^)]+\)\s+(\w+)/);
145
+ if (goMethodMatch) {
146
+ symbols.push({
147
+ filePath,
148
+ symbolName: goMethodMatch[1],
149
+ symbolType: 'method',
150
+ startLine: lineNum,
151
+ endLine: findBlockEnd(lines, i),
152
+ signature: trimmed.replace(/\s*\{$/, ''),
153
+ content: '',
154
+ });
155
+ continue;
156
+ }
157
+ // Type declaration
158
+ const goTypeMatch = trimmed.match(/^type\s+(\w+)/);
159
+ if (goTypeMatch) {
160
+ symbols.push({
161
+ filePath,
162
+ symbolName: goTypeMatch[1],
163
+ symbolType: 'type',
164
+ startLine: lineNum,
165
+ endLine: findBlockEnd(lines, i),
166
+ signature: trimmed.replace(/\s*\{$/, ''),
167
+ content: '',
168
+ });
169
+ continue;
170
+ }
171
+ }
172
+ // Rust patterns
173
+ if (ext === 'rs') {
174
+ // Function
175
+ const rustFuncMatch = trimmed.match(/^(pub\s+)?(async\s+)?fn\s+(\w+)/);
176
+ if (rustFuncMatch) {
177
+ symbols.push({
178
+ filePath,
179
+ symbolName: rustFuncMatch[3],
180
+ symbolType: 'function',
181
+ startLine: lineNum,
182
+ endLine: findBlockEnd(lines, i),
183
+ signature: trimmed.replace(/\s*\{$/, ''),
184
+ content: '',
185
+ });
186
+ continue;
187
+ }
188
+ // Struct/Enum
189
+ const rustStructMatch = trimmed.match(/^(pub\s+)?(struct|enum)\s+(\w+)/);
190
+ if (rustStructMatch) {
191
+ symbols.push({
192
+ filePath,
193
+ symbolName: rustStructMatch[3],
194
+ symbolType: 'class',
195
+ startLine: lineNum,
196
+ endLine: findBlockEnd(lines, i),
197
+ signature: trimmed.replace(/\s*\{$/, ''),
198
+ content: '',
199
+ });
200
+ continue;
201
+ }
202
+ // Trait
203
+ const rustTraitMatch = trimmed.match(/^(pub\s+)?trait\s+(\w+)/);
204
+ if (rustTraitMatch) {
205
+ symbols.push({
206
+ filePath,
207
+ symbolName: rustTraitMatch[2],
208
+ symbolType: 'interface',
209
+ startLine: lineNum,
210
+ endLine: findBlockEnd(lines, i),
211
+ signature: trimmed.replace(/\s*\{$/, ''),
212
+ content: '',
213
+ });
214
+ continue;
215
+ }
216
+ }
217
+ }
218
+ return symbols;
219
+ }
220
+ /** Find end of a brace-delimited block */
221
+ function findBlockEnd(lines, startIdx) {
222
+ let braceCount = 0;
223
+ let started = false;
224
+ for (let i = startIdx; i < lines.length; i++) {
225
+ const line = lines[i];
226
+ for (const char of line) {
227
+ if (char === '{') {
228
+ braceCount++;
229
+ started = true;
230
+ }
231
+ else if (char === '}') {
232
+ braceCount--;
233
+ if (started && braceCount === 0) {
234
+ return i + 1;
235
+ }
236
+ }
237
+ }
238
+ }
239
+ return lines.length;
240
+ }
241
+ /** Find end of a Python indented block */
242
+ function findPythonBlockEnd(lines, startIdx) {
243
+ const startLine = lines[startIdx];
244
+ const startIndent = startLine.length - startLine.trimStart().length;
245
+ for (let i = startIdx + 1; i < lines.length; i++) {
246
+ const line = lines[i];
247
+ const trimmed = line.trim();
248
+ if (!trimmed)
249
+ continue; // Skip empty lines
250
+ const indent = line.length - line.trimStart().length;
251
+ if (indent <= startIndent) {
252
+ return i;
253
+ }
254
+ }
255
+ return lines.length;
256
+ }
257
+ /** Find end of a type declaration */
258
+ function findTypeEnd(lines, startIdx) {
259
+ // Types can span multiple lines until semicolon
260
+ for (let i = startIdx; i < lines.length; i++) {
261
+ if (lines[i].includes(';')) {
262
+ return i + 1;
263
+ }
264
+ }
265
+ return startIdx + 1;
266
+ }
267
+ /** Find end of a const/let/var statement */
268
+ function findStatementEnd(lines, startIdx) {
269
+ // Check if it's a simple one-liner
270
+ const startLine = lines[startIdx];
271
+ if (startLine.trim().endsWith(';')) {
272
+ return startIdx + 1;
273
+ }
274
+ // Check for arrow function or object literal
275
+ if (startLine.includes('=>') || startLine.includes('{')) {
276
+ return findBlockEnd(lines, startIdx);
277
+ }
278
+ // Multi-line statement ending with semicolon
279
+ for (let i = startIdx; i < Math.min(startIdx + 20, lines.length); i++) {
280
+ if (lines[i].trim().endsWith(';')) {
281
+ return i + 1;
282
+ }
283
+ }
284
+ return startIdx + 1;
285
+ }
286
+ /** Extract signature from a line (remove body) */
287
+ function extractSignatureLine(line) {
288
+ const braceIdx = line.indexOf('{');
289
+ if (braceIdx > 0) {
290
+ return line.substring(0, braceIdx).trim();
291
+ }
292
+ return line.trim();
293
+ }
294
+ /** Search for symbols by name */
295
+ function searchSymbols(db, query, options) {
296
+ const { exact = false, limit = 20, sources } = options;
297
+ // Build SQL query
298
+ let sql = 'SELECT DISTINCT file_path, content FROM chunks';
299
+ const params = [];
300
+ if (sources && sources.length > 0) {
301
+ sql += ' WHERE source_id IN (' + sources.map(() => '?').join(',') + ')';
302
+ params.push(...sources);
303
+ }
304
+ const rows = db.prepare(sql).all(...params);
305
+ // Extract and filter symbols
306
+ const allSymbols = [];
307
+ const queryLower = query.toLowerCase();
308
+ for (const row of rows) {
309
+ const symbols = extractSymbols(row.content, row.file_path);
310
+ for (const sym of symbols) {
311
+ const nameLower = sym.symbolName.toLowerCase();
312
+ if (exact) {
313
+ if (nameLower === queryLower) {
314
+ allSymbols.push(sym);
315
+ }
316
+ }
317
+ else {
318
+ // Fuzzy match: name must contain the query as a substring
319
+ // Skip very short names (< 3 chars) unless exact match
320
+ const isExactMatch = nameLower === queryLower;
321
+ const containsQuery = nameLower.includes(queryLower);
322
+ const isSignificantName = sym.symbolName.length >= 3;
323
+ if (isExactMatch || (containsQuery && isSignificantName)) {
324
+ allSymbols.push(sym);
325
+ }
326
+ }
327
+ }
328
+ }
329
+ // Sort by relevance (exact matches first, then by name length)
330
+ allSymbols.sort((a, b) => {
331
+ const aExact = a.symbolName.toLowerCase() === queryLower;
332
+ const bExact = b.symbolName.toLowerCase() === queryLower;
333
+ if (aExact && !bExact)
334
+ return -1;
335
+ if (!aExact && bExact)
336
+ return 1;
337
+ return a.symbolName.length - b.symbolName.length;
338
+ });
339
+ return allSymbols.slice(0, limit);
340
+ }
341
+ /** Format symbol output */
342
+ function formatSymbolOutput(symbols, json) {
343
+ if (json) {
344
+ return JSON.stringify(symbols, null, 2);
345
+ }
346
+ if (symbols.length === 0) {
347
+ return '';
348
+ }
349
+ const lines = [];
350
+ // Group by file
351
+ const byFile = new Map();
352
+ for (const sym of symbols) {
353
+ const existing = byFile.get(sym.filePath) || [];
354
+ existing.push(sym);
355
+ byFile.set(sym.filePath, existing);
356
+ }
357
+ for (const [filePath, fileSymbols] of byFile) {
358
+ lines.push(`📄 ${filePath}`);
359
+ for (const sym of fileSymbols) {
360
+ const typeIcon = getTypeIcon(sym.symbolType);
361
+ lines.push(`│ ${typeIcon} ${sym.symbolName} (line ${sym.startLine})`);
362
+ lines.push(`│ ${sym.signature}`);
363
+ }
364
+ lines.push('');
365
+ }
366
+ return lines.join('\n');
367
+ }
368
+ /** Get icon for symbol type */
369
+ function getTypeIcon(type) {
370
+ switch (type) {
371
+ case 'function': return '𝑓';
372
+ case 'class': return '◆';
373
+ case 'method': return '◇';
374
+ case 'interface': return '◈';
375
+ case 'type': return '⊤';
376
+ case 'constant': return '●';
377
+ case 'variable': return '○';
378
+ default: return '•';
379
+ }
380
+ }
381
+ export const symbolCommand = new Command('symbol')
382
+ .description('Search for symbols by name')
383
+ .argument('<name>', 'Symbol name to search for')
384
+ .option('-e, --exact', 'Exact match only')
385
+ .option('-l, --limit <n>', 'Maximum results', '20')
386
+ .option('-s, --sources <sources>', 'Filter sources (comma-separated)')
387
+ .action(async (name, options) => {
388
+ ensureInitialized();
389
+ const opts = getGlobalOpts(symbolCommand);
390
+ const limit = parseInt(options.limit, 10) || 20;
391
+ const sources = options.sources
392
+ ? options.sources.split(',').map((s) => s.trim())
393
+ : undefined;
394
+ const db = openDatabase();
395
+ try {
396
+ const symbols = searchSymbols(db, name, {
397
+ exact: options.exact,
398
+ limit,
399
+ sources,
400
+ });
401
+ if (symbols.length === 0) {
402
+ writeMessage('');
403
+ writeMessage(formatDim(`No symbols found matching "${name}"`));
404
+ writeMessage(formatDim('Try a different name or remove --exact flag.'));
405
+ writeMessage('');
406
+ return;
407
+ }
408
+ const output = formatSymbolOutput(symbols, opts.json ?? false);
409
+ writeData(output);
410
+ // Summary
411
+ if (!opts.json) {
412
+ writeMessage('');
413
+ writeMessage(formatDim(`Found ${symbols.length} symbol(s)`));
414
+ }
415
+ }
416
+ finally {
417
+ db.close();
418
+ }
419
+ });
420
+ //# sourceMappingURL=symbol.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"symbol.js","sourceRoot":"","sources":["../../src/commands/symbol.ts"],"names":[],"mappings":"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"}
@@ -11,4 +11,52 @@ export declare function openDatabase(): Database.Database;
11
11
  * Close the database connection
12
12
  */
13
13
  export declare function closeDatabase(db: Database.Database): void;
14
+ /** Cache entry structure */
15
+ export interface CacheEntry {
16
+ cacheKey: string;
17
+ result: string;
18
+ indexVersion: string;
19
+ createdAt: string;
20
+ hitCount: number;
21
+ }
22
+ /** Parameters that affect cache key */
23
+ export interface CacheKeyParams {
24
+ query: string;
25
+ budget: number;
26
+ sources?: string[];
27
+ format: string;
28
+ mode?: string;
29
+ includeImports?: boolean;
30
+ }
31
+ /**
32
+ * Compute index version hash based on chunk count and last indexed time
33
+ * This invalidates cache when the index changes
34
+ */
35
+ export declare function computeIndexVersion(db: Database.Database): string;
36
+ /**
37
+ * Generate cache key from query parameters
38
+ */
39
+ export declare function generateCacheKey(params: CacheKeyParams): string;
40
+ /**
41
+ * Get cached result if valid
42
+ * Returns null if not found or index has changed
43
+ */
44
+ export declare function getCachedResult(db: Database.Database, cacheKey: string, currentIndexVersion: string): string | null;
45
+ /**
46
+ * Store result in cache
47
+ */
48
+ export declare function setCachedResult(db: Database.Database, cacheKey: string, result: string, indexVersion: string): void;
49
+ /**
50
+ * Clear all cache entries
51
+ */
52
+ export declare function clearCache(db: Database.Database): number;
53
+ /**
54
+ * Get cache statistics
55
+ */
56
+ export declare function getCacheStats(db: Database.Database): {
57
+ entryCount: number;
58
+ totalHits: number;
59
+ oldestEntry: string | null;
60
+ newestEntry: string | null;
61
+ };
14
62
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/db/index.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AA+CtC;;GAEG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,QAAQ,CAAC,QAAQ,CAU9D;AAED;;GAEG;AACH,wBAAgB,YAAY,IAAI,QAAQ,CAAC,QAAQ,CAKhD;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,GAAG,IAAI,CAEzD"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/db/index.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AA0DtC;;GAEG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,QAAQ,CAAC,QAAQ,CAU9D;AAED;;GAEG;AACH,wBAAgB,YAAY,IAAI,QAAQ,CAAC,QAAQ,CAKhD;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,GAAG,IAAI,CAEzD;AAMD,4BAA4B;AAC5B,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,uCAAuC;AACvC,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,GAAG,MAAM,CAcjE;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,cAAc,GAAG,MAAM,CAY/D;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAC7B,EAAE,EAAE,QAAQ,CAAC,QAAQ,EACrB,QAAQ,EAAE,MAAM,EAChB,mBAAmB,EAAE,MAAM,GAC1B,MAAM,GAAG,IAAI,CAyBf;AAED;;GAEG;AACH,wBAAgB,eAAe,CAC7B,EAAE,EAAE,QAAQ,CAAC,QAAQ,EACrB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,MAAM,GACnB,IAAI,CAKN;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,GAAG,MAAM,CAGxD;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,GAAG;IACpD,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B,CAgBA"}
package/dist/db/index.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import Database from 'better-sqlite3';
2
+ import { createHash } from 'crypto';
2
3
  import { getDbPath } from '../config/index.js';
3
4
  /**
4
5
  * Database schema for ContextKit
@@ -37,11 +38,21 @@ CREATE TABLE IF NOT EXISTS chunks (
37
38
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
38
39
  );
39
40
 
41
+ -- Query cache table
42
+ CREATE TABLE IF NOT EXISTS query_cache (
43
+ cache_key TEXT PRIMARY KEY,
44
+ result JSON NOT NULL,
45
+ index_version TEXT NOT NULL,
46
+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
47
+ hit_count INTEGER DEFAULT 0
48
+ );
49
+
40
50
  -- Indexes for performance
41
51
  CREATE INDEX IF NOT EXISTS idx_chunks_source ON chunks(source_id);
42
52
  CREATE INDEX IF NOT EXISTS idx_chunks_file ON chunks(file_path);
43
53
  CREATE INDEX IF NOT EXISTS idx_files_source ON files(source_id);
44
54
  CREATE INDEX IF NOT EXISTS idx_files_path ON files(source_id, file_path);
55
+ CREATE INDEX IF NOT EXISTS idx_cache_created ON query_cache(created_at);
45
56
  `;
46
57
  /**
47
58
  * Initialize the database with schema
@@ -69,4 +80,92 @@ export function openDatabase() {
69
80
  export function closeDatabase(db) {
70
81
  db.close();
71
82
  }
83
+ /**
84
+ * Compute index version hash based on chunk count and last indexed time
85
+ * This invalidates cache when the index changes
86
+ */
87
+ export function computeIndexVersion(db) {
88
+ const stats = db.prepare(`
89
+ SELECT
90
+ COUNT(*) as chunkCount,
91
+ MAX(created_at) as lastIndexed
92
+ FROM chunks
93
+ `).get();
94
+ const sourceStats = db.prepare(`
95
+ SELECT COUNT(*) as sourceCount FROM sources
96
+ `).get();
97
+ const versionData = `${stats.chunkCount}:${sourceStats.sourceCount}:${stats.lastIndexed || ''}`;
98
+ return createHash('sha256').update(versionData).digest('hex').slice(0, 16);
99
+ }
100
+ /**
101
+ * Generate cache key from query parameters
102
+ */
103
+ export function generateCacheKey(params) {
104
+ const normalized = {
105
+ query: params.query,
106
+ budget: params.budget,
107
+ sources: params.sources?.slice().sort() || [],
108
+ format: params.format,
109
+ mode: params.mode || 'full',
110
+ includeImports: params.includeImports || false,
111
+ };
112
+ const keyData = JSON.stringify(normalized);
113
+ return createHash('sha256').update(keyData).digest('hex');
114
+ }
115
+ /**
116
+ * Get cached result if valid
117
+ * Returns null if not found or index has changed
118
+ */
119
+ export function getCachedResult(db, cacheKey, currentIndexVersion) {
120
+ const row = db.prepare(`
121
+ SELECT result, index_version, hit_count
122
+ FROM query_cache
123
+ WHERE cache_key = ?
124
+ `).get(cacheKey);
125
+ if (!row) {
126
+ return null;
127
+ }
128
+ // Invalidate if index has changed
129
+ if (row.index_version !== currentIndexVersion) {
130
+ db.prepare('DELETE FROM query_cache WHERE cache_key = ?').run(cacheKey);
131
+ return null;
132
+ }
133
+ // Update hit count
134
+ db.prepare(`
135
+ UPDATE query_cache
136
+ SET hit_count = hit_count + 1
137
+ WHERE cache_key = ?
138
+ `).run(cacheKey);
139
+ return row.result;
140
+ }
141
+ /**
142
+ * Store result in cache
143
+ */
144
+ export function setCachedResult(db, cacheKey, result, indexVersion) {
145
+ db.prepare(`
146
+ INSERT OR REPLACE INTO query_cache (cache_key, result, index_version, created_at, hit_count)
147
+ VALUES (?, ?, ?, datetime('now'), 0)
148
+ `).run(cacheKey, result, indexVersion);
149
+ }
150
+ /**
151
+ * Clear all cache entries
152
+ */
153
+ export function clearCache(db) {
154
+ const result = db.prepare('DELETE FROM query_cache').run();
155
+ return result.changes;
156
+ }
157
+ /**
158
+ * Get cache statistics
159
+ */
160
+ export function getCacheStats(db) {
161
+ const stats = db.prepare(`
162
+ SELECT
163
+ COUNT(*) as entryCount,
164
+ COALESCE(SUM(hit_count), 0) as totalHits,
165
+ MIN(created_at) as oldestEntry,
166
+ MAX(created_at) as newestEntry
167
+ FROM query_cache
168
+ `).get();
169
+ return stats;
170
+ }
72
171
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/db/index.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AACtC,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAE/C;;GAEG;AACH,MAAM,MAAM,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAuCd,CAAC;AAEF;;GAEG;AACH,MAAM,UAAU,YAAY,CAAC,MAAc;IACzC,MAAM,EAAE,GAAG,IAAI,QAAQ,CAAC,MAAM,CAAC,CAAC;IAEhC,sBAAsB;IACtB,EAAE,CAAC,MAAM,CAAC,mBAAmB,CAAC,CAAC;IAE/B,gBAAgB;IAChB,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAEhB,OAAO,EAAE,CAAC;AACZ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,YAAY;IAC1B,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;IAC3B,MAAM,EAAE,GAAG,IAAI,QAAQ,CAAC,MAAM,CAAC,CAAC;IAChC,EAAE,CAAC,MAAM,CAAC,mBAAmB,CAAC,CAAC;IAC/B,OAAO,EAAE,CAAC;AACZ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,aAAa,CAAC,EAAqB;IACjD,EAAE,CAAC,KAAK,EAAE,CAAC;AACb,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/db/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -7,8 +7,12 @@ import { initCommand } from './commands/init.js';
7
7
  import { sourceCommand } from './commands/source/index.js';
8
8
  import { indexCommand } from './commands/index-cmd.js';
9
9
  import { selectCommand } from './commands/select.js';
10
+ import { symbolCommand } from './commands/symbol.js';
11
+ import { graphCommand } from './commands/graph.js';
12
+ import { cacheCommand } from './commands/cache.js';
10
13
  import { mcpCommand } from './commands/mcp.js';
11
14
  import { watchCommand } from './commands/watch.js';
15
+ import { doctorCommand } from './commands/doctor.js';
12
16
  import { ContextKitError, InvalidUsageError } from './errors/index.js';
13
17
  import { writeError, writeMessage } from './utils/streams.js';
14
18
  // Get version from package.json
@@ -62,8 +66,12 @@ program.addCommand(initCommand);
62
66
  program.addCommand(sourceCommand);
63
67
  program.addCommand(indexCommand);
64
68
  program.addCommand(selectCommand);
69
+ program.addCommand(symbolCommand);
70
+ program.addCommand(graphCommand);
71
+ program.addCommand(cacheCommand);
65
72
  program.addCommand(mcpCommand);
66
73
  program.addCommand(watchCommand);
74
+ program.addCommand(doctorCommand);
67
75
  // Default action when no command given
68
76
  program.action(() => {
69
77
  console.log(`
@@ -80,8 +88,12 @@ Commands:
80
88
  source Manage source directories
81
89
  index Index all sources (incremental by default)
82
90
  select Select context for a query
91
+ symbol Search for symbols by name
92
+ graph Show call graph for a function
93
+ cache Manage query cache
83
94
  watch Watch sources and auto-reindex on changes
84
95
  mcp Start MCP server for AI assistants
96
+ doctor Diagnose setup issues
85
97
 
86
98
  Global Options:
87
99
  --json Output as JSON