@orquentra/codebuddy 2.7.0 → 2.9.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 (52) hide show
  1. package/README.md +10 -0
  2. package/dist/adapters-S4HHTWJW.js +24 -0
  3. package/dist/{chunk-EEUFU7KV.js → chunk-2WH2Q4TA.js} +180 -22
  4. package/dist/chunk-2WH2Q4TA.js.map +1 -0
  5. package/dist/{chunk-BQM7FJ7D.js → chunk-6NZEZJYD.js} +5 -3
  6. package/dist/{chunk-BQM7FJ7D.js.map → chunk-6NZEZJYD.js.map} +1 -1
  7. package/dist/{chunk-AQHPEJR6.js → chunk-ENKDFLOO.js} +2 -2
  8. package/dist/{chunk-YJIA2MFL.js → chunk-F4BJ3DXW.js} +15 -13
  9. package/dist/{chunk-YJIA2MFL.js.map → chunk-F4BJ3DXW.js.map} +1 -1
  10. package/dist/{chunk-MSUAVR3R.js → chunk-GXOML4UZ.js} +2 -2
  11. package/dist/chunk-ITQO632W.js +673 -0
  12. package/dist/chunk-ITQO632W.js.map +1 -0
  13. package/dist/chunk-J4T6HHI4.js +1444 -0
  14. package/dist/chunk-J4T6HHI4.js.map +1 -0
  15. package/dist/{chunk-AK2UAE32.js → chunk-QN76UJP7.js} +2 -2
  16. package/dist/{chunk-JUAFCLRB.js → chunk-SRA4MDVG.js} +2 -2
  17. package/dist/{chunk-JUAFCLRB.js.map → chunk-SRA4MDVG.js.map} +1 -1
  18. package/dist/{chunk-5EDGAZQN.js → chunk-TLWGZVPC.js} +64 -725
  19. package/dist/chunk-TLWGZVPC.js.map +1 -0
  20. package/dist/{chunk-LCSBL5TT.js → chunk-UK6XTS2Y.js} +5 -3
  21. package/dist/{chunk-LCSBL5TT.js.map → chunk-UK6XTS2Y.js.map} +1 -1
  22. package/dist/chunk-W7GAXL6C.js +104 -0
  23. package/dist/chunk-W7GAXL6C.js.map +1 -0
  24. package/dist/{chunk-TUR6YKEE.js → chunk-YN7TEIUH.js} +1 -1
  25. package/dist/chunk-YN7TEIUH.js.map +1 -0
  26. package/dist/cli/index.js +4 -4
  27. package/dist/index.js +9 -8
  28. package/dist/install-BXM56QCD.js +19 -0
  29. package/dist/{lean-command-CWJAVQ5G.js → lean-command-7DFW32MA.js} +4 -3
  30. package/dist/{main-AHNGHC4L.js → main-YJKSYFPT.js} +1422 -1772
  31. package/dist/main-YJKSYFPT.js.map +1 -0
  32. package/dist/{operations-7BTAAUHF.js → operations-OG4ISWIM.js} +3 -3
  33. package/dist/{pretool-command-3SXQSMAO.js → pretool-command-PRFOIHMW.js} +3 -3
  34. package/dist/{runtime-E7JQZ2BZ.js → runtime-GCSEIAVD.js} +7 -6
  35. package/dist/{summaries-XV3JGGCC.js → summaries-ML53R7EL.js} +4 -3
  36. package/dist/summaries-ML53R7EL.js.map +1 -0
  37. package/dist/{zvec-KP4KNB7Y.js → zvec-XDZNZ2OL.js} +4 -3
  38. package/dist/zvec-XDZNZ2OL.js.map +1 -0
  39. package/package.json +1 -1
  40. package/dist/chunk-5EDGAZQN.js.map +0 -1
  41. package/dist/chunk-EEUFU7KV.js.map +0 -1
  42. package/dist/chunk-TUR6YKEE.js.map +0 -1
  43. package/dist/main-AHNGHC4L.js.map +0 -1
  44. /package/dist/{lean-command-CWJAVQ5G.js.map → adapters-S4HHTWJW.js.map} +0 -0
  45. /package/dist/{chunk-AQHPEJR6.js.map → chunk-ENKDFLOO.js.map} +0 -0
  46. /package/dist/{chunk-MSUAVR3R.js.map → chunk-GXOML4UZ.js.map} +0 -0
  47. /package/dist/{chunk-AK2UAE32.js.map → chunk-QN76UJP7.js.map} +0 -0
  48. /package/dist/{operations-7BTAAUHF.js.map → install-BXM56QCD.js.map} +0 -0
  49. /package/dist/{pretool-command-3SXQSMAO.js.map → lean-command-7DFW32MA.js.map} +0 -0
  50. /package/dist/{runtime-E7JQZ2BZ.js.map → operations-OG4ISWIM.js.map} +0 -0
  51. /package/dist/{summaries-XV3JGGCC.js.map → pretool-command-PRFOIHMW.js.map} +0 -0
  52. /package/dist/{zvec-KP4KNB7Y.js.map → runtime-GCSEIAVD.js.map} +0 -0
@@ -1,8 +1,7 @@
1
1
  import {
2
- extractPythonImports,
3
- extractSymbolTable,
4
- supportsSymbols
5
- } from "./chunk-Y7D7PUBE.js";
2
+ loadArchitectureMap,
3
+ loadFreshIndex
4
+ } from "./chunk-ITQO632W.js";
6
5
  import {
7
6
  isCredentialPath
8
7
  } from "./chunk-AL6VBTNA.js";
@@ -13,681 +12,26 @@ import {
13
12
  readConfigFile
14
13
  } from "./chunk-KNR2P2UY.js";
15
14
  import {
16
- assertNoSymlinkBetween,
17
15
  writeAtomic
18
16
  } from "./chunk-CG5B3LYG.js";
19
17
 
