clast-ai 0.1.2 → 0.2.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 (290) hide show
  1. package/.claude-plugin/marketplace.json +14 -0
  2. package/.claude-plugin/plugin.json +11 -9
  3. package/README.md +447 -401
  4. package/bench/ab/onair-concept.json +22 -0
  5. package/bench/ab/onair-deadcode.json +7 -0
  6. package/bench/ab/onair-hard.json +32 -0
  7. package/bench/ab/onair-impact.json +17 -0
  8. package/bench/ab/onair-refactors.json +18 -0
  9. package/bench/ab/onair-survey.json +17 -0
  10. package/bench/ab/onair-tasks.json +20 -0
  11. package/bench/ab/onair.json +52 -0
  12. package/bench/ab/vscode-concept.json +22 -0
  13. package/bench/ab/vscode-hard.json +32 -0
  14. package/bench/ab/vscode-impact.json +17 -0
  15. package/bench/ab/vscode-refactors.json +18 -0
  16. package/bench/ab/vscode-tasks.json +20 -0
  17. package/bench/ab/vscode.json +52 -0
  18. package/bench/ab.mjs +213 -0
  19. package/bench/bench.mjs +98 -0
  20. package/bench/resolution.mjs +75 -0
  21. package/dist/cli.d.ts +2 -0
  22. package/dist/cli.js +257 -0
  23. package/dist/cli.js.map +1 -0
  24. package/dist/config/defaults.d.ts +12 -2
  25. package/dist/config/defaults.js +38 -31
  26. package/dist/config/defaults.js.map +1 -1
  27. package/dist/config/index.d.ts +1 -1
  28. package/dist/config/index.js +26 -14
  29. package/dist/config/index.js.map +1 -1
  30. package/dist/db/index.d.ts +73 -13
  31. package/dist/db/index.js +481 -39
  32. package/dist/db/index.js.map +1 -1
  33. package/dist/engine.d.ts +15 -0
  34. package/dist/engine.js +28 -0
  35. package/dist/engine.js.map +1 -0
  36. package/dist/indexer/imports.d.ts +6 -0
  37. package/dist/indexer/imports.js +254 -0
  38. package/dist/indexer/imports.js.map +1 -0
  39. package/dist/indexer/index.d.ts +63 -0
  40. package/dist/indexer/index.js +360 -0
  41. package/dist/indexer/index.js.map +1 -0
  42. package/dist/indexer/process.d.ts +22 -0
  43. package/dist/indexer/process.js +42 -0
  44. package/dist/indexer/process.js.map +1 -0
  45. package/dist/indexer/scan.d.ts +43 -0
  46. package/dist/indexer/scan.js +223 -0
  47. package/dist/indexer/scan.js.map +1 -0
  48. package/dist/indexer/worker.d.ts +1 -0
  49. package/dist/indexer/worker.js +23 -0
  50. package/dist/indexer/worker.js.map +1 -0
  51. package/dist/llm/comment-generator.d.ts +17 -19
  52. package/dist/llm/comment-generator.js +46 -80
  53. package/dist/llm/comment-generator.js.map +1 -1
  54. package/dist/llm/index.d.ts +0 -1
  55. package/dist/llm/index.js.map +1 -1
  56. package/dist/llm/prompts.d.ts +0 -1
  57. package/dist/llm/prompts.js +16 -16
  58. package/dist/parser/extractor.d.ts +21 -16
  59. package/dist/parser/extractor.js +700 -228
  60. package/dist/parser/extractor.js.map +1 -1
  61. package/dist/parser/index.d.ts +17 -21
  62. package/dist/parser/index.js +115 -171
  63. package/dist/parser/index.js.map +1 -1
  64. package/dist/parser/langs/c.d.ts +3 -0
  65. package/dist/parser/langs/c.js +879 -0
  66. package/dist/parser/langs/c.js.map +1 -0
  67. package/dist/parser/langs/csharp.d.ts +2 -0
  68. package/dist/parser/langs/csharp.js +548 -0
  69. package/dist/parser/langs/csharp.js.map +1 -0
  70. package/dist/parser/langs/dart.d.ts +2 -0
  71. package/dist/parser/langs/dart.js +893 -0
  72. package/dist/parser/langs/dart.js.map +1 -0
  73. package/dist/parser/langs/go.d.ts +2 -0
  74. package/dist/parser/langs/go.js +455 -0
  75. package/dist/parser/langs/go.js.map +1 -0
  76. package/dist/parser/langs/java.d.ts +2 -0
  77. package/dist/parser/langs/java.js +390 -0
  78. package/dist/parser/langs/java.js.map +1 -0
  79. package/dist/parser/langs/php.d.ts +2 -0
  80. package/dist/parser/langs/php.js +486 -0
  81. package/dist/parser/langs/php.js.map +1 -0
  82. package/dist/parser/langs/python.d.ts +2 -0
  83. package/dist/parser/langs/python.js +216 -0
  84. package/dist/parser/langs/python.js.map +1 -0
  85. package/dist/parser/langs/ruby.d.ts +2 -0
  86. package/dist/parser/langs/ruby.js +602 -0
  87. package/dist/parser/langs/ruby.js.map +1 -0
  88. package/dist/parser/langs/rust.d.ts +2 -0
  89. package/dist/parser/langs/rust.js +931 -0
  90. package/dist/parser/langs/rust.js.map +1 -0
  91. package/dist/parser/langs/swift.d.ts +2 -0
  92. package/dist/parser/langs/swift.js +616 -0
  93. package/dist/parser/langs/swift.js.map +1 -0
  94. package/dist/parser/langs/typescript.d.ts +4 -0
  95. package/dist/parser/langs/typescript.js +535 -0
  96. package/dist/parser/langs/typescript.js.map +1 -0
  97. package/dist/parser/registry.d.ts +16 -0
  98. package/dist/parser/registry.js +87 -0
  99. package/dist/parser/registry.js.map +1 -0
  100. package/dist/parser/returns.d.ts +9 -0
  101. package/dist/parser/returns.js +152 -0
  102. package/dist/parser/returns.js.map +1 -0
  103. package/dist/parser/spec.d.ts +165 -0
  104. package/dist/parser/spec.js +188 -0
  105. package/dist/parser/spec.js.map +1 -0
  106. package/dist/query/arity.d.ts +27 -0
  107. package/dist/query/arity.js +187 -0
  108. package/dist/query/arity.js.map +1 -0
  109. package/dist/query/callgraph.d.ts +113 -0
  110. package/dist/query/callgraph.js +332 -0
  111. package/dist/query/callgraph.js.map +1 -0
  112. package/dist/query/format.d.ts +36 -0
  113. package/dist/query/format.js +136 -0
  114. package/dist/query/format.js.map +1 -0
  115. package/dist/query/hierarchy.d.ts +44 -0
  116. package/dist/query/hierarchy.js +441 -0
  117. package/dist/query/hierarchy.js.map +1 -0
  118. package/dist/query/resolve.d.ts +265 -0
  119. package/dist/query/resolve.js +1957 -0
  120. package/dist/query/resolve.js.map +1 -0
  121. package/dist/query/search.d.ts +35 -0
  122. package/dist/query/search.js +379 -0
  123. package/dist/query/search.js.map +1 -0
  124. package/dist/query/words.d.ts +30 -0
  125. package/dist/query/words.js +201 -0
  126. package/dist/query/words.js.map +1 -0
  127. package/dist/server/index.d.ts +1 -3
  128. package/dist/server/index.js +313 -73
  129. package/dist/server/index.js.map +1 -1
  130. package/dist/tools/context.d.ts +35 -0
  131. package/dist/tools/context.js +79 -0
  132. package/dist/tools/context.js.map +1 -0
  133. package/dist/tools/explore.d.ts +51 -0
  134. package/dist/tools/explore.js +779 -0
  135. package/dist/tools/explore.js.map +1 -0
  136. package/dist/tools/impact.d.ts +21 -0
  137. package/dist/tools/impact.js +743 -0
  138. package/dist/tools/impact.js.map +1 -0
  139. package/dist/tools/search.d.ts +59 -0
  140. package/dist/tools/search.js +843 -0
  141. package/dist/tools/search.js.map +1 -0
  142. package/dist/tools/stats.d.ts +26 -0
  143. package/dist/tools/stats.js +604 -0
  144. package/dist/tools/stats.js.map +1 -0
  145. package/dist/types.d.ts +95 -40
  146. package/dist/types.js +9 -1
  147. package/dist/types.js.map +1 -1
  148. package/dist/version.d.ts +2 -0
  149. package/dist/version.js +3 -0
  150. package/dist/version.js.map +1 -0
  151. package/dist/watcher/index.d.ts +18 -16
  152. package/dist/watcher/index.js +94 -77
  153. package/dist/watcher/index.js.map +1 -1
  154. package/package.json +21 -24
  155. package/plugin/server.mjs +50 -0
  156. package/skills/audit/SKILL.md +37 -0
  157. package/skills/deadcode/SKILL.md +33 -0
  158. package/skills/explore/SKILL.md +54 -0
  159. package/skills/impact/SKILL.md +24 -0
  160. package/skills/status/SKILL.md +11 -0
  161. package/src/cli.ts +256 -0
  162. package/src/config/defaults.ts +50 -32
  163. package/src/config/index.ts +23 -14
  164. package/src/db/index.ts +540 -43
  165. package/src/engine.ts +30 -0
  166. package/src/indexer/imports.ts +241 -0
  167. package/src/indexer/index.ts +369 -0
  168. package/src/indexer/process.ts +63 -0
  169. package/src/indexer/scan.ts +226 -0
  170. package/src/indexer/worker.ts +24 -0
  171. package/src/llm/comment-generator.ts +52 -103
  172. package/src/llm/index.ts +80 -80
  173. package/src/llm/prompts.ts +95 -95
  174. package/src/parser/extractor.ts +643 -256
  175. package/src/parser/index.ts +105 -205
  176. package/src/parser/langs/c.ts +860 -0
  177. package/src/parser/langs/csharp.ts +519 -0
  178. package/src/parser/langs/dart.ts +820 -0
  179. package/src/parser/langs/go.ts +437 -0
  180. package/src/parser/langs/java.ts +361 -0
  181. package/src/parser/langs/php.ts +450 -0
  182. package/src/parser/langs/python.ts +206 -0
  183. package/src/parser/langs/ruby.ts +554 -0
  184. package/src/parser/langs/rust.ts +904 -0
  185. package/src/parser/langs/swift.ts +590 -0
  186. package/src/parser/langs/typescript.ts +499 -0
  187. package/src/parser/registry.ts +88 -0
  188. package/src/parser/returns.ts +137 -0
  189. package/src/parser/spec.ts +309 -0
  190. package/src/query/arity.ts +173 -0
  191. package/src/query/callgraph.ts +473 -0
  192. package/src/query/format.ts +136 -0
  193. package/src/query/hierarchy.ts +447 -0
  194. package/src/query/resolve.ts +1972 -0
  195. package/src/query/search.ts +430 -0
  196. package/src/query/words.ts +183 -0
  197. package/src/server/index.ts +390 -79
  198. package/src/tools/context.ts +82 -0
  199. package/src/tools/explore.ts +860 -0
  200. package/src/tools/impact.ts +748 -0
  201. package/src/tools/search.ts +886 -0
  202. package/src/tools/stats.ts +633 -0
  203. package/src/types.ts +113 -45
  204. package/src/version.ts +2 -0
  205. package/src/watcher/index.ts +82 -88
  206. package/tsconfig.json +7 -4
  207. package/.mcp.json +0 -8
  208. package/commands/clast-status.md +0 -9
  209. package/dist/config/defaults.d.ts.map +0 -1
  210. package/dist/config/index.d.ts.map +0 -1
  211. package/dist/db/index.d.ts.map +0 -1
  212. package/dist/db/queries.d.ts +0 -44
  213. package/dist/db/queries.d.ts.map +0 -1
  214. package/dist/db/queries.js +0 -251
  215. package/dist/db/queries.js.map +0 -1
  216. package/dist/db/schema.d.ts +0 -3
  217. package/dist/db/schema.d.ts.map +0 -1
  218. package/dist/db/schema.js +0 -94
  219. package/dist/db/schema.js.map +0 -1
  220. package/dist/db/types.d.ts +0 -44
  221. package/dist/db/types.d.ts.map +0 -1
  222. package/dist/db/types.js +0 -2
  223. package/dist/db/types.js.map +0 -1
  224. package/dist/llm/comment-generator.d.ts.map +0 -1
  225. package/dist/llm/index.d.ts.map +0 -1
  226. package/dist/llm/prompts.d.ts.map +0 -1
  227. package/dist/parser/call-resolver.d.ts +0 -15
  228. package/dist/parser/call-resolver.d.ts.map +0 -1
  229. package/dist/parser/call-resolver.js +0 -16
  230. package/dist/parser/call-resolver.js.map +0 -1
  231. package/dist/parser/extractor.d.ts.map +0 -1
  232. package/dist/parser/index.d.ts.map +0 -1
  233. package/dist/parser/languages.d.ts +0 -11
  234. package/dist/parser/languages.d.ts.map +0 -1
  235. package/dist/parser/languages.js +0 -74
  236. package/dist/parser/languages.js.map +0 -1
  237. package/dist/server/index.d.ts.map +0 -1
  238. package/dist/server/register-tools.d.ts +0 -7
  239. package/dist/server/register-tools.d.ts.map +0 -1
  240. package/dist/server/register-tools.js +0 -17
  241. package/dist/server/register-tools.js.map +0 -1
  242. package/dist/server/tools/clast-call-graph.d.ts +0 -4
  243. package/dist/server/tools/clast-call-graph.d.ts.map +0 -1
  244. package/dist/server/tools/clast-call-graph.js +0 -70
  245. package/dist/server/tools/clast-call-graph.js.map +0 -1
  246. package/dist/server/tools/clast-comment.d.ts +0 -5
  247. package/dist/server/tools/clast-comment.d.ts.map +0 -1
  248. package/dist/server/tools/clast-comment.js +0 -64
  249. package/dist/server/tools/clast-comment.js.map +0 -1
  250. package/dist/server/tools/clast-file-summary.d.ts +0 -4
  251. package/dist/server/tools/clast-file-summary.d.ts.map +0 -1
  252. package/dist/server/tools/clast-file-summary.js +0 -42
  253. package/dist/server/tools/clast-file-summary.js.map +0 -1
  254. package/dist/server/tools/clast-get-context.d.ts +0 -4
  255. package/dist/server/tools/clast-get-context.d.ts.map +0 -1
  256. package/dist/server/tools/clast-get-context.js +0 -80
  257. package/dist/server/tools/clast-get-context.js.map +0 -1
  258. package/dist/server/tools/clast-reindex.d.ts +0 -5
  259. package/dist/server/tools/clast-reindex.d.ts.map +0 -1
  260. package/dist/server/tools/clast-reindex.js +0 -36
  261. package/dist/server/tools/clast-reindex.js.map +0 -1
  262. package/dist/server/tools/clast-search.d.ts +0 -4
  263. package/dist/server/tools/clast-search.d.ts.map +0 -1
  264. package/dist/server/tools/clast-search.js +0 -29
  265. package/dist/server/tools/clast-search.js.map +0 -1
  266. package/dist/server/tools/clast-status.d.ts +0 -5
  267. package/dist/server/tools/clast-status.d.ts.map +0 -1
  268. package/dist/server/tools/clast-status.js +0 -23
  269. package/dist/server/tools/clast-status.js.map +0 -1
  270. package/dist/types.d.ts.map +0 -1
  271. package/dist/watcher/gitignore.d.ts +0 -9
  272. package/dist/watcher/gitignore.d.ts.map +0 -1
  273. package/dist/watcher/gitignore.js +0 -38
  274. package/dist/watcher/gitignore.js.map +0 -1
  275. package/dist/watcher/index.d.ts.map +0 -1
  276. package/skills/clast-explore/SKILL.md +0 -41
  277. package/src/db/queries.ts +0 -332
  278. package/src/db/schema.ts +0 -106
  279. package/src/db/types.ts +0 -47
  280. package/src/parser/call-resolver.ts +0 -17
  281. package/src/parser/languages.ts +0 -86
  282. package/src/server/register-tools.ts +0 -30
  283. package/src/server/tools/clast-call-graph.ts +0 -82
  284. package/src/server/tools/clast-comment.ts +0 -76
  285. package/src/server/tools/clast-file-summary.ts +0 -59
  286. package/src/server/tools/clast-get-context.ts +0 -97
  287. package/src/server/tools/clast-reindex.ts +0 -52
  288. package/src/server/tools/clast-search.ts +0 -38
  289. package/src/server/tools/clast-status.ts +0 -37
  290. package/src/watcher/gitignore.ts +0 -42
