@mutmutco/cli 4.1.19 → 4.1.20

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.
@@ -1,1070 +0,0 @@
1
- "use strict";
2
- var __create = Object.create;
3
- var __defProp = Object.defineProperty;
4
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
- var __getOwnPropNames = Object.getOwnPropertyNames;
6
- var __getProtoOf = Object.getPrototypeOf;
7
- var __hasOwnProp = Object.prototype.hasOwnProperty;
8
- var __export = (target, all) => {
9
- for (var name in all)
10
- __defProp(target, name, { get: all[name], enumerable: true });
11
- };
12
- var __copyProps = (to, from, except, desc) => {
13
- if (from && typeof from === "object" || typeof from === "function") {
14
- for (let key of __getOwnPropNames(from))
15
- if (!__hasOwnProp.call(to, key) && key !== except)
16
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
- }
18
- return to;
19
- };
20
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
- // If the importer is in node compatibility mode or this is not an ESM
22
- // file that has been converted to a CommonJS file using a Babel-
23
- // compatible transform (i.e. "__esModule" has not been set), then set
24
- // "default" to the CommonJS "module.exports" for node compatibility.
25
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
- mod
27
- ));
28
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
-
30
- // src/repo-index-v4/index.ts
31
- var index_exports = {};
32
- __export(index_exports, {
33
- REPO_INDEX_V4_SCHEMA: () => REPO_INDEX_V4_SCHEMA,
34
- V4_DELTA_DEEPEN_STEPS: () => V4_DELTA_DEEPEN_STEPS,
35
- V4_GRAPH_MAX_EDGES: () => V4_GRAPH_MAX_EDGES,
36
- V4_GRAPH_MAX_EDGES_PER_FILE: () => V4_GRAPH_MAX_EDGES_PER_FILE,
37
- V4_MAX_ARTIFACT_BYTES: () => V4_MAX_ARTIFACT_BYTES,
38
- V4_MAX_CHUNKS: () => V4_MAX_CHUNKS,
39
- V4_STAGE_MAX_BODY_BYTES: () => V4_STAGE_MAX_BODY_BYTES,
40
- V4_STAGE_MAX_RECORDS: () => V4_STAGE_MAX_RECORDS,
41
- buildGraphEdges: () => buildGraphEdges,
42
- buildRepoIndexV4: () => buildRepoIndexV4,
43
- buildRepoIndexV4Detailed: () => buildRepoIndexV4Detailed,
44
- buildStructuralChunks: () => buildStructuralChunks,
45
- buildStructuralChunksForPaths: () => buildStructuralChunksForPaths,
46
- canonicalRepoIndexPaths: () => canonicalRepoIndexPaths,
47
- changedPaths: () => changedPaths,
48
- compareV4Chunks: () => compareV4Chunks,
49
- encodedStageBytes: () => encodedStageBytes,
50
- formatV4BuildMetrics: () => formatV4BuildMetrics,
51
- gitRunner: () => gitRunner,
52
- graphEdgesForSource: () => graphEdgesForSource,
53
- isRepoIndexDeltaCompatible: () => isRepoIndexDeltaCompatible,
54
- languageForPath: () => languageForPath,
55
- parseNameStatusZ: () => parseNameStatusZ,
56
- planRepoIndexV4Delta: () => planRepoIndexV4Delta,
57
- readRepoIndexProvenance: () => readRepoIndexProvenance,
58
- removedPaths: () => removedPaths,
59
- repoIndexV4DeltaBase: () => repoIndexV4DeltaBase,
60
- repoIndexV4StorePath: () => repoIndexV4StorePath,
61
- shardRepoIndexV4: () => shardRepoIndexV4,
62
- structuralChunksForSource: () => structuralChunksForSource
63
- });
64
- module.exports = __toCommonJS(index_exports);
65
-
66
- // src/repo-index-v4/chunks.ts
67
- var import_node_crypto3 = require("node:crypto");
68
- var import_node_fs2 = require("node:fs");
69
- var import_node_path3 = require("node:path");
70
-
71
- // ../infra/repo-index-path-policy.mjs
72
- var HARD_DENY = Object.freeze([
73
- /(^|\/)\.env(\.|$)/i,
74
- /(^|\/)\.env\./i,
75
- /credentials/i,
76
- /secrets?\.json$/i,
77
- /\.pem$/i,
78
- /\.p12$/i,
79
- /\.key$/i,
80
- /(^|\/)id_rsa/i,
81
- /(^|\/)id_ed25519/i,
82
- /\.keystore$/i
83
- ]);
84
- function isHardDeniedRepoIndexPath(value) {
85
- return typeof value !== "string" || HARD_DENY.some((pattern) => pattern.test(value));
86
- }
87
- function isSafeRepoIndexPath(value) {
88
- if (typeof value !== "string" || !value || value.length > 1024) return false;
89
- if (value.startsWith("/") || value.includes("\\") || /[\u0000-\u001f\u007f]/u.test(value)) return false;
90
- const segments = value.split("/");
91
- if (segments.some((segment) => !segment || segment === "." || segment === "..")) return false;
92
- return !isHardDeniedRepoIndexPath(value);
93
- }
94
- var REPO_INDEX_ALGORITHM_VERSION = 1;
95
- var REPO_INDEX_FILTER_VERSION = 2;
96
- var REPO_INDEX_MATERIAL_LAYOUT_VERSION = 2;
97
- var LEGACY_REPO_INDEX_PROVENANCE = Object.freeze({
98
- algorithmVersion: 1,
99
- filterVersion: 1,
100
- materialLayoutVersion: 1
101
- });
102
- var CURRENT_REPO_INDEX_PROVENANCE = Object.freeze({
103
- algorithmVersion: REPO_INDEX_ALGORITHM_VERSION,
104
- filterVersion: REPO_INDEX_FILTER_VERSION,
105
- materialLayoutVersion: REPO_INDEX_MATERIAL_LAYOUT_VERSION
106
- });
107
- function repoIndexProvenanceToken(provenance = CURRENT_REPO_INDEX_PROVENANCE) {
108
- const resolved = provenance && typeof provenance === "object" ? provenance : {};
109
- return `a${resolved.algorithmVersion}-f${resolved.filterVersion}-l${resolved.materialLayoutVersion}`;
110
- }
111
- var CURRENT_REPO_INDEX_PROVENANCE_TOKEN = repoIndexProvenanceToken(CURRENT_REPO_INDEX_PROVENANCE);
112
- var GENERATED_PROJECTION = Object.freeze([
113
- // Host plugin packages: the assembled skills/hooks/scripts/bin payload and the copied host
114
- // manifest directory. `packages/<host>-plugin/<file>` at the root stays admitted.
115
- /^packages\/(?:claude|codex|kimi|cursor|hermes)-plugin\/(?:skills|hooks|scripts|bin)\//,
116
- /^packages\/(?:claude|codex|kimi|cursor|hermes)-plugin\/\.[A-Za-z0-9-]+-plugin\//,
117
- // In-repo plugin roots assembled by the same declaration.
118
- /^\.kilo-plugin\/(?:skills|scripts)\//,
119
- /^\.pi-plugin\/(?:skills|scripts|extensions)\//,
120
- // Release metadata regenerated from the tracked tree at every prepare.
121
- /^distribution-bom\.json$/,
122
- // Cross-repo generator outputs the estate audit named.
123
- /^product\/connector\/generated\//,
124
- /^packages\/jerv-pi\/generated\/roster\//,
125
- /^docs\/\.release-inbox\//
126
- ]);
127
- function isGeneratedRepoIndexProjection(value) {
128
- return typeof value === "string" && GENERATED_PROJECTION.some((pattern) => pattern.test(value));
129
- }
130
- function isCanonicalRepoIndexPath(value) {
131
- return isSafeRepoIndexPath(value) && !isGeneratedRepoIndexProjection(value);
132
- }
133
- function readRepoIndexProvenance(manifest) {
134
- if (!manifest || typeof manifest !== "object" || Array.isArray(manifest)) return null;
135
- const provenance = manifest.indexProvenance;
136
- if (provenance === void 0) return { ...LEGACY_REPO_INDEX_PROVENANCE };
137
- if (!provenance || typeof provenance !== "object" || Array.isArray(provenance)) return null;
138
- const keys = ["algorithmVersion", "filterVersion", "materialLayoutVersion"];
139
- if (Object.keys(provenance).length !== keys.length) return null;
140
- for (const key of keys) {
141
- const value = provenance[key];
142
- if (!Number.isInteger(value) || value < 1) return null;
143
- }
144
- return {
145
- algorithmVersion: provenance.algorithmVersion,
146
- filterVersion: provenance.filterVersion,
147
- materialLayoutVersion: provenance.materialLayoutVersion
148
- };
149
- }
150
- function isRepoIndexDeltaCompatible(manifest) {
151
- const provenance = readRepoIndexProvenance(manifest);
152
- return provenance !== null && provenance.algorithmVersion === REPO_INDEX_ALGORITHM_VERSION && provenance.filterVersion === REPO_INDEX_FILTER_VERSION && provenance.materialLayoutVersion === REPO_INDEX_MATERIAL_LAYOUT_VERSION;
153
- }
154
-
155
- // ../infra/repo-index-material-buckets.mjs
156
- var import_node_crypto = require("node:crypto");
157
- var REPO_INDEX_MATERIAL_BUCKET_COUNT = 2;
158
- var REPO_INDEX_MATERIAL_KINDS = Object.freeze(["chunks", "embeddings"]);
159
- var REPO_INDEX_MATERIAL_PREFIX = "material-v2";
160
- function canonicalMaterialJson(value) {
161
- if (value === null || typeof value !== "object") return JSON.stringify(value);
162
- if (Array.isArray(value)) return `[${value.map(canonicalMaterialJson).join(",")}]`;
163
- return `{${Object.keys(value).sort().map((key) => `${JSON.stringify(key)}:${canonicalMaterialJson(value[key])}`).join(",")}}`;
164
- }
165
- function repoIndexMaterialDigest(value) {
166
- return (0, import_node_crypto.createHash)("sha256").update(canonicalMaterialJson(value)).digest("hex");
167
- }
168
- function normalizeRepoIndexMaterialPath(path) {
169
- return String(path).replace(/^\.\//, "").normalize("NFC");
170
- }
171
- function repoIndexMaterialBucket(path) {
172
- const hash = (0, import_node_crypto.createHash)("sha256").update(normalizeRepoIndexMaterialPath(path), "utf8").digest();
173
- return hash.readUInt32BE(0) % REPO_INDEX_MATERIAL_BUCKET_COUNT;
174
- }
175
- function compareRepoIndexChunks(a, b) {
176
- const aPath = String(a?.path ?? "");
177
- const bPath = String(b?.path ?? "");
178
- if (aPath !== bPath) return aPath < bPath ? -1 : 1;
179
- const aLine = Number(a?.citations?.[0]?.startLine ?? 0);
180
- const bLine = Number(b?.citations?.[0]?.startLine ?? 0);
181
- if (aLine !== bLine) return aLine - bLine;
182
- const aId = String(a?.id ?? "");
183
- const bId = String(b?.id ?? "");
184
- return aId === bId ? 0 : aId < bId ? -1 : 1;
185
- }
186
- function compareRepoIndexEmbeddings(a, b) {
187
- const aId = String(a?.chunkId ?? "");
188
- const bId = String(b?.chunkId ?? "");
189
- return aId === bId ? 0 : aId < bId ? -1 : 1;
190
- }
191
- function stripRepoIndexChunkCommit(chunk) {
192
- const citations = Array.isArray(chunk?.citations) ? chunk.citations : [];
193
- return {
194
- ...chunk,
195
- citations: citations.map((citation2) => {
196
- const rest = { ...citation2 };
197
- delete rest.commit;
198
- return rest;
199
- })
200
- };
201
- }
202
- function repoIndexMaterialIndexKey(repoBase, digest) {
203
- return `${repoBase}/${REPO_INDEX_MATERIAL_PREFIX}/index/${digest}.json`;
204
- }
205
- function repoIndexMaterialIndexUri(repo, digest) {
206
- return `s3://${repoIndexMaterialIndexKey(`repo-index/v4/${repo}`, digest)}`;
207
- }
208
- function repoIndexMaterialBucketBody(kind, bucket, records) {
209
- return { schemaVersion: 4, materialLayoutVersion: 2, kind, bucket, bucketCount: REPO_INDEX_MATERIAL_BUCKET_COUNT, count: records.length, records };
210
- }
211
- var bucketBody = repoIndexMaterialBucketBody;
212
- function buildRepoIndexMaterialLayout(repo, chunks, embeddings) {
213
- const chunkList = Array.isArray(chunks) ? chunks : [];
214
- const embeddingList = Array.isArray(embeddings) ? embeddings : [];
215
- const pathByChunkId = new Map(chunkList.map((chunk) => [String(chunk?.id), String(chunk?.path)]));
216
- const grouped = /* @__PURE__ */ new Map();
217
- for (const kind of REPO_INDEX_MATERIAL_KINDS) {
218
- for (let bucket = 0; bucket < REPO_INDEX_MATERIAL_BUCKET_COUNT; bucket++) grouped.set(`${kind}:${bucket}`, []);
219
- }
220
- for (const chunk of chunkList) {
221
- grouped.get(`chunks:${repoIndexMaterialBucket(chunk?.path)}`).push(stripRepoIndexChunkCommit(chunk));
222
- }
223
- for (const embedding of embeddingList) {
224
- const path = pathByChunkId.get(String(embedding?.chunkId));
225
- if (path === void 0) throw new Error("repo-index material embeds a chunk that is not in the corpus");
226
- grouped.get(`embeddings:${repoIndexMaterialBucket(path)}`).push(embedding);
227
- }
228
- const buckets = [];
229
- for (const kind of REPO_INDEX_MATERIAL_KINDS) {
230
- for (let bucket = 0; bucket < REPO_INDEX_MATERIAL_BUCKET_COUNT; bucket++) {
231
- const records = grouped.get(`${kind}:${bucket}`);
232
- records.sort(kind === "chunks" ? compareRepoIndexChunks : compareRepoIndexEmbeddings);
233
- const body = bucketBody(kind, bucket, records);
234
- buckets.push({ kind, bucket, count: records.length, digest: repoIndexMaterialDigest(body), body });
235
- }
236
- }
237
- const index = {
238
- schemaVersion: 4,
239
- materialLayoutVersion: 2,
240
- repo,
241
- bucketCount: REPO_INDEX_MATERIAL_BUCKET_COUNT,
242
- chunkCount: chunkList.length,
243
- embeddingCount: embeddingList.length,
244
- // Ordered descriptors: chunks buckets ascending, then embeddings buckets ascending.
245
- buckets: buckets.map(({ kind, bucket, count, digest }) => ({ kind, bucket, count, digest }))
246
- };
247
- return { bucketCount: REPO_INDEX_MATERIAL_BUCKET_COUNT, buckets, index, indexDigest: repoIndexMaterialDigest(index) };
248
- }
249
-
250
- // src/doc-refs-core.ts
251
- var import_node_child_process = require("node:child_process");
252
- var CHECK_IGNORE_MAX_BUFFER = 32 * 1024 * 1024;
253
- function defaultIsIgnored(root, relPaths, exec = import_node_child_process.execFileSync) {
254
- const inRepo = relPaths.filter((p) => !p.startsWith(".."));
255
- if (inRepo.length === 0) return /* @__PURE__ */ new Set();
256
- try {
257
- const out = exec("git", ["check-ignore", "--stdin"], {
258
- cwd: root,
259
- input: inRepo.join("\n"),
260
- encoding: "utf8",
261
- maxBuffer: CHECK_IGNORE_MAX_BUFFER
262
- });
263
- return new Set(out.split(/\r?\n/).filter(Boolean));
264
- } catch (error) {
265
- if (error?.status === 1) return /* @__PURE__ */ new Set();
266
- if (error?.status === 128) return /* @__PURE__ */ new Set();
267
- if (error?.code === "ENOENT") return /* @__PURE__ */ new Set();
268
- if (error?.code === "ENOBUFS") {
269
- throw new Error(
270
- `git check-ignore produced more than ${CHECK_IGNORE_MAX_BUFFER} bytes for ${inRepo.length} path(s) \u2014 the ignore set cannot be read, and treating it as empty would index gitignored paths (#4062)`
271
- );
272
- }
273
- throw error;
274
- }
275
- }
276
-
277
- // src/repo-index.ts
278
- var import_node_child_process2 = require("node:child_process");
279
- var import_node_path2 = require("node:path");
280
-
281
- // src/repo-runtime-state.ts
282
- var import_node_crypto2 = require("node:crypto");
283
- var import_node_fs = require("node:fs");
284
- var import_node_os = require("node:os");
285
- var import_node_path = require("node:path");
286
- var RUNTIME_DIR = "mmi-runtime";
287
- function hashPath(path) {
288
- return (0, import_node_crypto2.createHash)("sha256").update((0, import_node_path.resolve)(path)).digest("hex").slice(0, 16);
289
- }
290
- function resolveGitDir(cwd) {
291
- const dotGit = (0, import_node_path.join)(cwd, ".git");
292
- try {
293
- const st = (0, import_node_fs.statSync)(dotGit);
294
- if (st.isDirectory()) return dotGit;
295
- if (!st.isFile()) return void 0;
296
- } catch {
297
- return void 0;
298
- }
299
- try {
300
- const raw = (0, import_node_fs.readFileSync)(dotGit, "utf8").trim();
301
- const match = /^gitdir:\s*(.+)$/i.exec(raw);
302
- if (!match) return void 0;
303
- const gitdir = match[1].trim();
304
- return (0, import_node_path.isAbsolute)(gitdir) ? gitdir : (0, import_node_path.resolve)(cwd, gitdir);
305
- } catch {
306
- return void 0;
307
- }
308
- }
309
- function repoRuntimeStatePath(cwd, ...parts) {
310
- const gitDir = resolveGitDir(cwd);
311
- if (gitDir && (0, import_node_fs.existsSync)(gitDir)) return (0, import_node_path.join)(gitDir, RUNTIME_DIR, ...parts);
312
- return (0, import_node_path.join)((0, import_node_os.tmpdir)(), "mmi-cli", hashPath(cwd), ...parts);
313
- }
314
-
315
- // src/repo-index.ts
316
- var INDEXABLE_EXT = /* @__PURE__ */ new Set([
317
- ".ts",
318
- ".tsx",
319
- ".js",
320
- ".jsx",
321
- ".mjs",
322
- ".cjs",
323
- ".py",
324
- ".go",
325
- ".rs",
326
- ".java",
327
- ".kt",
328
- ".md",
329
- ".yml",
330
- ".yaml",
331
- ".json",
332
- ".toml",
333
- ".sh",
334
- ".ps1",
335
- ".css",
336
- ".html"
337
- ]);
338
- function isHardDeniedPath(relPosix) {
339
- return isHardDeniedRepoIndexPath(relPosix);
340
- }
341
- function isIndexablePath(relPosix) {
342
- if (!isSafeRepoIndexPath(relPosix)) return false;
343
- if (relPosix.startsWith(".git/")) return false;
344
- if (relPosix.includes("node_modules/")) return false;
345
- if (relPosix.includes("dist/")) return false;
346
- const dot = relPosix.lastIndexOf(".");
347
- if (dot < 0) return false;
348
- return INDEXABLE_EXT.has(relPosix.slice(dot).toLowerCase());
349
- }
350
- function toPosix(p) {
351
- return p.split(import_node_path2.sep).join("/");
352
- }
353
- function listCandidatePaths(cwd, exec = import_node_child_process2.execFileSync) {
354
- try {
355
- const out = exec("git", ["ls-files", "-z", "-c", "-o", "--exclude-standard"], {
356
- cwd,
357
- encoding: "utf8",
358
- maxBuffer: 64 * 1024 * 1024
359
- });
360
- return out.split("\0").filter(Boolean).map(toPosix);
361
- } catch {
362
- return [];
363
- }
364
- }
365
-
366
- // src/repo-index-v4/language.ts
367
- var LANGUAGE_BY_EXTENSION = {
368
- ".ts": { name: "typescript", parserName: "typescript" },
369
- ".mts": { name: "typescript", parserName: "typescript" },
370
- ".cts": { name: "typescript", parserName: "typescript" },
371
- ".tsx": { name: "tsx", parserName: "tsx" },
372
- ".js": { name: "javascript", parserName: "javascript" },
373
- ".mjs": { name: "javascript", parserName: "javascript" },
374
- ".cjs": { name: "javascript", parserName: "javascript" },
375
- ".jsx": { name: "jsx", parserName: "javascript" },
376
- ".py": { name: "python", parserName: "python" },
377
- ".go": { name: "go", parserName: "go" },
378
- ".rs": { name: "rust", parserName: "rust" },
379
- ".java": { name: "java", parserName: "java" },
380
- ".kt": { name: "kotlin", parserName: "kotlin" }
381
- };
382
- function languageForPath(path) {
383
- const dot = path.lastIndexOf(".");
384
- return dot < 0 ? void 0 : LANGUAGE_BY_EXTENSION[path.slice(dot).toLowerCase()];
385
- }
386
-
387
- // src/repo-index-v4/chunks.ts
388
- var BLURB_CAP = 200;
389
- var SIGNATURE_CAP = 300;
390
- var STRUCTURAL_KINDS = /* @__PURE__ */ new Set([
391
- "function_declaration",
392
- "function_definition",
393
- "function_item",
394
- "function",
395
- "method_declaration",
396
- "method_definition",
397
- "method",
398
- "class_declaration",
399
- "class_definition",
400
- "class",
401
- "interface_declaration",
402
- "interface_definition",
403
- "enum_declaration",
404
- "enum_definition",
405
- "enum_item",
406
- "struct_item",
407
- "struct_specifier",
408
- "trait_item",
409
- "impl_item",
410
- "type_declaration",
411
- "type_alias_declaration",
412
- "object_declaration"
413
- ]);
414
- var parserRuntime;
415
- var grammarCache = /* @__PURE__ */ new Map();
416
- async function parserFor(language) {
417
- const api = await (parserRuntime ??= import("web-tree-sitter"));
418
- await api.Parser.init();
419
- let grammar = grammarCache.get(language);
420
- if (!grammar) {
421
- grammar = import("tree-sitter-wasm").then(({ getWasmPath }) => api.Language.load(getWasmPath(language)));
422
- grammarCache.set(language, grammar);
423
- }
424
- const parser = new api.Parser();
425
- parser.setLanguage(await grammar);
426
- return parser;
427
- }
428
- function sha256(value) {
429
- return (0, import_node_crypto3.createHash)("sha256").update(value).digest("hex");
430
- }
431
- function pointerId(path, kind, contentHash, start, end, symbol) {
432
- return sha256(["repo-index-v4", path, kind, contentHash, String(start), String(end), symbol ?? ""].join("\0"));
433
- }
434
- function lineAt(bytes, offset) {
435
- let line = 1;
436
- for (let i = 0; i < Math.min(offset, bytes.length); i++) if (bytes[i] === 10) line++;
437
- return line;
438
- }
439
- function lineRange(bytes, start, end) {
440
- const startLine = lineAt(bytes, start);
441
- const endLine = lineAt(bytes, Math.max(start, end - 1));
442
- return { startLine, endLine: Math.max(startLine, endLine) };
443
- }
444
- function boundedLine(value, cap) {
445
- const line = value?.replace(/\r?\n/g, " ").replace(/\s+/g, " ").trim();
446
- return line ? line.slice(0, cap) : void 0;
447
- }
448
- function citation(repo, commit, path, bytes, start, end, symbol) {
449
- return { repo, commit, path, ...lineRange(bytes, start, end), ...symbol ? { symbol } : {} };
450
- }
451
- function doclineBefore(bytes, start) {
452
- const prior2 = Buffer.from(bytes.subarray(0, start)).toString("utf8").split(/\r?\n/);
453
- for (let i = prior2.length - 1; i >= 0; i--) {
454
- const line = prior2[i].trim();
455
- if (!line) continue;
456
- const text = line.replace(/^(?:\/\/\/|\/\/|#|\/\*\*?|\*)\s?/, "").replace(/\*\/$/, "").trim();
457
- return text === line ? void 0 : boundedLine(text, BLURB_CAP);
458
- }
459
- return void 0;
460
- }
461
- function fileChunk(repo, commit, path, source, language) {
462
- const bytes = Buffer.from(source, "utf8");
463
- const contentHash = sha256(bytes);
464
- return {
465
- id: pointerId(path, "file", contentHash, 0, bytes.length),
466
- path,
467
- kind: "file",
468
- contentHash,
469
- ...language ? { language } : {},
470
- citations: [citation(repo, commit, path, bytes, 0, bytes.length)]
471
- };
472
- }
473
- function structuralNode(node) {
474
- if (STRUCTURAL_KINDS.has(node.type)) return node;
475
- return node.namedChildren.find((child) => STRUCTURAL_KINDS.has(child.type));
476
- }
477
- function structureChunk(repo, commit, path, sourceBytes, language, owner) {
478
- const item = structuralNode(owner);
479
- if (!item) return void 0;
480
- const start = owner.startIndex;
481
- const end = owner.endIndex;
482
- if (start < 0 || end < start || end > sourceBytes.length) return void 0;
483
- const contentHash = sha256(sourceBytes.subarray(start, end));
484
- const name = boundedLine(item.childForFieldName("name")?.text, SIGNATURE_CAP);
485
- const bodyStart = item.childForFieldName("body")?.startIndex ?? end;
486
- const symbol = boundedLine(Buffer.from(sourceBytes.subarray(start, bodyStart)).toString("utf8"), SIGNATURE_CAP) ?? name;
487
- return {
488
- id: pointerId(path, "symbol", contentHash, start, end, symbol),
489
- path,
490
- kind: "symbol",
491
- contentHash,
492
- language,
493
- ...symbol ? { symbol } : {},
494
- ...doclineBefore(sourceBytes, start) ? { blurb: doclineBefore(sourceBytes, start) } : {},
495
- citations: [citation(repo, commit, path, sourceBytes, start, end, name)]
496
- };
497
- }
498
- async function structuralChunksForSource(repo, commit, path, source) {
499
- const language = languageForPath(path);
500
- if (!language) return [fileChunk(repo, commit, path, source)];
501
- let parser;
502
- let tree;
503
- try {
504
- parser = await parserFor(language.parserName);
505
- tree = parser.parse(source) ?? void 0;
506
- if (!tree || tree.rootNode.hasError) return [fileChunk(repo, commit, path, source, language.name)];
507
- const bytes = Buffer.from(source, "utf8");
508
- const chunks = tree.rootNode.namedChildren.map((node) => structureChunk(repo, commit, path, bytes, language.name, node)).filter((chunk) => chunk !== void 0).sort((a, b) => a.citations[0].startLine - b.citations[0].startLine || a.id.localeCompare(b.id));
509
- return chunks.length ? chunks : [fileChunk(repo, commit, path, source, language.name)];
510
- } catch {
511
- return [fileChunk(repo, commit, path, source, language.name)];
512
- } finally {
513
- tree?.delete();
514
- parser?.delete();
515
- }
516
- }
517
- function canonicalRepoIndexPaths(cwd) {
518
- const candidates = listCandidatePaths(cwd).filter(isIndexablePath).sort((a, b) => a.localeCompare(b));
519
- const ignored = defaultIsIgnored(cwd, candidates);
520
- return candidates.filter((path) => !ignored.has(path) && !isHardDeniedPath(path) && isCanonicalRepoIndexPath(path));
521
- }
522
- function compareV4Chunks(a, b) {
523
- return compareRepoIndexChunks(a, b);
524
- }
525
- async function buildStructuralChunksForPaths(cwd, repo, commit, paths) {
526
- const chunks = [];
527
- for (const path of paths) {
528
- const absolute = (0, import_node_path3.join)(cwd, ...path.split("/"));
529
- if (!(0, import_node_fs2.existsSync)(absolute)) continue;
530
- let source;
531
- try {
532
- source = (0, import_node_fs2.readFileSync)(absolute, "utf8");
533
- } catch {
534
- continue;
535
- }
536
- chunks.push(...await structuralChunksForSource(repo, commit, path, source));
537
- }
538
- return chunks.sort(compareV4Chunks);
539
- }
540
- async function buildStructuralChunks(cwd, repo, commit) {
541
- return buildStructuralChunksForPaths(cwd, repo, commit, canonicalRepoIndexPaths(cwd));
542
- }
543
-
544
- // src/repo-index-v4/types.ts
545
- var REPO_INDEX_V4_SCHEMA = 4;
546
-
547
- // src/repo-index-v4/builder.ts
548
- var import_node_crypto4 = require("node:crypto");
549
- var import_node_child_process4 = require("node:child_process");
550
- var import_node_fs3 = require("node:fs");
551
- var import_node_os2 = require("node:os");
552
- var import_node_path4 = require("node:path");
553
-
554
- // src/repo-index-v4/delta.ts
555
- var import_node_child_process3 = require("node:child_process");
556
- var COMMIT = /^[a-f0-9]{40}$/;
557
- var V4_DELTA_DEEPEN_STEPS = [50, 250, 1e3];
558
- function gitRunner(cwd) {
559
- return (args) => {
560
- const result = (0, import_node_child_process3.spawnSync)("git", [...args], { cwd, encoding: "utf8", windowsHide: true, maxBuffer: 64 * 1024 * 1024 });
561
- if (result.error) return { status: -1, stdout: "" };
562
- return { status: typeof result.status === "number" ? result.status : -1, stdout: String(result.stdout ?? "") };
563
- };
564
- }
565
- function parseNameStatusZ(output) {
566
- const fields = output.split("\0");
567
- if (fields.length && fields[fields.length - 1] === "") fields.pop();
568
- const changes = [];
569
- for (let i = 0; i < fields.length; ) {
570
- const raw = fields[i++] ?? "";
571
- const letter = raw[0];
572
- if (!letter || !/^[AMDTRC]\d*$/.test(raw)) return null;
573
- if (letter === "R" || letter === "C") {
574
- const oldPath = fields[i++];
575
- const path2 = fields[i++];
576
- if (!oldPath || !path2) return null;
577
- changes.push(letter === "C" ? { status: "A", path: path2 } : { status: "R", path: path2, oldPath });
578
- continue;
579
- }
580
- const path = fields[i++];
581
- if (!path) return null;
582
- changes.push({ status: letter, path });
583
- }
584
- return changes;
585
- }
586
- function changedPaths(changes) {
587
- return [...new Set(changes.filter((change) => change.status !== "D").map((change) => change.path))].sort();
588
- }
589
- function removedPaths(changes) {
590
- const removed = changes.flatMap((change) => change.status === "D" ? [change.path] : change.status === "R" && change.oldPath ? [change.oldPath] : []);
591
- return [...new Set(removed)].sort();
592
- }
593
- function commitPresent(git2, commit) {
594
- return git2(["cat-file", "-e", `${commit}^{commit}`]).status === 0;
595
- }
596
- function isAncestor(git2, base, head) {
597
- return git2(["merge-base", "--is-ancestor", base, head]).status === 0;
598
- }
599
- function planRepoIndexV4Delta(opts) {
600
- const headCommit = opts.headCommit.toLowerCase();
601
- const baseCommit = opts.baseCommit ? opts.baseCommit.toLowerCase() : null;
602
- const full = (fallbackReason) => ({ mode: "full", headCommit, fallbackReason, ...baseCommit ? { baseCommit } : {} });
603
- if (opts.forceFull) return full("explicit-full-rebuild");
604
- if (!baseCommit || !COMMIT.test(baseCommit)) return full("no-active-authority");
605
- if (baseCommit === headCommit) return { mode: "unchanged", baseCommit, headCommit };
606
- if (opts.basePipelineCompatible === false) return full("incompatible-base-provenance");
607
- if (opts.hasPriorMaterial === false) return full("no-prior-material");
608
- const { git: git2 } = opts;
609
- let usable = commitPresent(git2, baseCommit) && isAncestor(git2, baseCommit, headCommit);
610
- for (const depth of V4_DELTA_DEEPEN_STEPS) {
611
- if (usable || !opts.deepen) break;
612
- try {
613
- opts.deepen(depth);
614
- } catch {
615
- break;
616
- }
617
- usable = commitPresent(git2, baseCommit) && isAncestor(git2, baseCommit, headCommit);
618
- }
619
- if (!usable) {
620
- return full(commitPresent(git2, baseCommit) ? "base-not-ancestor" : "base-commit-unavailable");
621
- }
622
- const diff = git2(["diff", "--name-status", "-z", "--find-renames", baseCommit, headCommit]);
623
- if (diff.status !== 0) return full("diff-unreadable");
624
- const changes = parseNameStatusZ(diff.stdout);
625
- if (!changes) return full("unsupported-change-status");
626
- return { mode: "delta", baseCommit, headCommit, changes };
627
- }
628
-
629
- // src/repo-index-v4/builder.ts
630
- var V4_MAX_CHUNKS = 1e4;
631
- var V4_MAX_ARTIFACT_BYTES = 64 * 1024 * 1024;
632
- var V4_EMBED_BATCH = 32;
633
- var V4_VECTOR_DECIMAL_PLACES = 6;
634
- var COMMIT2 = /^[a-f0-9]{40}$/;
635
- function canonicalJson(value) {
636
- if (value === null || typeof value !== "object") return JSON.stringify(value);
637
- if (Array.isArray(value)) return `[${value.map(canonicalJson).join(",")}]`;
638
- const record = value;
639
- return `{${Object.keys(record).sort().map((k) => `${JSON.stringify(k)}:${canonicalJson(record[k])}`).join(",")}}`;
640
- }
641
- function sha2562(value) {
642
- return (0, import_node_crypto4.createHash)("sha256").update(canonicalJson(value)).digest("hex");
643
- }
644
- function quantizeV4Vector(vector) {
645
- return vector.map((value) => Number(value.toFixed(V4_VECTOR_DECIMAL_PLACES)));
646
- }
647
- function statePath(cwd) {
648
- return repoRuntimeStatePath(cwd, "repo-index", "v4.json");
649
- }
650
- function git(cwd, args) {
651
- return String((0, import_node_child_process4.execFileSync)("git", args, { cwd, encoding: "utf8", windowsHide: true, stdio: ["ignore", "pipe", "ignore"] })).trim();
652
- }
653
- function gitInfo(cwd) {
654
- const commit = git(cwd, ["rev-parse", "HEAD"]).toLowerCase();
655
- if (!COMMIT2.test(commit)) throw new Error("repo-index v4 requires an exact git HEAD commit");
656
- let defaultBranch = "main";
657
- try {
658
- defaultBranch = git(cwd, ["symbolic-ref", "--short", "refs/remotes/origin/HEAD"]).replace(/^origin\//, "") || defaultBranch;
659
- } catch {
660
- }
661
- let createdAt;
662
- try {
663
- createdAt = new Date(git(cwd, ["show", "-s", "--format=%cI", "HEAD"])).toISOString();
664
- } catch {
665
- createdAt = "1970-01-01T00:00:00.000Z";
666
- }
667
- return { commit, defaultBranch, createdAt };
668
- }
669
- function prior(cwd) {
670
- try {
671
- const p = JSON.parse((0, import_node_fs3.readFileSync)(statePath(cwd), "utf8"));
672
- return p?.schemaVersion === 4 && p?.manifest?.immutable === true ? p : null;
673
- } catch {
674
- return null;
675
- }
676
- }
677
- function repoIndexV4DeltaBase(envelope) {
678
- return envelope && isRepoIndexDeltaCompatible(envelope.manifest) ? envelope : null;
679
- }
680
- function tombstone(repo, commit, path, createdAt) {
681
- const base = { repo, commit, path, reason: "deleted", createdAt };
682
- return { ...base, id: sha2562(base) };
683
- }
684
- function embeddingInput(cwd, chunk) {
685
- const c = chunk.citations[0];
686
- if (!c) return `${chunk.path}
687
- ${chunk.symbol ?? ""}
688
- ${chunk.blurb ?? ""}`;
689
- try {
690
- const lines = (0, import_node_fs3.readFileSync)((0, import_node_path4.join)(cwd, ...chunk.path.split("/")), "utf8").split(/\r?\n/);
691
- const body = lines.slice(Math.max(0, (c.startLine ?? 1) - 1), Math.min(lines.length, c.endLine ?? lines.length)).join("\n");
692
- return body.slice(0, 1e5);
693
- } catch {
694
- return `${chunk.path}
695
- ${chunk.symbol ?? ""}
696
- ${chunk.blurb ?? ""}`;
697
- }
698
- }
699
- var V4_EMBED_TIMEOUT_MS = 15 * 6e4;
700
- var V4_EMBED_RETRY = 1;
701
- function runEmbedderOnce(cwd, chunks, modelDirectory, createdAt) {
702
- if (!chunks.length) return { ok: true, embeddings: [] };
703
- const orchestratorRunner = (0, import_node_path4.join)(process.cwd(), "repo-indexer", "src", "batch.mjs");
704
- const targetRunner = (0, import_node_path4.join)(cwd, "repo-indexer", "src", "batch.mjs");
705
- const file = (0, import_node_fs3.existsSync)(orchestratorRunner) ? orchestratorRunner : targetRunner;
706
- if (!(0, import_node_fs3.existsSync)(file)) return { ok: false, reason: "embeddings-unavailable" };
707
- const request = { texts: chunks.map((chunk) => ({ id: chunk.id, text: embeddingInput(cwd, chunk) })), maxBatch: V4_EMBED_BATCH };
708
- const env = { ...process.env, ...modelDirectory ? { MMI_REPO_INDEXER_MODEL_DIR: modelDirectory } : {} };
709
- const requestDir = (0, import_node_fs3.mkdtempSync)((0, import_node_path4.join)((0, import_node_os2.tmpdir)(), "mmi-repo-index-req-"));
710
- const requestFile = (0, import_node_path4.join)(requestDir, "request.json");
711
- (0, import_node_fs3.writeFileSync)(requestFile, JSON.stringify(request));
712
- let result;
713
- try {
714
- result = (0, import_node_child_process4.spawnSync)(process.execPath, [file, requestFile], { encoding: "utf8", windowsHide: true, timeout: V4_EMBED_TIMEOUT_MS, maxBuffer: V4_MAX_ARTIFACT_BYTES, env });
715
- } finally {
716
- (0, import_node_fs3.rmSync)(requestDir, { recursive: true, force: true });
717
- }
718
- if (result.error || result.status !== 0) {
719
- const cleanExit = result.error === void 0 && result.signal === void 0 && typeof result.status === "number" && result.status !== 0;
720
- const stdout = String(result.stdout).trim();
721
- const stderrTail = String(result.stderr).trim().slice(-400) || void 0;
722
- let code;
723
- if (cleanExit) {
724
- try {
725
- code = JSON.parse(stdout)?.code;
726
- } catch {
727
- }
728
- }
729
- return {
730
- ok: false,
731
- code,
732
- stdoutTail: code ? void 0 : stdout.slice(-400) || void 0,
733
- stderrTail,
734
- cleanExit,
735
- detail: result.error?.message ?? result.signal ?? `exit status ${result.status ?? "unknown"}`
736
- };
737
- }
738
- try {
739
- const response = JSON.parse(String(result.stdout));
740
- if (!response.ok || !response.provenance || !Array.isArray(response.embeddings)) return { ok: false, reason: "embeddings-unavailable" };
741
- const provenance = {
742
- provider: response.provenance.provider,
743
- model: response.provenance.model,
744
- modelDigest: response.provenance.modelDigest,
745
- dimensions: response.provenance.dimensions,
746
- input: response.provenance.input,
747
- createdAt
748
- };
749
- const byId = new Map(response.embeddings.map((e) => [e.id, e.vector]));
750
- const embeddings = chunks.map((chunk) => ({ chunkId: chunk.id, vector: byId.get(chunk.id), provenance })).filter((e) => Array.isArray(e.vector) && e.vector.length === provenance.dimensions && e.vector.every(Number.isFinite));
751
- return embeddings.length === chunks.length ? { ok: true, embeddings } : { ok: false, reason: "partial-coverage" };
752
- } catch {
753
- return { ok: false, reason: "embeddings-unavailable" };
754
- }
755
- }
756
- function runEmbedder(cwd, chunks, modelDirectory, createdAt) {
757
- if (!chunks.length) return { embeddings: [] };
758
- let last;
759
- for (let attempt = 1; attempt <= V4_EMBED_RETRY + 1; attempt++) {
760
- last = runEmbedderOnce(cwd, chunks, modelDirectory, createdAt);
761
- if (last.ok) return { embeddings: last.embeddings, reason: last.reason };
762
- if (attempt > V4_EMBED_RETRY || last.cleanExit !== true) break;
763
- }
764
- const runner = last;
765
- const code = runner.code ? ` code=${runner.code}` : "";
766
- const stdout = runner.stdoutTail ? ` stdout=${runner.stdoutTail}` : "";
767
- const stderr = runner.stderrTail ? ` stderr=${runner.stderrTail}` : "";
768
- throw new Error(`repo-index v4 embedding runner failed: ${runner.detail ?? "unknown"}${code}${stdout}${stderr}`);
769
- }
770
- function restampCitations(chunk, repo, commit) {
771
- return { ...chunk, citations: chunk.citations.map((citation2) => ({ ...citation2, repo, commit })) };
772
- }
773
- async function buildRepoIndexV4(cwd, repo, opts = {}) {
774
- return (await buildRepoIndexV4Detailed(cwd, repo, opts)).envelope;
775
- }
776
- async function buildRepoIndexV4Detailed(cwd, repo, opts = {}) {
777
- const { commit, defaultBranch, createdAt } = gitInfo(cwd);
778
- const delta = opts.delta;
779
- const old = prior(cwd);
780
- const deltaBase = repoIndexV4DeltaBase(old);
781
- let chunks;
782
- let carried = 0;
783
- let built = 0;
784
- let changedCount = 0;
785
- let removedCount = 0;
786
- if (delta) {
787
- const admitted = new Set(canonicalRepoIndexPaths(cwd));
788
- const changed = new Set(changedPaths(delta.changes));
789
- const removed = new Set(removedPaths(delta.changes));
790
- changedCount = changed.size;
791
- removedCount = removed.size;
792
- const rebuilt = await buildStructuralChunksForPaths(cwd, repo, commit, [...changed].filter((path2) => admitted.has(path2)).sort());
793
- const kept = delta.prior.chunks.filter((chunk) => !changed.has(chunk.path) && !removed.has(chunk.path) && admitted.has(chunk.path)).map((chunk) => restampCitations(chunk, repo, commit));
794
- carried = kept.length;
795
- built = rebuilt.length;
796
- chunks = [...kept, ...rebuilt].sort(compareV4Chunks);
797
- } else {
798
- chunks = await buildStructuralChunks(cwd, repo, commit);
799
- built = chunks.length;
800
- }
801
- if (chunks.length > V4_MAX_CHUNKS) throw new Error(`repo-index v4 exceeds ${V4_MAX_CHUNKS} chunk ceiling`);
802
- const currentPaths = new Set(chunks.map((c) => c.path));
803
- const priorChunks = delta ? delta.prior.chunks : old?.manifest.chunks ?? [];
804
- const priorTombstones = delta ? delta.prior.tombstones ?? [] : old?.manifest.tombstones ?? [];
805
- const tombstonePaths = [
806
- ...priorTombstones.map((t) => t.path),
807
- ...priorChunks.map((c) => c.path).filter((path2) => !currentPaths.has(path2))
808
- ];
809
- const tombstones = [...new Set(tombstonePaths)].sort().map((path2) => tombstone(repo, commit, path2, createdAt));
810
- const embeddingSource = delta ? delta.prior : { chunks: deltaBase?.manifest.chunks ?? [], embeddings: deltaBase?.manifest.embeddings ?? [] };
811
- const oldChunkHashById = new Map(embeddingSource.chunks.map((c) => [c.id, c.contentHash]));
812
- const reusableEmbedding = (embedding) => {
813
- const norm = Math.hypot(...embedding.vector);
814
- return embedding.vector.length === 384 && embedding.vector.every(Number.isFinite) && norm >= 0.98 && norm <= 1.02 && embedding.provenance.provider === "local" && embedding.provenance.modelDigest === "828e1496d7fabb79cfa4dcd84fa38625c0d3d21da474a00f08db0f559940cf35" && embedding.provenance.dimensions === 384 && embedding.provenance.input === "pointer-safe-structural-chunk";
815
- };
816
- const oldEmbeddingByHash = new Map(embeddingSource.embeddings.filter(reusableEmbedding).map((e) => [oldChunkHashById.get(e.chunkId), e]));
817
- const reusable = chunks.flatMap((chunk) => {
818
- const priorEmbedding = oldEmbeddingByHash.get(chunk.contentHash);
819
- return priorEmbedding ? [{ ...priorEmbedding, chunkId: chunk.id }] : [];
820
- });
821
- const reusableIds = new Set(reusable.map((e) => e.chunkId));
822
- const missing = chunks.filter((chunk) => !reusableIds.has(chunk.id));
823
- const generated = missing.length === 0 ? { embeddings: [] } : opts.embed === false ? { embeddings: [], reason: "embeddings-unavailable" } : runEmbedder(cwd, missing, opts.modelDirectory, createdAt);
824
- const embeddings = [...reusable, ...generated.embeddings].map((embedding) => ({ ...embedding, vector: quantizeV4Vector(embedding.vector) })).sort(compareRepoIndexEmbeddings);
825
- const materialIndexDigest = buildRepoIndexMaterialLayout(repo, chunks, embeddings).indexDigest;
826
- const artifact = (kind, digest, uri) => {
827
- const identity2 = { repo, commit, immutable: true, kind, uri, sha256: digest, createdAt };
828
- return { ...identity2, id: sha2562(identity2) };
829
- };
830
- const artifacts = [artifact("material-index", materialIndexDigest, repoIndexMaterialIndexUri(repo, materialIndexDigest))];
831
- const grammarProvenance = {
832
- runtime: { name: "web-tree-sitter", version: "0.26.12", license: "MIT" },
833
- grammarPack: { name: "tree-sitter-wasm", version: "1.1.4", license: "MIT", digest: "f3089ddf2c9615a423783b645c4dfb23ccda30807bbd059746f583952357c489" },
834
- languages: ["go", "java", "javascript", "jsx", "kotlin", "python", "rust", "tsx", "typescript"]
835
- };
836
- const rrf = { algorithm: "reciprocal-rank-fusion", k: 60, lexicalWeight: 1, semanticWeight: 1 };
837
- const indexProvenance = { ...CURRENT_REPO_INDEX_PROVENANCE };
838
- const identity = { repo, commit, defaultBranch, immutable: true, ...delta ? { parentCommit: delta.baseCommit } : {}, createdAt, grammarProvenance, indexProvenance, chunks, embeddings, artifacts, tombstones, rrf };
839
- const manifest = { ...identity, id: sha2562(identity) };
840
- const complete = embeddings.length === chunks.length;
841
- const envelope = {
842
- schemaVersion: 4,
843
- manifest,
844
- status: { repo, commit, state: complete ? "ready" : "degraded", updatedAt: createdAt, ...!complete ? { degradedReasons: [generated.reason === "partial-coverage" ? "partial-coverage" : "embeddings-unavailable"] } : {} }
845
- };
846
- const encoded = canonicalJson(envelope);
847
- if (Buffer.byteLength(encoded) > V4_MAX_ARTIFACT_BYTES) throw new Error(`repo-index v4 artifact exceeds ${V4_MAX_ARTIFACT_BYTES} byte ceiling`);
848
- const path = statePath(cwd);
849
- (0, import_node_fs3.mkdirSync)((0, import_node_path4.dirname)(path), { recursive: true });
850
- (0, import_node_fs3.writeFileSync)(path, `${JSON.stringify(envelope, null, 2)}
851
- `, "utf8");
852
- const metrics = {
853
- mode: delta ? "delta" : "full",
854
- ...delta ? { baseCommit: delta.baseCommit } : {},
855
- changedPaths: changedCount,
856
- removedPaths: removedCount,
857
- chunksTotal: chunks.length,
858
- chunksCarried: carried,
859
- chunksBuilt: built,
860
- embeddingsReused: reusable.length,
861
- embeddingsEmbedded: generated.embeddings.length,
862
- tombstones: tombstones.length
863
- };
864
- return { envelope, metrics };
865
- }
866
- function formatV4BuildMetrics(repo, metrics) {
867
- const base = metrics.baseCommit ? ` base=${metrics.baseCommit.slice(0, 12)}` : "";
868
- return `${repo}: ${metrics.mode}${base} changed=${metrics.changedPaths} removed=${metrics.removedPaths} chunks=${metrics.chunksTotal} (carried=${metrics.chunksCarried} built=${metrics.chunksBuilt}) embeddings(reused=${metrics.embeddingsReused} new=${metrics.embeddingsEmbedded}) tombstones=${metrics.tombstones}`;
869
- }
870
- function repoIndexV4StorePath(cwd) {
871
- return statePath(cwd);
872
- }
873
-
874
- // src/repo-index-v4/shards.ts
875
- var V4_STAGE_MAX_BODY_BYTES = 750 * 1024;
876
- var V4_STAGE_MAX_RECORDS = 256;
877
- var V4_STAGE_MAX_SHARDS = 128;
878
- function encodedBytes(value) {
879
- return Buffer.byteLength(JSON.stringify(value));
880
- }
881
- function split(kind, records, manifest, bucket) {
882
- const groups = [];
883
- let group = [];
884
- for (const record of records) {
885
- const next = [...group, record];
886
- const probe = { repo: manifest.repo, commit: manifest.commit, manifestId: manifest.id, kind, ...bucket === void 0 ? {} : { bucket }, index: 127, total: 128, digest: "0".repeat(64), records: next };
887
- if (group.length && (group.length >= V4_STAGE_MAX_RECORDS || encodedBytes(probe) > V4_STAGE_MAX_BODY_BYTES)) {
888
- groups.push(group);
889
- group = [record];
890
- } else {
891
- group = next;
892
- }
893
- }
894
- if (group.length || records.length === 0) groups.push(group);
895
- if (groups.length > V4_STAGE_MAX_SHARDS) throw new Error(`repo-index v4 ${kind} requires ${groups.length} shards (max ${V4_STAGE_MAX_SHARDS})`);
896
- return groups.map((items, index) => {
897
- const request = {
898
- repo: manifest.repo,
899
- commit: manifest.commit,
900
- manifestId: manifest.id,
901
- kind,
902
- ...bucket === void 0 ? {} : { bucket },
903
- index,
904
- total: groups.length,
905
- digest: sha2562(items),
906
- records: items
907
- };
908
- if (encodedBytes(request) > V4_STAGE_MAX_BODY_BYTES) throw new Error(`repo-index v4 ${kind} shard ${index} exceeds ${V4_STAGE_MAX_BODY_BYTES} bytes`);
909
- return request;
910
- });
911
- }
912
- function shardRepoIndexV4(envelope, opts = {}) {
913
- const { chunks, embeddings, ...header } = envelope.manifest;
914
- const identity = { repo: header.repo, commit: header.commit, manifestId: header.id, header, status: envelope.status };
915
- if ((header.indexProvenance?.materialLayoutVersion ?? 1) < 2) {
916
- const stages2 = [...split("chunks", chunks, envelope.manifest), ...split("embeddings", embeddings ?? [], envelope.manifest)];
917
- const shards2 = stages2.map(({ kind, index, total, digest, records }) => ({ kind, index, total, digest, count: records.length }));
918
- return { stages: stages2, finalize: { ...identity, shards: shards2 } };
919
- }
920
- const reusable = new Set(opts.priorBucketDigests ?? []);
921
- const layout = buildRepoIndexMaterialLayout(header.repo, chunks, embeddings ?? []);
922
- const stages = [];
923
- const shards = [];
924
- const buckets = layout.buckets.map((bucket) => {
925
- if (reusable.has(bucket.digest)) return { kind: bucket.kind, bucket: bucket.bucket, count: bucket.count, digest: bucket.digest, shards: 0 };
926
- const fragments = split(bucket.kind, bucket.body.records, envelope.manifest, bucket.bucket);
927
- stages.push(...fragments);
928
- shards.push(...fragments.map(({ kind, index, total, digest, records }) => ({ kind, bucket: bucket.bucket, index, total, digest, count: records.length })));
929
- return { kind: bucket.kind, bucket: bucket.bucket, count: bucket.count, digest: bucket.digest, shards: fragments.length };
930
- });
931
- if (buckets.length !== 2 * REPO_INDEX_MATERIAL_BUCKET_COUNT) throw new Error("repo-index v4 material layout is incomplete");
932
- return { stages, finalize: { ...identity, shards, materialLayout: 2, buckets } };
933
- }
934
- function encodedStageBytes(stage) {
935
- return encodedBytes(stage);
936
- }
937
-
938
- // src/repo-index-v4/edges.ts
939
- var import_node_fs4 = require("node:fs");
940
- var import_node_path5 = require("node:path");
941
- var V4_GRAPH_MAX_EDGES = 5e3;
942
- var V4_GRAPH_MAX_EDGES_PER_FILE = 64;
943
- var SUPPORTED = /* @__PURE__ */ new Map([
944
- [".js", "javascript"],
945
- [".jsx", "javascript"],
946
- [".mjs", "javascript"],
947
- [".cjs", "javascript"],
948
- [".ts", "typescript"],
949
- [".tsx", "typescript"],
950
- [".py", "python"],
951
- [".go", "go"],
952
- [".rs", "rust"],
953
- [".cs", "csharp"],
954
- [".md", "resource"],
955
- [".json", "resource"],
956
- [".yaml", "resource"],
957
- [".yml", "resource"]
958
- ]);
959
- function extension(path) {
960
- const index = path.lastIndexOf(".");
961
- return index < 0 ? "" : path.slice(index).toLowerCase();
962
- }
963
- function lineAt2(source, offset) {
964
- return source.slice(0, offset).split(/\r?\n/).length;
965
- }
966
- function normalizedRepo(value) {
967
- return value.toLowerCase().replace(/^https?:\/\/github\.com\//, "").replace(/\.git(?:[#/?].*)?$/, "").replace(/[?#].*$/, "");
968
- }
969
- function targetRepo(specifier, roster) {
970
- const direct = normalizedRepo(specifier).match(/(?:^|\/)mutmutco\/([a-z0-9._-]+)/)?.[1];
971
- if (direct && roster.has(`mutmutco/${direct}`)) return `mutmutco/${direct}`;
972
- const scoped = specifier.toLowerCase().match(/^@mutmutco\/([a-z0-9._-]+)/)?.[1];
973
- if (scoped && roster.has(`mutmutco/${scoped}`)) return `mutmutco/${scoped}`;
974
- const crate = specifier.toLowerCase().replace(/_/g, "-");
975
- return roster.has(`mutmutco/${crate}`) ? `mutmutco/${crate}` : void 0;
976
- }
977
- function candidate(base) {
978
- return { ...base, id: sha2562(base) };
979
- }
980
- function graphEdgesForSource(repo, commit, path, source, rosterRepos) {
981
- const language = SUPPORTED.get(extension(path));
982
- if (!language) return [];
983
- const roster = new Set(rosterRepos.map((value) => value.toLowerCase()));
984
- roster.delete(repo.toLowerCase());
985
- const edges = [];
986
- const seen = /* @__PURE__ */ new Set();
987
- const push = (kind, offset, target, confidence, rule, symbol) => {
988
- const targetName = targetRepo(target, roster);
989
- if (!targetName) return;
990
- const base = { kind, confidence, source: { repo, commit, path, line: lineAt2(source, offset), ...symbol ? { symbol } : {} }, target: { repo: targetName, ...symbol ? { symbol } : {} }, resolver: { name: "repo-index-v4-static", version: 1, language, rule } };
991
- const edge = candidate(base);
992
- if (!seen.has(edge.id) && edges.length < V4_GRAPH_MAX_EDGES_PER_FILE) {
993
- seen.add(edge.id);
994
- edges.push(edge);
995
- }
996
- };
997
- const imports = [];
998
- const patterns = [
999
- /\bimport\s+(?:\{?\s*([A-Za-z_$][\w$]*)[^'";]*?\s+from\s+)?['"]([^'"]+)['"]/g,
1000
- /\brequire\(\s*['"]([^'"]+)['"]\s*\)/g,
1001
- /\bfrom\s+([A-Za-z0-9_.\/-]+)\s+import\s+([A-Za-z_]\w*)/g,
1002
- /\b(?:use|extern\s+crate)\s+([A-Za-z0-9_:\/-]+)/g,
1003
- /\bimport\s+"([^"]+)"/g,
1004
- /<ProjectReference\b[^>]*Include=["']([^"']+)["']/gi
1005
- ];
1006
- for (const pattern of patterns) for (const match of source.matchAll(pattern)) {
1007
- const values = match.slice(1).filter((value) => !!value);
1008
- const target = values.find((value) => targetRepo(value, roster));
1009
- if (!target || match.index === void 0) continue;
1010
- const binding = values.find((value) => value !== target && /^[A-Za-z_$][\w$]*$/.test(value));
1011
- imports.push({ binding, target });
1012
- push("import", match.index, target, 0.95, `import-${pattern.source.slice(0, 16)}`, binding);
1013
- }
1014
- for (const imported of imports) if (imported.binding) {
1015
- const call = new RegExp(`\\b${imported.binding.replace(/[$]/g, "\\$&")}\\s*\\(`, "g");
1016
- for (const match of source.matchAll(call)) if (match.index !== void 0) push("call", match.index, imported.target, 0.85, "import-bound-call", imported.binding);
1017
- }
1018
- const resource = /https?:\/\/github\.com\/mutmutco\/[A-Za-z0-9._-]+(?:\.git)?/g;
1019
- for (const match of source.matchAll(resource)) if (match.index !== void 0) push("resource", match.index, match[0], 1, "github-url");
1020
- return edges.sort((a, b) => a.source.path.localeCompare(b.source.path) || a.source.line - b.source.line || a.kind.localeCompare(b.kind) || a.id.localeCompare(b.id));
1021
- }
1022
- function buildGraphEdges(cwd, repo, commit, rosterRepos) {
1023
- const paths = listCandidatePaths(cwd).filter(isIndexablePath).sort((a, b) => a.localeCompare(b));
1024
- const ignored = defaultIsIgnored(cwd, paths);
1025
- const edges = [];
1026
- for (const path of paths) {
1027
- if (ignored.has(path) || isHardDeniedPath(path) || !SUPPORTED.has(extension(path))) continue;
1028
- const absolute = (0, import_node_path5.join)(cwd, ...path.split("/"));
1029
- if (!(0, import_node_fs4.existsSync)(absolute)) continue;
1030
- try {
1031
- edges.push(...graphEdgesForSource(repo, commit, path, (0, import_node_fs4.readFileSync)(absolute, "utf8"), rosterRepos));
1032
- } catch {
1033
- }
1034
- if (edges.length >= V4_GRAPH_MAX_EDGES) break;
1035
- }
1036
- return edges.slice(0, V4_GRAPH_MAX_EDGES).sort((a, b) => a.source.path.localeCompare(b.source.path) || a.source.line - b.source.line || a.kind.localeCompare(b.kind) || a.id.localeCompare(b.id));
1037
- }
1038
- // Annotate the CommonJS export names for ESM import in node:
1039
- 0 && (module.exports = {
1040
- REPO_INDEX_V4_SCHEMA,
1041
- V4_DELTA_DEEPEN_STEPS,
1042
- V4_GRAPH_MAX_EDGES,
1043
- V4_GRAPH_MAX_EDGES_PER_FILE,
1044
- V4_MAX_ARTIFACT_BYTES,
1045
- V4_MAX_CHUNKS,
1046
- V4_STAGE_MAX_BODY_BYTES,
1047
- V4_STAGE_MAX_RECORDS,
1048
- buildGraphEdges,
1049
- buildRepoIndexV4,
1050
- buildRepoIndexV4Detailed,
1051
- buildStructuralChunks,
1052
- buildStructuralChunksForPaths,
1053
- canonicalRepoIndexPaths,
1054
- changedPaths,
1055
- compareV4Chunks,
1056
- encodedStageBytes,
1057
- formatV4BuildMetrics,
1058
- gitRunner,
1059
- graphEdgesForSource,
1060
- isRepoIndexDeltaCompatible,
1061
- languageForPath,
1062
- parseNameStatusZ,
1063
- planRepoIndexV4Delta,
1064
- readRepoIndexProvenance,
1065
- removedPaths,
1066
- repoIndexV4DeltaBase,
1067
- repoIndexV4StorePath,
1068
- shardRepoIndexV4,
1069
- structuralChunksForSource
1070
- });