@blamechris/repo-memory 0.1.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 (111) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +85 -0
  3. package/dist/cache/gc.d.ts +14 -0
  4. package/dist/cache/gc.d.ts.map +1 -0
  5. package/dist/cache/gc.js +75 -0
  6. package/dist/cache/gc.js.map +1 -0
  7. package/dist/cache/hash.d.ts +10 -0
  8. package/dist/cache/hash.d.ts.map +1 -0
  9. package/dist/cache/hash.js +22 -0
  10. package/dist/cache/hash.js.map +1 -0
  11. package/dist/cache/invalidation.d.ts +29 -0
  12. package/dist/cache/invalidation.d.ts.map +1 -0
  13. package/dist/cache/invalidation.js +58 -0
  14. package/dist/cache/invalidation.js.map +1 -0
  15. package/dist/cache/ranking.d.ts +57 -0
  16. package/dist/cache/ranking.d.ts.map +1 -0
  17. package/dist/cache/ranking.js +196 -0
  18. package/dist/cache/ranking.js.map +1 -0
  19. package/dist/cache/store.d.ts +16 -0
  20. package/dist/cache/store.d.ts.map +1 -0
  21. package/dist/cache/store.js +70 -0
  22. package/dist/cache/store.js.map +1 -0
  23. package/dist/graph/dependency-graph.d.ts +26 -0
  24. package/dist/graph/dependency-graph.d.ts.map +1 -0
  25. package/dist/graph/dependency-graph.js +131 -0
  26. package/dist/graph/dependency-graph.js.map +1 -0
  27. package/dist/indexer/diff-analyzer.d.ts +8 -0
  28. package/dist/indexer/diff-analyzer.d.ts.map +1 -0
  29. package/dist/indexer/diff-analyzer.js +95 -0
  30. package/dist/indexer/diff-analyzer.js.map +1 -0
  31. package/dist/indexer/imports.d.ts +3 -0
  32. package/dist/indexer/imports.d.ts.map +1 -0
  33. package/dist/indexer/imports.js +123 -0
  34. package/dist/indexer/imports.js.map +1 -0
  35. package/dist/indexer/project-map.d.ts +20 -0
  36. package/dist/indexer/project-map.d.ts.map +1 -0
  37. package/dist/indexer/project-map.js +120 -0
  38. package/dist/indexer/project-map.js.map +1 -0
  39. package/dist/indexer/scanner.d.ts +7 -0
  40. package/dist/indexer/scanner.d.ts.map +1 -0
  41. package/dist/indexer/scanner.js +114 -0
  42. package/dist/indexer/scanner.js.map +1 -0
  43. package/dist/indexer/smart-summarizer.d.ts +6 -0
  44. package/dist/indexer/smart-summarizer.d.ts.map +1 -0
  45. package/dist/indexer/smart-summarizer.js +26 -0
  46. package/dist/indexer/smart-summarizer.js.map +1 -0
  47. package/dist/indexer/summarizer.d.ts +3 -0
  48. package/dist/indexer/summarizer.d.ts.map +1 -0
  49. package/dist/indexer/summarizer.js +145 -0
  50. package/dist/indexer/summarizer.js.map +1 -0
  51. package/dist/memory/session.d.ts +18 -0
  52. package/dist/memory/session.d.ts.map +1 -0
  53. package/dist/memory/session.js +75 -0
  54. package/dist/memory/session.js.map +1 -0
  55. package/dist/memory/task.d.ts +35 -0
  56. package/dist/memory/task.d.ts.map +1 -0
  57. package/dist/memory/task.js +120 -0
  58. package/dist/memory/task.js.map +1 -0
  59. package/dist/persistence/db.d.ts +4 -0
  60. package/dist/persistence/db.d.ts.map +1 -0
  61. package/dist/persistence/db.js +146 -0
  62. package/dist/persistence/db.js.map +1 -0
  63. package/dist/server.d.ts +3 -0
  64. package/dist/server.d.ts.map +1 -0
  65. package/dist/server.js +197 -0
  66. package/dist/server.js.map +1 -0
  67. package/dist/telemetry/tracker.d.ts +40 -0
  68. package/dist/telemetry/tracker.d.ts.map +1 -0
  69. package/dist/telemetry/tracker.js +136 -0
  70. package/dist/telemetry/tracker.js.map +1 -0
  71. package/dist/tools/force-reread.d.ts +9 -0
  72. package/dist/tools/force-reread.d.ts.map +1 -0
  73. package/dist/tools/force-reread.js +17 -0
  74. package/dist/tools/force-reread.js.map +1 -0
  75. package/dist/tools/get-changed-files.d.ts +8 -0
  76. package/dist/tools/get-changed-files.d.ts.map +1 -0
  77. package/dist/tools/get-changed-files.js +61 -0
  78. package/dist/tools/get-changed-files.js.map +1 -0
  79. package/dist/tools/get-dependency-graph.d.ts +17 -0
  80. package/dist/tools/get-dependency-graph.d.ts.map +1 -0
  81. package/dist/tools/get-dependency-graph.js +88 -0
  82. package/dist/tools/get-dependency-graph.js.map +1 -0
  83. package/dist/tools/get-file-summary.d.ts +12 -0
  84. package/dist/tools/get-file-summary.d.ts.map +1 -0
  85. package/dist/tools/get-file-summary.js +53 -0
  86. package/dist/tools/get-file-summary.js.map +1 -0
  87. package/dist/tools/get-project-map.d.ts +3 -0
  88. package/dist/tools/get-project-map.d.ts.map +1 -0
  89. package/dist/tools/get-project-map.js +5 -0
  90. package/dist/tools/get-project-map.js.map +1 -0
  91. package/dist/tools/get-token-report.d.ts +16 -0
  92. package/dist/tools/get-token-report.d.ts.map +1 -0
  93. package/dist/tools/get-token-report.js +44 -0
  94. package/dist/tools/get-token-report.js.map +1 -0
  95. package/dist/tools/invalidate.d.ts +5 -0
  96. package/dist/tools/invalidate.d.ts.map +1 -0
  97. package/dist/tools/invalidate.js +19 -0
  98. package/dist/tools/invalidate.js.map +1 -0
  99. package/dist/tools/task-context.d.ts +18 -0
  100. package/dist/tools/task-context.d.ts.map +1 -0
  101. package/dist/tools/task-context.js +28 -0
  102. package/dist/tools/task-context.js.map +1 -0
  103. package/dist/types.d.ts +21 -0
  104. package/dist/types.d.ts.map +1 -0
  105. package/dist/types.js +2 -0
  106. package/dist/types.js.map +1 -0
  107. package/dist/utils/validate-path.d.ts +10 -0
  108. package/dist/utils/validate-path.d.ts.map +1 -0
  109. package/dist/utils/validate-path.js +22 -0
  110. package/dist/utils/validate-path.js.map +1 -0
  111. package/package.json +62 -0