@@ -0,0 +1,360 @@
1
+ import { Worker } from 'node:worker_threads';
2
+ import { availableParallelism } from 'node:os';
3
+ import { existsSync, statSync } from 'node:fs';
4
+ import { fileURLToPath } from 'node:url';
5
+ import { isAbsolute, join, relative } from 'node:path';
6
+ import { SourceParser } from '../parser/index.js';
7
+ import { IgnoreRules } from './scan.js';
8
+ import { processFile } from './process.js';
9
+ import { resolveImports } from './imports.js';
10
+ const WORKER_THRESHOLD = 48;
11
+ const TASK_BATCH = 12;
12
+ const WRITE_BATCH = 150;
13
+ const BULK_THRESHOLD = 400;
14
+ const BULK_WRITE_BATCH = 800;
15
+ /**
16
+ * Keeps the database in sync with the working tree: bulk (re)indexing with a
17
+ * worker pool, single-file updates, and on-demand freshness checks.
18
+ */
19
+ export class Indexer {
20
+ config;
21
+ db;
22
+ root;
23
+ rules;
24
+ parser = new SourceParser();
25
+ progress = { phase: 'idle', done: 0, total: 0 };
26
+ lastResult = null;
27
+ /** True while a first-time index is being loaded (secondary indexes are not built yet). */
28
+ coldBuild = false;
29
+ running = null;
30
+ structureChanged = false;
31
+ constructor(root, config, db) {
32
+ this.config = config;
33
+ this.db = db;
34
+ this.root = root;
35
+ this.rules = new IgnoreRules(root, config);
36
+ }
37
+ get isIndexing() {
38
+ return this.running !== null;
39
+ }
40
+ /** Resolves when the in-flight bulk index (if any) is finished. */
41
+ async whenIdle(timeoutMs) {
42
+ if (!this.running)
43
+ return true;
44
+ if (timeoutMs === undefined) {
45
+ await this.running.catch(() => undefined);
46
+ return true;
47
+ }
48
+ let timer;
49
+ const timedOut = new Promise(res => { timer = setTimeout(() => res(false), timeoutMs); });
50
+ const done = this.running.then(() => true, () => true);
51
+ const result = await Promise.race([done, timedOut]);
52
+ clearTimeout(timer);
53
+ return result;
54
+ }
55
+ toRel(path) {
56
+ const rel = isAbsolute(path) ? relative(this.root, path) : path;
57
+ return rel.replace(/\\/g, '/').replace(/^\.\//, '');
58
+ }
59
+ /** Bring the whole index up to date. Concurrent calls share one run. */
60
+ indexAll(opts = {}) {
61
+ if (this.running)
62
+ return this.running;
63
+ this.running = this.runIndexAll(opts).finally(() => {
64
+ this.running = null;
65
+ this.progress = { phase: 'idle', done: 0, total: 0 };
66
+ });
67
+ return this.running;
68
+ }
69
+ async runIndexAll(opts) {
70
+ const start = performance.now();
71
+ this.progress = { phase: 'scanning', done: 0, total: 0 };
72
+ this.rules.invalidate();
73
+ const scanned = await this.rules.scan();
74
+ // A forced rebuild starts from an empty index so it can use the cold bulk path.
75
+ if (opts.force)
76
+ this.db.clearIndex();
77
+ const known = new Map();
78
+ for (const row of this.db.allFiles())
79
+ known.set(row.path, row);
80
+ const tasks = [];
81
+ const seen = new Set();
82
+ for (const f of scanned) {
83
+ seen.add(f.rel);
84
+ const row = known.get(f.rel);
85
+ if (!opts.force && row && row.mtime === f.mtime && row.size === f.size)
86
+ continue;
87
+ tasks.push({ abs: f.abs, rel: f.rel, knownHash: opts.force ? undefined : row?.hash });
88
+ }
89
+ let removed = 0;
90
+ const gone = [...known.keys()].filter(p => !seen.has(p));
91
+ if (gone.length) {
92
+ this.db.transaction(() => {
93
+ for (const p of gone)
94
+ if (this.db.deleteFile(p))
95
+ removed++;
96
+ });
97
+ this.structureChanged = true;
98
+ }
99
+ const bulk = tasks.length >= BULK_THRESHOLD;
100
+ const cold = known.size === 0;
101
+ const writeBatch = bulk ? BULK_WRITE_BATCH : WRITE_BATCH;
102
+ if (bulk)
103
+ this.db.beginBulk(cold);
104
+ this.coldBuild = bulk && cold;
105
+ this.progress = { phase: 'parsing', done: 0, total: tasks.length };
106
+ let parsed = 0;
107
+ let unchanged = 0;
108
+ const touchedIds = [];
109
+ let pending = [];
110
+ let writeMs = 0;
111
+ const flush = () => {
112
+ if (pending.length === 0)
113
+ return;
114
+ const batch = pending;
115
+ pending = [];
116
+ const t0 = performance.now();
117
+ this.db.transaction(() => {
118
+ for (const r of batch) {
119
+ const outcome = this.apply(r);
120
+ if (outcome.parsed) {
121
+ parsed++;
122
+ touchedIds.push(outcome.fileId);
123
+ }
124
+ else if (r.status === 'unchanged')
125
+ unchanged++;
126
+ }
127
+ });
128
+ writeMs += performance.now() - t0;
129
+ };
130
+ const completed = new Set();
131
+ const onResult = (r) => {
132
+ pending.push(r);
133
+ completed.add(r.rel);
134
+ this.progress.done++;
135
+ if (pending.length >= writeBatch)
136
+ flush();
137
+ };
138
+ const inline = async (list) => {
139
+ for (const task of list) {
140
+ onResult(await processFile(this.parser, task, this.config.maxFileSize));
141
+ // Yield so the MCP transport stays responsive during a cold index.
142
+ if (this.progress.done % 25 === 0)
143
+ await new Promise(res => setImmediate(res));
144
+ }
145
+ };
146
+ let workerCount = this.workerCount(tasks.length);
147
+ let endBulkMs = 0;
148
+ try {
149
+ if (workerCount > 1) {
150
+ try {
151
+ await this.runPool(tasks, workerCount, onResult);
152
+ }
153
+ catch (err) {
154
+ // A worker died (out of memory, a crashing grammar): finish the rest on this thread.
155
+ console.error(`[clast] parser worker failed (${err instanceof Error ? err.message : err}); continuing without workers`);
156
+ workerCount = 1;
157
+ await inline(tasks.filter(t => !completed.has(t.rel)));
158
+ }
159
+ }
160
+ else {
161
+ await inline(tasks);
162
+ }
163
+ flush();
164
+ }
165
+ finally {
166
+ // Always leave bulk mode: it restores the journal and rebuilds the secondary indexes,
167
+ // without which every query would scan whole tables.
168
+ const tBulk = performance.now();
169
+ if (bulk)
170
+ this.db.endBulk();
171
+ endBulkMs = performance.now() - tBulk;
172
+ this.coldBuild = false;
173
+ }
174
+ const parseDoneMs = performance.now() - start;
175
+ this.progress.phase = 'finalizing';
176
+ if (parsed > 0 || removed > 0 || this.structureChanged) {
177
+ // New or removed files can change how *other* files' imports resolve.
178
+ const full = removed > 0 || this.structureChanged || parsed > 200;
179
+ resolveImports(this.db, full ? undefined : touchedIds);
180
+ this.structureChanged = false;
181
+ try {
182
+ this.db.db.exec('PRAGMA optimize');
183
+ }
184
+ catch { /* ignore */ }
185
+ }
186
+ const result = {
187
+ scanned: scanned.length,
188
+ parsed,
189
+ unchanged,
190
+ removed,
191
+ durationMs: Math.round(performance.now() - start),
192
+ workers: workerCount,
193
+ };
194
+ if (process.env.CLAST_DEBUG) {
195
+ console.error(`[clast] timing: total ${result.durationMs}ms, parse+write phase ${Math.round(parseDoneMs)}ms, db writes ${Math.round(writeMs)}ms, index build ${Math.round(endBulkMs)}ms`);
196
+ }
197
+ this.lastResult = result;
198
+ this.db.setMeta('last_full_index', String(Date.now()));
199
+ return result;
200
+ }
201
+ /** Write one processing result. Must run inside a transaction. */
202
+ apply(r) {
203
+ if (r.status === 'ok' && r.extraction) {
204
+ const isNew = !this.db.fileByPath(r.rel);
205
+ const fileId = this.db.writeFile({ path: r.rel, hash: r.hash, mtime: r.mtime, size: r.size }, r.extraction);
206
+ if (isNew)
207
+ this.structureChanged = true;
208
+ return { parsed: true, fileId };
209
+ }
210
+ if (r.status === 'unchanged') {
211
+ const row = this.db.fileByPath(r.rel);
212
+ if (row)
213
+ this.db.touchFile(row.id, r.mtime, r.size);
214
+ return { parsed: false };
215
+ }
216
+ // skip / missing: make sure nothing stale remains.
217
+ if (this.db.deleteFile(r.rel))
218
+ this.structureChanged = true;
219
+ return { parsed: false };
220
+ }
221
+ workerCount(taskCount) {
222
+ if (taskCount < WORKER_THRESHOLD)
223
+ return 1;
224
+ if (!existsSync(workerPath()))
225
+ return 1;
226
+ const configured = this.config.workers;
227
+ if (configured === 1)
228
+ return 1;
229
+ const auto = Math.max(1, Math.min(12, availableParallelism() - 1));
230
+ const n = configured > 0 ? configured : auto;
231
+ return Math.max(1, Math.min(n, Math.ceil(taskCount / TASK_BATCH)));
232
+ }
233
+ runPool(tasks, count, onResult) {
234
+ return new Promise((resolveAll, rejectAll) => {
235
+ let next = 0;
236
+ let active = 0;
237
+ let failed = false;
238
+ const workers = [];
239
+ const finish = (err) => {
240
+ if (failed)
241
+ return;
242
+ if (err) {
243
+ failed = true;
244
+ for (const w of workers)
245
+ void w.terminate();
246
+ rejectAll(err);
247
+ return;
248
+ }
249
+ if (active === 0 && next >= tasks.length) {
250
+ for (const w of workers)
251
+ w.postMessage(null);
252
+ resolveAll();
253
+ }
254
+ };
255
+ const dispatch = (w) => {
256
+ if (next >= tasks.length)
257
+ return finish();
258
+ const batch = tasks.slice(next, next + TASK_BATCH);
259
+ next += batch.length;
260
+ active++;
261
+ w.postMessage(batch);
262
+ };
263
+ for (let i = 0; i < count; i++) {
264
+ const w = new Worker(workerPath(), { workerData: { maxFileSize: this.config.maxFileSize } });
265
+ workers.push(w);
266
+ w.on('message', (results) => {
267
+ active--;
268
+ try {
269
+ for (const r of results)
270
+ onResult(r);
271
+ }
272
+ catch (err) {
273
+ return finish(err);
274
+ }
275
+ dispatch(w);
276
+ });
277
+ w.on('error', err => finish(err));
278
+ // Two batches in flight per worker so it never idles while the main
279
+ // thread is busy writing a transaction.
280
+ dispatch(w);
281
+ dispatch(w);
282
+ }
283
+ });
284
+ }
285
+ /**
286
+ * Re-index a single file inline. Returns true if the index changed.
287
+ * Accepts absolute or project-relative paths.
288
+ */
289
+ async indexFile(path, opts = {}) {
290
+ const rel = this.toRel(path);
291
+ if (rel.startsWith('..'))
292
+ return false;
293
+ const abs = join(this.root, rel);
294
+ if (!this.rules.isSupported(rel) || this.rules.isIgnored(rel)) {
295
+ return this.removeFile(rel);
296
+ }
297
+ const row = this.db.fileByPath(rel);
298
+ const result = await processFile(this.parser, { abs, rel, knownHash: opts.force ? undefined : row?.hash }, this.config.maxFileSize);
299
+ let changed = false;
300
+ let fileId;
301
+ this.db.transaction(() => {
302
+ const outcome = this.apply(result);
303
+ changed = outcome.parsed || (result.status !== 'unchanged' && !!row);
304
+ fileId = outcome.fileId;
305
+ });
306
+ if (fileId !== undefined) {
307
+ // A new file can also satisfy other files' previously unresolved imports;
308
+ // only those that mention its name are retried (not the whole project).
309
+ resolveImports(this.db, [fileId], this.structureChanged ? [rel] : undefined);
310
+ this.structureChanged = false;
311
+ }
312
+ return changed;
313
+ }
314
+ removeFile(path) {
315
+ const rel = this.toRel(path);
316
+ let removed = false;
317
+ this.db.transaction(() => {
318
+ removed = this.db.deleteFile(rel);
319
+ });
320
+ return removed;
321
+ }
322
+ /**
323
+ * Make sure the given indexed files reflect what is on disk right now
324
+ * (cheap stat check, inline re-parse when stale). Query paths call this
325
+ * before returning line numbers or source text.
326
+ */
327
+ async ensureFresh(paths) {
328
+ let updated = 0;
329
+ const seen = new Set();
330
+ for (const rel of paths) {
331
+ if (seen.has(rel))
332
+ continue;
333
+ seen.add(rel);
334
+ const row = this.db.fileByPath(rel);
335
+ if (!row)
336
+ continue;
337
+ let st;
338
+ try {
339
+ st = statSync(join(this.root, rel));
340
+ }
341
+ catch {
342
+ if (this.removeFile(rel))
343
+ updated++;
344
+ continue;
345
+ }
346
+ if (st.mtimeMs === row.mtime && st.size === row.size)
347
+ continue;
348
+ if (await this.indexFile(rel))
349
+ updated++;
350
+ }
351
+ return updated;
352
+ }
353
+ scan() {
354
+ return this.rules.scan();
355
+ }
356
+ }
357
+ function workerPath() {
358
+ return fileURLToPath(new URL('./worker.js', import.meta.url));
359
+ }
360
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/indexer/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ import type { Extraction } from '../types.js';
2
+ import type { SourceParser } from '../parser/index.js';
3
+ export interface FileTask {
4
+ abs: string;
5
+ rel: string;
6
+ /** Hash currently stored in the index, if any. */
7
+ knownHash?: string;
8
+ }
9
+ export interface FileResult {
10
+ rel: string;
11
+ /**
12
+ * ok: parsed, `extraction` is set. unchanged: content hash matches the index.
13
+ * skip: not indexable (binary, too large, unsupported). missing: file is gone.
14
+ */
15
+ status: 'ok' | 'unchanged' | 'skip' | 'missing';
16
+ hash: string;
17
+ mtime: number;
18
+ size: number;
19
+ extraction?: Extraction;
20
+ }
21
+ /** Read, hash and (if changed) parse one file. Never throws. */
22
+ export declare function processFile(parser: SourceParser, task: FileTask, maxFileSize: number): Promise<FileResult>;
@@ -0,0 +1,42 @@
1
+ import { createHash } from 'node:crypto';
2
+ import { readFileSync, statSync } from 'node:fs';
3
+ /** Read, hash and (if changed) parse one file. Never throws. */
4
+ export async function processFile(parser, task, maxFileSize) {
5
+ const base = { rel: task.rel, hash: '', mtime: 0, size: 0 };
6
+ let buf;
7
+ try {
8
+ const st = statSync(task.abs);
9
+ base.mtime = st.mtimeMs;
10
+ base.size = st.size;
11
+ if (!st.isFile())
12
+ return { ...base, status: 'missing' };
13
+ if (st.size > maxFileSize)
14
+ return { ...base, status: 'skip' };
15
+ buf = readFileSync(task.abs);
16
+ }
17
+ catch {
18
+ return { ...base, status: 'missing' };
19
+ }
20
+ // Binary sniff: NUL byte in the first block.
21
+ const head = buf.subarray(0, 4096);
22
+ if (head.includes(0))
23
+ return { ...base, status: 'skip' };
24
+ base.hash = createHash('sha1').update(buf).digest('hex');
25
+ if (task.knownHash && task.knownHash === base.hash)
26
+ return { ...base, status: 'unchanged' };
27
+ let source = buf.toString('utf-8');
28
+ if (source.charCodeAt(0) === 0xfeff)
29
+ source = source.slice(1);
30
+ try {
31
+ const extraction = await parser.extract(task.rel, source);
32
+ if (!extraction)
33
+ return { ...base, status: 'skip' };
34
+ return { ...base, status: 'ok', extraction };
35
+ }
36
+ catch (err) {
37
+ if (process.env.CLAST_DEBUG)
38
+ console.error(`[clast] parse failed for ${task.rel}:`, err);
39
+ return { ...base, status: 'skip' };
40
+ }
41
+ }
42
+ //# sourceMappingURL=process.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"process.js","sourceRoot":"","sources":["../../src/indexer/process.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAwBjD,gEAAgE;AAChE,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,MAAoB,EACpB,IAAc,EACd,WAAmB;IAEnB,MAAM,IAAI,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;IAC5D,IAAI,GAAW,CAAC;IAChB,IAAI,CAAC;QACH,MAAM,EAAE,GAAG,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC9B,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC,OAAO,CAAC;QACxB,IAAI,CAAC,IAAI,GAAG,EAAE,CAAC,IAAI,CAAC;QACpB,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE;YAAE,OAAO,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC;QACxD,IAAI,EAAE,CAAC,IAAI,GAAG,WAAW;YAAE,OAAO,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;QAC9D,GAAG,GAAG,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC/B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC;IACxC,CAAC;IAED,6CAA6C;IAC7C,MAAM,IAAI,GAAG,GAAG,CAAC,QAAQ,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;IACnC,IAAI,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;QAAE,OAAO,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;IAEzD,IAAI,CAAC,IAAI,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACzD,IAAI,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,SAAS,KAAK,IAAI,CAAC,IAAI;QAAE,OAAO,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC;IAE5F,IAAI,MAAM,GAAG,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;IACnC,IAAI,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,KAAK,MAAM;QAAE,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAE9D,IAAI,CAAC;QACH,MAAM,UAAU,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;QAC1D,IAAI,CAAC,UAAU;YAAE,OAAO,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;QACpD,OAAO,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC;IAC/C,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,OAAO,CAAC,GAAG,CAAC,WAAW;YAAE,OAAO,CAAC,KAAK,CAAC,4BAA4B,IAAI,CAAC,GAAG,GAAG,EAAE,GAAG,CAAC,CAAC;QACzF,OAAO,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;IACrC,CAAC;AACH,CAAC"}
@@ -0,0 +1,43 @@
1
+ import type { ClastConfig } from '../config/index.js';
2
+ export interface ScannedFile {
3
+ abs: string;
4
+ /** Project-relative path with forward slashes. */
5
+ rel: string;
6
+ mtime: number;
7
+ size: number;
8
+ }
9
+ /**
10
+ * Ignore decisions shared by the scanner and the watcher: config patterns plus
11
+ * (optionally) every .gitignore from the project root down to the file.
12
+ */
13
+ export declare class IgnoreRules {
14
+ private readonly root;
15
+ private readonly useGitignore;
16
+ private readonly rootRule;
17
+ private readonly dirRules;
18
+ readonly extensions: Set<string>;
19
+ readonly maxFileSize: number;
20
+ constructor(root: string, config: ClastConfig);
21
+ /** Forget cached .gitignore contents (call when a .gitignore changes). */
22
+ invalidate(): void;
23
+ /** Rule for the .gitignore inside `dirRel` ('' or 'a/b/'), if any. */
24
+ private ruleFor;
25
+ private static test;
26
+ /** Full check for an arbitrary project-relative path (used by the watcher). */
27
+ isIgnored(rel: string): boolean;
28
+ isSupported(rel: string): boolean;
29
+ /** Files skipped by the last scan because they exceed maxFileSize. */
30
+ skippedLarge: number;
31
+ /** True when the last scan stopped at the maxFiles cap. */
32
+ truncated: boolean;
33
+ private readonly maxFiles;
34
+ /**
35
+ * Project-relative paths of text-like files that are NOT indexed (config,
36
+ * docs, data, unsupported languages) but pass the ignore rules. Used by
37
+ * text search so it can replace a plain grep.
38
+ */
39
+ otherTextFiles(limit?: number): string[];
40
+ /** Walk the project and return every indexable file. */
41
+ scan(): Promise<ScannedFile[]>;
42
+ private walk;
43
+ }