20
- // src/map/indexer.ts
21
- import { readdir, readFile, stat } from "fs/promises";
22
- import { dirname, extname, join, relative, resolve } from "path";
23
- var SUPPORTED_EXTENSIONS = /* @__PURE__ */ new Set([".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs", ".py"]);
24
- var IGNORED_DIRECTORIES = /* @__PURE__ */ new Set([
25
- ".git",
26
- "node_modules",
27
- "dist",
28
- "build",
29
- "coverage",
30
- ".codebuddy",
31
- // Python virtualenvs and caches would otherwise map site-packages.
32
- ".venv",
33
- "venv",
34
- ".tox",
35
- "__pycache__"
36
- ]);
37
- async function buildArchitectureMap(repositoryRoot = process.cwd()) {
38
- const root = resolve(repositoryRoot);
39
- const files = await listSourceFiles(root);
40
- const fileSet = new Set(files.map((file) => normalize(relative(root, file))));
41
- const modules = [];
42
- const edges = [];
43
- for (const absolutePath of files) {
44
- const source = await readFile(absolutePath, "utf8");
45
- const from = normalize(relative(root, absolutePath));
46
- const resolvedImports = moduleImports(root, from, source, fileSet);
47
- edges.push(...resolvedImports.map(({ to, kind }) => ({ from, to, kind })));
48
- modules.push({
49
- path: from,
50
- language: moduleLanguage(from),
51
- imports: [...new Set(resolvedImports.map(({ to }) => to))].sort()
52
- });
53
- }
54
- return {
55
- modules: modules.sort((left, right) => left.path.localeCompare(right.path)),
56
- edges: edges.sort(
57
- (left, right) => `${left.from}:${left.to}`.localeCompare(`${right.from}:${right.to}`)
58
- )
59
- };
60
- }
61
- async function updateArchitectureMap(repositoryRoot, sourcePaths, previous, changedPaths) {
62
- const root = resolve(repositoryRoot);
63
- const normalizedPaths = sourcePaths.map(normalize).sort();
64
- const fileSet = new Set(normalizedPaths);
65
- const changed = new Set(changedPaths.map(normalize));
66
- const retainedModules = (previous?.modules ?? []).filter(
67
- (module) => fileSet.has(module.path) && !changed.has(module.path)
68
- );
69
- const retainedEdges = (previous?.edges ?? []).filter(
70
- (edge) => fileSet.has(edge.from) && fileSet.has(edge.to) && !changed.has(edge.from)
71
- );
72
- const modules = [...retainedModules];
73
- const edges = [...retainedEdges];
74
- for (const path of normalizedPaths) {
75
- if (!changed.has(path)) continue;
76
- const source = await readFile(join(root, path), "utf8");
77
- const resolvedImports = moduleImports(root, path, source, fileSet);
78
- edges.push(...resolvedImports.map(({ to, kind }) => ({ from: path, to, kind })));
79
- modules.push({
80
- path,
81
- language: moduleLanguage(path),
82
- imports: [...new Set(resolvedImports.map(({ to }) => to))].sort()
83
- });
84
- }
85
- return {
86
- map: {
87
- modules: modules.sort((left, right) => left.path.localeCompare(right.path)),
88
- edges: edges.sort(
89
- (left, right) => `${left.from}:${left.to}`.localeCompare(`${right.from}:${right.to}`)
90
- )
91
- },
92
- stats: {
93
- readFiles: changed.size,
94
- reusedFiles: retainedModules.length,
95
- rebuilt: previous === null || changed.size === normalizedPaths.length
96
- }
97
- };
98
- }
99
- function queryMap(map, query) {
100
- const limit = query.limit ?? 50;
101
- return map.edges.filter((edge) => query.from ? edge.from === normalize(query.from) : true).filter((edge) => query.to ? edge.to === normalize(query.to) : true).slice(0, limit);
102
- }
103
- function neighbours(map, modulePath, direction = "both") {
104
- const target = normalize(modulePath);
105
- const edges = map.edges.filter((edge) => {
106
- if (direction === "in") return edge.to === target;
107
- if (direction === "out") return edge.from === target;
108
- return edge.from === target || edge.to === target;
109
- });
110
- const paths = /* @__PURE__ */ new Set([target]);
111
- for (const edge of edges) {
112
- paths.add(edge.from);
113
- paths.add(edge.to);
114
- }
115
- return {
116
- modules: map.modules.filter((module) => paths.has(module.path)),
117
- edges
118
- };
119
- }
120
- async function listSourceFiles(root) {
121
- const files = [];
122
- await walk(root, files);
123
- return files.sort();
124
- }
125
- async function walk(directory, files) {
126
- const entries = await readdir(directory, { withFileTypes: true });
127
- for (const entry of entries) {
128
- const absolute = join(directory, entry.name);
129
- if (entry.isDirectory()) {
130
- if (IGNORED_DIRECTORIES.has(entry.name)) continue;
131
- await walk(absolute, files);
132
- continue;
133
- }
134
- if (!entry.isFile()) continue;
135
- if (!SUPPORTED_EXTENSIONS.has(extname(entry.name))) continue;
136
- const info = await stat(absolute);
137
- if (info.size > 5e5) continue;
138
- files.push(absolute);
139
- }
140
- }
141
- function moduleLanguage(path) {
142
- const extension = extname(path);
143
- if (extension === ".py") return "py";
144
- return extension.includes("ts") ? "ts" : "js";
145
- }
146
- function moduleImports(root, from, source, fileSet) {
147
- if (extname(from) === ".py") {
148
- return pythonImports(from, source, fileSet).map((to) => ({ to, kind: "import" }));
149
- }
150
- return extractImports(source).flatMap((specifier) => {
151
- const to = resolveImport(root, from, specifier.value, fileSet);
152
- return to ? [{ to, kind: specifier.kind }] : [];
153
- });
154
- }
155
- var PYTHON_ROOTS = ["", "src/"];
156
- function pythonImports(from, source, fileSet) {
157
- const pick = (...candidates) => candidates.find((candidate) => fileSet.has(candidate)) ?? null;
158
- const moduleFile = (base) => pick(`${base}.py`, `${base}/__init__.py`);
159
- const packageDir = from.split("/").slice(0, -1);
160
- const targets = [];
161
- for (const statement of extractPythonImports(source)) {
162
- const parts = statement.module ? statement.module.split(".") : [];
163
- let bases;
164
- if (statement.level > 0) {
165
- const up = statement.level - 1;
166
- if (up > packageDir.length) continue;
167
- bases = [[...packageDir.slice(0, packageDir.length - up), ...parts].join("/")];
168
- } else {
169
- bases = PYTHON_ROOTS.map((prefix) => `${prefix}${parts.join("/")}`);
170
- }
171
- for (const base of bases) {
172
- const prefix = base ? `${base}/` : "";
173
- const module = parts.length > 0 ? moduleFile(base) : pick(`${prefix}__init__.py`);
174
- const submodules = statement.names.flatMap((name) => moduleFile(`${prefix}${name}`) ?? []);
175
- if (!module && submodules.length === 0) continue;
176
- targets.push(...submodules);
177
- if (module && submodules.length < Math.max(1, statement.names.length)) targets.push(module);
178
- break;
179
- }
180
- }
181
- return [...new Set(targets)].filter((target) => target !== from);
182
- }
183
- function extractImports(source) {
184
- const imports = [];
185
- const stripped = source.replace(/\/\*[\s\S]*?\*\//g, " ").replace(/(^|[^:])\/\/[^\n]*/g, "$1 ");
186
- const staticImport = /\bimport\s+(?:type\s+)?(?:[^'"()+]+?\s+from\s+)?["']([^"']+)["']/g;
187
- const exportFrom = /\bexport\s+[^'"()+]+?\s+from\s+["']([^"']+)["']/g;
188
- const dynamicImport = /\bimport\s*\(\s*["']([^"']+)["']\s*\)/g;
189
- for (const match of stripped.matchAll(staticImport)) {
190
- if (match[1]) imports.push({ value: match[1], kind: "import" });
191
- }
192
- for (const match of stripped.matchAll(exportFrom)) {
193
- if (match[1]) imports.push({ value: match[1], kind: "import" });
194
- }
195
- for (const match of stripped.matchAll(dynamicImport)) {
196
- if (match[1]) imports.push({ value: match[1], kind: "dynamic_import" });
197
- }
198
- return imports;
199
- }
200
- function resolveImport(root, from, specifier, fileSet) {
201
- if (!specifier.startsWith(".")) return null;
202
- const base = normalize(relative(root, resolve(root, dirname(from), specifier)));
203
- const stem = base.replace(/\.(js|jsx|mjs|cjs)$/, "");
204
- const bases = stem === base ? [base] : [base, stem];
205
- const candidates = bases.flatMap((b) => [
206
- b,
207
- `${b}.ts`,
208
- `${b}.tsx`,
209
- `${b}.js`,
210
- `${b}.jsx`,
211
- `${b}.mjs`,
212
- `${b}.cjs`,
213
- `${b}/index.ts`,
214
- `${b}/index.tsx`,
215
- `${b}/index.js`,
216
- `${b}/index.jsx`
217
- ]);
218
- return candidates.find((candidate) => fileSet.has(candidate)) ?? null;
219
- }
220
- function normalize(path) {
221
- return path.replace(/\\/g, "/").replace(/^\.\//, "");
222
- }
223
-
224
- // src/indexer/engine.ts
225
- import { createHash } from "crypto";
226
- import { readFile as readFile4, stat as stat2 } from "fs/promises";
227
- import { join as join5, resolve as resolve4 } from "path";
228
-
229
- // src/map/cache.ts
230
- import { mkdir as mkdir2, readFile as readFile3 } from "fs/promises";
231
- import { dirname as dirname3, extname as extname2, join as join3, resolve as resolve3 } from "path";
232
-
233
- // src/indexer/store.ts
234
- import { mkdir, readFile as readFile2 } from "fs/promises";
235
- import { dirname as dirname2, join as join2, resolve as resolve2 } from "path";
236
- import { z } from "zod";
237
-
238
- // src/indexer/types.ts
239
- var INDEX_MANIFEST_VERSION = 3;
240
-
241
- // src/indexer/store.ts
242
- var symbolSpanSchema = z.object({
243
- name: z.string(),
244
- kind: z.enum(["function", "method", "class", "interface", "type", "enum", "const", "heading"]),
245
- startLine: z.number().int().nonnegative(),
246
- endLine: z.number().int().nonnegative(),
247
- signature: z.string(),
248
- exported: z.boolean()
249
- });
250
- var entrySchema = z.object({
251
- path: z.string(),
252
- hash: z.string(),
253
- size: z.number().int().nonnegative(),
254
- mtimeMs: z.number().optional(),
255
- ctimeMs: z.number().optional(),
256
- language: z.string(),
257
- lines: z.number().int().nonnegative(),
258
- symbols: z.array(z.string()),
259
- symbolTable: z.array(symbolSpanSchema).optional(),
260
- summary: z.string(),
261
- indexedAt: z.string()
262
- });
263
- var manifestSchema = z.object({
264
- version: z.literal(INDEX_MANIFEST_VERSION),
265
- generatedAt: z.string(),
266
- entries: z.record(z.string(), entrySchema)
267
- });
268
- var IndexStore = class {
269
- repositoryRoot;
270
- cacheDirectory;
271
- manifestPath;
272
- constructor(repositoryRoot = process.cwd()) {
273
- this.repositoryRoot = resolve2(repositoryRoot);
274
- this.cacheDirectory = join2(this.repositoryRoot, ".codebuddy", "cache");
275
- this.manifestPath = join2(this.cacheDirectory, "index.json");
276
- }
277
- /** Read the manifest, or an empty one if absent/corrupt/version-mismatched. */
278
- async read() {
279
- try {
280
- const raw = await readFile2(this.manifestPath, "utf8");
281
- const parsed = manifestSchema.safeParse(JSON.parse(raw));
282
- if (!parsed.success) return emptyManifest();
283
- return parsed.data;
284
- } catch (error) {
285
- if (error.code === "ENOENT") return emptyManifest();
286
- return emptyManifest();
287
- }
288
- }
289
- async write(manifest) {
290
- await assertNoSymlinkBetween(this.repositoryRoot, dirname2(this.manifestPath));
291
- await mkdir(this.cacheDirectory, { recursive: true, mode: 448 });
292
- await writeAtomic(this.manifestPath, `${JSON.stringify(manifest, null, 2)}
293
- `);
294
- }
295
- };
296
- function emptyManifest() {
297
- return { version: INDEX_MANIFEST_VERSION, generatedAt: (/* @__PURE__ */ new Date(0)).toISOString(), entries: {} };
298
- }
299
-
300
- // src/map/cache.ts
301
- var CACHE_VERSION = 1;
302
- var SOURCE_EXTENSIONS = /* @__PURE__ */ new Set([".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs", ".py"]);
303
- async function loadArchitectureMap(repositoryRoot = process.cwd(), suppliedManifest) {
304
- const root = resolve3(repositoryRoot);
305
- const manifest = suppliedManifest ?? await new IndexStore(root).read();
306
- if (Object.keys(manifest.entries).length === 0) {
307
- const map = await buildArchitectureMap(root);
308
- return {
309
- map,
310
- stats: { readFiles: map.modules.length, reusedFiles: 0, rebuilt: true },
311
- source: "fallback"
312
- };
313
- }
314
- return refreshArchitectureCache(root, manifest);
315
- }
316
- async function refreshArchitectureCache(repositoryRoot, manifest) {
317
- const root = resolve3(repositoryRoot);
318
- const path = join3(root, ".codebuddy", "cache", "architecture.json");
319
- const currentHashes = sourceHashes(manifest);
320
- const currentPaths = Object.keys(currentHashes).sort();
321
- const cached = await readCache(path);
322
- const cachedPaths = cached ? Object.keys(cached.sourceHashes).sort() : [];
323
- const fileSetChanged = cachedPaths.join("\n") !== currentPaths.join("\n");
324
- const changedPaths = !cached || fileSetChanged ? currentPaths : currentPaths.filter(
325
- (sourcePath) => cached.sourceHashes[sourcePath] !== currentHashes[sourcePath]
326
- );
327
- if (cached && changedPaths.length === 0) {
328
- return {
329
- map: cached.map,
330
- stats: { readFiles: 0, reusedFiles: cached.map.modules.length, rebuilt: false },
331
- source: "cache"
332
- };
333
- }
334
- const updated = await updateArchitectureMap(
335
- root,
336
- currentPaths,
337
- fileSetChanged ? null : cached?.map ?? null,
338
- changedPaths
339
- );
340
- const next = {
341
- version: CACHE_VERSION,
342
- generatedAt: manifest.generatedAt,
343
- sourceHashes: currentHashes,
344
- map: updated.map
345
- };
346
- await assertNoSymlinkBetween(root, dirname3(path));
347
- await mkdir2(dirname3(path), { recursive: true, mode: 448 });
348
- await writeAtomic(path, `${JSON.stringify(next, null, 2)}
349
- `);
350
- return { ...updated, source: fileSetChanged || !cached ? "rebuild" : "incremental" };
351
- }
352
- async function readCache(path) {
353
- try {
354
- const parsed = JSON.parse(await readFile3(path, "utf8"));
355
- if (parsed.version !== CACHE_VERSION || !parsed.map || !parsed.sourceHashes) return null;
356
- if (!Array.isArray(parsed.map.modules) || !Array.isArray(parsed.map.edges)) return null;
357
- if (!parsed.map.modules.every(
358
- (module) => module && typeof module.path === "string" && typeof module.language === "string" && Array.isArray(module.imports)
359
- ) || !parsed.map.edges.every(
360
- (edge) => edge && typeof edge.from === "string" && typeof edge.to === "string"
361
- )) {
362
- return null;
363
- }
364
- return parsed;
365
- } catch {
366
- return null;
367
- }
368
- }
369
- function sourceHashes(manifest) {
370
- return Object.fromEntries(
371
- Object.values(manifest.entries).filter((entry) => SOURCE_EXTENSIONS.has(extname2(entry.path).toLowerCase())).map((entry) => [entry.path, entry.hash])
372
- );
373
- }
374
-
375
- // src/indexer/scan.ts
376
- import { spawn } from "child_process";
377
- import { readdir as readdir2 } from "fs/promises";
378
- import { extname as extname4, join as join4, relative as relative2, sep } from "path";
379
-
380
- // src/indexer/summary.ts
381
- import { extname as extname3 } from "path";
382
- var LANGUAGE_BY_EXTENSION = {
383
- ".ts": "ts",
384
- ".tsx": "tsx",
385
- ".js": "js",
386
- ".jsx": "jsx",
387
- ".mjs": "js",
388
- ".cjs": "js",
389
- ".json": "json",
390
- ".md": "md",
391
- ".mdx": "md",
392
- ".rst": "rst",
393
- ".yaml": "yaml",
394
- ".yml": "yaml",
395
- ".toml": "toml",
396
- ".css": "css",
397
- ".scss": "scss",
398
- ".html": "html",
399
- ".py": "py",
400
- ".go": "go",
401
- ".rs": "rust",
402
- ".java": "java",
403
- ".rb": "ruby",
404
- ".php": "php",
405
- ".sh": "shell",
406
- ".sql": "sql",
407
- ".txt": "text"
408
- };
409
- var SUPPORTED_EXTENSIONS2 = new Set(Object.keys(LANGUAGE_BY_EXTENSION));
410
- var CODE_LANGUAGES = /* @__PURE__ */ new Set(["ts", "tsx", "js", "jsx"]);
411
- var SYMBOL_LIMIT = 8;
412
- var SUMMARY_COMMENT_MAX = 80;
413
- function languageFor(path) {
414
- return LANGUAGE_BY_EXTENSION[extname3(path).toLowerCase()] ?? "text";
415
- }
416
- function summarizeSource(path, content) {
417
- const language = languageFor(path);
418
- const lines = countLines(content);
419
- const symbols = CODE_LANGUAGES.has(language) ? extractSymbols(content) : language === "py" ? pythonPublicNames(content) : [];
420
- const summary = composeSummary(language, lines, symbols, content);
421
- return { language, lines, symbols, summary };
422
- }
423
- function countLines(content) {
424
- if (content.length === 0) return 0;
425
- return content.replace(/\r/g, "").replace(/\n$/, "").split("\n").length;
426
- }
427
- function extractSymbols(content) {
428
- const names = [];
429
- const push = (name) => {
430
- const trimmed = name?.trim();
431
- if (trimmed && /^[A-Za-z_$][\w$]*$/.test(trimmed) && !names.includes(trimmed)) {
432
- names.push(trimmed);
433
- }
434
- };
435
- const declaration = /^export\s+(?:default\s+)?(?:async\s+)?(?:abstract\s+)?(?:const|let|var|function|class|interface|type|enum)\s+([A-Za-z_$][\w$]*)/gm;
436
- for (const match of content.matchAll(declaration)) push(match[1]);
437
- const namedExports = /^export\s*\{([^}]*)\}/gm;
438
- for (const match of content.matchAll(namedExports)) {
439
- for (const part of (match[1] ?? "").split(",")) {
440
- const alias = part.includes(" as ") ? part.split(" as ").pop() : part;
441
- push(alias);
442
- }
443
- }
444
- return names.slice(0, SYMBOL_LIMIT);
445
- }
446
- function pythonPublicNames(content) {
447
- return extractSymbolTable(content, "x.py").filter((symbol) => symbol.exported && symbol.kind !== "method").map((symbol) => symbol.name).slice(0, SYMBOL_LIMIT);
448
- }
449
- function composeSummary(language, lines, symbols, content) {
450
- const head = `${language} \u2022 ${lines} line${lines === 1 ? "" : "s"}`;
451
- if (symbols.length > 0) return `${head} \u2022 exports ${symbols.join(", ")}`;
452
- const comment = leadingComment(content);
453
- if (comment) return `${head} \u2022 ${comment}`;
454
- return head;
455
- }
456
- function leadingComment(content) {
457
- for (const raw of content.split(/\r?\n/)) {
458
- const line = raw.trim();
459
- if (line === "") continue;
460
- const stripped = line.replace(/^\/\/+/, "").replace(/^\/\*+/, "").replace(/\*+\/$/, "").replace(/^[#*]+/, "").trim();
461
- if (line.startsWith("//") || line.startsWith("/*") || line.startsWith("#") || line.startsWith("*")) {
462
- if (stripped) return truncate(stripped, SUMMARY_COMMENT_MAX);
463
- continue;
464
- }
465
- return null;
466
- }
467
- return null;
468
- }
469
- function truncate(value, max) {
470
- return value.length <= max ? value : `${value.slice(0, max - 1)}\u2026`;
471
- }
472
-
473
- // src/indexer/scan.ts
474
- var FALLBACK_IGNORED_DIRECTORIES = /* @__PURE__ */ new Set([
475
- ".git",
476
- "node_modules",
477
- "dist",
478
- "build",
479
- "coverage",
480
- ".codebuddy",
481
- "graphify-out",
482
- ".next",
483
- ".turbo",
484
- "out",
485
- ".venv",
486
- "venv",
487
- "__pycache__"
488
- ]);
489
- async function listIndexableFiles(repositoryRoot) {
490
- const tracked = await gitListFiles(repositoryRoot);
491
- const paths = tracked ?? await walkFiles(repositoryRoot);
492
- return paths.map(normalize2).filter((path) => !path.startsWith(".codebuddy/") && !path.startsWith("graphify-out/")).filter((path) => SUPPORTED_EXTENSIONS2.has(extname4(path).toLowerCase())).sort();
493
- }
494
- async function gitListFiles(repositoryRoot) {
495
- const result = await runGit(repositoryRoot, [
496
- "ls-files",
497
- "-z",
498
- "--cached",
499
- "--others",
500
- "--exclude-standard"
501
- ]);
502
- if (result.code !== 0) return null;
503
- return result.stdout.split("\0").filter(Boolean);
504
- }
505
- async function walkFiles(root) {
506
- const files = [];
507
- const walk2 = async (directory) => {
508
- const entries = await readdir2(directory, { withFileTypes: true });
509
- for (const entry of entries) {
510
- const absolute = join4(directory, entry.name);
511
- if (entry.isDirectory()) {
512
- if (FALLBACK_IGNORED_DIRECTORIES.has(entry.name)) continue;
513
- await walk2(absolute);
514
- continue;
515
- }
516
- if (entry.isFile()) files.push(relative2(root, absolute));
517
- }
518
- };
519
- await walk2(root);
520
- return files;
521
- }
522
- function runGit(cwd, args) {
523
- return new Promise((resolveResult) => {
524
- const child = spawn("git", args, { cwd, stdio: ["ignore", "pipe", "pipe"] });
525
- let stdout = "";
526
- let stderr = "";
527
- child.stdout.setEncoding("utf8");
528
- child.stdout.on("data", (chunk2) => {
529
- stdout += String(chunk2);
530
- });
531
- child.stderr.on("data", (chunk2) => {
532
- stderr += String(chunk2);
533
- });
534
- child.on("error", () => resolveResult({ code: -1, stdout: "", stderr: "git unavailable" }));
535
- child.on("close", (code) => resolveResult({ code: code ?? 0, stdout, stderr }));
536
- });
537
- }
538
- function normalize2(path) {
539
- return (sep === "\\" ? path.replace(/\\/g, "/") : path).replace(/^\.\//, "");
540
- }
541
-
542
- // src/indexer/engine.ts
543
- var MAX_FILE_BYTES = 512e3;
544
- var RACY_WINDOW_MS = 3e3;
545
- async function indexRepository(options = {}) {
546
- return (await refreshIndex(options)).result;
547
- }
548
- async function loadFreshIndex(repositoryRoot) {
549
- try {
550
- const { result, manifest } = await refreshIndex({ repositoryRoot });
551
- const delta = result.added + result.changed + result.removed;
552
- const failures = result.errors.length > 0 ? `; ${result.errors.length} file(s) could not be validated and were omitted` : "";
553
- return {
554
- manifest,
555
- explain: delta === 0 ? `index: ${result.totalIndexed} indexed file(s) match current source${failures}` : `index: refreshed against current source (${result.changed} changed, ${result.added} added, ${result.removed} removed; ${result.totalIndexed} indexed)${failures}`
556
- };
557
- } catch (error) {
558
- return {
559
- manifest: emptyManifest(),
560
- explain: `index: freshness check failed (${error.message}); indexed evidence omitted`
561
- };
562
- }
563
- }
564
- var passes = /* @__PURE__ */ new Map();
565
- function refreshIndex(options) {
566
- const key = resolve4(options.repositoryRoot ?? process.cwd());
567
- const next = (passes.get(key) ?? Promise.resolve()).catch(() => void 0).then(() => runIndexPass(options));
568
- passes.set(key, next);
569
- void next.finally(() => {
570
- if (passes.get(key) === next) passes.delete(key);
571
- }).catch(() => void 0);
572
- return next;
573
- }
574
- async function runIndexPass(options) {
575
- const start = Date.now();
576
- const now = options.now ?? (() => /* @__PURE__ */ new Date());
577
- const repositoryRoot = resolve4(options.repositoryRoot ?? process.cwd());
578
- const store = new IndexStore(repositoryRoot);
579
- const [files, previous] = await Promise.all([listIndexableFiles(repositoryRoot), store.read()]);
580
- const entries = {};
581
- const errors = [];
582
- let added = 0;
583
- let changed = 0;
584
- let unchanged = 0;
585
- let skipped = 0;
586
- let dirty = previous.generatedAt === emptyManifest().generatedAt;
587
- for (const path of files) {
588
- try {
589
- const info = await stat2(join5(repositoryRoot, path));
590
- if (!info.isFile()) continue;
591
- if (info.size > MAX_FILE_BYTES) {
592
- skipped++;
593
- continue;
594
- }
595
- const existing = previous.entries[path];
596
- if (!options.full && existing && statUnchanged(existing, info)) {
597
- entries[path] = existing;
598
- unchanged++;
599
- continue;
600
- }
601
- const content = await readFile4(join5(repositoryRoot, path), "utf8");
602
- const hash = hashContent(content);
603
- const metadata = trustedMetadata(info);
604
- dirty = true;
605
- if (!options.full && existing && existing.hash === hash) {
606
- const { mtimeMs: _mtime, ctimeMs: _ctime, ...rest } = existing;
607
- entries[path] = { ...rest, size: info.size, ...metadata };
608
- unchanged++;
609
- continue;
610
- }
611
- const { language, lines, symbols, summary } = summarizeSource(path, content);
612
- const symbolTable = supportsSymbols(path) ? extractSymbolTable(content, path) : [];
613
- entries[path] = {
614
- path,
615
- hash,
616
- size: info.size,
617
- ...metadata,
618
- language,
619
- lines,
620
- symbols,
621
- ...symbolTable.length > 0 ? { symbolTable } : {},
622
- summary,
623
- indexedAt: now().toISOString()
624
- };
625
- if (existing) changed++;
626
- else added++;
627
- } catch (error) {
628
- errors.push({ path, error: error.message });
629
- skipped++;
630
- }
631
- }
632
- const removed = Object.keys(previous.entries).filter((path) => !(path in entries)).length;
633
- const manifest = {
634
- version: INDEX_MANIFEST_VERSION,
635
- generatedAt: now().toISOString(),
636
- entries: sortEntries(entries)
637
- };
638
- if (dirty || removed > 0) await store.write(manifest);
639
- const architecture = await refreshArchitectureCache(repositoryRoot, manifest);
640
- const result = {
641
- scanned: files.length,
642
- added,
643
- changed,
644
- unchanged,
645
- removed,
646
- skipped,
647
- errors,
648
- durationMs: Date.now() - start,
649
- totalIndexed: Object.keys(entries).length,
650
- architecture: {
651
- source: architecture.source,
652
- readFiles: architecture.stats.readFiles,
653
- reusedFiles: architecture.stats.reusedFiles
654
- }
655
- };
656
- return { result, manifest };
657
- }
658
- function statUnchanged(entry, info) {
659
- return entry.mtimeMs !== void 0 && entry.size === info.size && entry.mtimeMs === info.mtimeMs && entry.ctimeMs === info.ctimeMs;
660
- }
661
- function trustedMetadata(info) {
662
- if (Date.now() - Math.max(info.mtimeMs, info.ctimeMs) < RACY_WINDOW_MS) return {};
663
- return { mtimeMs: info.mtimeMs, ctimeMs: info.ctimeMs };
664
- }
665
- function hashContent(content) {
666
- return createHash("sha256").update(content, "utf8").digest("hex");
667
- }
668
- function sortEntries(entries) {
669
- return Object.fromEntries(
670
- Object.keys(entries).sort().map((key) => [key, entries[key]])
671
- );
672
- }
673
-
674
18
  // src/integrations/graphify.ts
675
19
  import { execFile } from "child_process";
676
- import { mkdir as mkdir3, mkdtemp, readFile as readFile6, rm, stat as stat3, utimes } from "fs/promises";
20
+ import { mkdir, mkdtemp, readFile as readFile2, rm, stat, utimes } from "fs/promises";
677
21
  import { tmpdir } from "os";
678
- import { dirname as dirname4, join as join6, relative as relative3, resolve as resolve5, sep as sep2 } from "path";
22
+ import { dirname, join, relative, resolve, sep } from "path";
679
23
  import { promisify } from "util";
680
24
 
681
25
  // src/map/graph-freshness.ts
682
- import { createHash as createHash2 } from "crypto";
683
- import { readFile as readFile5 } from "fs/promises";
684
- var digest = (value) => createHash2("sha256").update(value).digest("hex");
26
+ import { createHash } from "crypto";
27
+ import { readFile } from "fs/promises";
28
+ var digest = (value) => createHash("sha256").update(value).digest("hex");
685
29
  async function writeGraphSourceSnapshot(path, manifest) {
686
30
  await writeAtomic(
687
31
  `${path}.sources.json`,
688
32
  JSON.stringify({
689
33
  version: 1,
690
- graphHash: digest(await readFile5(path, "utf8")),
34
+ graphHash: digest(await readFile(path, "utf8")),
691
35
  sources: Object.fromEntries(
692
36
  Object.values(manifest.entries).map((entry) => [entry.path, entry.hash])
693
37
  )
@@ -697,13 +41,13 @@ async function writeGraphSourceSnapshot(path, manifest) {
697
41
  async function readGraphSourceSnapshot(path) {
698
42
  let raw;
699
43
  try {
700
- raw = await readFile5(`${path}.sources.json`, "utf8");
44
+ raw = await readFile(`${path}.sources.json`, "utf8");
701
45
  } catch (error) {
702
46
  return error.code === "ENOENT" ? null : {};
703
47
  }
704
48
  try {
705
49
  const snapshot = JSON.parse(raw);
706
- if (snapshot.version !== 1 || snapshot.graphHash !== digest(await readFile5(path, "utf8")) || !snapshot.sources || typeof snapshot.sources !== "object" || Array.isArray(snapshot.sources))
50
+ if (snapshot.version !== 1 || snapshot.graphHash !== digest(await readFile(path, "utf8")) || !snapshot.sources || typeof snapshot.sources !== "object" || Array.isArray(snapshot.sources))
707
51
  return {};
708
52
  return Object.fromEntries(
709
53
  Object.entries(snapshot.sources).filter(
@@ -790,17 +134,17 @@ async function graphifyGraphExists(repositoryRoot, graphPath = DEFAULT_GRAPH_PAT
790
134
  }
791
135
  async function generateGraphifyGraph(options) {
792
136
  const run = options.run ?? runCommand;
793
- const repositoryRoot = resolve5(options.repositoryRoot);
137
+ const repositoryRoot = resolve(options.repositoryRoot);
794
138
  const graphPath = options.graphPath ?? DEFAULT_GRAPH_PATH;
795
139
  const destination = resolveGraphPath(repositoryRoot, graphPath);
796
- await mkdir3(dirname4(destination), { recursive: true });
797
- await ignoreGeneratedGraphDirectory(dirname4(destination));
140
+ await mkdir(dirname(destination), { recursive: true });
141
+ await ignoreGeneratedGraphDirectory(dirname(destination));
798
142
  const { manifest: sourceSnapshot } = await loadFreshIndex(repositoryRoot);
799
143
  const current = await readGraphFileIfPresent(destination);
800
144
  const isDefaultPath = graphPath === DEFAULT_GRAPH_PATH;
801
145
  if (current && isDefaultPath) {
802
- const backup = await readFile6(destination, "utf8");
803
- const backupStat = await stat3(destination);
146
+ const backup = await readFile2(destination, "utf8");
147
+ const backupStat = await stat(destination);
804
148
  try {
805
149
  await run("graphify", ["update", repositoryRoot, "--force", "--no-cluster"], repositoryRoot);
806
150
  const updated = await readGraphFile(destination);
@@ -814,16 +158,16 @@ async function generateGraphifyGraph(options) {
814
158
  );
815
159
  }
816
160
  }
817
- const stagingRoot = await mkdtemp(join6(tmpdir(), "codebuddy-graphify-"));
161
+ const stagingRoot = await mkdtemp(join(tmpdir(), "codebuddy-graphify-"));
818
162
  try {
819
163
  await run(
820
164
  "graphify",
821
165
  ["extract", repositoryRoot, "--out", stagingRoot, "--code-only", "--no-cluster"],
822
166
  repositoryRoot
823
167
  );
824
- const stagedPath = join6(stagingRoot, DEFAULT_GRAPH_PATH);
168
+ const stagedPath = join(stagingRoot, DEFAULT_GRAPH_PATH);
825
169
  const staged = await readGraphFile(stagedPath);
826
- await writeAtomic(destination, await readFile6(stagedPath, "utf8"));
170
+ await writeAtomic(destination, await readFile2(stagedPath, "utf8"));
827
171
  await writeGraphSourceSnapshot(destination, sourceSnapshot);
828
172
  return { graphPath, generated: true, ...staged };
829
173
  } finally {
@@ -831,17 +175,17 @@ async function generateGraphifyGraph(options) {
831
175
  }
832
176
  }
833
177
  async function ignoreGeneratedGraphDirectory(directory) {
834
- const path = join6(directory, ".gitignore");
178
+ const path = join(directory, ".gitignore");
835
179
  try {
836
- await stat3(path);
180
+ await stat(path);
837
181
  } catch {
838
182
  await writeAtomic(path, "# CodeBuddy-generated Graphify output (derived, rebuildable)\n*\n");
839
183
  }
840
184
  }
841
185
  function resolveGraphPath(repositoryRoot, graphPath) {
842
- const absolute = resolve5(repositoryRoot, graphPath);
843
- const relativePath = relative3(repositoryRoot, absolute);
844
- if (relativePath === "" || relativePath === ".." || relativePath.startsWith(`..${sep2}`)) {
186
+ const absolute = resolve(repositoryRoot, graphPath);
187
+ const relativePath = relative(repositoryRoot, absolute);
188
+ if (relativePath === "" || relativePath === ".." || relativePath.startsWith(`..${sep}`)) {
845
189
  throw new Error(`Graph path must be inside the project root: ${graphPath}`);
846
190
  }
847
191
  return absolute;
@@ -854,10 +198,10 @@ async function readGraphFileIfPresent(path) {
854
198
  }
855
199
  }
856
200
  async function readGraphFile(path) {
857
- const info = await stat3(path);
201
+ const info = await stat(path);
858
202
  if (!info.isFile() || info.size === 0)
859
203
  throw new Error(`Graphify graph is missing or empty: ${path}`);
860
- const raw = JSON.parse(await readFile6(path, "utf8"));
204
+ const raw = JSON.parse(await readFile2(path, "utf8"));
861
205
  const nodes = arrayLength(raw.nodes ?? raw.entities);
862
206
  const edges = arrayLength(raw.edges ?? raw.links ?? raw.relationships);
863
207
  if (nodes === 0) throw new Error(`Graphify graph contains no nodes: ${path}`);
@@ -868,16 +212,16 @@ function arrayLength(value) {
868
212
  }
869
213
 
870
214
  // src/context/file-vectors.ts
871
- import { mkdir as mkdir5, readFile as readFile10 } from "fs/promises";
872
- import { dirname as dirname6, join as join9 } from "path";
215
+ import { mkdir as mkdir3, readFile as readFile6 } from "fs/promises";
216
+ import { dirname as dirname3, join as join4 } from "path";
873
217
 
874
218
  // src/context/discovery.ts
875
- import { readFile as readFile9, realpath, stat as stat4 } from "fs/promises";
876
- import { isAbsolute as isAbsolute3, join as join8, relative as relative6 } from "path";
219
+ import { readFile as readFile5, realpath, stat as stat2 } from "fs/promises";
220
+ import { isAbsolute as isAbsolute3, join as join3, relative as relative4 } from "path";
877
221
 
878
222
  // src/map/graphify.ts
879
- import { readFile as readFile7 } from "fs/promises";
880
- import { isAbsolute, relative as relative4, resolve as resolve6 } from "path";
223
+ import { readFile as readFile3 } from "fs/promises";
224
+ import { isAbsolute, relative as relative2, resolve as resolve2 } from "path";
881
225
  var NON_DEPENDENCY_RELATIONS = /* @__PURE__ */ new Set([
882
226
  "contains",
883
227
  "part_of",
@@ -911,7 +255,7 @@ var DIRECT_DEPENDENCY_RELATIONS = /* @__PURE__ */ new Set([
911
255
  ]);
912
256
  var MAX_EDGE_SYMBOLS = 8;
913
257
  async function loadGraphifyMap(graphPath, repositoryRoot = process.cwd()) {
914
- const raw = JSON.parse(await readFile7(graphPath, "utf8"));
258
+ const raw = JSON.parse(await readFile3(graphPath, "utf8"));
915
259
  const nodes = arrayRecord(raw.nodes ?? raw.entities);
916
260
  const edges = arrayRecord(raw.edges ?? raw.links ?? raw.relationships);
917
261
  const nodePaths = /* @__PURE__ */ new Map();
@@ -924,7 +268,7 @@ async function loadGraphifyMap(graphPath, repositoryRoot = process.cwd()) {
924
268
  nodePaths.set(id, path);
925
269
  const label = stringValue(node.label ?? node.name);
926
270
  if (label && label !== path && !path.endsWith(`/${label}`)) nodeLabels.set(id, label);
927
- modules.push({ path, language: languageFor2(path), imports: [] });
271
+ modules.push({ path, language: languageFor(path), imports: [] });
928
272
  }
929
273
  const modulePaths = new Set(modules.map((module) => module.path));
930
274
  const importedEdges = [];
@@ -1004,21 +348,21 @@ function graphifyPath(node, repositoryRoot) {
1004
348
  return candidate ? normalizeGraphPath(candidate, repositoryRoot) : null;
1005
349
  }
1006
350
  function normalizeGraphPath(path, repositoryRoot) {
1007
- const absolute = isAbsolute(path) ? resolve6(path) : resolve6(repositoryRoot, path);
1008
- const relativePath = relative4(resolve6(repositoryRoot), absolute).replace(/\\/g, "/");
351
+ const absolute = isAbsolute(path) ? resolve2(path) : resolve2(repositoryRoot, path);
352
+ const relativePath = relative2(resolve2(repositoryRoot), absolute).replace(/\\/g, "/");
1009
353
  if (relativePath === "" || relativePath === ".." || relativePath.startsWith("../")) return null;
1010
354
  return relativePath.replace(/^\.\//, "");
1011
355
  }
1012
356
  function stringValue(value) {
1013
357
  return typeof value === "string" && value.length > 0 ? value : null;
1014
358
  }
1015
- function languageFor2(path) {
359
+ function languageFor(path) {
1016
360
  if (/\.py$/.test(path)) return "py";
1017
361
  return /\.tsx?$/.test(path) ? "ts" : "js";
1018
362
  }
1019
363
 
1020
364
  // src/context/anchors.ts
1021
- import { isAbsolute as isAbsolute2, relative as relative5, resolve as resolve7, sep as sep3 } from "path";
365
+ import { isAbsolute as isAbsolute2, relative as relative3, resolve as resolve3, sep as sep2 } from "path";
1022
366
  var MAX_ANCHORS = 3;
1023
367
  var MAX_ERROR_SEARCH_FILES = 2e3;
1024
368
  var JS_FRAME = /\bat\s+(?:[^\s()]+\s+\()?([^\s()]+?):(\d+):\d+\)?/g;
@@ -1026,7 +370,7 @@ var PY_FRAME = /\bFile\s+"([^"]+)",\s+line\s+(\d+)/g;
1026
370
  var PATH_TOKEN = /(?:^|[\s(`'"[])((?:\.{0,2}\/)?[\w@.-]+(?:\/[\w@.-]+)*\.[A-Za-z0-9]+)(?::(\d+))?/g;
1027
371
  var QUOTED = /"([^"\n]{8,200})"|'([^'\n]{8,200})'|`([^`\n]{8,200})`/g;
1028
372
  async function extractTaskAnchors(repositoryRoot, task, paths) {
1029
- const root = resolve7(repositoryRoot);
373
+ const root = resolve3(repositoryRoot);
1030
374
  const found = [];
1031
375
  const add = (raw, line, kind, at) => {
1032
376
  const path = toIndexedPath(root, raw, paths);
@@ -1054,9 +398,9 @@ async function extractTaskAnchors(repositoryRoot, task, paths) {
1054
398
  return anchors.slice(0, MAX_ANCHORS);
1055
399
  }
1056
400
  function toIndexedPath(root, raw, paths) {
1057
- const absolute = isAbsolute2(raw) ? raw : resolve7(root, raw);
1058
- const rel = relative5(root, absolute);
1059
- if (rel === "" || rel.startsWith(`..${sep3}`) || rel === ".." || isAbsolute2(rel)) return null;
401
+ const absolute = isAbsolute2(raw) ? raw : resolve3(root, raw);
402
+ const rel = relative3(root, absolute);
403
+ if (rel === "" || rel.startsWith(`..${sep2}`) || rel === ".." || isAbsolute2(rel)) return null;
1060
404
  const normalized = rel.replace(/\\/g, "/");
1061
405
  return paths.has(normalized) ? normalized : null;
1062
406
  }
@@ -1082,8 +426,8 @@ async function errorAnchors(root, task, paths) {
1082
426
  }
1083
427
 
1084
428
  // src/context/content-index.ts
1085
- import { mkdir as mkdir4, readFile as readFile8 } from "fs/promises";
1086
- import { dirname as dirname5, join as join7 } from "path";
429
+ import { mkdir as mkdir2, readFile as readFile4 } from "fs/promises";
430
+ import { dirname as dirname2, join as join2 } from "path";
1087
431
  var PASSAGE_LINES = 40;
1088
432
  var K1 = 1.2;
1089
433
  var B = 0.75;
@@ -1176,11 +520,11 @@ function idfCoverage(text, terms, idf) {
1176
520
  return terms.reduce((sum, term) => sum + (words.has(term) ? idf.get(term) ?? 0 : 0), 0) / total;
1177
521
  }
1178
522
  function cachePath(repositoryRoot) {
1179
- return join7(repositoryRoot, ".codebuddy", "cache", "content-terms.json");
523
+ return join2(repositoryRoot, ".codebuddy", "cache", "content-terms.json");
1180
524
  }
1181
525
  async function loadCache(repositoryRoot) {
1182
526
  try {
1183
- const parsed = JSON.parse(await readFile8(cachePath(repositoryRoot), "utf8"));
527
+ const parsed = JSON.parse(await readFile4(cachePath(repositoryRoot), "utf8"));
1184
528
  if (parsed.version === 2 && parsed.files && typeof parsed.files === "object") return parsed;
1185
529
  } catch {
1186
530
  }
@@ -1189,7 +533,7 @@ async function loadCache(repositoryRoot) {
1189
533
  async function saveCache(repositoryRoot, cache) {
1190
534
  try {
1191
535
  const path = cachePath(repositoryRoot);
1192
- await mkdir4(dirname5(path), { recursive: true });
536
+ await mkdir2(dirname2(path), { recursive: true });
1193
537
  await writeAtomic(path, JSON.stringify(cache));
1194
538
  } catch {
1195
539
  }
@@ -1203,9 +547,9 @@ var MAX_EVIDENCE_BYTES = 512e3;
1203
547
  async function readBoundedSource(repositoryRoot, path) {
1204
548
  if (isCredentialPath(path)) return null;
1205
549
  try {
1206
- const absolute = join8(repositoryRoot, path);
1207
- if ((await stat4(absolute)).size > MAX_EVIDENCE_BYTES) return null;
1208
- const source = await readFile9(absolute, "utf8");
550
+ const absolute = join3(repositoryRoot, path);
551
+ if ((await stat2(absolute)).size > MAX_EVIDENCE_BYTES) return null;
552
+ const source = await readFile5(absolute, "utf8");
1209
553
  return source.includes("\0") ? null : source;
1210
554
  } catch {
1211
555
  return null;
@@ -1253,7 +597,7 @@ async function withLlmSummaries(repositoryRoot, manifest) {
1253
597
  const { resolveLlmConfig } = await import("./config-GEZFLXK6.js");
1254
598
  const config = await resolveLlmConfig(repositoryRoot);
1255
599
  if (!config.enabled || !config.features.summaries) return entries;
1256
- const { loadLlmSummaries } = await import("./summaries-XV3JGGCC.js");
600
+ const { loadLlmSummaries } = await import("./summaries-ML53R7EL.js");
1257
601
  const summaries = await loadLlmSummaries(repositoryRoot, manifest);
1258
602
  if (summaries.size === 0) return entries;
1259
603
  return entries.map((entry) => {
@@ -1320,7 +664,7 @@ async function rankTaskFiles(repositoryRoot, task, manifest, mapSource, options)
1320
664
  reason: "semantic retrieval off",
1321
665
  stale: 0,
1322
666
  changed: 0
1323
- } : await import("./zvec-KP4KNB7Y.js").then(
667
+ } : await import("./zvec-XDZNZ2OL.js").then(
1324
668
  ({ zvecCandidates }) => zvecCandidates(
1325
669
  repositoryRoot,
1326
670
  task,
@@ -1544,7 +888,7 @@ async function commandFiles(repositoryRoot, task, entries) {
1544
888
  var COMMAND_DIR = /(^|\/)(cli|cmd|commands?)\//;
1545
889
  async function packageBins(repositoryRoot) {
1546
890
  try {
1547
- const manifest = JSON.parse(await readFile9(join8(repositoryRoot, "package.json"), "utf8"));
891
+ const manifest = JSON.parse(await readFile5(join3(repositoryRoot, "package.json"), "utf8"));
1548
892
  if (typeof manifest.bin === "string" && typeof manifest.name === "string") {
1549
893
  return [manifest.name.slice(manifest.name.lastIndexOf("/") + 1)];
1550
894
  }
@@ -1739,24 +1083,24 @@ async function loadProjectArchitectureMap(repositoryRoot, manifestSource) {
1739
1083
  const builtIn = (await loadArchitectureMap(repositoryRoot, manifest)).map;
1740
1084
  if (config.graphify?.enabled && await graphifyGraphExists(repositoryRoot, config.graphify.graphPath)) {
1741
1085
  try {
1742
- const graphPath = join8(
1086
+ const graphPath = join3(
1743
1087
  repositoryRoot,
1744
1088
  config.graphify.graphPath ?? "graphify-out/graph.json"
1745
1089
  );
1746
- const [graph, graphFile, sourceHashes2] = await Promise.all([
1090
+ const [graph, graphFile, sourceHashes] = await Promise.all([
1747
1091
  loadGraphifyMap(graphPath, repositoryRoot),
1748
- stat4(graphPath),
1092
+ stat2(graphPath),
1749
1093
  readGraphSourceSnapshot(graphPath)
1750
1094
  ]);
1751
1095
  const livePaths = new Set(
1752
1096
  (await Promise.all(
1753
1097
  graph.modules.map(async (module) => {
1754
1098
  try {
1755
- const absolute = await realpath(join8(repositoryRoot, module.path));
1756
- const inside = relative6(await realpath(repositoryRoot), absolute);
1099
+ const absolute = await realpath(join3(repositoryRoot, module.path));
1100
+ const inside = relative4(await realpath(repositoryRoot), absolute);
1757
1101
  if (inside.startsWith("..") || isAbsolute3(inside)) return null;
1758
- const source = await stat4(absolute);
1759
- const fresh = sourceHashes2 === null ? source.mtimeMs <= graphFile.mtimeMs : sourceHashes2[module.path] !== void 0 && sourceHashes2[module.path] === manifest.entries[module.path]?.hash;
1102
+ const source = await stat2(absolute);
1103
+ const fresh = sourceHashes === null ? source.mtimeMs <= graphFile.mtimeMs : sourceHashes[module.path] !== void 0 && sourceHashes[module.path] === manifest.entries[module.path]?.hash;
1760
1104
  return source.isFile() && fresh ? module.path : null;
1761
1105
  } catch {
1762
1106
  return null;
@@ -1907,11 +1251,11 @@ function dot(left, right) {
1907
1251
  return sum;
1908
1252
  }
1909
1253
  function storePath(repositoryRoot) {
1910
- return join9(repositoryRoot, ".codebuddy", "cache", "file-vectors.json");
1254
+ return join4(repositoryRoot, ".codebuddy", "cache", "file-vectors.json");
1911
1255
  }
1912
1256
  async function loadStore(repositoryRoot) {
1913
1257
  try {
1914
- const parsed = JSON.parse(await readFile10(storePath(repositoryRoot), "utf8"));
1258
+ const parsed = JSON.parse(await readFile6(storePath(repositoryRoot), "utf8"));
1915
1259
  if (parsed.version === 1 && parsed.model === MODEL && parsed.files) return parsed;
1916
1260
  } catch {
1917
1261
  }
@@ -1919,16 +1263,11 @@ async function loadStore(repositoryRoot) {
1919
1263
  }
1920
1264
  async function saveStore(repositoryRoot, store) {
1921
1265
  const path = storePath(repositoryRoot);
1922
- await mkdir5(dirname6(path), { recursive: true });
1266
+ await mkdir3(dirname3(path), { recursive: true });
1923
1267
  await writeAtomic(path, JSON.stringify(store));
1924
1268
  }
1925
1269
 
1926
1270
  export {
1927
- buildArchitectureMap,
1928
- queryMap,
1929
- neighbours,
1930
- indexRepository,
1931
- loadFreshIndex,
1932
1271
  setupGraphify,
1933
1272
  generateGraphifyGraph,
1934
1273
  loadGraphifyMap,
@@ -1945,4 +1284,4 @@ export {
1945
1284
  namedSegments,
1946
1285
  loadProjectArchitectureMap
1947
1286
  };
1948
- //# sourceMappingURL=chunk-5EDGAZQN.js.map
1287
+ //# sourceMappingURL=chunk-TLWGZVPC.js.map