codetree-claude 1.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 (108) hide show
  1. package/.codetreerc.default.json +41 -0
  2. package/README.md +171 -0
  3. package/dist/cli.d.ts +3 -0
  4. package/dist/cli.d.ts.map +1 -0
  5. package/dist/cli.js +185 -0
  6. package/dist/cli.js.map +1 -0
  7. package/dist/config.d.ts +131 -0
  8. package/dist/config.d.ts.map +1 -0
  9. package/dist/config.js +111 -0
  10. package/dist/config.js.map +1 -0
  11. package/dist/hook/hook-client.d.ts +6 -0
  12. package/dist/hook/hook-client.d.ts.map +1 -0
  13. package/dist/hook/hook-client.js +48 -0
  14. package/dist/hook/hook-client.js.map +1 -0
  15. package/dist/hook/pre-tool-use.bundled.js +162 -0
  16. package/dist/hook/pre-tool-use.d.ts +14 -0
  17. package/dist/hook/pre-tool-use.d.ts.map +1 -0
  18. package/dist/hook/pre-tool-use.js +140 -0
  19. package/dist/hook/pre-tool-use.js.map +1 -0
  20. package/dist/index.d.ts +10 -0
  21. package/dist/index.d.ts.map +1 -0
  22. package/dist/index.js +12 -0
  23. package/dist/index.js.map +1 -0
  24. package/dist/indexer/extractor-registry.d.ts +10 -0
  25. package/dist/indexer/extractor-registry.d.ts.map +1 -0
  26. package/dist/indexer/extractor-registry.js +39 -0
  27. package/dist/indexer/extractor-registry.js.map +1 -0
  28. package/dist/indexer/extractors/generic.d.ts +11 -0
  29. package/dist/indexer/extractors/generic.d.ts.map +1 -0
  30. package/dist/indexer/extractors/generic.js +12 -0
  31. package/dist/indexer/extractors/generic.js.map +1 -0
  32. package/dist/indexer/extractors/go.d.ts +10 -0
  33. package/dist/indexer/extractors/go.d.ts.map +1 -0
  34. package/dist/indexer/extractors/go.js +119 -0
  35. package/dist/indexer/extractors/go.js.map +1 -0
  36. package/dist/indexer/extractors/java.d.ts +10 -0
  37. package/dist/indexer/extractors/java.d.ts.map +1 -0
  38. package/dist/indexer/extractors/java.js +89 -0
  39. package/dist/indexer/extractors/java.js.map +1 -0
  40. package/dist/indexer/extractors/javascript.d.ts +11 -0
  41. package/dist/indexer/extractors/javascript.d.ts.map +1 -0
  42. package/dist/indexer/extractors/javascript.js +190 -0
  43. package/dist/indexer/extractors/javascript.js.map +1 -0
  44. package/dist/indexer/extractors/python.d.ts +11 -0
  45. package/dist/indexer/extractors/python.d.ts.map +1 -0
  46. package/dist/indexer/extractors/python.js +115 -0
  47. package/dist/indexer/extractors/python.js.map +1 -0
  48. package/dist/indexer/extractors/types.d.ts +26 -0
  49. package/dist/indexer/extractors/types.d.ts.map +1 -0
  50. package/dist/indexer/extractors/types.js +36 -0
  51. package/dist/indexer/extractors/types.js.map +1 -0
  52. package/dist/indexer/hasher.d.ts +11 -0
  53. package/dist/indexer/hasher.d.ts.map +1 -0
  54. package/dist/indexer/hasher.js +41 -0
  55. package/dist/indexer/hasher.js.map +1 -0
  56. package/dist/indexer/ignore.d.ts +15 -0
  57. package/dist/indexer/ignore.d.ts.map +1 -0
  58. package/dist/indexer/ignore.js +63 -0
  59. package/dist/indexer/ignore.js.map +1 -0
  60. package/dist/indexer/indexer.d.ts +64 -0
  61. package/dist/indexer/indexer.d.ts.map +1 -0
  62. package/dist/indexer/indexer.js +295 -0
  63. package/dist/indexer/indexer.js.map +1 -0
  64. package/dist/indexer/watcher.d.ts +16 -0
  65. package/dist/indexer/watcher.d.ts.map +1 -0
  66. package/dist/indexer/watcher.js +79 -0
  67. package/dist/indexer/watcher.js.map +1 -0
  68. package/dist/server/ipc.d.ts +38 -0
  69. package/dist/server/ipc.d.ts.map +1 -0
  70. package/dist/server/ipc.js +212 -0
  71. package/dist/server/ipc.js.map +1 -0
  72. package/dist/server/mcp-server.d.ts +2 -0
  73. package/dist/server/mcp-server.d.ts.map +1 -0
  74. package/dist/server/mcp-server.js +133 -0
  75. package/dist/server/mcp-server.js.map +1 -0
  76. package/dist/server/tools/codetree-find-refs.d.ts +46 -0
  77. package/dist/server/tools/codetree-find-refs.d.ts.map +1 -0
  78. package/dist/server/tools/codetree-find-refs.js +83 -0
  79. package/dist/server/tools/codetree-find-refs.js.map +1 -0
  80. package/dist/server/tools/codetree-read.d.ts +46 -0
  81. package/dist/server/tools/codetree-read.d.ts.map +1 -0
  82. package/dist/server/tools/codetree-read.js +82 -0
  83. package/dist/server/tools/codetree-read.js.map +1 -0
  84. package/dist/server/tools/codetree-search.d.ts +59 -0
  85. package/dist/server/tools/codetree-search.d.ts.map +1 -0
  86. package/dist/server/tools/codetree-search.js +92 -0
  87. package/dist/server/tools/codetree-search.js.map +1 -0
  88. package/dist/server/tools/codetree-structure.d.ts +55 -0
  89. package/dist/server/tools/codetree-structure.d.ts.map +1 -0
  90. package/dist/server/tools/codetree-structure.js +137 -0
  91. package/dist/server/tools/codetree-structure.js.map +1 -0
  92. package/dist/server/tools/codetree-summary.d.ts +36 -0
  93. package/dist/server/tools/codetree-summary.d.ts.map +1 -0
  94. package/dist/server/tools/codetree-summary.js +94 -0
  95. package/dist/server/tools/codetree-summary.js.map +1 -0
  96. package/dist/setup/install.d.ts +26 -0
  97. package/dist/setup/install.d.ts.map +1 -0
  98. package/dist/setup/install.js +127 -0
  99. package/dist/setup/install.js.map +1 -0
  100. package/dist/storage/cache.d.ts +29 -0
  101. package/dist/storage/cache.d.ts.map +1 -0
  102. package/dist/storage/cache.js +54 -0
  103. package/dist/storage/cache.js.map +1 -0
  104. package/dist/storage/database.d.ts +52 -0
  105. package/dist/storage/database.d.ts.map +1 -0
  106. package/dist/storage/database.js +346 -0
  107. package/dist/storage/database.js.map +1 -0
  108. package/package.json +60 -0