@@ -0,0 +1,61 @@
1
+ import { join } from 'path';
2
+ import { CacheStore } from '../cache/store.js';
3
+ import { hashFile } from '../cache/hash.js';
4
+ import { scanProject } from '../indexer/scanner.js';
5
+ export async function getChangedFiles(projectRoot, since) {
6
+ const store = new CacheStore(projectRoot);
7
+ const scannedFiles = await scanProject(projectRoot);
8
+ const allEntries = store.getAllEntries();
9
+ const cachedByPath = new Map(allEntries.map((e) => [e.path, e]));
10
+ const scannedSet = new Set(scannedFiles);
11
+ const sinceTimestamp = parseSince(since);
12
+ const changed = [];
13
+ const added = [];
14
+ await Promise.all(scannedFiles.map(async (relativePath) => {
15
+ const absolutePath = join(projectRoot, relativePath);
16
+ const currentHash = await hashFile(absolutePath);
17
+ if (!currentHash)
18
+ return;
19
+ const cached = cachedByPath.get(relativePath);
20
+ if (!cached) {
21
+ added.push(relativePath);
22
+ }
23
+ else if (cached.hash !== currentHash) {
24
+ if (sinceTimestamp === null || cached.lastChecked >= sinceTimestamp) {
25
+ changed.push(relativePath);
26
+ }
27
+ }
28
+ // Update the cache entry with current hash and timestamp
29
+ store.setEntry(relativePath, currentHash, cached?.summary ?? null);
30
+ }));
31
+ // Files in cache but not in scan are deleted
32
+ const deleted = [];
33
+ for (const [path, entry] of cachedByPath) {
34
+ if (!scannedSet.has(path)) {
35
+ if (sinceTimestamp === null || entry.lastChecked >= sinceTimestamp) {
36
+ deleted.push(path);
37
+ }
38
+ store.deleteEntry(path);
39
+ }
40
+ }
41
+ changed.sort();
42
+ added.sort();
43
+ deleted.sort();
44
+ return {
45
+ changed,
46
+ added,
47
+ deleted,
48
+ checkedAt: new Date().toISOString(),
49
+ };
50
+ }
51
+ function parseSince(since) {
52
+ if (!since || since === 'last_check') {
53
+ return null;
54
+ }
55
+ const parsed = Date.parse(since);
56
+ if (!isNaN(parsed)) {
57
+ return parsed;
58
+ }
59
+ return null;
60
+ }
61
+ //# sourceMappingURL=get-changed-files.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-changed-files.js","sourceRoot":"","sources":["../../src/tools/get-changed-files.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ export interface DependencyGraphResult {
2
+ nodes: string[];
3
+ edges: Array<{
4
+ from: string;
5
+ to: string;
6
+ }>;
7
+ stats: {
8
+ totalFiles: number;
9
+ totalEdges: number;
10
+ mostConnected: Array<{
11
+ path: string;
12
+ connections: number;
13
+ }>;
14
+ };
15
+ }
16
+ export declare function getDependencyGraphTool(projectRoot: string, path?: string, direction?: 'dependencies' | 'dependents' | 'both', depth?: number): Promise<DependencyGraphResult>;
17
+ //# sourceMappingURL=get-dependency-graph.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-dependency-graph.d.ts","sourceRoot":"","sources":["../../src/tools/get-dependency-graph.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,qBAAqB;IACpC,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,KAAK,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC3C,KAAK,EAAE;QACL,UAAU,EAAE,MAAM,CAAC;QACnB,UAAU,EAAE,MAAM,CAAC;QACnB,aAAa,EAAE,KAAK,CAAC;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,WAAW,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;KAC7D,CAAC;CACH;AAED,wBAAsB,sBAAsB,CAC1C,WAAW,EAAE,MAAM,EACnB,IAAI,CAAC,EAAE,MAAM,EACb,SAAS,CAAC,EAAE,cAAc,GAAG,YAAY,GAAG,MAAM,EAClD,KAAK,CAAC,EAAE,MAAM,GACb,OAAO,CAAC,qBAAqB,CAAC,CA0BhC"}
@@ -0,0 +1,88 @@
1
+ import { readFile } from 'node:fs/promises';
2
+ import { join } from 'node:path';
3
+ import { DependencyGraph } from '../graph/dependency-graph.js';
4
+ import { scanProject } from '../indexer/scanner.js';
5
+ import { validatePath } from '../utils/validate-path.js';
6
+ export async function getDependencyGraphTool(projectRoot, path, direction, depth) {
7
+ if (path) {
8
+ path = validatePath(projectRoot, path);
9
+ }
10
+ const graph = new DependencyGraph(projectRoot);
11
+ // Index all files to build the graph
12
+ const files = await scanProject(projectRoot);
13
+ for (const file of files) {
14
+ if (!file.endsWith('.ts') && !file.endsWith('.js') && !file.endsWith('.tsx') &&
15
+ !file.endsWith('.jsx') && !file.endsWith('.mjs') && !file.endsWith('.cjs')) {
16
+ continue;
17
+ }
18
+ try {
19
+ const contents = await readFile(join(projectRoot, file), 'utf-8');
20
+ graph.updateFile(file, contents);
21
+ }
22
+ catch {
23
+ // Skip unreadable files
24
+ }
25
+ }
26
+ if (path) {
27
+ return getNeighborhood(graph, path, direction ?? 'both', depth);
28
+ }
29
+ return getFullSummary(graph);
30
+ }
31
+ function getNeighborhood(graph, path, direction, depth) {
32
+ const nodes = new Set();
33
+ const edges = [];
34
+ nodes.add(path);
35
+ if (direction === 'dependencies' || direction === 'both') {
36
+ const deps = depth !== undefined
37
+ ? graph.getTransitiveDependencies(path, depth)
38
+ : graph.getDependencies(path);
39
+ for (const dep of deps) {
40
+ nodes.add(dep);
41
+ edges.push({ from: path, to: dep });
42
+ }
43
+ }
44
+ if (direction === 'dependents' || direction === 'both') {
45
+ const deps = depth !== undefined
46
+ ? graph.getTransitiveDependents(path, depth)
47
+ : graph.getDependents(path);
48
+ for (const dep of deps) {
49
+ nodes.add(dep);
50
+ edges.push({ from: dep, to: path });
51
+ }
52
+ }
53
+ return {
54
+ nodes: [...nodes].sort(),
55
+ edges,
56
+ stats: {
57
+ totalFiles: nodes.size,
58
+ totalEdges: edges.length,
59
+ mostConnected: graph.getMostConnected(5),
60
+ },
61
+ };
62
+ }
63
+ function getFullSummary(graph) {
64
+ const mostConnected = graph.getMostConnected(10);
65
+ const allNodes = new Set();
66
+ const edges = [];
67
+ for (const entry of mostConnected) {
68
+ allNodes.add(entry.path);
69
+ for (const dep of graph.getDependencies(entry.path)) {
70
+ allNodes.add(dep);
71
+ edges.push({ from: entry.path, to: dep });
72
+ }
73
+ for (const dep of graph.getDependents(entry.path)) {
74
+ allNodes.add(dep);
75
+ edges.push({ from: dep, to: entry.path });
76
+ }
77
+ }
78
+ return {
79
+ nodes: [...allNodes].sort(),
80
+ edges,
81
+ stats: {
82
+ totalFiles: allNodes.size,
83
+ totalEdges: edges.length,
84
+ mostConnected,
85
+ },
86
+ };
87
+ }
88
+ //# sourceMappingURL=get-dependency-graph.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-dependency-graph.js","sourceRoot":"","sources":["../../src/tools/get-dependency-graph.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import type { FileSummary } from '../types.js';
2
+ export interface FileSummaryResult {
3
+ path: string;
4
+ hash: string;
5
+ summary: FileSummary;
6
+ fromCache: boolean;
7
+ reason: string;
8
+ cacheAge: number | null;
9
+ suggestFullRead: boolean;
10
+ }
11
+ export declare function getFileSummary(projectRoot: string, relativePath: string): Promise<FileSummaryResult>;
12
+ //# sourceMappingURL=get-file-summary.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-file-summary.d.ts","sourceRoot":"","sources":["../../src/tools/get-file-summary.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAG/C,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,WAAW,CAAC;IACrB,SAAS,EAAE,OAAO,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,eAAe,EAAE,OAAO,CAAC;CAC1B;AAED,wBAAsB,cAAc,CAClC,WAAW,EAAE,MAAM,EACnB,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC,iBAAiB,CAAC,CAiD5B"}
@@ -0,0 +1,53 @@
1
+ import { readFile } from 'node:fs/promises';
2
+ import { join } from 'node:path';
3
+ import { hashContents } from '../cache/hash.js';
4
+ import { CacheStore } from '../cache/store.js';
5
+ import { summarizeFile } from '../indexer/summarizer.js';
6
+ import { validatePath } from '../utils/validate-path.js';
7
+ export async function getFileSummary(projectRoot, relativePath) {
8
+ relativePath = validatePath(projectRoot, relativePath);
9
+ const store = new CacheStore(projectRoot);
10
+ const absolutePath = join(projectRoot, relativePath);
11
+ // Read and hash the file
12
+ const contents = await readFile(absolutePath, 'utf-8');
13
+ const currentHash = hashContents(contents);
14
+ // Check cache
15
+ const cached = store.getEntry(relativePath);
16
+ const cacheAge = cached
17
+ ? Math.floor((Date.now() - cached.lastChecked) / 1000)
18
+ : null;
19
+ if (cached && cached.hash === currentHash && cached.summary) {
20
+ return {
21
+ path: relativePath,
22
+ hash: currentHash,
23
+ summary: cached.summary,
24
+ fromCache: true,
25
+ reason: 'cache_hit: hash unchanged',
26
+ cacheAge,
27
+ suggestFullRead: cached.summary.confidence === 'low',
28
+ };
29
+ }
30
+ // Generate fresh summary
31
+ const summary = summarizeFile(relativePath, contents);
32
+ store.setEntry(relativePath, currentHash, summary);
33
+ let reason;
34
+ if (!cached) {
35
+ reason = 'cache_miss: no prior entry';
36
+ }
37
+ else if (cached.hash !== currentHash) {
38
+ reason = 'cache_miss: hash changed';
39
+ }
40
+ else {
41
+ reason = 'cache_miss: no summary in cache';
42
+ }
43
+ return {
44
+ path: relativePath,
45
+ hash: currentHash,
46
+ summary,
47
+ fromCache: false,
48
+ reason,
49
+ cacheAge,
50
+ suggestFullRead: summary.confidence === 'low',
51
+ };
52
+ }
53
+ //# sourceMappingURL=get-file-summary.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-file-summary.js","sourceRoot":"","sources":["../../src/tools/get-file-summary.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAChD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAEzD,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAYzD,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,WAAmB,EACnB,YAAoB;IAEpB,YAAY,GAAG,YAAY,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC;IACvD,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,WAAW,CAAC,CAAC;IAC1C,MAAM,YAAY,GAAG,IAAI,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC;IAErD,yBAAyB;IACzB,MAAM,QAAQ,GAAG,MAAM,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;IACvD,MAAM,WAAW,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAC;IAE3C,cAAc;IACd,MAAM,MAAM,GAAG,KAAK,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC;IAC5C,MAAM,QAAQ,GAAG,MAAM;QACrB,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,MAAM,CAAC,WAAW,CAAC,GAAG,IAAI,CAAC;QACtD,CAAC,CAAC,IAAI,CAAC;IAET,IAAI,MAAM,IAAI,MAAM,CAAC,IAAI,KAAK,WAAW,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;QAC5D,OAAO;YACL,IAAI,EAAE,YAAY;YAClB,IAAI,EAAE,WAAW;YACjB,OAAO,EAAE,MAAM,CAAC,OAAO;YACvB,SAAS,EAAE,IAAI;YACf,MAAM,EAAE,2BAA2B;YACnC,QAAQ;YACR,eAAe,EAAE,MAAM,CAAC,OAAO,CAAC,UAAU,KAAK,KAAK;SACrD,CAAC;IACJ,CAAC;IAED,yBAAyB;IACzB,MAAM,OAAO,GAAG,aAAa,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC;IACtD,KAAK,CAAC,QAAQ,CAAC,YAAY,EAAE,WAAW,EAAE,OAAO,CAAC,CAAC;IAEnD,IAAI,MAAc,CAAC;IACnB,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,GAAG,4BAA4B,CAAC;IACxC,CAAC;SAAM,IAAI,MAAM,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;QACvC,MAAM,GAAG,0BAA0B,CAAC;IACtC,CAAC;SAAM,CAAC;QACN,MAAM,GAAG,iCAAiC,CAAC;IAC7C,CAAC;IAED,OAAO;QACL,IAAI,EAAE,YAAY;QAClB,IAAI,EAAE,WAAW;QACjB,OAAO;QACP,SAAS,EAAE,KAAK;QAChB,MAAM;QACN,QAAQ;QACR,eAAe,EAAE,OAAO,CAAC,UAAU,KAAK,KAAK;KAC9C,CAAC;AACJ,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { type ProjectMap } from '../indexer/project-map.js';
2
+ export declare function getProjectMap(projectRoot: string, depth?: number): Promise<ProjectMap>;
3
+ //# sourceMappingURL=get-project-map.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-project-map.d.ts","sourceRoot":"","sources":["../../src/tools/get-project-map.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmB,KAAK,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAE7E,wBAAsB,aAAa,CACjC,WAAW,EAAE,MAAM,EACnB,KAAK,CAAC,EAAE,MAAM,GACb,OAAO,CAAC,UAAU,CAAC,CAErB"}
@@ -0,0 +1,5 @@
1
+ import { buildProjectMap } from '../indexer/project-map.js';
2
+ export async function getProjectMap(projectRoot, depth) {
3
+ return buildProjectMap(projectRoot, depth !== undefined ? { depth } : undefined);
4
+ }
5
+ //# sourceMappingURL=get-project-map.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-project-map.js","sourceRoot":"","sources":["../../src/tools/get-project-map.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAmB,MAAM,2BAA2B,CAAC;AAE7E,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,WAAmB,EACnB,KAAc;IAEd,OAAO,eAAe,CAAC,WAAW,EAAE,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;AACnF,CAAC"}
@@ -0,0 +1,16 @@
1
+ export interface TokenReport {
2
+ period: string;
3
+ totalEvents: number;
4
+ cacheHits: number;
5
+ cacheMisses: number;
6
+ cacheHitRatio: number;
7
+ estimatedTokensSaved: number;
8
+ topFiles: Array<{
9
+ path: string;
10
+ accessCount: number;
11
+ tokensEstimated: number;
12
+ }>;
13
+ eventBreakdown: Record<string, number>;
14
+ }
15
+ export declare function getTokenReport(projectRoot: string, period?: 'session' | 'all' | 'last_n_hours', hours?: number, sessionId?: string): TokenReport;
16
+ //# sourceMappingURL=get-token-report.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-token-report.d.ts","sourceRoot":"","sources":["../../src/tools/get-token-report.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,QAAQ,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAC;QAAC,eAAe,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAChF,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACxC;AAED,wBAAgB,cAAc,CAC5B,WAAW,EAAE,MAAM,EACnB,MAAM,CAAC,EAAE,SAAS,GAAG,KAAK,GAAG,cAAc,EAC3C,KAAK,CAAC,EAAE,MAAM,EACd,SAAS,CAAC,EAAE,MAAM,GACjB,WAAW,CA4Cb"}
@@ -0,0 +1,44 @@
1
+ import { TelemetryTracker } from '../telemetry/tracker.js';
2
+ import { SessionManager } from '../memory/session.js';
3
+ export function getTokenReport(projectRoot, period, hours, sessionId) {
4
+ const tracker = new TelemetryTracker(projectRoot);
5
+ const effectivePeriod = period ?? 'all';
6
+ let since;
7
+ if (effectivePeriod === 'session' && sessionId) {
8
+ const sessionManager = new SessionManager(projectRoot);
9
+ const session = sessionManager.getSession(sessionId);
10
+ if (session) {
11
+ since = session.startedAt;
12
+ }
13
+ }
14
+ else if (effectivePeriod === 'last_n_hours' && hours != null) {
15
+ since = Date.now() - hours * 3600000;
16
+ }
17
+ const events = tracker.getEvents({ since });
18
+ const stats = tracker.getStats(since);
19
+ // Aggregate top files by access count and tokens
20
+ const fileMap = new Map();
21
+ for (const event of events) {
22
+ if (!event.filePath)
23
+ continue;
24
+ const entry = fileMap.get(event.filePath) ?? { accessCount: 0, tokensEstimated: 0 };
25
+ entry.accessCount++;
26
+ entry.tokensEstimated += event.tokensEstimated ?? 0;
27
+ fileMap.set(event.filePath, entry);
28
+ }
29
+ const topFiles = [...fileMap.entries()]
30
+ .map(([path, data]) => ({ path, ...data }))
31
+ .sort((a, b) => b.accessCount - a.accessCount)
32
+ .slice(0, 10);
33
+ return {
34
+ period: effectivePeriod,
35
+ totalEvents: stats.totalEvents,
36
+ cacheHits: stats.cacheHits,
37
+ cacheMisses: stats.cacheMisses,
38
+ cacheHitRatio: stats.hitRatio,
39
+ estimatedTokensSaved: stats.totalTokensSaved,
40
+ topFiles,
41
+ eventBreakdown: stats.eventsByType,
42
+ };
43
+ }
44
+ //# sourceMappingURL=get-token-report.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-token-report.js","sourceRoot":"","sources":["../../src/tools/get-token-report.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAatD,MAAM,UAAU,cAAc,CAC5B,WAAmB,EACnB,MAA2C,EAC3C,KAAc,EACd,SAAkB;IAElB,MAAM,OAAO,GAAG,IAAI,gBAAgB,CAAC,WAAW,CAAC,CAAC;IAClD,MAAM,eAAe,GAAG,MAAM,IAAI,KAAK,CAAC;IAExC,IAAI,KAAyB,CAAC;IAE9B,IAAI,eAAe,KAAK,SAAS,IAAI,SAAS,EAAE,CAAC;QAC/C,MAAM,cAAc,GAAG,IAAI,cAAc,CAAC,WAAW,CAAC,CAAC;QACvD,MAAM,OAAO,GAAG,cAAc,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;QACrD,IAAI,OAAO,EAAE,CAAC;YACZ,KAAK,GAAG,OAAO,CAAC,SAAS,CAAC;QAC5B,CAAC;IACH,CAAC;SAAM,IAAI,eAAe,KAAK,cAAc,IAAI,KAAK,IAAI,IAAI,EAAE,CAAC;QAC/D,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,GAAG,OAAO,CAAC;IACvC,CAAC;IAED,MAAM,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;IAC5C,MAAM,KAAK,GAAG,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IAEtC,iDAAiD;IACjD,MAAM,OAAO,GAAG,IAAI,GAAG,EAA4D,CAAC;IACpF,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,IAAI,CAAC,KAAK,CAAC,QAAQ;YAAE,SAAS;QAC9B,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,EAAE,WAAW,EAAE,CAAC,EAAE,eAAe,EAAE,CAAC,EAAE,CAAC;QACpF,KAAK,CAAC,WAAW,EAAE,CAAC;QACpB,KAAK,CAAC,eAAe,IAAI,KAAK,CAAC,eAAe,IAAI,CAAC,CAAC;QACpD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;IACrC,CAAC;IAED,MAAM,QAAQ,GAAG,CAAC,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;SACpC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,GAAG,IAAI,EAAE,CAAC,CAAC;SAC1C,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,GAAG,CAAC,CAAC,WAAW,CAAC;SAC7C,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAEhB,OAAO;QACL,MAAM,EAAE,eAAe;QACvB,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,aAAa,EAAE,KAAK,CAAC,QAAQ;QAC7B,oBAAoB,EAAE,KAAK,CAAC,gBAAgB;QAC5C,QAAQ;QACR,cAAc,EAAE,KAAK,CAAC,YAAY;KACnC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,5 @@
1
+ export declare function invalidateCache(projectRoot: string, path?: string): Promise<{
2
+ invalidated: string | 'all';
3
+ entriesRemoved: number;
4
+ }>;
5
+ //# sourceMappingURL=invalidate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"invalidate.d.ts","sourceRoot":"","sources":["../../src/tools/invalidate.ts"],"names":[],"mappings":"AAGA,wBAAsB,eAAe,CACnC,WAAW,EAAE,MAAM,EACnB,IAAI,CAAC,EAAE,MAAM,GACZ,OAAO,CAAC;IAAE,WAAW,EAAE,MAAM,GAAG,KAAK,CAAC;IAAC,cAAc,EAAE,MAAM,CAAA;CAAE,CAAC,CAkBlE"}
@@ -0,0 +1,19 @@
1
+ import { CacheStore } from '../cache/store.js';
2
+ import { validatePath } from '../utils/validate-path.js';
3
+ export async function invalidateCache(projectRoot, path) {
4
+ if (path) {
5
+ path = validatePath(projectRoot, path);
6
+ }
7
+ const store = new CacheStore(projectRoot);
8
+ if (path) {
9
+ store.deleteEntry(path);
10
+ return { invalidated: path, entriesRemoved: 1 };
11
+ }
12
+ const entries = store.getAllEntries();
13
+ const count = entries.length;
14
+ for (const entry of entries) {
15
+ store.deleteEntry(entry.path);
16
+ }
17
+ return { invalidated: 'all', entriesRemoved: count };
18
+ }
19
+ //# sourceMappingURL=invalidate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"invalidate.js","sourceRoot":"","sources":["../../src/tools/invalidate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAEzD,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,WAAmB,EACnB,IAAa;IAEb,IAAI,IAAI,EAAE,CAAC;QACT,IAAI,GAAG,YAAY,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;IACzC,CAAC;IACD,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,WAAW,CAAC,CAAC;IAE1C,IAAI,IAAI,EAAE,CAAC;QACT,KAAK,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;QACxB,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,cAAc,EAAE,CAAC,EAAE,CAAC;IAClD,CAAC;IAED,MAAM,OAAO,GAAG,KAAK,CAAC,aAAa,EAAE,CAAC;IACtC,MAAM,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC;IAC7B,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,KAAK,CAAC,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAChC,CAAC;IAED,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,cAAc,EAAE,KAAK,EAAE,CAAC;AACvD,CAAC"}
@@ -0,0 +1,18 @@
1
+ import { type Task, type TaskFile } from '../memory/task.js';
2
+ export interface TaskContextResult {
3
+ task: Task;
4
+ exploredFiles: TaskFile[];
5
+ frontier: string[];
6
+ }
7
+ export interface TaskListResult {
8
+ tasks: Task[];
9
+ }
10
+ export declare function createTaskTool(projectRoot: string, name: string, metadata?: Record<string, unknown>): Task;
11
+ export declare function getTaskContext(projectRoot: string, taskId?: string, allProjectFiles?: string[]): TaskContextResult | TaskListResult;
12
+ export declare function markExploredTool(projectRoot: string, taskId: string, path: string, status?: 'explored' | 'skipped' | 'flagged', notes?: string): {
13
+ marked: true;
14
+ taskId: string;
15
+ path: string;
16
+ status: string;
17
+ };
18
+ //# sourceMappingURL=task-context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"task-context.d.ts","sourceRoot":"","sources":["../../src/tools/task-context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,KAAK,IAAI,EAAE,KAAK,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAGzE,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,IAAI,CAAC;IACX,aAAa,EAAE,QAAQ,EAAE,CAAC;IAC1B,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,IAAI,EAAE,CAAC;CACf;AAED,wBAAgB,cAAc,CAC5B,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE,MAAM,EACZ,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACjC,IAAI,CAGN;AAED,wBAAgB,cAAc,CAC5B,WAAW,EAAE,MAAM,EACnB,MAAM,CAAC,EAAE,MAAM,EACf,eAAe,CAAC,EAAE,MAAM,EAAE,GACzB,iBAAiB,GAAG,cAAc,CAkBpC;AAED,wBAAgB,gBAAgB,CAC9B,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,MAAM,CAAC,EAAE,UAAU,GAAG,SAAS,GAAG,SAAS,EAC3C,KAAK,CAAC,EAAE,MAAM,GACb;IAAE,MAAM,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAKhE"}
@@ -0,0 +1,28 @@
1
+ import { TaskMemory } from '../memory/task.js';
2
+ import { validatePath } from '../utils/validate-path.js';
3
+ export function createTaskTool(projectRoot, name, metadata) {
4
+ const memory = new TaskMemory(projectRoot);
5
+ return memory.createTask(name, metadata);
6
+ }
7
+ export function getTaskContext(projectRoot, taskId, allProjectFiles) {
8
+ const memory = new TaskMemory(projectRoot);
9
+ if (!taskId) {
10
+ return { tasks: memory.listTasks() };
11
+ }
12
+ const task = memory.getTask(taskId);
13
+ if (!task) {
14
+ throw new Error(`Task not found: ${taskId}`);
15
+ }
16
+ const exploredFiles = memory.getExploredFiles(taskId);
17
+ const frontier = allProjectFiles
18
+ ? memory.getUnexploredFrontier(taskId, allProjectFiles)
19
+ : [];
20
+ return { task, exploredFiles, frontier };
21
+ }
22
+ export function markExploredTool(projectRoot, taskId, path, status, notes) {
23
+ path = validatePath(projectRoot, path);
24
+ const memory = new TaskMemory(projectRoot);
25
+ memory.markExplored(taskId, path, status, notes);
26
+ return { marked: true, taskId, path, status: status ?? 'explored' };
27
+ }
28
+ //# sourceMappingURL=task-context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"task-context.js","sourceRoot":"","sources":["../../src/tools/task-context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAA4B,MAAM,mBAAmB,CAAC;AACzE,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAYzD,MAAM,UAAU,cAAc,CAC5B,WAAmB,EACnB,IAAY,EACZ,QAAkC;IAElC,MAAM,MAAM,GAAG,IAAI,UAAU,CAAC,WAAW,CAAC,CAAC;IAC3C,OAAO,MAAM,CAAC,UAAU,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;AAC3C,CAAC;AAED,MAAM,UAAU,cAAc,CAC5B,WAAmB,EACnB,MAAe,EACf,eAA0B;IAE1B,MAAM,MAAM,GAAG,IAAI,UAAU,CAAC,WAAW,CAAC,CAAC;IAE3C,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,EAAE,KAAK,EAAE,MAAM,CAAC,SAAS,EAAE,EAAE,CAAC;IACvC,CAAC;IAED,MAAM,IAAI,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IACpC,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,MAAM,IAAI,KAAK,CAAC,mBAAmB,MAAM,EAAE,CAAC,CAAC;IAC/C,CAAC;IAED,MAAM,aAAa,GAAG,MAAM,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC;IACtD,MAAM,QAAQ,GAAG,eAAe;QAC9B,CAAC,CAAC,MAAM,CAAC,qBAAqB,CAAC,MAAM,EAAE,eAAe,CAAC;QACvD,CAAC,CAAC,EAAE,CAAC;IAEP,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE,QAAQ,EAAE,CAAC;AAC3C,CAAC;AAED,MAAM,UAAU,gBAAgB,CAC9B,WAAmB,EACnB,MAAc,EACd,IAAY,EACZ,MAA2C,EAC3C,KAAc;IAEd,IAAI,GAAG,YAAY,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;IACvC,MAAM,MAAM,GAAG,IAAI,UAAU,CAAC,WAAW,CAAC,CAAC;IAC3C,MAAM,CAAC,YAAY,CAAC,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;IACjD,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,IAAI,UAAU,EAAE,CAAC;AACtE,CAAC"}
@@ -0,0 +1,21 @@
1
+ export interface CacheEntry {
2
+ path: string;
3
+ hash: string;
4
+ lastChecked: number;
5
+ summary: FileSummary | null;
6
+ }
7
+ export interface FileSummary {
8
+ purpose: string;
9
+ exports: string[];
10
+ imports: string[];
11
+ lineCount: number;
12
+ topLevelDeclarations: string[];
13
+ confidence: 'high' | 'medium' | 'low';
14
+ }
15
+ export interface ImportRef {
16
+ source: string;
17
+ target: string;
18
+ specifiers: string[];
19
+ type: 'static' | 'dynamic' | 're-export';
20
+ }
21
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,WAAW,GAAG,IAAI,CAAC;CAC7B;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,oBAAoB,EAAE,MAAM,EAAE,CAAC;IAC/B,UAAU,EAAE,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;CACvC;AAED,MAAM,WAAW,SAAS;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,IAAI,EAAE,QAAQ,GAAG,SAAS,GAAG,WAAW,CAAC;CAC1C"}
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Validates that a file path is safe and resolves within the project root.
3
+ * Throws an error if the path attempts traversal outside the project.
4
+ *
5
+ * @param projectRoot - The absolute path to the project root directory.
6
+ * @param filePath - The file path to validate (relative or absolute).
7
+ * @returns The validated relative path (relative to projectRoot).
8
+ */
9
+ export declare function validatePath(projectRoot: string, filePath: string): string;
10
+ //# sourceMappingURL=validate-path.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate-path.d.ts","sourceRoot":"","sources":["../../src/utils/validate-path.ts"],"names":[],"mappings":"AAEA;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAkB1E"}
@@ -0,0 +1,22 @@
1
+ import { resolve, normalize, relative, sep } from 'node:path';
2
+ /**
3
+ * Validates that a file path is safe and resolves within the project root.
4
+ * Throws an error if the path attempts traversal outside the project.
5
+ *
6
+ * @param projectRoot - The absolute path to the project root directory.
7
+ * @param filePath - The file path to validate (relative or absolute).
8
+ * @returns The validated relative path (relative to projectRoot).
9
+ */
10
+ export function validatePath(projectRoot, filePath) {
11
+ if (filePath.includes('\0')) {
12
+ throw new Error(`Invalid path: null byte detected in "${filePath}"`);
13
+ }
14
+ const normalizedRoot = normalize(resolve(projectRoot));
15
+ const resolvedPath = normalize(resolve(projectRoot, filePath));
16
+ if (resolvedPath !== normalizedRoot &&
17
+ !resolvedPath.startsWith(normalizedRoot + sep)) {
18
+ throw new Error(`Path traversal detected: ${filePath} resolves outside project root`);
19
+ }
20
+ return relative(normalizedRoot, resolvedPath);
21
+ }
22
+ //# sourceMappingURL=validate-path.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate-path.js","sourceRoot":"","sources":["../../src/utils/validate-path.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AAE9D;;;;;;;GAOG;AACH,MAAM,UAAU,YAAY,CAAC,WAAmB,EAAE,QAAgB;IAChE,IAAI,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QAC5B,MAAM,IAAI,KAAK,CAAC,wCAAwC,QAAQ,GAAG,CAAC,CAAC;IACvE,CAAC;IAED,MAAM,cAAc,GAAG,SAAS,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC;IACvD,MAAM,YAAY,GAAG,SAAS,CAAC,OAAO,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC,CAAC;IAE/D,IACE,YAAY,KAAK,cAAc;QAC/B,CAAC,YAAY,CAAC,UAAU,CAAC,cAAc,GAAG,GAAG,CAAC,EAC9C,CAAC;QACD,MAAM,IAAI,KAAK,CACb,4BAA4B,QAAQ,gCAAgC,CACrE,CAAC;IACJ,CAAC;IAED,OAAO,QAAQ,CAAC,cAAc,EAAE,YAAY,CAAC,CAAC;AAChD,CAAC"}
package/package.json ADDED
@@ -0,0 +1,62 @@
1
+ {
2
+ "name": "@blamechris/repo-memory",
3
+ "version": "0.1.0",
4
+ "description": "MCP server that gives AI coding agents persistent memory about your codebase",
5
+ "type": "module",
6
+ "main": "dist/server.js",
7
+ "types": "dist/server.d.ts",
8
+ "bin": {
9
+ "repo-memory": "dist/server.js"
10
+ },
11
+ "files": [
12
+ "dist",
13
+ "README.md",
14
+ "LICENSE"
15
+ ],
16
+ "scripts": {
17
+ "build": "tsc",
18
+ "typecheck": "tsc --noEmit",
19
+ "test": "vitest run",
20
+ "test:integration": "vitest run --config vitest.integration.config.ts",
21
+ "test:coverage": "vitest run --coverage",
22
+ "start": "node dist/server.js",
23
+ "lint": "eslint --no-error-on-unmatched-pattern 'src/**/*.ts' 'tests/**/*.ts'",
24
+ "format": "prettier --write 'src/**/*.ts' '*.json' '*.mjs' && prettier --write 'tests/**/*.ts' 2>/dev/null || true",
25
+ "prepublishOnly": "npm run typecheck && npm run lint && npm run test && npm run build",
26
+ "benchmark": "tsx tests/benchmarks/run-benchmarks.ts"
27
+ },
28
+ "keywords": [
29
+ "mcp",
30
+ "ai",
31
+ "agent",
32
+ "memory",
33
+ "codebase",
34
+ "cache",
35
+ "llm"
36
+ ],
37
+ "author": "blamechris",
38
+ "license": "MIT",
39
+ "repository": {
40
+ "type": "git",
41
+ "url": "https://github.com/blamechris/repo-memory.git"
42
+ },
43
+ "engines": {
44
+ "node": ">=20"
45
+ },
46
+ "devDependencies": {
47
+ "@types/better-sqlite3": "^7.6.13",
48
+ "@types/node": "^25.3.5",
49
+ "@typescript-eslint/eslint-plugin": "^8.56.1",
50
+ "@typescript-eslint/parser": "^8.56.1",
51
+ "eslint": "^10.0.2",
52
+ "eslint-config-prettier": "^10.1.8",
53
+ "prettier": "^3.8.1",
54
+ "typescript": "^5.9.3",
55
+ "vitest": "^4.0.18"
56
+ },
57
+ "dependencies": {
58
+ "@modelcontextprotocol/sdk": "^1.27.1",
59
+ "better-sqlite3": "^12.6.2",
60
+ "zod": "^4.3.6"
61
+ }
62
+ }