iosm-cli 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 (103) hide show
  1. package/CHANGELOG.md +33 -0
  2. package/README.md +37 -3
  3. package/dist/cli/args.d.ts.map +1 -1
  4. package/dist/cli/args.js +4 -2
  5. package/dist/cli/args.js.map +1 -1
  6. package/dist/core/agent-profiles.d.ts.map +1 -1
  7. package/dist/core/agent-profiles.js +1 -0
  8. package/dist/core/agent-profiles.js.map +1 -1
  9. package/dist/core/agent-session.d.ts.map +1 -1
  10. package/dist/core/agent-session.js +3 -0
  11. package/dist/core/agent-session.js.map +1 -1
  12. package/dist/core/blast.d.ts +62 -0
  13. package/dist/core/blast.d.ts.map +1 -0
  14. package/dist/core/blast.js +448 -0
  15. package/dist/core/blast.js.map +1 -0
  16. package/dist/core/contract.d.ts +54 -0
  17. package/dist/core/contract.d.ts.map +1 -0
  18. package/dist/core/contract.js +300 -0
  19. package/dist/core/contract.js.map +1 -0
  20. package/dist/core/sdk.d.ts +3 -3
  21. package/dist/core/sdk.d.ts.map +1 -1
  22. package/dist/core/sdk.js +11 -19
  23. package/dist/core/sdk.js.map +1 -1
  24. package/dist/core/semantic/chunking.d.ts +10 -0
  25. package/dist/core/semantic/chunking.d.ts.map +1 -0
  26. package/dist/core/semantic/chunking.js +82 -0
  27. package/dist/core/semantic/chunking.js.map +1 -0
  28. package/dist/core/semantic/cli.d.ts +23 -0
  29. package/dist/core/semantic/cli.d.ts.map +1 -0
  30. package/dist/core/semantic/cli.js +86 -0
  31. package/dist/core/semantic/cli.js.map +1 -0
  32. package/dist/core/semantic/config.d.ts +8 -0
  33. package/dist/core/semantic/config.d.ts.map +1 -0
  34. package/dist/core/semantic/config.js +266 -0
  35. package/dist/core/semantic/config.js.map +1 -0
  36. package/dist/core/semantic/index-store.d.ts +21 -0
  37. package/dist/core/semantic/index-store.d.ts.map +1 -0
  38. package/dist/core/semantic/index-store.js +73 -0
  39. package/dist/core/semantic/index-store.js.map +1 -0
  40. package/dist/core/semantic/index.d.ts +8 -0
  41. package/dist/core/semantic/index.d.ts.map +1 -0
  42. package/dist/core/semantic/index.js +7 -0
  43. package/dist/core/semantic/index.js.map +1 -0
  44. package/dist/core/semantic/providers.d.ts +22 -0
  45. package/dist/core/semantic/providers.d.ts.map +1 -0
  46. package/dist/core/semantic/providers.js +317 -0
  47. package/dist/core/semantic/providers.js.map +1 -0
  48. package/dist/core/semantic/runtime.d.ts +32 -0
  49. package/dist/core/semantic/runtime.d.ts.map +1 -0
  50. package/dist/core/semantic/runtime.js +510 -0
  51. package/dist/core/semantic/runtime.js.map +1 -0
  52. package/dist/core/semantic/types.d.ts +157 -0
  53. package/dist/core/semantic/types.d.ts.map +1 -0
  54. package/dist/core/semantic/types.js +23 -0
  55. package/dist/core/semantic/types.js.map +1 -0
  56. package/dist/core/shadow-guard.d.ts +30 -0
  57. package/dist/core/shadow-guard.d.ts.map +1 -0
  58. package/dist/core/shadow-guard.js +81 -0
  59. package/dist/core/shadow-guard.js.map +1 -0
  60. package/dist/core/singular.d.ts +73 -0
  61. package/dist/core/singular.d.ts.map +1 -0
  62. package/dist/core/singular.js +413 -0
  63. package/dist/core/singular.js.map +1 -0
  64. package/dist/core/slash-commands.d.ts.map +1 -1
  65. package/dist/core/slash-commands.js +12 -0
  66. package/dist/core/slash-commands.js.map +1 -1
  67. package/dist/core/system-prompt.d.ts.map +1 -1
  68. package/dist/core/system-prompt.js +21 -3
  69. package/dist/core/system-prompt.js.map +1 -1
  70. package/dist/core/tools/ast-grep.js +1 -1
  71. package/dist/core/tools/ast-grep.js.map +1 -1
  72. package/dist/core/tools/comby.js +1 -1
  73. package/dist/core/tools/comby.js.map +1 -1
  74. package/dist/core/tools/index.d.ts +9 -0
  75. package/dist/core/tools/index.d.ts.map +1 -1
  76. package/dist/core/tools/index.js +6 -0
  77. package/dist/core/tools/index.js.map +1 -1
  78. package/dist/core/tools/rg.js +1 -1
  79. package/dist/core/tools/rg.js.map +1 -1
  80. package/dist/core/tools/semantic-search.d.ts +21 -0
  81. package/dist/core/tools/semantic-search.d.ts.map +1 -0
  82. package/dist/core/tools/semantic-search.js +123 -0
  83. package/dist/core/tools/semantic-search.js.map +1 -0
  84. package/dist/index.d.ts +4 -2
  85. package/dist/index.d.ts.map +1 -1
  86. package/dist/index.js +3 -2
  87. package/dist/index.js.map +1 -1
  88. package/dist/main.d.ts.map +1 -1
  89. package/dist/main.js +124 -0
  90. package/dist/main.js.map +1 -1
  91. package/dist/modes/interactive/components/custom-editor.d.ts +8 -0
  92. package/dist/modes/interactive/components/custom-editor.d.ts.map +1 -1
  93. package/dist/modes/interactive/components/custom-editor.js +70 -1
  94. package/dist/modes/interactive/components/custom-editor.js.map +1 -1
  95. package/dist/modes/interactive/interactive-mode.d.ts +58 -0
  96. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  97. package/dist/modes/interactive/interactive-mode.js +2067 -104
  98. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  99. package/docs/cli-reference.md +36 -1
  100. package/docs/configuration.md +79 -2
  101. package/docs/getting-started.md +1 -0
  102. package/docs/interactive-mode.md +135 -1
  103. package/package.json +1 -1
