@maxgfr/codeindex 2.10.0 → 2.11.1
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.
- package/LICENSE +21 -0
- package/README.md +54 -2
- package/package.json +1 -1
- package/scripts/engine.d.mts +18 -3
- package/scripts/engine.mjs +326 -147
- package/src/embed/encode.ts +26 -16
- package/src/embed/endpoint.ts +110 -21
- package/src/embed/index.ts +30 -14
- package/src/embed/search.ts +9 -3
- package/src/engine-cli.ts +99 -22
- package/src/engine.ts +17 -5
- package/src/extract/code.ts +55 -47
- package/src/lang/common.ts +64 -0
- package/src/lang/registry.ts +21 -6
- package/src/mcp.ts +31 -17
- package/src/types.ts +10 -3
package/scripts/engine.mjs
CHANGED
|
@@ -14,9 +14,9 @@ var ENGINE_VERSION, SCHEMA_VERSION, EXTRACTOR_VERSION;
|
|
|
14
14
|
var init_types = __esm({
|
|
15
15
|
"src/types.ts"() {
|
|
16
16
|
"use strict";
|
|
17
|
-
ENGINE_VERSION = "2.
|
|
17
|
+
ENGINE_VERSION = "2.11.1";
|
|
18
18
|
SCHEMA_VERSION = 4;
|
|
19
|
-
EXTRACTOR_VERSION =
|
|
19
|
+
EXTRACTOR_VERSION = 8;
|
|
20
20
|
}
|
|
21
21
|
});
|
|
22
22
|
|
|
@@ -731,7 +731,57 @@ function scan(rel, content, lang, rules) {
|
|
|
731
731
|
function extToLang(ext) {
|
|
732
732
|
return EXT_LANG[ext] ?? "other";
|
|
733
733
|
}
|
|
734
|
-
|
|
734
|
+
function extractReexports(rel, content, localSymbols) {
|
|
735
|
+
if (!REEXPORT_EXTS.has(rel.slice(rel.lastIndexOf(".")))) return [];
|
|
736
|
+
const lang = /\.(ts|tsx|mts|cts)$/.test(rel) ? "typescript" : "javascript";
|
|
737
|
+
const out2 = [];
|
|
738
|
+
const seen = /* @__PURE__ */ new Set();
|
|
739
|
+
const lineAt = (idx) => content.slice(0, idx).split(/\r?\n/).length;
|
|
740
|
+
const localKindOf = /* @__PURE__ */ new Map();
|
|
741
|
+
for (const s of localSymbols) if (!localKindOf.has(s.name)) localKindOf.set(s.name, s.kind);
|
|
742
|
+
const named = /export\s*\{([\s\S]*?)\}\s*(?:from\s*['"]([^'"]+)['"])?\s*;?/g;
|
|
743
|
+
let m;
|
|
744
|
+
while ((m = named.exec(content)) && out2.length < 60) {
|
|
745
|
+
const from = m[2];
|
|
746
|
+
for (const part of m[1].split(",")) {
|
|
747
|
+
const p = part.trim().replace(/^type\s+/, "");
|
|
748
|
+
const as = /^(\S+)\s+as\s+([A-Za-z_$][\w$]*)$/.exec(p);
|
|
749
|
+
const orig = as ? as[1] : p;
|
|
750
|
+
const name2 = as ? as[2] : p;
|
|
751
|
+
if (!/^[A-Za-z_$][\w$]*$/.test(name2) || name2 === "default" || seen.has(name2)) continue;
|
|
752
|
+
seen.add(name2);
|
|
753
|
+
const mirroredKind = !from ? localKindOf.get(orig) : void 0;
|
|
754
|
+
out2.push({
|
|
755
|
+
name: name2,
|
|
756
|
+
kind: mirroredKind ?? "reexport",
|
|
757
|
+
file: rel,
|
|
758
|
+
line: lineAt(m.index),
|
|
759
|
+
signature: from ? `export { ${name2} } from "${from}"` : `export { ${name2} }`,
|
|
760
|
+
exported: true,
|
|
761
|
+
lang
|
|
762
|
+
});
|
|
763
|
+
}
|
|
764
|
+
}
|
|
765
|
+
const star = /export\s*\*\s*(?:as\s+([A-Za-z_$][\w$]*)\s+)?from\s*['"]([^'"]+)['"]/g;
|
|
766
|
+
while ((m = star.exec(content)) && out2.length < 60) {
|
|
767
|
+
const ns = m[1];
|
|
768
|
+
const from = m[2];
|
|
769
|
+
const key = "*" + (ns ?? from);
|
|
770
|
+
if (seen.has(key)) continue;
|
|
771
|
+
seen.add(key);
|
|
772
|
+
out2.push({
|
|
773
|
+
name: ns ?? `* (${from})`,
|
|
774
|
+
kind: ns ? "reexport" : "reexport-all",
|
|
775
|
+
file: rel,
|
|
776
|
+
line: lineAt(m.index),
|
|
777
|
+
signature: `export * ${ns ? `as ${ns} ` : ""}from "${from}"`,
|
|
778
|
+
exported: true,
|
|
779
|
+
lang
|
|
780
|
+
});
|
|
781
|
+
}
|
|
782
|
+
return out2;
|
|
783
|
+
}
|
|
784
|
+
var EXT_LANG, REEXPORT_EXTS;
|
|
735
785
|
var init_common = __esm({
|
|
736
786
|
"src/lang/common.ts"() {
|
|
737
787
|
"use strict";
|
|
@@ -799,6 +849,7 @@ var init_common = __esm({
|
|
|
799
849
|
".svelte": "svelte",
|
|
800
850
|
".astro": "astro"
|
|
801
851
|
};
|
|
852
|
+
REEXPORT_EXTS = /* @__PURE__ */ new Set([".ts", ".tsx", ".mts", ".cts", ".js", ".jsx", ".mjs", ".cjs"]);
|
|
802
853
|
}
|
|
803
854
|
});
|
|
804
855
|
|
|
@@ -1231,12 +1282,18 @@ var init_scala = __esm({
|
|
|
1231
1282
|
// src/lang/registry.ts
|
|
1232
1283
|
function extractSymbols(rel, ext, content) {
|
|
1233
1284
|
const extractor = BY_EXT.get(ext);
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1285
|
+
let symbols;
|
|
1286
|
+
if (!extractor) symbols = [];
|
|
1287
|
+
else {
|
|
1288
|
+
try {
|
|
1289
|
+
symbols = extractor.extract(rel, content);
|
|
1290
|
+
} catch {
|
|
1291
|
+
symbols = [];
|
|
1292
|
+
}
|
|
1239
1293
|
}
|
|
1294
|
+
const known = new Set(symbols.map((s) => s.name));
|
|
1295
|
+
const reexports = extractReexports(rel, content, symbols).filter((s) => !known.has(s.name));
|
|
1296
|
+
return reexports.length ? [...symbols, ...reexports] : symbols;
|
|
1240
1297
|
}
|
|
1241
1298
|
function languageOf(ext) {
|
|
1242
1299
|
return BY_EXT.get(ext)?.lang ?? extToLang(ext);
|
|
@@ -6340,54 +6397,9 @@ function extractImports(ext, content) {
|
|
|
6340
6397
|
}
|
|
6341
6398
|
return [...specs].map((spec) => ({ kind: "import", spec }));
|
|
6342
6399
|
}
|
|
6343
|
-
function
|
|
6344
|
-
if (!JS_TS.has(rel.slice(rel.lastIndexOf(".")))) return [];
|
|
6345
|
-
const lang = /\.(ts|tsx|mts|cts)$/.test(rel) ? "typescript" : "javascript";
|
|
6346
|
-
const out2 = [];
|
|
6347
|
-
const seen = /* @__PURE__ */ new Set();
|
|
6348
|
-
const lineAt = (idx) => content.slice(0, idx).split(/\r?\n/).length;
|
|
6349
|
-
const named = /export\s*\{([\s\S]*?)\}\s*(?:from\s*['"]([^'"]+)['"])?\s*;?/g;
|
|
6350
|
-
let m;
|
|
6351
|
-
while ((m = named.exec(content)) && out2.length < 60) {
|
|
6352
|
-
const from = m[2];
|
|
6353
|
-
for (const part of m[1].split(",")) {
|
|
6354
|
-
const p = part.trim().replace(/^type\s+/, "");
|
|
6355
|
-
const as = /^(\S+)\s+as\s+([A-Za-z_$][\w$]*)$/.exec(p);
|
|
6356
|
-
const name2 = as ? as[2] : p;
|
|
6357
|
-
if (!/^[A-Za-z_$][\w$]*$/.test(name2) || name2 === "default" || seen.has(name2)) continue;
|
|
6358
|
-
seen.add(name2);
|
|
6359
|
-
out2.push({
|
|
6360
|
-
name: name2,
|
|
6361
|
-
kind: "reexport",
|
|
6362
|
-
file: rel,
|
|
6363
|
-
line: lineAt(m.index),
|
|
6364
|
-
signature: from ? `export { ${name2} } from "${from}"` : `export { ${name2} }`,
|
|
6365
|
-
exported: true,
|
|
6366
|
-
lang
|
|
6367
|
-
});
|
|
6368
|
-
}
|
|
6369
|
-
}
|
|
6370
|
-
const star = /export\s*\*\s*(?:as\s+([A-Za-z_$][\w$]*)\s+)?from\s*['"]([^'"]+)['"]/g;
|
|
6371
|
-
while ((m = star.exec(content)) && out2.length < 60) {
|
|
6372
|
-
const ns = m[1];
|
|
6373
|
-
const from = m[2];
|
|
6374
|
-
const key = "*" + (ns ?? from);
|
|
6375
|
-
if (seen.has(key)) continue;
|
|
6376
|
-
seen.add(key);
|
|
6377
|
-
out2.push({
|
|
6378
|
-
name: ns ?? `* (${from})`,
|
|
6379
|
-
kind: ns ? "reexport" : "reexport-all",
|
|
6380
|
-
file: rel,
|
|
6381
|
-
line: lineAt(m.index),
|
|
6382
|
-
signature: `export * ${ns ? `as ${ns} ` : ""}from "${from}"`,
|
|
6383
|
-
exported: true,
|
|
6384
|
-
lang
|
|
6385
|
-
});
|
|
6386
|
-
}
|
|
6387
|
-
return out2;
|
|
6388
|
-
}
|
|
6389
|
-
function collectCallsRegex(content) {
|
|
6400
|
+
function collectCallsRegex(content, symbols = []) {
|
|
6390
6401
|
const out2 = /* @__PURE__ */ new Map();
|
|
6402
|
+
const ownDefLines = new Set(symbols.map((s) => `${s.name} ${s.line}`));
|
|
6391
6403
|
const lines = content.split("\n");
|
|
6392
6404
|
const CALL_RE = /(?:\bnew\s+)?(?:([A-Za-z_$][\w$]*)\s*\.\s*)?([A-Za-z_$][\w$]*)\s*\(/g;
|
|
6393
6405
|
for (let i2 = 0; i2 < lines.length && out2.size < 512; i2++) {
|
|
@@ -6395,13 +6407,28 @@ function collectCallsRegex(content) {
|
|
|
6395
6407
|
const trimmed = line.trimStart();
|
|
6396
6408
|
if (trimmed.startsWith("//") || trimmed.startsWith("#") || trimmed.startsWith("*")) continue;
|
|
6397
6409
|
CALL_RE.lastIndex = 0;
|
|
6410
|
+
let probe;
|
|
6411
|
+
const introducerCaught = /* @__PURE__ */ new Set();
|
|
6412
|
+
while ((probe = CALL_RE.exec(line)) !== null) {
|
|
6413
|
+
const name2 = probe[2];
|
|
6414
|
+
const key = `${name2} ${i2 + 1}`;
|
|
6415
|
+
if (ownDefLines.has(key) && DEF_INTRODUCERS.test(line.slice(0, probe.index))) introducerCaught.add(key);
|
|
6416
|
+
}
|
|
6417
|
+
CALL_RE.lastIndex = 0;
|
|
6398
6418
|
let m;
|
|
6419
|
+
const fallbackExcluded = /* @__PURE__ */ new Set();
|
|
6399
6420
|
while ((m = CALL_RE.exec(line)) !== null && out2.size < 512) {
|
|
6400
6421
|
const receiver = m[1];
|
|
6401
6422
|
const name2 = m[2];
|
|
6402
6423
|
if (name2.length < 2 || CALL_KEYWORDS.has(name2)) continue;
|
|
6403
6424
|
if (DEF_INTRODUCERS.test(line.slice(0, m.index))) continue;
|
|
6404
6425
|
const key = `${name2} ${i2 + 1}`;
|
|
6426
|
+
if (ownDefLines.has(key) && !introducerCaught.has(key)) {
|
|
6427
|
+
if (!fallbackExcluded.has(key)) {
|
|
6428
|
+
fallbackExcluded.add(key);
|
|
6429
|
+
continue;
|
|
6430
|
+
}
|
|
6431
|
+
}
|
|
6405
6432
|
if (!out2.has(key)) out2.set(key, receiver ? { name: name2, line: i2 + 1, receiver } : { name: name2, line: i2 + 1 });
|
|
6406
6433
|
}
|
|
6407
6434
|
}
|
|
@@ -6411,7 +6438,7 @@ function extractCode(rel, ext, content) {
|
|
|
6411
6438
|
const ast = extractAst(rel, ext, content);
|
|
6412
6439
|
const symbols = (ast ? ast.symbols : extractSymbols(rel, ext, content)).slice(0, 400);
|
|
6413
6440
|
const known = new Set(symbols.map((s) => s.name));
|
|
6414
|
-
const reexports = extractReexports(rel, content).filter((s) => !known.has(s.name));
|
|
6441
|
+
const reexports = extractReexports(rel, content, symbols).filter((s) => !known.has(s.name));
|
|
6415
6442
|
return {
|
|
6416
6443
|
symbols: [...symbols, ...reexports],
|
|
6417
6444
|
summary: topDocComment(content),
|
|
@@ -6422,7 +6449,9 @@ function extractCode(rel, ext, content) {
|
|
|
6422
6449
|
idents: ast?.idents,
|
|
6423
6450
|
// AST call sites when a grammar parsed the file; the conservative regex
|
|
6424
6451
|
// collector otherwise, so caller indexes exist without the wasm sidecar.
|
|
6425
|
-
|
|
6452
|
+
// `symbols` (this file's own regex-extracted defs) lets the collector
|
|
6453
|
+
// exclude a definition's own name+line from its call candidates.
|
|
6454
|
+
calls: ast ? ast.calls : collectCallsRegex(content, symbols),
|
|
6426
6455
|
importedNames: ast?.importedNames
|
|
6427
6456
|
};
|
|
6428
6457
|
}
|
|
@@ -6432,6 +6461,7 @@ var init_code = __esm({
|
|
|
6432
6461
|
"use strict";
|
|
6433
6462
|
init_registry();
|
|
6434
6463
|
init_extract();
|
|
6464
|
+
init_common();
|
|
6435
6465
|
JS_TS = /* @__PURE__ */ new Set([".ts", ".tsx", ".mts", ".cts", ".js", ".jsx", ".mjs", ".cjs"]);
|
|
6436
6466
|
PY = /* @__PURE__ */ new Set([".py", ".pyi"]);
|
|
6437
6467
|
C_CPP = /* @__PURE__ */ new Set([".c", ".h", ".cc", ".cpp", ".cxx", ".hpp", ".hh"]);
|
|
@@ -9447,30 +9477,34 @@ function roundHalfToEven(x) {
|
|
|
9447
9477
|
if (diff > 0.5) return f + 1;
|
|
9448
9478
|
return f % 2 === 0 ? f : f + 1;
|
|
9449
9479
|
}
|
|
9450
|
-
function
|
|
9451
|
-
const
|
|
9480
|
+
function quantize(vec) {
|
|
9481
|
+
const dim = vec.length;
|
|
9452
9482
|
const out2 = new Int8Array(dim);
|
|
9453
|
-
const ids = tokenize(text, model);
|
|
9454
|
-
if (ids.length === 0) return out2;
|
|
9455
|
-
const pooled = new Float64Array(dim);
|
|
9456
|
-
for (const id of ids) {
|
|
9457
|
-
const base = id * dim;
|
|
9458
|
-
for (let d = 0; d < dim; d++) pooled[d] += weights[base + d];
|
|
9459
|
-
}
|
|
9460
|
-
const inv = 1 / ids.length;
|
|
9461
|
-
for (let d = 0; d < dim; d++) pooled[d] *= inv;
|
|
9462
9483
|
let sumsq = 0;
|
|
9463
|
-
for (let d = 0; d < dim; d++) sumsq +=
|
|
9484
|
+
for (let d = 0; d < dim; d++) sumsq += vec[d] * vec[d];
|
|
9464
9485
|
const norm2 = Math.sqrt(sumsq);
|
|
9465
9486
|
if (norm2 === 0) return out2;
|
|
9466
9487
|
for (let d = 0; d < dim; d++) {
|
|
9467
|
-
let q = roundHalfToEven(
|
|
9488
|
+
let q = roundHalfToEven(vec[d] / norm2 * QUANT);
|
|
9468
9489
|
if (q > QUANT) q = QUANT;
|
|
9469
9490
|
else if (q < -QUANT) q = -QUANT;
|
|
9470
9491
|
out2[d] = q;
|
|
9471
9492
|
}
|
|
9472
9493
|
return out2;
|
|
9473
9494
|
}
|
|
9495
|
+
function encode(model, text) {
|
|
9496
|
+
const { dim, weights } = model;
|
|
9497
|
+
const ids = tokenize(text, model);
|
|
9498
|
+
if (ids.length === 0) return new Int8Array(dim);
|
|
9499
|
+
const pooled = new Float64Array(dim);
|
|
9500
|
+
for (const id of ids) {
|
|
9501
|
+
const base = id * dim;
|
|
9502
|
+
for (let d = 0; d < dim; d++) pooled[d] += weights[base + d];
|
|
9503
|
+
}
|
|
9504
|
+
const inv = 1 / ids.length;
|
|
9505
|
+
for (let d = 0; d < dim; d++) pooled[d] *= inv;
|
|
9506
|
+
return quantize(pooled);
|
|
9507
|
+
}
|
|
9474
9508
|
function intDot(a, b) {
|
|
9475
9509
|
const n = Math.min(a.length, b.length);
|
|
9476
9510
|
let dot = 0;
|
|
@@ -9493,8 +9527,8 @@ function symbolText(rel, name2, signature, summary) {
|
|
|
9493
9527
|
function fileText(rel, title, summary, headings) {
|
|
9494
9528
|
return [title ?? "", summary ?? "", ...headings, rel.replace(/\//g, " ")].join("\n");
|
|
9495
9529
|
}
|
|
9496
|
-
function
|
|
9497
|
-
const
|
|
9530
|
+
function embeddingUnits(scan2) {
|
|
9531
|
+
const units = [];
|
|
9498
9532
|
for (const f of scan2.files) {
|
|
9499
9533
|
const seen = /* @__PURE__ */ new Set();
|
|
9500
9534
|
let hadSymbol = false;
|
|
@@ -9502,20 +9536,22 @@ function buildEmbeddingIndex(scan2, model) {
|
|
|
9502
9536
|
if (seen.has(s.name)) continue;
|
|
9503
9537
|
seen.add(s.name);
|
|
9504
9538
|
hadSymbol = true;
|
|
9505
|
-
|
|
9506
|
-
file: f.rel,
|
|
9507
|
-
symbol: s.name,
|
|
9508
|
-
line: s.line,
|
|
9509
|
-
vec: encode(model, symbolText(f.rel, s.name, s.signature, f.summary))
|
|
9510
|
-
});
|
|
9539
|
+
units.push({ file: f.rel, symbol: s.name, line: s.line, text: symbolText(f.rel, s.name, s.signature, f.summary) });
|
|
9511
9540
|
}
|
|
9512
9541
|
if (!hadSymbol) {
|
|
9513
9542
|
const text = fileText(f.rel, f.title, f.summary, f.headings);
|
|
9514
|
-
if (text.replace(/\s+/g, "")) {
|
|
9515
|
-
records.push({ file: f.rel, vec: encode(model, text) });
|
|
9516
|
-
}
|
|
9543
|
+
if (text.replace(/\s+/g, "")) units.push({ file: f.rel, text });
|
|
9517
9544
|
}
|
|
9518
9545
|
}
|
|
9546
|
+
return units;
|
|
9547
|
+
}
|
|
9548
|
+
function buildEmbeddingIndex(scan2, model) {
|
|
9549
|
+
const records = embeddingUnits(scan2).map((u) => {
|
|
9550
|
+
const rec = { file: u.file, vec: encode(model, u.text) };
|
|
9551
|
+
if (u.symbol !== void 0) rec.symbol = u.symbol;
|
|
9552
|
+
if (u.line !== void 0) rec.line = u.line;
|
|
9553
|
+
return rec;
|
|
9554
|
+
});
|
|
9519
9555
|
return { embedVersion: EMBED_VERSION, modelId: model.modelId, dim: model.dim, records };
|
|
9520
9556
|
}
|
|
9521
9557
|
function serializeEmbeddings(index) {
|
|
@@ -9572,10 +9608,10 @@ var init_embed = __esm({
|
|
|
9572
9608
|
function searchSemantic(scan2, query, index, opts = {}) {
|
|
9573
9609
|
const limit = opts.limit ?? DEFAULT_LIMIT2;
|
|
9574
9610
|
const lexical = searchIndex(scan2, query, { limit: Math.max(limit, 50), fuzzy: opts.fuzzy });
|
|
9575
|
-
|
|
9611
|
+
const q = opts.queryVec ?? (opts.model ? encode(opts.model, query) : void 0);
|
|
9612
|
+
if (!q || !index || index.records.length === 0) {
|
|
9576
9613
|
return lexical.slice(0, limit);
|
|
9577
9614
|
}
|
|
9578
|
-
const q = encode(opts.model, query);
|
|
9579
9615
|
const bestByFile = /* @__PURE__ */ new Map();
|
|
9580
9616
|
for (const r of index.records) {
|
|
9581
9617
|
const dot = intDot(q, r.vec);
|
|
@@ -9614,6 +9650,99 @@ var init_search = __esm({
|
|
|
9614
9650
|
}
|
|
9615
9651
|
});
|
|
9616
9652
|
|
|
9653
|
+
// src/embed/endpoint.ts
|
|
9654
|
+
function resolveEmbedEndpoint(opts = {}) {
|
|
9655
|
+
const url = opts.url ?? process.env.CODEINDEX_EMBED_ENDPOINT;
|
|
9656
|
+
return url && url.trim() ? url.trim() : void 0;
|
|
9657
|
+
}
|
|
9658
|
+
function stripTrailingSlash(url) {
|
|
9659
|
+
return url.replace(/\/+$/, "");
|
|
9660
|
+
}
|
|
9661
|
+
function embedEndpointUrl(base) {
|
|
9662
|
+
const b = stripTrailingSlash(base);
|
|
9663
|
+
return b.endsWith("/embed") ? b : b + "/embed";
|
|
9664
|
+
}
|
|
9665
|
+
function healthzUrl(base) {
|
|
9666
|
+
return stripTrailingSlash(base).replace(/\/embed$/, "") + "/healthz";
|
|
9667
|
+
}
|
|
9668
|
+
function resolveTimeout(opts) {
|
|
9669
|
+
if (typeof opts.timeoutMs === "number") return opts.timeoutMs;
|
|
9670
|
+
const env = Number(process.env.CODEINDEX_EMBED_TIMEOUT_MS);
|
|
9671
|
+
return Number.isFinite(env) && env > 0 ? env : 3e4;
|
|
9672
|
+
}
|
|
9673
|
+
async function embedViaEndpoint(texts, opts = {}) {
|
|
9674
|
+
const base = resolveEmbedEndpoint(opts);
|
|
9675
|
+
if (!base) throw new Error("no embedding endpoint configured (set CODEINDEX_EMBED_ENDPOINT or pass opts.url)");
|
|
9676
|
+
const url = embedEndpointUrl(base);
|
|
9677
|
+
const controller = new AbortController();
|
|
9678
|
+
const timer = setTimeout(() => controller.abort(), resolveTimeout(opts));
|
|
9679
|
+
try {
|
|
9680
|
+
const res = await fetch(url, {
|
|
9681
|
+
method: "POST",
|
|
9682
|
+
headers: { "content-type": "application/json", ...opts.headers ?? {} },
|
|
9683
|
+
body: JSON.stringify({ texts }),
|
|
9684
|
+
signal: controller.signal
|
|
9685
|
+
});
|
|
9686
|
+
if (!res.ok) throw new Error(`embedding endpoint ${url} returned HTTP ${res.status}`);
|
|
9687
|
+
const data = await res.json();
|
|
9688
|
+
const vectors = data.vectors;
|
|
9689
|
+
if (!Array.isArray(vectors) || !vectors.every((v) => Array.isArray(v) && v.every((x) => typeof x === "number"))) {
|
|
9690
|
+
throw new Error(`embedding endpoint ${url} returned a malformed { vectors } payload`);
|
|
9691
|
+
}
|
|
9692
|
+
return vectors;
|
|
9693
|
+
} finally {
|
|
9694
|
+
clearTimeout(timer);
|
|
9695
|
+
}
|
|
9696
|
+
}
|
|
9697
|
+
async function probeEndpoint(base, opts = {}) {
|
|
9698
|
+
const controller = new AbortController();
|
|
9699
|
+
const timer = setTimeout(() => controller.abort(), resolveTimeout(opts));
|
|
9700
|
+
try {
|
|
9701
|
+
const res = await fetch(healthzUrl(base), { signal: controller.signal, headers: opts.headers });
|
|
9702
|
+
return res.ok;
|
|
9703
|
+
} catch {
|
|
9704
|
+
return false;
|
|
9705
|
+
} finally {
|
|
9706
|
+
clearTimeout(timer);
|
|
9707
|
+
}
|
|
9708
|
+
}
|
|
9709
|
+
async function encodeQueryViaEndpoint(query, opts = {}) {
|
|
9710
|
+
const [vec] = await embedViaEndpoint([query], opts);
|
|
9711
|
+
if (!vec) throw new Error("embedding endpoint returned no vector for the query");
|
|
9712
|
+
return quantize(vec);
|
|
9713
|
+
}
|
|
9714
|
+
async function buildEndpointIndex(scan2, opts = {}) {
|
|
9715
|
+
const units = embeddingUnits(scan2);
|
|
9716
|
+
const batchSize = opts.batchSize && opts.batchSize > 0 ? opts.batchSize : 64;
|
|
9717
|
+
const records = [];
|
|
9718
|
+
let dim = 0;
|
|
9719
|
+
for (let i2 = 0; i2 < units.length; i2 += batchSize) {
|
|
9720
|
+
const batch = units.slice(i2, i2 + batchSize);
|
|
9721
|
+
const vectors = await embedViaEndpoint(batch.map((u) => u.text), opts);
|
|
9722
|
+
if (vectors.length !== batch.length) {
|
|
9723
|
+
throw new Error(`embedding endpoint returned ${vectors.length} vectors for ${batch.length} texts`);
|
|
9724
|
+
}
|
|
9725
|
+
for (let j = 0; j < batch.length; j++) {
|
|
9726
|
+
const u = batch[j];
|
|
9727
|
+
const vec = quantize(vectors[j]);
|
|
9728
|
+
if (vec.length > dim) dim = vec.length;
|
|
9729
|
+
const rec = { file: u.file, vec };
|
|
9730
|
+
if (u.symbol !== void 0) rec.symbol = u.symbol;
|
|
9731
|
+
if (u.line !== void 0) rec.line = u.line;
|
|
9732
|
+
records.push(rec);
|
|
9733
|
+
}
|
|
9734
|
+
}
|
|
9735
|
+
return { embedVersion: EMBED_VERSION, modelId: "endpoint", dim, records };
|
|
9736
|
+
}
|
|
9737
|
+
var init_endpoint = __esm({
|
|
9738
|
+
"src/embed/endpoint.ts"() {
|
|
9739
|
+
"use strict";
|
|
9740
|
+
init_encode();
|
|
9741
|
+
init_model();
|
|
9742
|
+
init_embed();
|
|
9743
|
+
}
|
|
9744
|
+
});
|
|
9745
|
+
|
|
9617
9746
|
// src/rules.ts
|
|
9618
9747
|
function isEntrypointLike(rel) {
|
|
9619
9748
|
const base = rel.split("/").pop();
|
|
@@ -10009,7 +10138,7 @@ function str(v) {
|
|
|
10009
10138
|
function strArray(v) {
|
|
10010
10139
|
return Array.isArray(v) && v.every((x) => typeof x === "string") && v.length ? v : void 0;
|
|
10011
10140
|
}
|
|
10012
|
-
function callTool(name2, args2) {
|
|
10141
|
+
async function callTool(name2, args2) {
|
|
10013
10142
|
const repo = str(args2.repo);
|
|
10014
10143
|
if (!repo) throw new Error("`repo` is required (absolute path to the repository root)");
|
|
10015
10144
|
const scanOpts = { scope: str(args2.scope), include: strArray(args2.include), exclude: strArray(args2.exclude) };
|
|
@@ -10146,6 +10275,16 @@ function callTool(name2, args2) {
|
|
|
10146
10275
|
const limit = typeof args2.limit === "number" ? args2.limit : void 0;
|
|
10147
10276
|
const fuzzy = typeof args2.fuzzy === "boolean" ? args2.fuzzy : void 0;
|
|
10148
10277
|
if (args2.semantic === true) {
|
|
10278
|
+
const endpoint = resolveEmbedEndpoint();
|
|
10279
|
+
if (endpoint) {
|
|
10280
|
+
try {
|
|
10281
|
+
const index = await buildEndpointIndex(scan2);
|
|
10282
|
+
const queryVec = await encodeQueryViaEndpoint(query);
|
|
10283
|
+
return JSON.stringify(searchSemantic(scan2, query, index, { queryVec, limit, fuzzy }), null, 2);
|
|
10284
|
+
} catch {
|
|
10285
|
+
return JSON.stringify(searchIndex(scan2, query, { limit, fuzzy }), null, 2);
|
|
10286
|
+
}
|
|
10287
|
+
}
|
|
10149
10288
|
const modelDir = resolveEmbedModelDir(repo);
|
|
10150
10289
|
const model = modelDir ? loadEmbedModel(modelDir) : void 0;
|
|
10151
10290
|
if (model) {
|
|
@@ -10158,15 +10297,16 @@ function callTool(name2, args2) {
|
|
|
10158
10297
|
if (name2 === "embed_status") {
|
|
10159
10298
|
const modelDir = resolveEmbedModelDir(repo);
|
|
10160
10299
|
const model = modelDir ? loadEmbedModel(modelDir) : void 0;
|
|
10161
|
-
|
|
10162
|
-
|
|
10163
|
-
|
|
10164
|
-
|
|
10165
|
-
|
|
10166
|
-
},
|
|
10167
|
-
null
|
|
10168
|
-
|
|
10169
|
-
);
|
|
10300
|
+
const endpoint = resolveEmbedEndpoint();
|
|
10301
|
+
const mode = endpoint ? "endpoint" : model ? "static" : "none";
|
|
10302
|
+
const status = {
|
|
10303
|
+
embedVersion: EMBED_VERSION,
|
|
10304
|
+
mode,
|
|
10305
|
+
model: model ? { present: true, dir: modelDir, modelId: model.modelId, dim: model.dim, vocabSize: model.vocabSize } : { present: false },
|
|
10306
|
+
endpoint: endpoint ?? null
|
|
10307
|
+
};
|
|
10308
|
+
if (endpoint) status.endpointReachable = await probeEndpoint(endpoint);
|
|
10309
|
+
return JSON.stringify(status, null, 2);
|
|
10170
10310
|
}
|
|
10171
10311
|
if (name2 === "check_rules") {
|
|
10172
10312
|
const rules = parseRules(args2.rules);
|
|
@@ -10192,9 +10332,9 @@ async function runMcpServer() {
|
|
|
10192
10332
|
continue;
|
|
10193
10333
|
}
|
|
10194
10334
|
const requests = Array.isArray(parsed) ? parsed : [parsed];
|
|
10195
|
-
for (const req of requests) handle2(req);
|
|
10335
|
+
for (const req of requests) await handle2(req);
|
|
10196
10336
|
}
|
|
10197
|
-
function handle2(req) {
|
|
10337
|
+
async function handle2(req) {
|
|
10198
10338
|
if (req.id === void 0 || req.id === null) return;
|
|
10199
10339
|
try {
|
|
10200
10340
|
if (req.method === "initialize") {
|
|
@@ -10215,7 +10355,7 @@ async function runMcpServer() {
|
|
|
10215
10355
|
const name2 = str(params.name) ?? "";
|
|
10216
10356
|
const args2 = params.arguments ?? {};
|
|
10217
10357
|
try {
|
|
10218
|
-
const text = callTool(name2, args2);
|
|
10358
|
+
const text = await callTool(name2, args2);
|
|
10219
10359
|
send({ id: req.id, result: { content: [{ type: "text", text }] } });
|
|
10220
10360
|
} catch (e) {
|
|
10221
10361
|
send({
|
|
@@ -10257,6 +10397,7 @@ var init_mcp = __esm({
|
|
|
10257
10397
|
init_model();
|
|
10258
10398
|
init_embed();
|
|
10259
10399
|
init_search();
|
|
10400
|
+
init_endpoint();
|
|
10260
10401
|
repoProp = { repo: { type: "string", description: "Absolute path to the repository root" } };
|
|
10261
10402
|
scopeProps = {
|
|
10262
10403
|
scope: { type: "string", description: "Restrict to one directory (repo-relative)" },
|
|
@@ -10483,7 +10624,7 @@ var init_mcp = __esm({
|
|
|
10483
10624
|
},
|
|
10484
10625
|
semantic: {
|
|
10485
10626
|
type: "boolean",
|
|
10486
|
-
description: "RRF-fuse
|
|
10627
|
+
description: "RRF-fuse an embedding tier with lexical (default false). Precedence: the HTTP endpoint (CODEINDEX_EMBED_ENDPOINT) if set, else a local static model. Degrades silently to lexical-only when neither is available/reachable \u2014 see embed_status."
|
|
10487
10628
|
}
|
|
10488
10629
|
},
|
|
10489
10630
|
required: ["repo", "query"]
|
|
@@ -10491,7 +10632,7 @@ var init_mcp = __esm({
|
|
|
10491
10632
|
},
|
|
10492
10633
|
{
|
|
10493
10634
|
name: "embed_status",
|
|
10494
|
-
description: "Report the
|
|
10635
|
+
description: "Report the embedding tier: the effective mode (none/static/endpoint; endpoint > static model), the resolved model (opt-in, never shipped in the package) with its modelId/dim, EMBED_VERSION, and the configured HTTP endpoint with its reachability. Use to check whether `search` with semantic:true will fuse embeddings or degrade to lexical.",
|
|
10495
10636
|
inputSchema: { type: "object", properties: { ...repoProp }, required: ["repo"] }
|
|
10496
10637
|
},
|
|
10497
10638
|
{
|
|
@@ -10912,37 +11053,7 @@ init_model();
|
|
|
10912
11053
|
init_encode();
|
|
10913
11054
|
init_embed();
|
|
10914
11055
|
init_search();
|
|
10915
|
-
|
|
10916
|
-
// src/embed/endpoint.ts
|
|
10917
|
-
function resolveEmbedEndpoint(opts = {}) {
|
|
10918
|
-
const url = opts.url ?? process.env.CODEINDEX_EMBED_ENDPOINT;
|
|
10919
|
-
return url && url.trim() ? url.trim() : void 0;
|
|
10920
|
-
}
|
|
10921
|
-
async function embedViaEndpoint(texts, opts = {}) {
|
|
10922
|
-
const url = resolveEmbedEndpoint(opts);
|
|
10923
|
-
if (!url) throw new Error("no embedding endpoint configured (set CODEINDEX_EMBED_ENDPOINT or pass opts.url)");
|
|
10924
|
-
const controller = new AbortController();
|
|
10925
|
-
const timer = setTimeout(() => controller.abort(), opts.timeoutMs ?? 3e4);
|
|
10926
|
-
try {
|
|
10927
|
-
const res = await fetch(url, {
|
|
10928
|
-
method: "POST",
|
|
10929
|
-
headers: { "content-type": "application/json", ...opts.headers ?? {} },
|
|
10930
|
-
body: JSON.stringify({ texts }),
|
|
10931
|
-
signal: controller.signal
|
|
10932
|
-
});
|
|
10933
|
-
if (!res.ok) throw new Error(`embedding endpoint ${url} returned HTTP ${res.status}`);
|
|
10934
|
-
const data = await res.json();
|
|
10935
|
-
const vectors = data.vectors;
|
|
10936
|
-
if (!Array.isArray(vectors) || !vectors.every((v) => Array.isArray(v) && v.every((x) => typeof x === "number"))) {
|
|
10937
|
-
throw new Error(`embedding endpoint ${url} returned a malformed { vectors } payload`);
|
|
10938
|
-
}
|
|
10939
|
-
return vectors;
|
|
10940
|
-
} finally {
|
|
10941
|
-
clearTimeout(timer);
|
|
10942
|
-
}
|
|
10943
|
-
}
|
|
10944
|
-
|
|
10945
|
-
// src/engine.ts
|
|
11056
|
+
init_endpoint();
|
|
10946
11057
|
init_rules();
|
|
10947
11058
|
init_coupling();
|
|
10948
11059
|
init_repomap();
|
|
@@ -10978,6 +11089,8 @@ init_rules();
|
|
|
10978
11089
|
init_model();
|
|
10979
11090
|
init_embed();
|
|
10980
11091
|
init_search();
|
|
11092
|
+
init_endpoint();
|
|
11093
|
+
init_util();
|
|
10981
11094
|
var HELP = `codeindex engine v${ENGINE_VERSION} \u2014 deterministic repo indexing
|
|
10982
11095
|
|
|
10983
11096
|
Usage: engine.mjs <command> [flags]
|
|
@@ -10996,13 +11109,17 @@ Commands:
|
|
|
10996
11109
|
grep Search: cli.mjs grep <pattern> --repo <dir> (JSON hits)
|
|
10997
11110
|
search Keyless BM25 lexical search over symbol names, path segments,
|
|
10998
11111
|
markdown headings and summaries: cli.mjs search "<query>" --repo <dir>.
|
|
10999
|
-
--semantic fuses in
|
|
11000
|
-
|
|
11001
|
-
|
|
11002
|
-
|
|
11003
|
-
embed
|
|
11112
|
+
--semantic fuses in an embedding tier (RRF) \u2014 the HTTP endpoint
|
|
11113
|
+
(CODEINDEX_EMBED_ENDPOINT) if set, else a local static model;
|
|
11114
|
+
degrades to lexical (exit 0) when neither is available/reachable
|
|
11115
|
+
embed Embedding tiers (opt-in). Precedence: endpoint > static model:
|
|
11116
|
+
embed status Effective mode (none/static/endpoint), model +
|
|
11117
|
+
EMBED_VERSION, and endpoint reachability (JSON)
|
|
11118
|
+
embed build Write embeddings.bin into --out <dir> (static tier)
|
|
11004
11119
|
embed pull Fetch the model asset into CODEINDEX_EMBED_DIR (or
|
|
11005
11120
|
<repo>/.codeindex/models/) \u2014 needs CODEINDEX_EMBED_URL
|
|
11121
|
+
embed serve Print (or --run) the docker command that starts the
|
|
11122
|
+
containerized embedding server (rich tier)
|
|
11006
11123
|
rules Architecture rules (forbidden edges, cycles, orphans) validated
|
|
11007
11124
|
against the link-graph: --config <codeindex.rules.json>; exits 1
|
|
11008
11125
|
on any error-severity violation (a CI gate)
|
|
@@ -11030,8 +11147,10 @@ Flags:
|
|
|
11030
11147
|
--limit <n> Max results for \`search\` (default 20)
|
|
11031
11148
|
--no-fuzzy \`search\`: disable trigram fuzzy fallback for query terms
|
|
11032
11149
|
with zero document frequency (default: enabled)
|
|
11033
|
-
--semantic \`search\`: RRF-fuse
|
|
11034
|
-
|
|
11150
|
+
--semantic \`search\`: RRF-fuse an embedding tier with lexical \u2014 the
|
|
11151
|
+
HTTP endpoint if CODEINDEX_EMBED_ENDPOINT is set, else a
|
|
11152
|
+
local static model (lexical-only when neither is available)
|
|
11153
|
+
--run \`embed serve\`: run the docker command instead of printing it
|
|
11035
11154
|
--recall \`callers\`: recall-oriented binding (issue #7) \u2014 relaxes
|
|
11036
11155
|
the JS/TS import gate to unique repo-wide names and labels
|
|
11037
11156
|
each site corroborated|unique-name
|
|
@@ -11072,6 +11191,7 @@ function parseFlags(args2) {
|
|
|
11072
11191
|
else if (a === "--no-fuzzy") flags2.fuzzy = false;
|
|
11073
11192
|
else if (a === "--semantic") flags2.semantic = true;
|
|
11074
11193
|
else if (a === "--recall") flags2.recall = true;
|
|
11194
|
+
else if (a === "--run") flags2.run = true;
|
|
11075
11195
|
else if (!a.startsWith("--") && flags2.positional === void 0) flags2.positional = a;
|
|
11076
11196
|
else throw new Error(`unknown flag: ${a}`);
|
|
11077
11197
|
}
|
|
@@ -11182,18 +11302,37 @@ async function runCli(argv) {
|
|
|
11182
11302
|
if (!flags2.positional) throw new Error('search needs a query: cli.mjs search "<query>" --repo <dir>');
|
|
11183
11303
|
const scan2 = scanRepo(flags2.repo, scanOptions(flags2));
|
|
11184
11304
|
if (flags2.semantic) {
|
|
11185
|
-
const
|
|
11186
|
-
const
|
|
11187
|
-
if (!model) {
|
|
11188
|
-
process.stderr.write(
|
|
11189
|
-
"codeindex: semantic search unavailable (no embedding model present) \u2014 returning lexical results; run `codeindex embed pull` to enable it\n"
|
|
11190
|
-
);
|
|
11305
|
+
const endpoint = resolveEmbedEndpoint();
|
|
11306
|
+
const lexical = () => {
|
|
11191
11307
|
const results = searchIndex(scan2, flags2.positional, { limit: flags2.limit, fuzzy: flags2.fuzzy });
|
|
11192
11308
|
emit(JSON.stringify(results, null, 2) + "\n", flags2.out);
|
|
11309
|
+
};
|
|
11310
|
+
if (endpoint) {
|
|
11311
|
+
try {
|
|
11312
|
+
const index = await buildEndpointIndex(scan2);
|
|
11313
|
+
const queryVec = await encodeQueryViaEndpoint(flags2.positional);
|
|
11314
|
+
const results = searchSemantic(scan2, flags2.positional, index, { queryVec, limit: flags2.limit, fuzzy: flags2.fuzzy });
|
|
11315
|
+
emit(JSON.stringify(results, null, 2) + "\n", flags2.out);
|
|
11316
|
+
} catch (e) {
|
|
11317
|
+
process.stderr.write(
|
|
11318
|
+
`codeindex: embedding endpoint ${endpoint} unavailable (${e instanceof Error ? e.message : e}) \u2014 returning lexical results
|
|
11319
|
+
`
|
|
11320
|
+
);
|
|
11321
|
+
lexical();
|
|
11322
|
+
}
|
|
11193
11323
|
} else {
|
|
11194
|
-
const
|
|
11195
|
-
const
|
|
11196
|
-
|
|
11324
|
+
const modelDir = resolveEmbedModelDir(flags2.repo);
|
|
11325
|
+
const model = modelDir ? loadEmbedModel(modelDir) : void 0;
|
|
11326
|
+
if (!model) {
|
|
11327
|
+
process.stderr.write(
|
|
11328
|
+
"codeindex: semantic search unavailable (no embedding model or endpoint) \u2014 returning lexical results; run `codeindex embed pull` or set CODEINDEX_EMBED_ENDPOINT to enable it\n"
|
|
11329
|
+
);
|
|
11330
|
+
lexical();
|
|
11331
|
+
} else {
|
|
11332
|
+
const index = buildEmbeddingIndex(scan2, model);
|
|
11333
|
+
const results = searchSemantic(scan2, flags2.positional, index, { model, limit: flags2.limit, fuzzy: flags2.fuzzy });
|
|
11334
|
+
emit(JSON.stringify(results, null, 2) + "\n", flags2.out);
|
|
11335
|
+
}
|
|
11197
11336
|
}
|
|
11198
11337
|
} else {
|
|
11199
11338
|
const results = searchIndex(scan2, flags2.positional, { limit: flags2.limit, fuzzy: flags2.fuzzy });
|
|
@@ -11204,12 +11343,45 @@ async function runCli(argv) {
|
|
|
11204
11343
|
const modelDir = resolveEmbedModelDir(flags2.repo);
|
|
11205
11344
|
if (sub === "status") {
|
|
11206
11345
|
const model = modelDir ? loadEmbedModel(modelDir) : void 0;
|
|
11346
|
+
const endpoint = resolveEmbedEndpoint();
|
|
11347
|
+
const mode = endpoint ? "endpoint" : model ? "static" : "none";
|
|
11207
11348
|
const status = {
|
|
11208
11349
|
embedVersion: EMBED_VERSION,
|
|
11350
|
+
mode,
|
|
11209
11351
|
model: model ? { present: true, dir: modelDir, modelId: model.modelId, dim: model.dim, vocabSize: model.vocabSize } : { present: false },
|
|
11210
|
-
endpoint:
|
|
11352
|
+
endpoint: endpoint ?? null
|
|
11211
11353
|
};
|
|
11354
|
+
if (endpoint) status.endpointReachable = await probeEndpoint(endpoint);
|
|
11212
11355
|
emit(JSON.stringify(status, null, 2) + "\n", flags2.out);
|
|
11356
|
+
} else if (sub === "serve") {
|
|
11357
|
+
const dockerArgs = ["run", "-d", "-p", "8756:8756", "ghcr.io/maxgfr/codeindex-embed:latest"];
|
|
11358
|
+
const oneLiner = `docker ${dockerArgs.join(" ")}`;
|
|
11359
|
+
if (!have("docker")) {
|
|
11360
|
+
process.stderr.write(
|
|
11361
|
+
"codeindex: docker not found on PATH. Install Docker, then run:\n " + oneLiner + "\n"
|
|
11362
|
+
);
|
|
11363
|
+
process.exitCode = 1;
|
|
11364
|
+
return;
|
|
11365
|
+
}
|
|
11366
|
+
if (flags2.run) {
|
|
11367
|
+
process.stderr.write(`codeindex: starting embedding server \u2192 ${oneLiner}
|
|
11368
|
+
`);
|
|
11369
|
+
const res = sh("docker", dockerArgs);
|
|
11370
|
+
if (res.stdout.trim()) process.stdout.write(res.stdout.trim() + "\n");
|
|
11371
|
+
if (!res.ok) {
|
|
11372
|
+
process.stderr.write(res.stderr || "codeindex: docker run failed\n");
|
|
11373
|
+
process.exitCode = 1;
|
|
11374
|
+
return;
|
|
11375
|
+
}
|
|
11376
|
+
process.stderr.write(
|
|
11377
|
+
'codeindex: server starting on http://localhost:8756 \u2014 then:\n CODEINDEX_EMBED_ENDPOINT=http://localhost:8756 codeindex search "<query>" --repo . --semantic\n'
|
|
11378
|
+
);
|
|
11379
|
+
} else {
|
|
11380
|
+
process.stdout.write(oneLiner + "\n");
|
|
11381
|
+
process.stderr.write(
|
|
11382
|
+
'codeindex: run the line above to start the embedding server (or `embed serve --run`), then:\n CODEINDEX_EMBED_ENDPOINT=http://localhost:8756 codeindex search "<query>" --repo . --semantic\n'
|
|
11383
|
+
);
|
|
11384
|
+
}
|
|
11213
11385
|
} else if (sub === "build") {
|
|
11214
11386
|
if (!flags2.out) throw new Error("embed build needs --out <dir>");
|
|
11215
11387
|
if (!modelDir) {
|
|
@@ -11256,7 +11428,7 @@ async function runCli(argv) {
|
|
|
11256
11428
|
process.stderr.write(`codeindex: model written to ${join12(destDir, "model.json")}
|
|
11257
11429
|
`);
|
|
11258
11430
|
} else {
|
|
11259
|
-
throw new Error("embed needs a subcommand:
|
|
11431
|
+
throw new Error("embed needs a subcommand: status | build | pull | serve");
|
|
11260
11432
|
}
|
|
11261
11433
|
} else if (cmd === "rules") {
|
|
11262
11434
|
if (!flags2.config) throw new Error("rules needs --config <codeindex.rules.json>");
|
|
@@ -11332,6 +11504,7 @@ export {
|
|
|
11332
11504
|
betweennessOf,
|
|
11333
11505
|
buildCallerIndex,
|
|
11334
11506
|
buildEmbeddingIndex,
|
|
11507
|
+
buildEndpointIndex,
|
|
11335
11508
|
buildGraph,
|
|
11336
11509
|
buildIndexArtifacts,
|
|
11337
11510
|
buildModules,
|
|
@@ -11359,9 +11532,12 @@ export {
|
|
|
11359
11532
|
detectWorkspaces,
|
|
11360
11533
|
diffFiles,
|
|
11361
11534
|
diffHunks,
|
|
11535
|
+
embedEndpointUrl,
|
|
11362
11536
|
embedViaEndpoint,
|
|
11537
|
+
embeddingUnits,
|
|
11363
11538
|
enclosingSymbol,
|
|
11364
11539
|
encode,
|
|
11540
|
+
encodeQueryViaEndpoint,
|
|
11365
11541
|
ensureGrammars,
|
|
11366
11542
|
escapeRegExp,
|
|
11367
11543
|
extToLang,
|
|
@@ -11380,6 +11556,7 @@ export {
|
|
|
11380
11556
|
hasEmbedModel,
|
|
11381
11557
|
have,
|
|
11382
11558
|
headCommit,
|
|
11559
|
+
healthzUrl,
|
|
11383
11560
|
insertAfterSymbol,
|
|
11384
11561
|
insertBeforeSymbol,
|
|
11385
11562
|
intDot,
|
|
@@ -11397,6 +11574,8 @@ export {
|
|
|
11397
11574
|
pagerankOf,
|
|
11398
11575
|
parseGitignore,
|
|
11399
11576
|
parseRules,
|
|
11577
|
+
probeEndpoint,
|
|
11578
|
+
quantize,
|
|
11400
11579
|
rankHotspots,
|
|
11401
11580
|
rankedKeywords,
|
|
11402
11581
|
readMemory,
|