@@ -0,0 +1,63 @@
1
+ import ignoreModule from "ignore";
2
+ const ignore = ignoreModule.default || ignoreModule;
3
+ import { readFileSync, existsSync } from "node:fs";
4
+ import { join, extname } from "node:path";
5
+ import { isBinaryExtension } from "../config.js";
6
+ export class IgnoreFilter {
7
+ ig;
8
+ config;
9
+ constructor(config) {
10
+ this.config = config;
11
+ this.ig = ignore();
12
+ // Add configured ignore patterns
13
+ this.ig.add(config.ignore);
14
+ // Add .codetree directory itself
15
+ this.ig.add(".codetree");
16
+ // Load .gitignore if present
17
+ const gitignorePath = join(config.projectRoot, ".gitignore");
18
+ if (existsSync(gitignorePath)) {
19
+ try {
20
+ const content = readFileSync(gitignorePath, "utf-8");
21
+ this.ig.add(content);
22
+ }
23
+ catch {
24
+ // Ignore read errors
25
+ }
26
+ }
27
+ // Load .codetreeignore if present
28
+ const codetreeIgnorePath = join(config.projectRoot, ".codetreeignore");
29
+ if (existsSync(codetreeIgnorePath)) {
30
+ try {
31
+ const content = readFileSync(codetreeIgnorePath, "utf-8");
32
+ this.ig.add(content);
33
+ }
34
+ catch {
35
+ // Ignore read errors
36
+ }
37
+ }
38
+ }
39
+ /**
40
+ * Check if a relative path should be ignored.
41
+ */
42
+ isIgnored(relativePath) {
43
+ // Normalize to forward slashes
44
+ const normalized = relativePath.replace(/\\/g, "/");
45
+ // Check ignore patterns
46
+ if (this.ig.ignores(normalized))
47
+ return true;
48
+ // Check binary extensions
49
+ if (this.config.ignoreBinary) {
50
+ const ext = extname(normalized);
51
+ if (ext && isBinaryExtension(ext))
52
+ return true;
53
+ }
54
+ return false;
55
+ }
56
+ /**
57
+ * Filter a list of relative paths, returning only non-ignored ones.
58
+ */
59
+ filter(paths) {
60
+ return paths.filter((p) => !this.isIgnored(p));
61
+ }
62
+ }
63
+ //# sourceMappingURL=ignore.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ignore.js","sourceRoot":"","sources":["../../src/indexer/ignore.ts"],"names":[],"mappings":"AAAA,OAAO,YAAY,MAAM,QAAQ,CAAC;AAClC,MAAM,MAAM,GAAG,YAAY,CAAC,OAAO,IAAI,YAAY,CAAC;AAEpD,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,iBAAiB,EAAuB,MAAM,cAAc,CAAC;AAEtE,MAAM,OAAO,YAAY;IACf,EAAE,CAAS;IACX,MAAM,CAAiB;IAE/B,YAAY,MAAsB;QAChC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,EAAE,GAAG,MAAM,EAAE,CAAC;QAEnB,iCAAiC;QACjC,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QAE3B,iCAAiC;QACjC,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;QAEzB,6BAA6B;QAC7B,MAAM,aAAa,GAAG,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC;QAC7D,IAAI,UAAU,CAAC,aAAa,CAAC,EAAE,CAAC;YAC9B,IAAI,CAAC;gBACH,MAAM,OAAO,GAAG,YAAY,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC;gBACrD,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YACvB,CAAC;YAAC,MAAM,CAAC;gBACP,qBAAqB;YACvB,CAAC;QACH,CAAC;QAED,kCAAkC;QAClC,MAAM,kBAAkB,GAAG,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,iBAAiB,CAAC,CAAC;QACvE,IAAI,UAAU,CAAC,kBAAkB,CAAC,EAAE,CAAC;YACnC,IAAI,CAAC;gBACH,MAAM,OAAO,GAAG,YAAY,CAAC,kBAAkB,EAAE,OAAO,CAAC,CAAC;gBAC1D,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YACvB,CAAC;YAAC,MAAM,CAAC;gBACP,qBAAqB;YACvB,CAAC;QACH,CAAC;IACH,CAAC;IAED;;OAEG;IACH,SAAS,CAAC,YAAoB;QAC5B,+BAA+B;QAC/B,MAAM,UAAU,GAAG,YAAY,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QAEpD,wBAAwB;QACxB,IAAI,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,UAAU,CAAC;YAAE,OAAO,IAAI,CAAC;QAE7C,0BAA0B;QAC1B,IAAI,IAAI,CAAC,MAAM,CAAC,YAAY,EAAE,CAAC;YAC7B,MAAM,GAAG,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;YAChC,IAAI,GAAG,IAAI,iBAAiB,CAAC,GAAG,CAAC;gBAAE,OAAO,IAAI,CAAC;QACjD,CAAC;QAED,OAAO,KAAK,CAAC;IACf,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,KAAe;QACpB,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;IACjD,CAAC;CACF"}
@@ -0,0 +1,64 @@
1
+ import { type CodeTreeConfig } from "../config.js";
2
+ import { Database } from "../storage/database.js";
3
+ import { ContentCache } from "../storage/cache.js";
4
+ export interface IndexStats {
5
+ totalFiles: number;
6
+ indexedFiles: number;
7
+ symbolCount: number;
8
+ indexTimeMs: number;
9
+ cacheHitRate: number;
10
+ }
11
+ export interface IndexerEvents {
12
+ onProgress?: (indexed: number, total: number) => void;
13
+ onError?: (path: string, error: Error) => void;
14
+ onComplete?: (stats: IndexStats) => void;
15
+ }
16
+ export declare class Indexer {
17
+ private db;
18
+ private cache;
19
+ private ignoreFilter;
20
+ private extractors;
21
+ private config;
22
+ private indexing;
23
+ private ready;
24
+ constructor(config: CodeTreeConfig, db: Database, cache: ContentCache);
25
+ init(): Promise<void>;
26
+ isReady(): boolean;
27
+ isIndexing(): boolean;
28
+ /**
29
+ * Full scan of the project directory. Incremental: skips files that haven't changed.
30
+ */
31
+ fullScan(events?: IndexerEvents): Promise<IndexStats>;
32
+ /**
33
+ * Index a single file. Returns null if file hasn't changed since last index.
34
+ */
35
+ indexFile(absPath: string): {
36
+ symbolCount: number;
37
+ } | null;
38
+ /**
39
+ * Remove a file from the index (when it's deleted from disk).
40
+ */
41
+ removeFile(absPath: string): void;
42
+ /**
43
+ * Read a file from cache. Returns null on cache miss.
44
+ */
45
+ readCached(relPath: string): string | null;
46
+ /**
47
+ * Check if a file is in the cache and still valid.
48
+ */
49
+ isCacheValid(absPath: string): boolean;
50
+ /**
51
+ * Get project structure as a tree.
52
+ */
53
+ getProjectTree(): Record<string, {
54
+ language: string | null;
55
+ size: number;
56
+ lineCount: number;
57
+ symbolCount: number;
58
+ }>;
59
+ getStats(): IndexStats;
60
+ private collectFiles;
61
+ private walkDir;
62
+ private pruneDeletedFiles;
63
+ }
64
+ //# sourceMappingURL=indexer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"indexer.d.ts","sourceRoot":"","sources":["../../src/indexer/indexer.ts"],"names":[],"mappings":"AAGA,OAAO,EAAiB,KAAK,cAAc,EAAE,MAAM,cAAc,CAAC;AAClE,OAAO,EAAE,QAAQ,EAA6D,MAAM,wBAAwB,CAAC;AAC7G,OAAO,EAAE,YAAY,EAAmB,MAAM,qBAAqB,CAAC;AAMpE,MAAM,WAAW,UAAU;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,aAAa;IAC5B,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACtD,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IAC/C,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,CAAC;CAC1C;AAED,qBAAa,OAAO;IAClB,OAAO,CAAC,EAAE,CAAW;IACrB,OAAO,CAAC,KAAK,CAAe;IAC5B,OAAO,CAAC,YAAY,CAAe;IACnC,OAAO,CAAC,UAAU,CAAoB;IACtC,OAAO,CAAC,MAAM,CAAiB;IAC/B,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,KAAK,CAAS;gBAEV,MAAM,EAAE,cAAc,EAAE,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,YAAY;IAQ/D,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAK3B,OAAO,IAAI,OAAO;IAIlB,UAAU,IAAI,OAAO;IAIrB;;OAEG;IACG,QAAQ,CAAC,MAAM,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,UAAU,CAAC;IA2C3D;;OAEG;IACH,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG;QAAE,WAAW,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IA0G1D;;OAEG;IACH,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAMjC;;OAEG;IACH,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IA+B1C;;OAEG;IACH,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO;IAatC;;OAEG;IACH,cAAc,IAAI,MAAM,CAAC,MAAM,EAAE;QAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,CAAC;IAiBnH,QAAQ,IAAI,UAAU;IAatB,OAAO,CAAC,YAAY;IAMpB,OAAO,CAAC,OAAO;IAsBf,OAAO,CAAC,iBAAiB;CAa1B"}
@@ -0,0 +1,295 @@
1
+ import { readFileSync, statSync, readdirSync } from "node:fs";
2
+ import { join, relative } from "node:path";
3
+ import { deflateSync, inflateSync } from "node:zlib";
4
+ import { normalizePath } from "../config.js";
5
+ import { hashContent, ensureHasherReady, quickHash } from "./hasher.js";
6
+ import { IgnoreFilter } from "./ignore.js";
7
+ import { ExtractorRegistry } from "./extractor-registry.js";
8
+ import { detectLanguage } from "./extractors/types.js";
9
+ export class Indexer {
10
+ db;
11
+ cache;
12
+ ignoreFilter;
13
+ extractors;
14
+ config;
15
+ indexing = false;
16
+ ready = false;
17
+ constructor(config, db, cache) {
18
+ this.config = config;
19
+ this.db = db;
20
+ this.cache = cache;
21
+ this.ignoreFilter = new IgnoreFilter(config);
22
+ this.extractors = new ExtractorRegistry();
23
+ }
24
+ async init() {
25
+ await ensureHasherReady();
26
+ this.ready = true;
27
+ }
28
+ isReady() {
29
+ return this.ready && !this.indexing;
30
+ }
31
+ isIndexing() {
32
+ return this.indexing;
33
+ }
34
+ /**
35
+ * Full scan of the project directory. Incremental: skips files that haven't changed.
36
+ */
37
+ async fullScan(events) {
38
+ if (!this.ready)
39
+ throw new Error("Indexer not initialized");
40
+ this.indexing = true;
41
+ const startTime = Date.now();
42
+ const filePaths = this.collectFiles(this.config.projectRoot);
43
+ let indexed = 0;
44
+ let symbolCount = 0;
45
+ for (const absPath of filePaths) {
46
+ try {
47
+ const result = this.indexFile(absPath);
48
+ if (result) {
49
+ symbolCount += result.symbolCount;
50
+ }
51
+ indexed++;
52
+ events?.onProgress?.(indexed, filePaths.length);
53
+ }
54
+ catch (err) {
55
+ events?.onError?.(absPath, err);
56
+ }
57
+ }
58
+ // Remove files from index that no longer exist on disk
59
+ this.pruneDeletedFiles(filePaths);
60
+ // Evict old content cache entries
61
+ this.db.evictContentCache(this.config.cache.contentCacheMaxMB);
62
+ this.db.persistToDisk();
63
+ this.indexing = false;
64
+ const stats = {
65
+ totalFiles: filePaths.length,
66
+ indexedFiles: indexed,
67
+ symbolCount,
68
+ indexTimeMs: Date.now() - startTime,
69
+ cacheHitRate: this.cache.getStats().hitRate,
70
+ };
71
+ events?.onComplete?.(stats);
72
+ return stats;
73
+ }
74
+ /**
75
+ * Index a single file. Returns null if file hasn't changed since last index.
76
+ */
77
+ indexFile(absPath) {
78
+ const relPath = normalizePath(relative(this.config.projectRoot, absPath));
79
+ let stat;
80
+ try {
81
+ stat = statSync(absPath);
82
+ }
83
+ catch {
84
+ // File doesn't exist or can't be read — remove from index
85
+ this.db.deleteFile(relPath);
86
+ this.cache.delete(relPath);
87
+ return null;
88
+ }
89
+ // Skip files over size limit
90
+ if (stat.size > this.config.maxFileSize)
91
+ return null;
92
+ if (stat.size === 0)
93
+ return null;
94
+ // Quick check: has the file changed since last index?
95
+ const existing = this.db.getFile(relPath);
96
+ if (existing) {
97
+ const quick = quickHash(stat.size, Math.floor(stat.mtimeMs));
98
+ const existingQuick = quickHash(existing.size, existing.mtime_ms);
99
+ if (quick === existingQuick) {
100
+ // File hasn't changed — skip
101
+ return null;
102
+ }
103
+ }
104
+ // Read and index the file
105
+ let content;
106
+ try {
107
+ content = readFileSync(absPath, "utf-8");
108
+ }
109
+ catch {
110
+ return null;
111
+ }
112
+ const hash = hashContent(content);
113
+ // Double check: if hash matches, file content is truly the same
114
+ if (existing && existing.hash === hash) {
115
+ // Update mtime but skip re-extraction
116
+ this.db.upsertFile({
117
+ ...existing,
118
+ mtime_ms: Math.floor(stat.mtimeMs),
119
+ indexed_at: Date.now(),
120
+ });
121
+ return null;
122
+ }
123
+ const lineCount = content.split("\n").length;
124
+ const language = detectLanguage(absPath);
125
+ // Store file record
126
+ const fileRecord = {
127
+ path: relPath,
128
+ hash,
129
+ size: stat.size,
130
+ mtime_ms: Math.floor(stat.mtimeMs),
131
+ language,
132
+ line_count: lineCount,
133
+ indexed_at: Date.now(),
134
+ };
135
+ this.db.upsertFile(fileRecord);
136
+ // Extract symbols and dependencies
137
+ let symbolCount = 0;
138
+ if (this.config.symbols.enabled) {
139
+ const extraction = this.extractors.extract(content, absPath);
140
+ const symbolRecords = extraction.symbols.map((s) => ({
141
+ file_path: relPath,
142
+ name: s.name,
143
+ kind: s.kind,
144
+ line_start: s.lineStart,
145
+ line_end: s.lineEnd,
146
+ signature: s.signature,
147
+ exported: s.exported,
148
+ }));
149
+ this.db.upsertSymbols(relPath, symbolRecords);
150
+ symbolCount = symbolRecords.length;
151
+ const depRecords = extraction.dependencies.map((d) => ({
152
+ source_path: relPath,
153
+ target_spec: d.specifier,
154
+ target_resolved: null, // Could resolve in a second pass
155
+ }));
156
+ this.db.upsertDependencies(relPath, depRecords);
157
+ }
158
+ // Cache content (compressed in SQLite, raw in LRU)
159
+ try {
160
+ const compressed = deflateSync(Buffer.from(content, "utf-8"));
161
+ this.db.cacheContent(relPath, compressed);
162
+ }
163
+ catch {
164
+ // Compression failed, skip caching in DB
165
+ }
166
+ this.cache.set(relPath, {
167
+ content,
168
+ hash,
169
+ mtimeMs: stat.mtimeMs,
170
+ size: stat.size,
171
+ });
172
+ return { symbolCount };
173
+ }
174
+ /**
175
+ * Remove a file from the index (when it's deleted from disk).
176
+ */
177
+ removeFile(absPath) {
178
+ const relPath = normalizePath(relative(this.config.projectRoot, absPath));
179
+ this.db.deleteFile(relPath);
180
+ this.cache.delete(relPath);
181
+ }
182
+ /**
183
+ * Read a file from cache. Returns null on cache miss.
184
+ */
185
+ readCached(relPath) {
186
+ const normalized = normalizePath(relPath);
187
+ // Try in-memory LRU first
188
+ const cached = this.cache.get(normalized);
189
+ if (cached)
190
+ return cached.content;
191
+ // Try SQLite content cache
192
+ const dbContent = this.db.getCachedContent(normalized);
193
+ if (dbContent) {
194
+ try {
195
+ const content = inflateSync(dbContent).toString("utf-8");
196
+ // Promote to LRU
197
+ const fileRecord = this.db.getFile(normalized);
198
+ if (fileRecord) {
199
+ this.cache.set(normalized, {
200
+ content,
201
+ hash: fileRecord.hash,
202
+ mtimeMs: fileRecord.mtime_ms,
203
+ size: fileRecord.size,
204
+ });
205
+ }
206
+ return content;
207
+ }
208
+ catch {
209
+ return null;
210
+ }
211
+ }
212
+ return null;
213
+ }
214
+ /**
215
+ * Check if a file is in the cache and still valid.
216
+ */
217
+ isCacheValid(absPath) {
218
+ const relPath = normalizePath(relative(this.config.projectRoot, absPath));
219
+ const record = this.db.getFile(relPath);
220
+ if (!record)
221
+ return false;
222
+ try {
223
+ const stat = statSync(absPath);
224
+ return record.size === stat.size && record.mtime_ms === Math.floor(stat.mtimeMs);
225
+ }
226
+ catch {
227
+ return false;
228
+ }
229
+ }
230
+ /**
231
+ * Get project structure as a tree.
232
+ */
233
+ getProjectTree() {
234
+ const files = this.db.getAllFiles();
235
+ const tree = {};
236
+ for (const file of files) {
237
+ const symbols = this.db.getSymbolsForFile(file.path);
238
+ tree[file.path] = {
239
+ language: file.language,
240
+ size: file.size,
241
+ lineCount: file.line_count,
242
+ symbolCount: symbols.length,
243
+ };
244
+ }
245
+ return tree;
246
+ }
247
+ getStats() {
248
+ const cacheStats = this.cache.getStats();
249
+ return {
250
+ totalFiles: this.db.getFileCount(),
251
+ indexedFiles: this.db.getFileCount(),
252
+ symbolCount: 0, // Would need a separate query
253
+ indexTimeMs: 0,
254
+ cacheHitRate: cacheStats.hitRate,
255
+ };
256
+ }
257
+ // ─── Private ─────────────────────────────────────────────────
258
+ collectFiles(dir) {
259
+ const files = [];
260
+ this.walkDir(dir, files);
261
+ return files;
262
+ }
263
+ walkDir(dir, files) {
264
+ let entries;
265
+ try {
266
+ entries = readdirSync(dir, { withFileTypes: true });
267
+ }
268
+ catch {
269
+ return;
270
+ }
271
+ for (const entry of entries) {
272
+ const fullPath = join(dir, entry.name);
273
+ const relPath = normalizePath(relative(this.config.projectRoot, fullPath));
274
+ if (this.ignoreFilter.isIgnored(relPath))
275
+ continue;
276
+ if (entry.isDirectory()) {
277
+ this.walkDir(fullPath, files);
278
+ }
279
+ else if (entry.isFile()) {
280
+ files.push(fullPath);
281
+ }
282
+ }
283
+ }
284
+ pruneDeletedFiles(currentFiles) {
285
+ const currentSet = new Set(currentFiles.map((f) => normalizePath(relative(this.config.projectRoot, f))));
286
+ const indexedFiles = this.db.getAllFiles();
287
+ for (const file of indexedFiles) {
288
+ if (!currentSet.has(file.path)) {
289
+ this.db.deleteFile(file.path);
290
+ this.cache.delete(file.path);
291
+ }
292
+ }
293
+ }
294
+ }
295
+ //# sourceMappingURL=indexer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"indexer.js","sourceRoot":"","sources":["../../src/indexer/indexer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import { type CodeTreeConfig } from "../config.js";
2
+ import type { Indexer } from "./indexer.js";
3
+ export declare class FileWatcher {
4
+ private watcher;
5
+ private config;
6
+ private indexer;
7
+ private debounceTimers;
8
+ private running;
9
+ constructor(config: CodeTreeConfig, indexer: Indexer);
10
+ start(): void;
11
+ stop(): void;
12
+ isRunning(): boolean;
13
+ private handleChange;
14
+ private handleDelete;
15
+ }
16
+ //# sourceMappingURL=watcher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"watcher.d.ts","sourceRoot":"","sources":["../../src/indexer/watcher.ts"],"names":[],"mappings":"AAEA,OAAO,EAAiB,KAAK,cAAc,EAAE,MAAM,cAAc,CAAC;AAClE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAE5C,qBAAa,WAAW;IACtB,OAAO,CAAC,OAAO,CAA0B;IACzC,OAAO,CAAC,MAAM,CAAiB;IAC/B,OAAO,CAAC,OAAO,CAAU;IACzB,OAAO,CAAC,cAAc,CAAyD;IAC/E,OAAO,CAAC,OAAO,CAAS;gBAEZ,MAAM,EAAE,cAAc,EAAE,OAAO,EAAE,OAAO;IAKpD,KAAK,IAAI,IAAI;IA4Bb,IAAI,IAAI,IAAI;IAYZ,SAAS,IAAI,OAAO;IAIpB,OAAO,CAAC,YAAY;IAqBpB,OAAO,CAAC,YAAY;CAQrB"}
@@ -0,0 +1,79 @@
1
+ import chokidar from "chokidar";
2
+ import { resolve } from "node:path";
3
+ import { normalizePath } from "../config.js";
4
+ export class FileWatcher {
5
+ watcher = null;
6
+ config;
7
+ indexer;
8
+ debounceTimers = new Map();
9
+ running = false;
10
+ constructor(config, indexer) {
11
+ this.config = config;
12
+ this.indexer = indexer;
13
+ }
14
+ start() {
15
+ if (this.running)
16
+ return;
17
+ const ignored = [
18
+ ...this.config.ignore.map((p) => `**/${p}/**`),
19
+ "**/.codetree/**",
20
+ "**/node_modules/**",
21
+ "**/.git/**",
22
+ ];
23
+ this.watcher = chokidar.watch(this.config.projectRoot, {
24
+ ignored,
25
+ persistent: true,
26
+ ignoreInitial: true,
27
+ usePolling: this.config.watch.usePolling,
28
+ awaitWriteFinish: {
29
+ stabilityThreshold: 200,
30
+ pollInterval: 100,
31
+ },
32
+ });
33
+ this.watcher.on("change", (path) => this.handleChange(path));
34
+ this.watcher.on("add", (path) => this.handleChange(path));
35
+ this.watcher.on("unlink", (path) => this.handleDelete(path));
36
+ this.running = true;
37
+ }
38
+ stop() {
39
+ if (this.watcher) {
40
+ this.watcher.close();
41
+ this.watcher = null;
42
+ }
43
+ for (const timer of this.debounceTimers.values()) {
44
+ clearTimeout(timer);
45
+ }
46
+ this.debounceTimers.clear();
47
+ this.running = false;
48
+ }
49
+ isRunning() {
50
+ return this.running;
51
+ }
52
+ handleChange(path) {
53
+ const absPath = resolve(path);
54
+ const key = normalizePath(absPath);
55
+ // Debounce rapid changes to the same file
56
+ const existing = this.debounceTimers.get(key);
57
+ if (existing)
58
+ clearTimeout(existing);
59
+ this.debounceTimers.set(key, setTimeout(() => {
60
+ this.debounceTimers.delete(key);
61
+ try {
62
+ this.indexer.indexFile(absPath);
63
+ }
64
+ catch (err) {
65
+ console.error(`[codetree] Failed to reindex ${key}:`, err);
66
+ }
67
+ }, this.config.watch.debounceMs));
68
+ }
69
+ handleDelete(path) {
70
+ const absPath = resolve(path);
71
+ try {
72
+ this.indexer.removeFile(absPath);
73
+ }
74
+ catch (err) {
75
+ console.error(`[codetree] Failed to remove ${normalizePath(absPath)} from index:`, err);
76
+ }
77
+ }
78
+ }
79
+ //# sourceMappingURL=watcher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"watcher.js","sourceRoot":"","sources":["../../src/indexer/watcher.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ import type { Indexer } from "../indexer/indexer.js";
2
+ import type { Database } from "../storage/database.js";
3
+ import { type CodeTreeConfig } from "../config.js";
4
+ /**
5
+ * Lightweight HTTP server for hook->MCP server IPC.
6
+ * The PreToolUse hook queries this to check cache status before deciding to allow/deny.
7
+ */
8
+ export declare class IpcServer {
9
+ private server;
10
+ private port;
11
+ private config;
12
+ private indexer;
13
+ private db;
14
+ private stats;
15
+ constructor(config: CodeTreeConfig, indexer: Indexer, db: Database);
16
+ start(): Promise<number>;
17
+ getPort(): number;
18
+ stop(): void;
19
+ private writePortFile;
20
+ private handleRequest;
21
+ /**
22
+ * Check if a file Read can be served from cache.
23
+ * Returns { cached: true, tool: "codetree_read", path: "..." } or { cached: false }
24
+ */
25
+ private handleCheck;
26
+ /**
27
+ * Check if a Grep search can be answered from the index.
28
+ */
29
+ private handleCheckSearch;
30
+ /**
31
+ * Check if a Glob can be answered from the file tree.
32
+ */
33
+ private handleCheckGlob;
34
+ private handleStatus;
35
+ private handleStats;
36
+ private persistStats;
37
+ }
38
+ //# sourceMappingURL=ipc.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ipc.d.ts","sourceRoot":"","sources":["../../src/server/ipc.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AACrD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,EAAiB,KAAK,cAAc,EAAE,MAAM,cAAc,CAAC;AAGlE;;;GAGG;AACH,qBAAa,SAAS;IACpB,OAAO,CAAC,MAAM,CAAuB;IACrC,OAAO,CAAC,IAAI,CAAK;IACjB,OAAO,CAAC,MAAM,CAAiB;IAC/B,OAAO,CAAC,OAAO,CAAU;IACzB,OAAO,CAAC,EAAE,CAAW;IAGrB,OAAO,CAAC,KAAK,CAKX;gBAEU,MAAM,EAAE,cAAc,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,QAAQ;IAM5D,KAAK,IAAI,OAAO,CAAC,MAAM,CAAC;IAkB9B,OAAO,IAAI,MAAM;IAIjB,IAAI,IAAI,IAAI;IAQZ,OAAO,CAAC,aAAa;IAOrB,OAAO,CAAC,aAAa;IA2BrB;;;OAGG;IACH,OAAO,CAAC,WAAW;IAgCnB;;OAEG;IACH,OAAO,CAAC,iBAAiB;IA6BzB;;OAEG;IACH,OAAO,CAAC,eAAe;IA0BvB,OAAO,CAAC,YAAY;IAUpB,OAAO,CAAC,WAAW;IAWnB,OAAO,CAAC,YAAY;CAWrB"}