@@ -0,0 +1,510 @@
1
+ import { createHash } from "node:crypto";
2
+ import { readFileSync, statSync } from "node:fs";
3
+ import { relative, resolve, sep } from "node:path";
4
+ import { globSync } from "glob";
5
+ import { getSemanticConfigPath, loadMergedSemanticConfig, } from "./config.js";
6
+ import { chunkTextForSemantic } from "./chunking.js";
7
+ import { getSemanticIndexDir, getSemanticProjectHash, loadSemanticIndex, writeSemanticIndex, } from "./index-store.js";
8
+ import { createSemanticEmbeddingProvider } from "./providers.js";
9
+ import { SemanticConfigMissingError, SemanticIndexRequiredError, SemanticRebuildRequiredError, } from "./types.js";
10
+ function toPosixPath(filePath) {
11
+ return filePath.split(sep).join("/");
12
+ }
13
+ function sha256(input) {
14
+ return createHash("sha256").update(input).digest("hex");
15
+ }
16
+ function fileHashFromContent(content) {
17
+ return sha256(content);
18
+ }
19
+ function chunkId(path, draft, index) {
20
+ return sha256(`${path}:${draft.hash}:${draft.lineStart}:${draft.lineEnd}:${index}`).slice(0, 24);
21
+ }
22
+ function normalizeIndexPath(cwd, absolutePath) {
23
+ const rel = relative(cwd, absolutePath);
24
+ return toPosixPath(rel);
25
+ }
26
+ function cosineSimilarity(a, b, normA, normB) {
27
+ if (normA <= 0 || normB <= 0 || a.length !== b.length)
28
+ return 0;
29
+ let dot = 0;
30
+ for (let index = 0; index < a.length; index++) {
31
+ dot += a[index] * b[index];
32
+ }
33
+ return dot / (normA * normB);
34
+ }
35
+ function vectorNorm(vector) {
36
+ let sum = 0;
37
+ for (const value of vector) {
38
+ sum += value * value;
39
+ }
40
+ return Math.sqrt(sum);
41
+ }
42
+ function ageSecondsFromIso(iso) {
43
+ const ms = Date.parse(iso);
44
+ if (!Number.isFinite(ms))
45
+ return undefined;
46
+ const ageMs = Date.now() - ms;
47
+ if (ageMs < 0)
48
+ return 0;
49
+ return Math.floor(ageMs / 1000);
50
+ }
51
+ function clampTopK(value) {
52
+ if (!Number.isFinite(value))
53
+ return 8;
54
+ const normalized = Math.floor(value);
55
+ if (normalized < 1)
56
+ return 1;
57
+ if (normalized > 20)
58
+ return 20;
59
+ return normalized;
60
+ }
61
+ export class SemanticSearchRuntime {
62
+ constructor(options) {
63
+ this.cwd = resolve(options.cwd);
64
+ this.agentDir = options.agentDir;
65
+ this.authStorage = options.authStorage;
66
+ }
67
+ async execute(action, query, topK) {
68
+ if (action === "status") {
69
+ return this.status();
70
+ }
71
+ if (action === "index") {
72
+ return this.index();
73
+ }
74
+ if (action === "rebuild") {
75
+ return this.rebuild();
76
+ }
77
+ return this.query(query ?? "", topK);
78
+ }
79
+ async status() {
80
+ const userConfigPath = getSemanticConfigPath("user", this.cwd, this.agentDir);
81
+ const projectConfigPath = getSemanticConfigPath("project", this.cwd, this.agentDir);
82
+ const indexPath = getSemanticIndexDir(this.cwd, this.agentDir);
83
+ const merged = loadMergedSemanticConfig(this.cwd, this.agentDir);
84
+ const config = merged.config;
85
+ if (!config) {
86
+ return {
87
+ action: "status",
88
+ configured: false,
89
+ enabled: false,
90
+ autoIndex: false,
91
+ indexed: false,
92
+ stale: true,
93
+ staleReason: "missing_index",
94
+ files: 0,
95
+ chunks: 0,
96
+ indexPath,
97
+ configPathUser: userConfigPath,
98
+ configPathProject: projectConfigPath,
99
+ };
100
+ }
101
+ const loaded = loadSemanticIndex(indexPath);
102
+ const stale = this.detectStaleness(config, loaded.meta);
103
+ const files = loaded.meta ? Object.keys(loaded.meta.fileMap).length : 0;
104
+ const chunks = loaded.chunks.length;
105
+ return {
106
+ action: "status",
107
+ configured: true,
108
+ enabled: config.enabled,
109
+ autoIndex: config.autoIndex,
110
+ indexed: loaded.exists && !!loaded.meta,
111
+ stale: stale.stale,
112
+ staleReason: stale.reason,
113
+ provider: config.provider.type,
114
+ model: config.provider.model,
115
+ files,
116
+ chunks,
117
+ dimension: loaded.meta?.dimension,
118
+ ageSeconds: loaded.meta ? ageSecondsFromIso(loaded.meta.builtAt) : undefined,
119
+ indexPath,
120
+ configPathUser: userConfigPath,
121
+ configPathProject: projectConfigPath,
122
+ };
123
+ }
124
+ async index() {
125
+ return this.buildIndex(false);
126
+ }
127
+ async rebuild() {
128
+ return this.buildIndex(true);
129
+ }
130
+ async query(rawQuery, topK) {
131
+ const query = rawQuery.trim();
132
+ if (!query) {
133
+ throw new Error("semantic query cannot be empty");
134
+ }
135
+ const config = this.loadConfiguredSemanticConfig();
136
+ if (!config.enabled) {
137
+ throw new Error("semantic search is disabled in semantic.json");
138
+ }
139
+ const status = await this.status();
140
+ let autoRefreshed = false;
141
+ if (!status.indexed || status.stale) {
142
+ const requiresRebuild = !status.indexed ||
143
+ status.staleReason === "provider_changed" ||
144
+ status.staleReason === "chunking_changed" ||
145
+ status.staleReason === "index_filters_changed" ||
146
+ status.staleReason === "dimension_mismatch";
147
+ if (!config.autoIndex) {
148
+ if (!status.indexed) {
149
+ throw new SemanticIndexRequiredError("Semantic index is missing and auto-indexing is disabled. Run /semantic index (or iosm semantic index), or enable auto-indexing in /semantic.");
150
+ }
151
+ if (requiresRebuild) {
152
+ throw new SemanticRebuildRequiredError(`Semantic index is stale${status.staleReason ? ` (${status.staleReason})` : ""} and auto-indexing is disabled. Run /semantic rebuild.`);
153
+ }
154
+ throw new SemanticIndexRequiredError(`Semantic index is stale${status.staleReason ? ` (${status.staleReason})` : ""} and auto-indexing is disabled. Run /semantic index (or enable auto-indexing in /semantic).`);
155
+ }
156
+ await this.buildIndex(requiresRebuild);
157
+ autoRefreshed = true;
158
+ }
159
+ const indexPath = getSemanticIndexDir(this.cwd, this.agentDir);
160
+ const loaded = loadSemanticIndex(indexPath);
161
+ const meta = loaded.meta;
162
+ if (!meta || loaded.vectors.length === 0 || loaded.chunks.length === 0) {
163
+ return {
164
+ action: "query",
165
+ query,
166
+ topK: clampTopK(topK),
167
+ autoRefreshed,
168
+ hits: [],
169
+ };
170
+ }
171
+ const provider = await createSemanticEmbeddingProvider(config.provider, {
172
+ authStorage: this.authStorage,
173
+ });
174
+ const queryVector = (await provider.embed([query]))[0];
175
+ if (!queryVector) {
176
+ throw new Error("provider returned no embedding for query");
177
+ }
178
+ if (queryVector.length !== meta.dimension) {
179
+ throw new SemanticRebuildRequiredError(`Embedding dimension changed (${queryVector.length} != ${meta.dimension}). Run /semantic rebuild.`);
180
+ }
181
+ const chunkById = new Map();
182
+ for (const chunk of loaded.chunks) {
183
+ chunkById.set(chunk.id, chunk);
184
+ }
185
+ const queryNorm = vectorNorm(queryVector);
186
+ const ranked = [];
187
+ for (const vector of loaded.vectors) {
188
+ const chunk = chunkById.get(vector.id);
189
+ if (!chunk)
190
+ continue;
191
+ const score = cosineSimilarity(queryVector, vector.vector, queryNorm, vector.norm);
192
+ if (!Number.isFinite(score))
193
+ continue;
194
+ ranked.push({
195
+ score,
196
+ path: chunk.path,
197
+ lineStart: chunk.lineStart,
198
+ lineEnd: chunk.lineEnd,
199
+ snippet: chunk.preview,
200
+ });
201
+ }
202
+ ranked.sort((a, b) => b.score - a.score);
203
+ const effectiveTopK = clampTopK(topK);
204
+ return {
205
+ action: "query",
206
+ query,
207
+ topK: effectiveTopK,
208
+ autoRefreshed,
209
+ hits: ranked.slice(0, effectiveTopK),
210
+ };
211
+ }
212
+ loadConfiguredSemanticConfig() {
213
+ const merged = loadMergedSemanticConfig(this.cwd, this.agentDir);
214
+ if (!merged.config) {
215
+ throw new SemanticConfigMissingError(getSemanticConfigPath("user", this.cwd, this.agentDir), getSemanticConfigPath("project", this.cwd, this.agentDir));
216
+ }
217
+ if (merged.errors.length > 0) {
218
+ throw new Error(`semantic config warnings: ${merged.errors.join(" | ")}`);
219
+ }
220
+ return merged.config;
221
+ }
222
+ detectStaleness(config, meta) {
223
+ if (!meta) {
224
+ return { stale: true, reason: "missing_index" };
225
+ }
226
+ if (meta.dimension <= 0) {
227
+ return { stale: true, reason: "dimension_mismatch" };
228
+ }
229
+ if (meta.providerFingerprint !== this.providerFingerprint(config)) {
230
+ return { stale: true, reason: "provider_changed" };
231
+ }
232
+ if (meta.chunkConfigFingerprint !== this.chunkConfigFingerprint(config.index)) {
233
+ return { stale: true, reason: "chunking_changed" };
234
+ }
235
+ if (meta.indexFilterFingerprint !== this.indexFilterFingerprint(config.index)) {
236
+ return { stale: true, reason: "index_filters_changed" };
237
+ }
238
+ const statusFileMap = this.collectProjectFileStats(config.index);
239
+ const indexedPaths = Object.keys(meta.fileMap);
240
+ if (indexedPaths.length !== statusFileMap.size) {
241
+ return { stale: true, reason: "files_changed" };
242
+ }
243
+ for (const [path, current] of statusFileMap.entries()) {
244
+ const previous = meta.fileMap[path];
245
+ if (!previous) {
246
+ return { stale: true, reason: "files_changed" };
247
+ }
248
+ if (previous.size !== current.size || previous.mtimeMs !== current.mtimeMs) {
249
+ return { stale: true, reason: "files_changed" };
250
+ }
251
+ }
252
+ return { stale: false };
253
+ }
254
+ collectCandidatePaths(indexConfig) {
255
+ const results = new Set();
256
+ for (const pattern of indexConfig.includeGlobs) {
257
+ for (const filePath of globSync(pattern, {
258
+ cwd: this.cwd,
259
+ absolute: true,
260
+ nodir: true,
261
+ dot: true,
262
+ ignore: indexConfig.excludeGlobs,
263
+ follow: false,
264
+ })) {
265
+ results.add(resolve(filePath));
266
+ }
267
+ }
268
+ return [...results].sort().slice(0, indexConfig.maxFiles);
269
+ }
270
+ collectProjectFileStats(indexConfig) {
271
+ const map = new Map();
272
+ for (const absPath of this.collectCandidatePaths(indexConfig)) {
273
+ let stat;
274
+ try {
275
+ stat = statSync(absPath);
276
+ }
277
+ catch {
278
+ continue;
279
+ }
280
+ if (!stat.isFile())
281
+ continue;
282
+ if (stat.size > indexConfig.maxFileBytes)
283
+ continue;
284
+ const relPath = normalizeIndexPath(this.cwd, absPath);
285
+ map.set(relPath, { size: stat.size, mtimeMs: stat.mtimeMs });
286
+ }
287
+ return map;
288
+ }
289
+ collectProjectFiles(indexConfig) {
290
+ const files = [];
291
+ for (const absPath of this.collectCandidatePaths(indexConfig)) {
292
+ let stat;
293
+ try {
294
+ stat = statSync(absPath);
295
+ }
296
+ catch {
297
+ continue;
298
+ }
299
+ if (!stat.isFile())
300
+ continue;
301
+ if (stat.size > indexConfig.maxFileBytes)
302
+ continue;
303
+ let buffer;
304
+ try {
305
+ buffer = readFileSync(absPath);
306
+ }
307
+ catch {
308
+ continue;
309
+ }
310
+ if (buffer.includes(0))
311
+ continue;
312
+ const text = buffer.toString("utf8");
313
+ const trimmed = text.trim();
314
+ if (!trimmed)
315
+ continue;
316
+ const relPath = normalizeIndexPath(this.cwd, absPath);
317
+ files.push({
318
+ absPath,
319
+ relPath,
320
+ size: stat.size,
321
+ mtimeMs: stat.mtimeMs,
322
+ hash: fileHashFromContent(text.replace(/\r\n/g, "\n")),
323
+ text: text.replace(/\r\n/g, "\n"),
324
+ });
325
+ }
326
+ return files;
327
+ }
328
+ providerFingerprint(config) {
329
+ const stableHeaders = config.provider.headers
330
+ ? Object.entries(config.provider.headers).sort(([a], [b]) => a.localeCompare(b))
331
+ : [];
332
+ return sha256(JSON.stringify({
333
+ type: config.provider.type,
334
+ model: config.provider.model,
335
+ baseUrl: config.provider.baseUrl ?? "",
336
+ headers: stableHeaders,
337
+ apiKeyEnv: config.provider.apiKeyEnv ?? "",
338
+ }));
339
+ }
340
+ chunkConfigFingerprint(indexConfig) {
341
+ return sha256(JSON.stringify({
342
+ chunkMaxChars: indexConfig.chunkMaxChars,
343
+ chunkOverlapChars: indexConfig.chunkOverlapChars,
344
+ }));
345
+ }
346
+ indexFilterFingerprint(indexConfig) {
347
+ return sha256(JSON.stringify({
348
+ includeGlobs: [...indexConfig.includeGlobs].sort(),
349
+ excludeGlobs: [...indexConfig.excludeGlobs].sort(),
350
+ maxFileBytes: indexConfig.maxFileBytes,
351
+ maxFiles: indexConfig.maxFiles,
352
+ }));
353
+ }
354
+ async buildIndex(forceRebuild) {
355
+ const startedAt = Date.now();
356
+ const config = this.loadConfiguredSemanticConfig();
357
+ if (!config.enabled) {
358
+ throw new Error("semantic search is disabled in semantic.json");
359
+ }
360
+ const indexDir = getSemanticIndexDir(this.cwd, this.agentDir);
361
+ const existing = loadSemanticIndex(indexDir);
362
+ const existingMeta = existing.meta;
363
+ const providerFingerprint = this.providerFingerprint(config);
364
+ const chunkFingerprint = this.chunkConfigFingerprint(config.index);
365
+ const filterFingerprint = this.indexFilterFingerprint(config.index);
366
+ if (!forceRebuild &&
367
+ existingMeta &&
368
+ (existingMeta.providerFingerprint !== providerFingerprint ||
369
+ existingMeta.chunkConfigFingerprint !== chunkFingerprint ||
370
+ existingMeta.indexFilterFingerprint !== filterFingerprint)) {
371
+ throw new SemanticRebuildRequiredError("Semantic index settings changed. Run /semantic rebuild (or iosm semantic rebuild).");
372
+ }
373
+ const provider = await createSemanticEmbeddingProvider(config.provider, {
374
+ authStorage: this.authStorage,
375
+ });
376
+ const files = this.collectProjectFiles(config.index);
377
+ const existingChunkById = new Map(existing.chunks.map((chunk) => [chunk.id, chunk]));
378
+ const existingVectorById = new Map(existing.vectors.map((vector) => [vector.id, vector]));
379
+ const nextChunks = [];
380
+ const nextVectors = [];
381
+ const nextFileMap = {};
382
+ let changedFiles = 0;
383
+ let newFiles = 0;
384
+ let reusedFiles = 0;
385
+ let removedFiles = 0;
386
+ // Full rebuild must not inherit previous dimension. Otherwise provider/model
387
+ // dimension changes can keep throwing mismatch even after rebuild.
388
+ let dimension = forceRebuild ? undefined : existingMeta?.dimension;
389
+ const currentPaths = new Set(files.map((file) => file.relPath));
390
+ if (existingMeta) {
391
+ for (const path of Object.keys(existingMeta.fileMap)) {
392
+ if (!currentPaths.has(path)) {
393
+ removedFiles += 1;
394
+ }
395
+ }
396
+ }
397
+ for (const file of files) {
398
+ const prev = !forceRebuild ? existingMeta?.fileMap[file.relPath] : undefined;
399
+ const canReuse = !!prev &&
400
+ prev.hash === file.hash &&
401
+ prev.chunks.length > 0 &&
402
+ prev.chunks.every((id) => existingChunkById.has(id) && existingVectorById.has(id));
403
+ if (canReuse && prev) {
404
+ reusedFiles += 1;
405
+ for (const chunkId of prev.chunks) {
406
+ const chunk = existingChunkById.get(chunkId);
407
+ const vector = existingVectorById.get(chunkId);
408
+ if (!chunk || !vector)
409
+ continue;
410
+ nextChunks.push(chunk);
411
+ nextVectors.push(vector);
412
+ }
413
+ nextFileMap[file.relPath] = {
414
+ path: file.relPath,
415
+ size: file.size,
416
+ mtimeMs: file.mtimeMs,
417
+ hash: file.hash,
418
+ chunks: [...prev.chunks],
419
+ };
420
+ continue;
421
+ }
422
+ if (prev)
423
+ changedFiles += 1;
424
+ else
425
+ newFiles += 1;
426
+ const drafts = chunkTextForSemantic(file.text, config.index);
427
+ const chunkRecords = drafts.map((draft, index) => {
428
+ const id = chunkId(file.relPath, draft, index);
429
+ return {
430
+ id,
431
+ path: file.relPath,
432
+ lineStart: draft.lineStart,
433
+ lineEnd: draft.lineEnd,
434
+ preview: draft.preview,
435
+ hash: draft.hash,
436
+ text: draft.text,
437
+ };
438
+ });
439
+ const chunkIds = chunkRecords.map((chunk) => chunk.id);
440
+ nextFileMap[file.relPath] = {
441
+ path: file.relPath,
442
+ size: file.size,
443
+ mtimeMs: file.mtimeMs,
444
+ hash: file.hash,
445
+ chunks: chunkIds,
446
+ };
447
+ if (chunkRecords.length === 0)
448
+ continue;
449
+ const embeddings = await provider.embed(chunkRecords.map((chunk) => chunk.text));
450
+ if (embeddings.length !== chunkRecords.length) {
451
+ throw new Error(`Embedding provider returned ${embeddings.length} vectors for ${chunkRecords.length} chunks.`);
452
+ }
453
+ for (let index = 0; index < chunkRecords.length; index++) {
454
+ const chunk = chunkRecords[index];
455
+ const vector = embeddings[index];
456
+ if (!Array.isArray(vector) || vector.length === 0) {
457
+ throw new Error("Embedding provider returned an empty vector.");
458
+ }
459
+ if (dimension === undefined || dimension <= 0) {
460
+ dimension = vector.length;
461
+ }
462
+ else if (dimension !== vector.length) {
463
+ throw new SemanticRebuildRequiredError(`Embedding dimension mismatch (${vector.length} != ${dimension}). Run /semantic rebuild.`);
464
+ }
465
+ nextChunks.push({
466
+ id: chunk.id,
467
+ path: chunk.path,
468
+ lineStart: chunk.lineStart,
469
+ lineEnd: chunk.lineEnd,
470
+ preview: chunk.preview,
471
+ hash: chunk.hash,
472
+ });
473
+ nextVectors.push({
474
+ id: chunk.id,
475
+ vector,
476
+ norm: vectorNorm(vector),
477
+ });
478
+ }
479
+ }
480
+ const builtAt = new Date().toISOString();
481
+ const meta = {
482
+ version: 1,
483
+ cwd: this.cwd,
484
+ projectHash: getSemanticProjectHash(this.cwd),
485
+ providerFingerprint,
486
+ providerType: config.provider.type,
487
+ model: config.provider.model,
488
+ dimension: dimension ?? 0,
489
+ builtAt,
490
+ chunkConfigFingerprint: chunkFingerprint,
491
+ indexFilterFingerprint: filterFingerprint,
492
+ fileMap: nextFileMap,
493
+ };
494
+ writeSemanticIndex(indexDir, meta, nextChunks, nextVectors);
495
+ return {
496
+ action: forceRebuild ? "rebuild" : "index",
497
+ indexPath: indexDir,
498
+ durationMs: Date.now() - startedAt,
499
+ processedFiles: files.length,
500
+ newFiles,
501
+ changedFiles,
502
+ removedFiles,
503
+ reusedFiles,
504
+ chunks: nextChunks.length,
505
+ dimension: meta.dimension,
506
+ builtAt,
507
+ };
508
+ }
509
+ }
510
+ //# sourceMappingURL=runtime.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime.js","sourceRoot":"","sources":["../../../src/core/semantic/runtime.ts"],"names":[],"mappings":"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","sourcesContent":["import { createHash } from \"node:crypto\";\nimport { existsSync, readFileSync, statSync } from \"node:fs\";\nimport { relative, resolve, sep } from \"node:path\";\nimport { globSync } from \"glob\";\nimport type { AuthStorage } from \"../auth-storage.js\";\nimport {\n\tgetSemanticConfigPath,\n\tloadMergedSemanticConfig,\n} from \"./config.js\";\nimport { chunkTextForSemantic, type SemanticChunkDraft } from \"./chunking.js\";\nimport {\n\tgetSemanticIndexDir,\n\tgetSemanticProjectHash,\n\tloadSemanticIndex,\n\twriteSemanticIndex,\n} from \"./index-store.js\";\nimport { createSemanticEmbeddingProvider } from \"./providers.js\";\nimport type {\n\tSemanticIndexConfig,\n\tSemanticIndexMeta,\n\tSemanticIndexOperationResult,\n\tSemanticIndexedChunk,\n\tSemanticIndexedVector,\n\tSemanticQueryHit,\n\tSemanticQueryResult,\n\tSemanticSearchConfig,\n\tSemanticStatusResult,\n\tSemanticStaleReason,\n\tSemanticToolResult,\n} from \"./types.js\";\nimport {\n\tSemanticConfigMissingError,\n\tSemanticIndexRequiredError,\n\tSemanticRebuildRequiredError,\n} from \"./types.js\";\n\ninterface SemanticRuntimeOptions {\n\tcwd: string;\n\tagentDir: string;\n\tauthStorage?: AuthStorage;\n}\n\ninterface ScannedSemanticFile {\n\tabsPath: string;\n\trelPath: string;\n\tsize: number;\n\tmtimeMs: number;\n\thash: string;\n\ttext: string;\n}\n\nfunction toPosixPath(filePath: string): string {\n\treturn filePath.split(sep).join(\"/\");\n}\n\nfunction sha256(input: string): string {\n\treturn createHash(\"sha256\").update(input).digest(\"hex\");\n}\n\nfunction fileHashFromContent(content: string): string {\n\treturn sha256(content);\n}\n\nfunction chunkId(path: string, draft: SemanticChunkDraft, index: number): string {\n\treturn sha256(`${path}:${draft.hash}:${draft.lineStart}:${draft.lineEnd}:${index}`).slice(0, 24);\n}\n\nfunction normalizeIndexPath(cwd: string, absolutePath: string): string {\n\tconst rel = relative(cwd, absolutePath);\n\treturn toPosixPath(rel);\n}\n\nfunction cosineSimilarity(a: number[], b: number[], normA: number, normB: number): number {\n\tif (normA <= 0 || normB <= 0 || a.length !== b.length) return 0;\n\tlet dot = 0;\n\tfor (let index = 0; index < a.length; index++) {\n\t\tdot += a[index]! * b[index]!;\n\t}\n\treturn dot / (normA * normB);\n}\n\nfunction vectorNorm(vector: number[]): number {\n\tlet sum = 0;\n\tfor (const value of vector) {\n\t\tsum += value * value;\n\t}\n\treturn Math.sqrt(sum);\n}\n\nfunction ageSecondsFromIso(iso: string): number | undefined {\n\tconst ms = Date.parse(iso);\n\tif (!Number.isFinite(ms)) return undefined;\n\tconst ageMs = Date.now() - ms;\n\tif (ageMs < 0) return 0;\n\treturn Math.floor(ageMs / 1000);\n}\n\nfunction clampTopK(value: number | undefined): number {\n\tif (!Number.isFinite(value)) return 8;\n\tconst normalized = Math.floor(value as number);\n\tif (normalized < 1) return 1;\n\tif (normalized > 20) return 20;\n\treturn normalized;\n}\n\nexport class SemanticSearchRuntime {\n\tprivate readonly cwd: string;\n\tprivate readonly agentDir: string;\n\tprivate readonly authStorage?: AuthStorage;\n\n\tconstructor(options: SemanticRuntimeOptions) {\n\t\tthis.cwd = resolve(options.cwd);\n\t\tthis.agentDir = options.agentDir;\n\t\tthis.authStorage = options.authStorage;\n\t}\n\n\tasync execute(action: \"status\"): Promise<SemanticStatusResult>;\n\tasync execute(action: \"index\"): Promise<SemanticIndexOperationResult>;\n\tasync execute(action: \"rebuild\"): Promise<SemanticIndexOperationResult>;\n\tasync execute(action: \"query\", query: string, topK?: number): Promise<SemanticQueryResult>;\n\tasync execute(action: \"status\" | \"index\" | \"rebuild\" | \"query\", query?: string, topK?: number): Promise<SemanticToolResult> {\n\t\tif (action === \"status\") {\n\t\t\treturn this.status();\n\t\t}\n\t\tif (action === \"index\") {\n\t\t\treturn this.index();\n\t\t}\n\t\tif (action === \"rebuild\") {\n\t\t\treturn this.rebuild();\n\t\t}\n\t\treturn this.query(query ?? \"\", topK);\n\t}\n\n\tasync status(): Promise<SemanticStatusResult> {\n\t\tconst userConfigPath = getSemanticConfigPath(\"user\", this.cwd, this.agentDir);\n\t\tconst projectConfigPath = getSemanticConfigPath(\"project\", this.cwd, this.agentDir);\n\t\tconst indexPath = getSemanticIndexDir(this.cwd, this.agentDir);\n\t\tconst merged = loadMergedSemanticConfig(this.cwd, this.agentDir);\n\t\tconst config = merged.config;\n\n\t\tif (!config) {\n\t\t\treturn {\n\t\t\t\taction: \"status\",\n\t\t\t\tconfigured: false,\n\t\t\t\tenabled: false,\n\t\t\t\tautoIndex: false,\n\t\t\t\tindexed: false,\n\t\t\t\tstale: true,\n\t\t\t\tstaleReason: \"missing_index\",\n\t\t\t\tfiles: 0,\n\t\t\t\tchunks: 0,\n\t\t\t\tindexPath,\n\t\t\t\tconfigPathUser: userConfigPath,\n\t\t\t\tconfigPathProject: projectConfigPath,\n\t\t\t};\n\t\t}\n\n\t\tconst loaded = loadSemanticIndex(indexPath);\n\t\tconst stale = this.detectStaleness(config, loaded.meta);\n\t\tconst files = loaded.meta ? Object.keys(loaded.meta.fileMap).length : 0;\n\t\tconst chunks = loaded.chunks.length;\n\n\t\treturn {\n\t\t\taction: \"status\",\n\t\t\tconfigured: true,\n\t\t\tenabled: config.enabled,\n\t\t\tautoIndex: config.autoIndex,\n\t\t\tindexed: loaded.exists && !!loaded.meta,\n\t\t\tstale: stale.stale,\n\t\t\tstaleReason: stale.reason,\n\t\t\tprovider: config.provider.type,\n\t\t\tmodel: config.provider.model,\n\t\t\tfiles,\n\t\t\tchunks,\n\t\t\tdimension: loaded.meta?.dimension,\n\t\t\tageSeconds: loaded.meta ? ageSecondsFromIso(loaded.meta.builtAt) : undefined,\n\t\t\tindexPath,\n\t\t\tconfigPathUser: userConfigPath,\n\t\t\tconfigPathProject: projectConfigPath,\n\t\t};\n\t}\n\n\tasync index(): Promise<SemanticIndexOperationResult> {\n\t\treturn this.buildIndex(false);\n\t}\n\n\tasync rebuild(): Promise<SemanticIndexOperationResult> {\n\t\treturn this.buildIndex(true);\n\t}\n\n\tasync query(rawQuery: string, topK?: number): Promise<SemanticQueryResult> {\n\t\tconst query = rawQuery.trim();\n\t\tif (!query) {\n\t\t\tthrow new Error(\"semantic query cannot be empty\");\n\t\t}\n\n\t\tconst config = this.loadConfiguredSemanticConfig();\n\t\tif (!config.enabled) {\n\t\t\tthrow new Error(\"semantic search is disabled in semantic.json\");\n\t\t}\n\n\t\tconst status = await this.status();\n\t\tlet autoRefreshed = false;\n\t\tif (!status.indexed || status.stale) {\n\t\t\tconst requiresRebuild =\n\t\t\t\t!status.indexed ||\n\t\t\t\tstatus.staleReason === \"provider_changed\" ||\n\t\t\t\tstatus.staleReason === \"chunking_changed\" ||\n\t\t\t\tstatus.staleReason === \"index_filters_changed\" ||\n\t\t\t\tstatus.staleReason === \"dimension_mismatch\";\n\t\t\tif (!config.autoIndex) {\n\t\t\t\tif (!status.indexed) {\n\t\t\t\t\tthrow new SemanticIndexRequiredError(\n\t\t\t\t\t\t\"Semantic index is missing and auto-indexing is disabled. Run /semantic index (or iosm semantic index), or enable auto-indexing in /semantic.\",\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tif (requiresRebuild) {\n\t\t\t\t\tthrow new SemanticRebuildRequiredError(\n\t\t\t\t\t\t`Semantic index is stale${status.staleReason ? ` (${status.staleReason})` : \"\"} and auto-indexing is disabled. Run /semantic rebuild.`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tthrow new SemanticIndexRequiredError(\n\t\t\t\t\t`Semantic index is stale${status.staleReason ? ` (${status.staleReason})` : \"\"} and auto-indexing is disabled. Run /semantic index (or enable auto-indexing in /semantic).`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tawait this.buildIndex(requiresRebuild);\n\t\t\tautoRefreshed = true;\n\t\t}\n\n\t\tconst indexPath = getSemanticIndexDir(this.cwd, this.agentDir);\n\t\tconst loaded = loadSemanticIndex(indexPath);\n\t\tconst meta = loaded.meta;\n\t\tif (!meta || loaded.vectors.length === 0 || loaded.chunks.length === 0) {\n\t\t\treturn {\n\t\t\t\taction: \"query\",\n\t\t\t\tquery,\n\t\t\t\ttopK: clampTopK(topK),\n\t\t\t\tautoRefreshed,\n\t\t\t\thits: [],\n\t\t\t};\n\t\t}\n\n\t\tconst provider = await createSemanticEmbeddingProvider(config.provider, {\n\t\t\tauthStorage: this.authStorage,\n\t\t});\n\t\tconst queryVector = (await provider.embed([query]))[0];\n\t\tif (!queryVector) {\n\t\t\tthrow new Error(\"provider returned no embedding for query\");\n\t\t}\n\n\t\tif (queryVector.length !== meta.dimension) {\n\t\t\tthrow new SemanticRebuildRequiredError(\n\t\t\t\t`Embedding dimension changed (${queryVector.length} != ${meta.dimension}). Run /semantic rebuild.`,\n\t\t\t);\n\t\t}\n\n\t\tconst chunkById = new Map<string, SemanticIndexedChunk>();\n\t\tfor (const chunk of loaded.chunks) {\n\t\t\tchunkById.set(chunk.id, chunk);\n\t\t}\n\t\tconst queryNorm = vectorNorm(queryVector);\n\t\tconst ranked: SemanticQueryHit[] = [];\n\t\tfor (const vector of loaded.vectors) {\n\t\t\tconst chunk = chunkById.get(vector.id);\n\t\t\tif (!chunk) continue;\n\t\t\tconst score = cosineSimilarity(queryVector, vector.vector, queryNorm, vector.norm);\n\t\t\tif (!Number.isFinite(score)) continue;\n\t\t\tranked.push({\n\t\t\t\tscore,\n\t\t\t\tpath: chunk.path,\n\t\t\t\tlineStart: chunk.lineStart,\n\t\t\t\tlineEnd: chunk.lineEnd,\n\t\t\t\tsnippet: chunk.preview,\n\t\t\t});\n\t\t}\n\n\t\tranked.sort((a, b) => b.score - a.score);\n\t\tconst effectiveTopK = clampTopK(topK);\n\t\treturn {\n\t\t\taction: \"query\",\n\t\t\tquery,\n\t\t\ttopK: effectiveTopK,\n\t\t\tautoRefreshed,\n\t\t\thits: ranked.slice(0, effectiveTopK),\n\t\t};\n\t}\n\n\tprivate loadConfiguredSemanticConfig(): SemanticSearchConfig {\n\t\tconst merged = loadMergedSemanticConfig(this.cwd, this.agentDir);\n\t\tif (!merged.config) {\n\t\t\tthrow new SemanticConfigMissingError(\n\t\t\t\tgetSemanticConfigPath(\"user\", this.cwd, this.agentDir),\n\t\t\t\tgetSemanticConfigPath(\"project\", this.cwd, this.agentDir),\n\t\t\t);\n\t\t}\n\t\tif (merged.errors.length > 0) {\n\t\t\tthrow new Error(`semantic config warnings: ${merged.errors.join(\" | \")}`);\n\t\t}\n\t\treturn merged.config;\n\t}\n\n\tprivate detectStaleness(\n\t\tconfig: SemanticSearchConfig,\n\t\tmeta: SemanticIndexMeta | undefined,\n\t): { stale: boolean; reason?: SemanticStaleReason } {\n\t\tif (!meta) {\n\t\t\treturn { stale: true, reason: \"missing_index\" };\n\t\t}\n\t\tif (meta.dimension <= 0) {\n\t\t\treturn { stale: true, reason: \"dimension_mismatch\" };\n\t\t}\n\t\tif (meta.providerFingerprint !== this.providerFingerprint(config)) {\n\t\t\treturn { stale: true, reason: \"provider_changed\" };\n\t\t}\n\t\tif (meta.chunkConfigFingerprint !== this.chunkConfigFingerprint(config.index)) {\n\t\t\treturn { stale: true, reason: \"chunking_changed\" };\n\t\t}\n\t\tif (meta.indexFilterFingerprint !== this.indexFilterFingerprint(config.index)) {\n\t\t\treturn { stale: true, reason: \"index_filters_changed\" };\n\t\t}\n\n\t\tconst statusFileMap = this.collectProjectFileStats(config.index);\n\t\tconst indexedPaths = Object.keys(meta.fileMap);\n\t\tif (indexedPaths.length !== statusFileMap.size) {\n\t\t\treturn { stale: true, reason: \"files_changed\" };\n\t\t}\n\t\tfor (const [path, current] of statusFileMap.entries()) {\n\t\t\tconst previous = meta.fileMap[path];\n\t\t\tif (!previous) {\n\t\t\t\treturn { stale: true, reason: \"files_changed\" };\n\t\t\t}\n\t\t\tif (previous.size !== current.size || previous.mtimeMs !== current.mtimeMs) {\n\t\t\t\treturn { stale: true, reason: \"files_changed\" };\n\t\t\t}\n\t\t}\n\n\t\treturn { stale: false };\n\t}\n\n\tprivate collectCandidatePaths(indexConfig: SemanticIndexConfig): string[] {\n\t\tconst results = new Set<string>();\n\t\tfor (const pattern of indexConfig.includeGlobs) {\n\t\t\tfor (const filePath of globSync(pattern, {\n\t\t\t\tcwd: this.cwd,\n\t\t\t\tabsolute: true,\n\t\t\t\tnodir: true,\n\t\t\t\tdot: true,\n\t\t\t\tignore: indexConfig.excludeGlobs,\n\t\t\t\tfollow: false,\n\t\t\t})) {\n\t\t\t\tresults.add(resolve(filePath));\n\t\t\t}\n\t\t}\n\n\t\treturn [...results].sort().slice(0, indexConfig.maxFiles);\n\t}\n\n\tprivate collectProjectFileStats(indexConfig: SemanticIndexConfig): Map<string, { size: number; mtimeMs: number }> {\n\t\tconst map = new Map<string, { size: number; mtimeMs: number }>();\n\t\tfor (const absPath of this.collectCandidatePaths(indexConfig)) {\n\t\t\tlet stat;\n\t\t\ttry {\n\t\t\t\tstat = statSync(absPath);\n\t\t\t} catch {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (!stat.isFile()) continue;\n\t\t\tif (stat.size > indexConfig.maxFileBytes) continue;\n\t\t\tconst relPath = normalizeIndexPath(this.cwd, absPath);\n\t\t\tmap.set(relPath, { size: stat.size, mtimeMs: stat.mtimeMs });\n\t\t}\n\t\treturn map;\n\t}\n\n\tprivate collectProjectFiles(indexConfig: SemanticIndexConfig): ScannedSemanticFile[] {\n\t\tconst files: ScannedSemanticFile[] = [];\n\t\tfor (const absPath of this.collectCandidatePaths(indexConfig)) {\n\t\t\tlet stat;\n\t\t\ttry {\n\t\t\t\tstat = statSync(absPath);\n\t\t\t} catch {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (!stat.isFile()) continue;\n\t\t\tif (stat.size > indexConfig.maxFileBytes) continue;\n\n\t\t\tlet buffer: Buffer;\n\t\t\ttry {\n\t\t\t\tbuffer = readFileSync(absPath);\n\t\t\t} catch {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (buffer.includes(0)) continue;\n\n\t\t\tconst text = buffer.toString(\"utf8\");\n\t\t\tconst trimmed = text.trim();\n\t\t\tif (!trimmed) continue;\n\n\t\t\tconst relPath = normalizeIndexPath(this.cwd, absPath);\n\t\t\tfiles.push({\n\t\t\t\tabsPath,\n\t\t\t\trelPath,\n\t\t\t\tsize: stat.size,\n\t\t\t\tmtimeMs: stat.mtimeMs,\n\t\t\t\thash: fileHashFromContent(text.replace(/\\r\\n/g, \"\\n\")),\n\t\t\t\ttext: text.replace(/\\r\\n/g, \"\\n\"),\n\t\t\t});\n\t\t}\n\t\treturn files;\n\t}\n\n\tprivate providerFingerprint(config: SemanticSearchConfig): string {\n\t\tconst stableHeaders = config.provider.headers\n\t\t\t? Object.entries(config.provider.headers).sort(([a], [b]) => a.localeCompare(b))\n\t\t\t: [];\n\t\treturn sha256(\n\t\t\tJSON.stringify({\n\t\t\t\ttype: config.provider.type,\n\t\t\t\tmodel: config.provider.model,\n\t\t\t\tbaseUrl: config.provider.baseUrl ?? \"\",\n\t\t\t\theaders: stableHeaders,\n\t\t\t\tapiKeyEnv: config.provider.apiKeyEnv ?? \"\",\n\t\t\t}),\n\t\t);\n\t}\n\n\tprivate chunkConfigFingerprint(indexConfig: SemanticIndexConfig): string {\n\t\treturn sha256(\n\t\t\tJSON.stringify({\n\t\t\t\tchunkMaxChars: indexConfig.chunkMaxChars,\n\t\t\t\tchunkOverlapChars: indexConfig.chunkOverlapChars,\n\t\t\t}),\n\t\t);\n\t}\n\n\tprivate indexFilterFingerprint(indexConfig: SemanticIndexConfig): string {\n\t\treturn sha256(\n\t\t\tJSON.stringify({\n\t\t\t\tincludeGlobs: [...indexConfig.includeGlobs].sort(),\n\t\t\t\texcludeGlobs: [...indexConfig.excludeGlobs].sort(),\n\t\t\t\tmaxFileBytes: indexConfig.maxFileBytes,\n\t\t\t\tmaxFiles: indexConfig.maxFiles,\n\t\t\t}),\n\t\t);\n\t}\n\n\tprivate async buildIndex(forceRebuild: boolean): Promise<SemanticIndexOperationResult> {\n\t\tconst startedAt = Date.now();\n\t\tconst config = this.loadConfiguredSemanticConfig();\n\t\tif (!config.enabled) {\n\t\t\tthrow new Error(\"semantic search is disabled in semantic.json\");\n\t\t}\n\n\t\tconst indexDir = getSemanticIndexDir(this.cwd, this.agentDir);\n\t\tconst existing = loadSemanticIndex(indexDir);\n\t\tconst existingMeta = existing.meta;\n\t\tconst providerFingerprint = this.providerFingerprint(config);\n\t\tconst chunkFingerprint = this.chunkConfigFingerprint(config.index);\n\t\tconst filterFingerprint = this.indexFilterFingerprint(config.index);\n\n\t\tif (\n\t\t\t!forceRebuild &&\n\t\t\texistingMeta &&\n\t\t\t(existingMeta.providerFingerprint !== providerFingerprint ||\n\t\t\t\texistingMeta.chunkConfigFingerprint !== chunkFingerprint ||\n\t\t\t\texistingMeta.indexFilterFingerprint !== filterFingerprint)\n\t\t) {\n\t\t\tthrow new SemanticRebuildRequiredError(\n\t\t\t\t\"Semantic index settings changed. Run /semantic rebuild (or iosm semantic rebuild).\",\n\t\t\t);\n\t\t}\n\n\t\tconst provider = await createSemanticEmbeddingProvider(config.provider, {\n\t\t\tauthStorage: this.authStorage,\n\t\t});\n\t\tconst files = this.collectProjectFiles(config.index);\n\t\tconst existingChunkById = new Map(existing.chunks.map((chunk) => [chunk.id, chunk]));\n\t\tconst existingVectorById = new Map(existing.vectors.map((vector) => [vector.id, vector]));\n\n\t\tconst nextChunks: SemanticIndexedChunk[] = [];\n\t\tconst nextVectors: SemanticIndexedVector[] = [];\n\t\tconst nextFileMap: SemanticIndexMeta[\"fileMap\"] = {};\n\n\t\tlet changedFiles = 0;\n\t\tlet newFiles = 0;\n\t\tlet reusedFiles = 0;\n\t\tlet removedFiles = 0;\n\t\t// Full rebuild must not inherit previous dimension. Otherwise provider/model\n\t\t// dimension changes can keep throwing mismatch even after rebuild.\n\t\tlet dimension = forceRebuild ? undefined : existingMeta?.dimension;\n\n\t\tconst currentPaths = new Set(files.map((file) => file.relPath));\n\t\tif (existingMeta) {\n\t\t\tfor (const path of Object.keys(existingMeta.fileMap)) {\n\t\t\t\tif (!currentPaths.has(path)) {\n\t\t\t\t\tremovedFiles += 1;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tfor (const file of files) {\n\t\t\tconst prev = !forceRebuild ? existingMeta?.fileMap[file.relPath] : undefined;\n\t\t\tconst canReuse =\n\t\t\t\t!!prev &&\n\t\t\t\tprev.hash === file.hash &&\n\t\t\t\tprev.chunks.length > 0 &&\n\t\t\t\tprev.chunks.every((id) => existingChunkById.has(id) && existingVectorById.has(id));\n\n\t\t\tif (canReuse && prev) {\n\t\t\t\treusedFiles += 1;\n\t\t\t\tfor (const chunkId of prev.chunks) {\n\t\t\t\t\tconst chunk = existingChunkById.get(chunkId);\n\t\t\t\t\tconst vector = existingVectorById.get(chunkId);\n\t\t\t\t\tif (!chunk || !vector) continue;\n\t\t\t\t\tnextChunks.push(chunk);\n\t\t\t\t\tnextVectors.push(vector);\n\t\t\t\t}\n\t\t\t\tnextFileMap[file.relPath] = {\n\t\t\t\t\tpath: file.relPath,\n\t\t\t\t\tsize: file.size,\n\t\t\t\t\tmtimeMs: file.mtimeMs,\n\t\t\t\t\thash: file.hash,\n\t\t\t\t\tchunks: [...prev.chunks],\n\t\t\t\t};\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (prev) changedFiles += 1;\n\t\t\telse newFiles += 1;\n\n\t\t\tconst drafts = chunkTextForSemantic(file.text, config.index);\n\t\t\tconst chunkRecords = drafts.map((draft, index) => {\n\t\t\t\tconst id = chunkId(file.relPath, draft, index);\n\t\t\t\treturn {\n\t\t\t\t\tid,\n\t\t\t\t\tpath: file.relPath,\n\t\t\t\t\tlineStart: draft.lineStart,\n\t\t\t\t\tlineEnd: draft.lineEnd,\n\t\t\t\t\tpreview: draft.preview,\n\t\t\t\t\thash: draft.hash,\n\t\t\t\t\ttext: draft.text,\n\t\t\t\t};\n\t\t\t});\n\t\t\tconst chunkIds = chunkRecords.map((chunk) => chunk.id);\n\t\t\tnextFileMap[file.relPath] = {\n\t\t\t\tpath: file.relPath,\n\t\t\t\tsize: file.size,\n\t\t\t\tmtimeMs: file.mtimeMs,\n\t\t\t\thash: file.hash,\n\t\t\t\tchunks: chunkIds,\n\t\t\t};\n\n\t\t\tif (chunkRecords.length === 0) continue;\n\t\t\tconst embeddings = await provider.embed(chunkRecords.map((chunk) => chunk.text));\n\t\t\tif (embeddings.length !== chunkRecords.length) {\n\t\t\t\tthrow new Error(`Embedding provider returned ${embeddings.length} vectors for ${chunkRecords.length} chunks.`);\n\t\t\t}\n\n\t\t\tfor (let index = 0; index < chunkRecords.length; index++) {\n\t\t\t\tconst chunk = chunkRecords[index]!;\n\t\t\t\tconst vector = embeddings[index]!;\n\t\t\t\tif (!Array.isArray(vector) || vector.length === 0) {\n\t\t\t\t\tthrow new Error(\"Embedding provider returned an empty vector.\");\n\t\t\t\t}\n\t\t\t\tif (dimension === undefined || dimension <= 0) {\n\t\t\t\t\tdimension = vector.length;\n\t\t\t\t} else if (dimension !== vector.length) {\n\t\t\t\t\tthrow new SemanticRebuildRequiredError(\n\t\t\t\t\t\t`Embedding dimension mismatch (${vector.length} != ${dimension}). Run /semantic rebuild.`,\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\tnextChunks.push({\n\t\t\t\t\tid: chunk.id,\n\t\t\t\t\tpath: chunk.path,\n\t\t\t\t\tlineStart: chunk.lineStart,\n\t\t\t\t\tlineEnd: chunk.lineEnd,\n\t\t\t\t\tpreview: chunk.preview,\n\t\t\t\t\thash: chunk.hash,\n\t\t\t\t});\n\t\t\t\tnextVectors.push({\n\t\t\t\t\tid: chunk.id,\n\t\t\t\t\tvector,\n\t\t\t\t\tnorm: vectorNorm(vector),\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\tconst builtAt = new Date().toISOString();\n\t\tconst meta: SemanticIndexMeta = {\n\t\t\tversion: 1,\n\t\t\tcwd: this.cwd,\n\t\t\tprojectHash: getSemanticProjectHash(this.cwd),\n\t\t\tproviderFingerprint,\n\t\t\tproviderType: config.provider.type,\n\t\t\tmodel: config.provider.model,\n\t\t\tdimension: dimension ?? 0,\n\t\t\tbuiltAt,\n\t\t\tchunkConfigFingerprint: chunkFingerprint,\n\t\t\tindexFilterFingerprint: filterFingerprint,\n\t\t\tfileMap: nextFileMap,\n\t\t};\n\t\twriteSemanticIndex(indexDir, meta, nextChunks, nextVectors);\n\n\t\treturn {\n\t\t\taction: forceRebuild ? \"rebuild\" : \"index\",\n\t\t\tindexPath: indexDir,\n\t\t\tdurationMs: Date.now() - startedAt,\n\t\t\tprocessedFiles: files.length,\n\t\t\tnewFiles,\n\t\t\tchangedFiles,\n\t\t\tremovedFiles,\n\t\t\treusedFiles,\n\t\t\tchunks: nextChunks.length,\n\t\t\tdimension: meta.dimension,\n\t\t\tbuiltAt,\n\t\t};\n\t}\n}\n"]}