orion-super-agent-dev 0.1.28 → 0.1.30
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/out/brains/darwin-arm64/orion-brain +0 -0
- package/out/brains/darwin-x64/orion-brain +0 -0
- package/out/brains/linux-arm64/orion-brain +0 -0
- package/out/brains/linux-x64/orion-brain +0 -0
- package/out/brains/win32-x64/orion-brain.exe +0 -0
- package/out/indexProcessWorker.cjs +1077 -340
- package/out/main.js +8070 -5099
- package/package.json +1 -1
|
@@ -1442,6 +1442,8 @@ ${JSON.stringify(t2, null, 2)}`);
|
|
|
1442
1442
|
});
|
|
1443
1443
|
|
|
1444
1444
|
// ../packages/orion-client-core/src/indexProcessWorker.ts
|
|
1445
|
+
var import_fs4 = require("fs");
|
|
1446
|
+
var path6 = __toESM(require("path"));
|
|
1445
1447
|
var v8 = __toESM(require("v8"));
|
|
1446
1448
|
|
|
1447
1449
|
// ../packages/orion-client-core/src/nodeFileSource.ts
|
|
@@ -1725,26 +1727,26 @@ function tokenizeSearchText(text) {
|
|
|
1725
1727
|
function tokenizeContentText(text) {
|
|
1726
1728
|
return [...iterateTokens(text)];
|
|
1727
1729
|
}
|
|
1728
|
-
function pathSegments(
|
|
1729
|
-
return
|
|
1730
|
+
function pathSegments(path7) {
|
|
1731
|
+
return path7.replace(/\\/g, "/").split("/").filter(Boolean);
|
|
1730
1732
|
}
|
|
1731
|
-
function basenameOf(
|
|
1732
|
-
const parts2 = pathSegments(
|
|
1733
|
-
return parts2.at(-1) ??
|
|
1733
|
+
function basenameOf(path7) {
|
|
1734
|
+
const parts2 = pathSegments(path7);
|
|
1735
|
+
return parts2.at(-1) ?? path7;
|
|
1734
1736
|
}
|
|
1735
1737
|
function stripExtension(name2) {
|
|
1736
1738
|
const dot = name2.lastIndexOf(".");
|
|
1737
1739
|
return dot > 0 ? name2.slice(0, dot) : name2;
|
|
1738
1740
|
}
|
|
1739
|
-
function acronymForPath(
|
|
1740
|
-
return pathSegments(
|
|
1741
|
+
function acronymForPath(path7) {
|
|
1742
|
+
return pathSegments(path7).map((segment) => stripExtension(segment).match(/[A-Za-z0-9]/)?.[0] ?? "").join("").toLowerCase();
|
|
1741
1743
|
}
|
|
1742
|
-
function isConfigPath(
|
|
1743
|
-
const lower =
|
|
1744
|
+
function isConfigPath(path7) {
|
|
1745
|
+
const lower = path7.toLowerCase();
|
|
1744
1746
|
return lower.endsWith(".json") || lower.endsWith(".yaml") || lower.endsWith(".yml") || lower.endsWith(".toml") || lower.endsWith(".sql") || lower.endsWith("dockerfile");
|
|
1745
1747
|
}
|
|
1746
|
-
function isMarkdownPath(
|
|
1747
|
-
const lower =
|
|
1748
|
+
function isMarkdownPath(path7) {
|
|
1749
|
+
const lower = path7.toLowerCase();
|
|
1748
1750
|
return lower.endsWith(".md") || lower.endsWith(".markdown");
|
|
1749
1751
|
}
|
|
1750
1752
|
function attentionRanker(attention) {
|
|
@@ -1876,8 +1878,8 @@ function cleanPreview(text) {
|
|
|
1876
1878
|
const collapsed = text.replace(/\s+/g, " ").trim();
|
|
1877
1879
|
return collapsed.length > MAX_PREVIEW_CHARS ? collapsed.slice(0, MAX_PREVIEW_CHARS).trimEnd() + "..." : collapsed;
|
|
1878
1880
|
}
|
|
1879
|
-
function chunkId(
|
|
1880
|
-
return `${
|
|
1881
|
+
function chunkId(path7, startLine, kind, title) {
|
|
1882
|
+
return `${path7}:${startLine}:${kind}:${title}`;
|
|
1881
1883
|
}
|
|
1882
1884
|
function firstCommentTokens(lines) {
|
|
1883
1885
|
const picked = [];
|
|
@@ -1889,7 +1891,7 @@ function firstCommentTokens(lines) {
|
|
|
1889
1891
|
}
|
|
1890
1892
|
return tokenizeSearchText(picked.join(" "));
|
|
1891
1893
|
}
|
|
1892
|
-
function makeChunk(
|
|
1894
|
+
function makeChunk(path7, lines, startLine, endLine, kind, title) {
|
|
1893
1895
|
const safeStart = Math.max(1, startLine);
|
|
1894
1896
|
const safeEnd = Math.max(safeStart, Math.min(lines.length, endLine));
|
|
1895
1897
|
const slice = lines.slice(safeStart - 1, safeEnd);
|
|
@@ -1899,12 +1901,12 @@ function makeChunk(path5, lines, startLine, endLine, kind, title) {
|
|
|
1899
1901
|
const commentTokens = firstCommentTokens(slice);
|
|
1900
1902
|
if (tokens.length === 0 && titleTokens.length === 0) return null;
|
|
1901
1903
|
return {
|
|
1902
|
-
id: chunkId(
|
|
1903
|
-
path:
|
|
1904
|
+
id: chunkId(path7, safeStart, kind, title || path7),
|
|
1905
|
+
path: path7,
|
|
1904
1906
|
startLine: safeStart,
|
|
1905
1907
|
endLine: safeEnd,
|
|
1906
1908
|
kind,
|
|
1907
|
-
title: title ||
|
|
1909
|
+
title: title || path7,
|
|
1908
1910
|
preview: cleanPreview(text),
|
|
1909
1911
|
tokens,
|
|
1910
1912
|
titleTokens,
|
|
@@ -1918,7 +1920,7 @@ function frontmatterValue(block, field) {
|
|
|
1918
1920
|
}
|
|
1919
1921
|
return "";
|
|
1920
1922
|
}
|
|
1921
|
-
function frontmatterChunk(
|
|
1923
|
+
function frontmatterChunk(path7, lines) {
|
|
1922
1924
|
if ((lines[0] ?? "").trim() !== "---") return null;
|
|
1923
1925
|
let close = -1;
|
|
1924
1926
|
for (let i2 = 1; i2 < Math.min(lines.length, 60); i2++) {
|
|
@@ -1931,9 +1933,9 @@ function frontmatterChunk(path5, lines) {
|
|
|
1931
1933
|
const block = lines.slice(1, close).map((line) => line.replace(/\r$/, ""));
|
|
1932
1934
|
const facets = ["type", "title", "name", "description", "tags"].map((field) => frontmatterValue(block, field)).filter((value) => value.length > 0);
|
|
1933
1935
|
if (facets.length === 0) return null;
|
|
1934
|
-
return makeChunk(
|
|
1936
|
+
return makeChunk(path7, lines, 1, close + 1, "frontmatter", facets.join(" \u2014 "));
|
|
1935
1937
|
}
|
|
1936
|
-
function buildChunksForFile(
|
|
1938
|
+
function buildChunksForFile(path7, content, symbols, fileSummary) {
|
|
1937
1939
|
const lines = content.split("\n");
|
|
1938
1940
|
const chunks = [];
|
|
1939
1941
|
const sorted = [...symbols].sort((a, b) => a.line - b.line);
|
|
@@ -1941,8 +1943,8 @@ function buildChunksForFile(path5, content, symbols, fileSummary) {
|
|
|
1941
1943
|
const headerEnd = sorted[0].line - 1;
|
|
1942
1944
|
for (let start2 = 1; start2 <= headerEnd; start2 += WINDOW_LINES - WINDOW_OVERLAP) {
|
|
1943
1945
|
const end = Math.min(headerEnd, start2 + WINDOW_LINES - 1);
|
|
1944
|
-
const title = start2 === 1 && fileSummary ? fileSummary : `${
|
|
1945
|
-
const chunk = makeChunk(
|
|
1946
|
+
const title = start2 === 1 && fileSummary ? fileSummary : `${path7}:${start2}-${end}`;
|
|
1947
|
+
const chunk = makeChunk(path7, lines, start2, end, "window", title);
|
|
1946
1948
|
if (chunk) chunks.push(chunk);
|
|
1947
1949
|
if (end >= headerEnd) break;
|
|
1948
1950
|
}
|
|
@@ -1952,25 +1954,25 @@ function buildChunksForFile(path5, content, symbols, fileSummary) {
|
|
|
1952
1954
|
const next = sorted[i2 + 1];
|
|
1953
1955
|
const end = next ? Math.max(sym.line, next.line - 1) : lines.length;
|
|
1954
1956
|
const kind = ["function", "method", "class"].includes(sym.kind) ? sym.kind : "module";
|
|
1955
|
-
const chunk = makeChunk(
|
|
1957
|
+
const chunk = makeChunk(path7, lines, sym.line, end, kind, sym.signature || sym.name);
|
|
1956
1958
|
if (chunk) chunks.push(chunk);
|
|
1957
1959
|
}
|
|
1958
|
-
if (isMarkdownPath(
|
|
1959
|
-
const fmChunk = frontmatterChunk(
|
|
1960
|
+
if (isMarkdownPath(path7)) {
|
|
1961
|
+
const fmChunk = frontmatterChunk(path7, lines);
|
|
1960
1962
|
if (fmChunk) chunks.push(fmChunk);
|
|
1961
1963
|
const headingLines = lines.map((line, i2) => ({ line, i: i2 + 1 })).filter((x) => /^#{1,6}\s+/.test(x.line));
|
|
1962
1964
|
for (let i2 = 0; i2 < headingLines.length; i2++) {
|
|
1963
1965
|
const h = headingLines[i2];
|
|
1964
1966
|
const end = headingLines[i2 + 1] ? headingLines[i2 + 1].i - 1 : lines.length;
|
|
1965
|
-
const chunk = makeChunk(
|
|
1967
|
+
const chunk = makeChunk(path7, lines, h.i, end, "markdown_section", h.line.replace(/^#+\s*/, ""));
|
|
1966
1968
|
if (chunk) chunks.push(chunk);
|
|
1967
1969
|
}
|
|
1968
1970
|
}
|
|
1969
|
-
if (chunks.length === 0 || isConfigPath(
|
|
1971
|
+
if (chunks.length === 0 || isConfigPath(path7)) {
|
|
1970
1972
|
for (let start2 = 1; start2 <= lines.length; start2 += WINDOW_LINES - WINDOW_OVERLAP) {
|
|
1971
1973
|
const end = Math.min(lines.length, start2 + WINDOW_LINES - 1);
|
|
1972
|
-
const title = start2 === 1 && fileSummary ? fileSummary : `${
|
|
1973
|
-
const chunk = makeChunk(
|
|
1974
|
+
const title = start2 === 1 && fileSummary ? fileSummary : `${path7}:${start2}-${end}`;
|
|
1975
|
+
const chunk = makeChunk(path7, lines, start2, end, isConfigPath(path7) ? "config" : "window", title);
|
|
1974
1976
|
if (chunk) chunks.push(chunk);
|
|
1975
1977
|
if (end >= lines.length) break;
|
|
1976
1978
|
}
|
|
@@ -2006,17 +2008,17 @@ var ContentChunkIndex = class _ContentChunkIndex {
|
|
|
2006
2008
|
this.clear();
|
|
2007
2009
|
for (const chunk of chunks) this.insert(chunk);
|
|
2008
2010
|
}
|
|
2009
|
-
replacePath(
|
|
2011
|
+
replacePath(path7, chunks) {
|
|
2010
2012
|
this.membershipMemo.clear();
|
|
2011
|
-
this.removePath(
|
|
2013
|
+
this.removePath(path7);
|
|
2012
2014
|
for (const chunk of chunks) this.insert(chunk);
|
|
2013
2015
|
}
|
|
2014
|
-
removePath(
|
|
2016
|
+
removePath(path7) {
|
|
2015
2017
|
this.membershipMemo.clear();
|
|
2016
|
-
const ids = this.chunksByPath.get(
|
|
2018
|
+
const ids = this.chunksByPath.get(path7);
|
|
2017
2019
|
if (!ids) return;
|
|
2018
2020
|
for (const id of ids) this.removeChunk(id);
|
|
2019
|
-
this.chunksByPath.delete(
|
|
2021
|
+
this.chunksByPath.delete(path7);
|
|
2020
2022
|
}
|
|
2021
2023
|
size() {
|
|
2022
2024
|
return this.chunks.size;
|
|
@@ -2126,8 +2128,8 @@ var ContentChunkIndex = class _ContentChunkIndex {
|
|
|
2126
2128
|
}
|
|
2127
2129
|
return hits.sort((a, b) => b.score - a.score || a.path.localeCompare(b.path) || a.startLine - b.startLine).slice(0, options.limit ?? 20);
|
|
2128
2130
|
}
|
|
2129
|
-
bestChunksForPath(
|
|
2130
|
-
return [...this.chunksByPath.get(
|
|
2131
|
+
bestChunksForPath(path7, limit = 3) {
|
|
2132
|
+
return [...this.chunksByPath.get(path7) ?? []].map((id) => this.chunks.get(id)).filter((c) => Boolean(c)).sort((a, b) => a.startLine - b.startLine).slice(0, limit).map((c) => this.toIndexedChunk(c));
|
|
2131
2133
|
}
|
|
2132
2134
|
/** Reconstruct the IndexedChunk shape (token multiset from interned term
|
|
2133
2135
|
* frequencies — order-insensitive by contract) for the handful of chunks
|
|
@@ -2230,8 +2232,8 @@ function computeRelatedPaths(touched, dependentsOf, limit = 16) {
|
|
|
2230
2232
|
const touchedSet = new Set(touched.map((p) => p.trim()).filter((p) => p.length > 0));
|
|
2231
2233
|
const related = [];
|
|
2232
2234
|
const seen = /* @__PURE__ */ new Set();
|
|
2233
|
-
for (const
|
|
2234
|
-
for (const dep of dependentsOf(
|
|
2235
|
+
for (const path7 of touchedSet) {
|
|
2236
|
+
for (const dep of dependentsOf(path7)) {
|
|
2235
2237
|
const d = dep.trim();
|
|
2236
2238
|
if (!d || touchedSet.has(d) || seen.has(d)) continue;
|
|
2237
2239
|
seen.add(d);
|
|
@@ -2242,31 +2244,31 @@ function computeRelatedPaths(touched, dependentsOf, limit = 16) {
|
|
|
2242
2244
|
return related;
|
|
2243
2245
|
}
|
|
2244
2246
|
function indexDependents(index, perSymbolLimit = 20) {
|
|
2245
|
-
return (
|
|
2247
|
+
return (path7) => {
|
|
2246
2248
|
const out2 = [];
|
|
2247
2249
|
const seen = /* @__PURE__ */ new Set();
|
|
2248
2250
|
const add = (edges) => {
|
|
2249
2251
|
for (const edge of edges) {
|
|
2250
2252
|
const src = edge.source_path;
|
|
2251
|
-
if (src && src !==
|
|
2253
|
+
if (src && src !== path7 && !seen.has(src)) {
|
|
2252
2254
|
seen.add(src);
|
|
2253
2255
|
out2.push(src);
|
|
2254
2256
|
}
|
|
2255
2257
|
}
|
|
2256
2258
|
};
|
|
2257
|
-
for (const symbol of index.byPath.get(
|
|
2259
|
+
for (const symbol of index.byPath.get(path7) ?? []) {
|
|
2258
2260
|
add(index.findCallers(symbol.name, { limit: perSymbolLimit }));
|
|
2259
2261
|
}
|
|
2260
|
-
const moduleName =
|
|
2262
|
+
const moduleName = path7.split("/").pop()?.replace(/\.[^.]+$/, "") ?? "";
|
|
2261
2263
|
if (moduleName) add(index.findImporters(moduleName, { limit: perSymbolLimit }));
|
|
2262
2264
|
return out2;
|
|
2263
2265
|
};
|
|
2264
2266
|
}
|
|
2265
2267
|
|
|
2266
2268
|
// ../packages/orion-client-core/src/pathIndex.ts
|
|
2267
|
-
function isConfigOrDocPath(
|
|
2268
|
-
if (isConfigPath(
|
|
2269
|
-
const lower =
|
|
2269
|
+
function isConfigOrDocPath(path7) {
|
|
2270
|
+
if (isConfigPath(path7) || isMarkdownPath(path7)) return true;
|
|
2271
|
+
const lower = path7.toLowerCase();
|
|
2270
2272
|
return lower.endsWith(".sh") || lower.endsWith(".bash") || lower.includes("/.github/") || lower.includes("/.gitlab/");
|
|
2271
2273
|
}
|
|
2272
2274
|
var PathIndex = class {
|
|
@@ -2276,29 +2278,29 @@ var PathIndex = class {
|
|
|
2276
2278
|
}
|
|
2277
2279
|
replace(paths, meta) {
|
|
2278
2280
|
this.clear();
|
|
2279
|
-
for (const
|
|
2281
|
+
for (const path7 of paths) this.upsert(path7, meta.get(path7));
|
|
2280
2282
|
}
|
|
2281
|
-
upsert(
|
|
2282
|
-
const basename = basenameOf(
|
|
2283
|
+
upsert(path7, meta) {
|
|
2284
|
+
const basename = basenameOf(path7);
|
|
2283
2285
|
const basenameStem = stripExtension(basename);
|
|
2284
|
-
const segments = pathSegments(
|
|
2286
|
+
const segments = pathSegments(path7);
|
|
2285
2287
|
const tokens = /* @__PURE__ */ new Set();
|
|
2286
|
-
for (const value of [
|
|
2288
|
+
for (const value of [path7, basename, basenameStem, ...segments]) {
|
|
2287
2289
|
for (const token of tokenizeIdentifier(value)) tokens.add(token);
|
|
2288
2290
|
}
|
|
2289
|
-
this.entries.set(
|
|
2290
|
-
path:
|
|
2291
|
-
lowerPath:
|
|
2291
|
+
this.entries.set(path7, {
|
|
2292
|
+
path: path7,
|
|
2293
|
+
lowerPath: path7.toLowerCase(),
|
|
2292
2294
|
basename: basename.toLowerCase(),
|
|
2293
2295
|
basenameStem: basenameStem.toLowerCase(),
|
|
2294
2296
|
segments: segments.map((s) => s.toLowerCase()),
|
|
2295
2297
|
tokens,
|
|
2296
|
-
acronym: acronymForPath(
|
|
2298
|
+
acronym: acronymForPath(path7),
|
|
2297
2299
|
meta
|
|
2298
2300
|
});
|
|
2299
2301
|
}
|
|
2300
|
-
remove(
|
|
2301
|
-
this.entries.delete(
|
|
2302
|
+
remove(path7) {
|
|
2303
|
+
this.entries.delete(path7);
|
|
2302
2304
|
}
|
|
2303
2305
|
size() {
|
|
2304
2306
|
return this.entries.size;
|
|
@@ -2646,27 +2648,27 @@ var KNOWN_EDGE_KINDS = /* @__PURE__ */ new Set([
|
|
|
2646
2648
|
"implements",
|
|
2647
2649
|
"references"
|
|
2648
2650
|
]);
|
|
2649
|
-
function isTestPath(
|
|
2650
|
-
const p = "/" +
|
|
2651
|
+
function isTestPath(path7) {
|
|
2652
|
+
const p = "/" + path7.toLowerCase();
|
|
2651
2653
|
if (TEST_SUBSTRINGS.some((s) => p.includes(s))) return true;
|
|
2652
|
-
const base =
|
|
2654
|
+
const base = path7.toLowerCase().split("/").pop() ?? "";
|
|
2653
2655
|
return base.startsWith("test_") || base.endsWith("_test.go");
|
|
2654
2656
|
}
|
|
2655
|
-
function isGeneratedPath(
|
|
2656
|
-
const lower =
|
|
2657
|
+
function isGeneratedPath(path7) {
|
|
2658
|
+
const lower = path7.toLowerCase();
|
|
2657
2659
|
const p = "/" + lower;
|
|
2658
2660
|
return GENERATED_SUBSTRINGS.some((s) => p.includes(s)) || GENERATED_SUFFIXES.some((s) => lower.endsWith(s));
|
|
2659
2661
|
}
|
|
2660
|
-
function pathStems(
|
|
2661
|
-
const parts2 =
|
|
2662
|
+
function pathStems(path7) {
|
|
2663
|
+
const parts2 = path7.replace(/\\/g, "/").split("/").filter(Boolean);
|
|
2662
2664
|
if (parts2.length === 0) return [];
|
|
2663
2665
|
const last = parts2[parts2.length - 1];
|
|
2664
2666
|
const dot = last.lastIndexOf(".");
|
|
2665
2667
|
if (dot > 0) parts2[parts2.length - 1] = last.slice(0, dot);
|
|
2666
2668
|
return parts2.map((p) => p.toLowerCase()).filter(Boolean);
|
|
2667
2669
|
}
|
|
2668
|
-
function dirnamePath(
|
|
2669
|
-
const parts2 =
|
|
2670
|
+
function dirnamePath(path7) {
|
|
2671
|
+
const parts2 = path7.replace(/\\/g, "/").split("/");
|
|
2670
2672
|
parts2.pop();
|
|
2671
2673
|
return parts2.join("/");
|
|
2672
2674
|
}
|
|
@@ -2680,11 +2682,11 @@ function joinRelPath(base, spec) {
|
|
|
2680
2682
|
}
|
|
2681
2683
|
return out2.join("/");
|
|
2682
2684
|
}
|
|
2683
|
-
function withoutKnownExtension(
|
|
2684
|
-
return
|
|
2685
|
+
function withoutKnownExtension(path7) {
|
|
2686
|
+
return path7.replace(/\.(tsx?|jsx?|mjs|cjs|py|go|rs|java|kt|kts|scala|rb)$/i, "");
|
|
2685
2687
|
}
|
|
2686
|
-
function normalizeTracePath(
|
|
2687
|
-
return
|
|
2688
|
+
function normalizeTracePath(path7) {
|
|
2689
|
+
return path7.trim().replace(/\\/g, "/").replace(/^file:\/\//, "").replace(/^\/+/, "").replace(/[:#]L?\d+(?::\d+)?$/, "").replace(/^['"`]|['"`]$/g, "");
|
|
2688
2690
|
}
|
|
2689
2691
|
function looksPathLike(value) {
|
|
2690
2692
|
return /[\\/]/.test(value) || /\.[A-Za-z0-9]+(?::\d+)?$/.test(value);
|
|
@@ -2721,21 +2723,16 @@ function clampInt(value, fallback, low, high) {
|
|
|
2721
2723
|
if (!Number.isFinite(n)) return fallback;
|
|
2722
2724
|
return Math.max(low, Math.min(high, Math.trunc(n)));
|
|
2723
2725
|
}
|
|
2724
|
-
function scopeFilter(
|
|
2726
|
+
function scopeFilter(path7, scope) {
|
|
2725
2727
|
const s = String(scope ?? "").trim().replace(/\\/g, "/").replace(/^\/+|\/+$/g, "");
|
|
2726
2728
|
if (!s || s === ".") return true;
|
|
2727
|
-
return
|
|
2729
|
+
return path7 === s || path7.startsWith(s + "/");
|
|
2728
2730
|
}
|
|
2729
2731
|
function detailLimit(detail, brief, normal, deep) {
|
|
2730
2732
|
if (detail === "brief") return brief;
|
|
2731
2733
|
if (detail === "deep") return deep;
|
|
2732
2734
|
return normal;
|
|
2733
2735
|
}
|
|
2734
|
-
var DEFAULT_RETRIEVAL_MODE = "default";
|
|
2735
|
-
function normalizeRetrievalMode(value, fallback = DEFAULT_RETRIEVAL_MODE) {
|
|
2736
|
-
if (value === "default" || value === "enhanced") return value;
|
|
2737
|
-
return fallback;
|
|
2738
|
-
}
|
|
2739
2736
|
var CONTENT_PROBE_DEADLINE_MS = 600;
|
|
2740
2737
|
async function boundedAll(promises2, deadlineMs) {
|
|
2741
2738
|
if (promises2.length === 0) return [];
|
|
@@ -2825,9 +2822,9 @@ function fuseHits(hitLists, topK) {
|
|
|
2825
2822
|
for (const hits of hitLists) {
|
|
2826
2823
|
const votedThisList = /* @__PURE__ */ new Set();
|
|
2827
2824
|
hits.forEach((hit, i2) => {
|
|
2828
|
-
const
|
|
2825
|
+
const path7 = String(hit.path ?? "");
|
|
2829
2826
|
const type = String(hit.result_type ?? "match");
|
|
2830
|
-
const key =
|
|
2827
|
+
const key = path7 || `${type}:${i2}`;
|
|
2831
2828
|
if (votedThisList.has(key)) return;
|
|
2832
2829
|
votedThisList.add(key);
|
|
2833
2830
|
scores.set(key, (scores.get(key) ?? 0) + 1 / (60 + i2 + 1));
|
|
@@ -2985,8 +2982,8 @@ var WorkspaceIndexStore = class {
|
|
|
2985
2982
|
this.setMeta(file, snapshot.file_meta[file]);
|
|
2986
2983
|
}
|
|
2987
2984
|
this.pathIndex.replace(this.files, this.fileMeta);
|
|
2988
|
-
for (const [
|
|
2989
|
-
if (summary) this.fileSummaries.set(
|
|
2985
|
+
for (const [path7, summary] of Object.entries(snapshot.file_summaries)) {
|
|
2986
|
+
if (summary) this.fileSummaries.set(path7, String(summary));
|
|
2990
2987
|
}
|
|
2991
2988
|
for (const sym of snapshot.symbols) this.insertSymbol(sym);
|
|
2992
2989
|
for (const edge of snapshot.edges) this.insertEdge(edge);
|
|
@@ -3117,19 +3114,19 @@ var WorkspaceIndexStore = class {
|
|
|
3117
3114
|
this.totalFiles = Math.max(this.totalFiles, this.processedFiles);
|
|
3118
3115
|
}
|
|
3119
3116
|
}
|
|
3120
|
-
removeFile(
|
|
3117
|
+
removeFile(path7) {
|
|
3121
3118
|
this.noteMutation();
|
|
3122
3119
|
const refreshTargets = /* @__PURE__ */ new Set();
|
|
3123
|
-
for (const sym of this.byPath.get(
|
|
3120
|
+
for (const sym of this.byPath.get(path7) ?? []) {
|
|
3124
3121
|
const name2 = sym.name.toLowerCase();
|
|
3125
3122
|
if (name2) refreshTargets.add(name2);
|
|
3126
3123
|
}
|
|
3127
|
-
for (const stem of this.pathStemsByFile.get(
|
|
3124
|
+
for (const stem of this.pathStemsByFile.get(path7) ?? []) {
|
|
3128
3125
|
if (stem) refreshTargets.add(stem);
|
|
3129
3126
|
}
|
|
3130
|
-
this.removePath(
|
|
3131
|
-
this.files.delete(
|
|
3132
|
-
this.removePathStems(
|
|
3127
|
+
this.removePath(path7);
|
|
3128
|
+
this.files.delete(path7);
|
|
3129
|
+
this.removePathStems(path7);
|
|
3133
3130
|
for (const target of refreshTargets) this.refreshEdgeResolutionForTarget(target);
|
|
3134
3131
|
this.indexedAt = Date.now() / 1e3;
|
|
3135
3132
|
if (this.buildState === "empty") this.buildState = "partial";
|
|
@@ -3228,11 +3225,11 @@ var WorkspaceIndexStore = class {
|
|
|
3228
3225
|
const now = Date.now() / 1e3;
|
|
3229
3226
|
return filtered.map((s) => [s, this.scoreSymbol(s, needle, needleTokens, options.attention, now)]).sort((a, b) => b[1] - a[1] || a[0].path.localeCompare(b[0].path) || a[0].line - b[0].line).slice(0, options.limit ?? 50);
|
|
3230
3227
|
}
|
|
3231
|
-
listSymbols(
|
|
3232
|
-
return [...this.byPath.get(
|
|
3228
|
+
listSymbols(path7) {
|
|
3229
|
+
return [...this.byPath.get(path7) ?? []].sort((a, b) => a.line - b.line);
|
|
3233
3230
|
}
|
|
3234
|
-
enclosingSymbol(
|
|
3235
|
-
const syms = this.listSymbols(
|
|
3231
|
+
enclosingSymbol(path7, line) {
|
|
3232
|
+
const syms = this.listSymbols(path7);
|
|
3236
3233
|
let candidate = null;
|
|
3237
3234
|
let nextStart = null;
|
|
3238
3235
|
for (const sym of syms) {
|
|
@@ -3394,14 +3391,13 @@ var WorkspaceIndexStore = class {
|
|
|
3394
3391
|
const missRank = options.attention?.length ?? 0;
|
|
3395
3392
|
return [...candidates].map((p) => [p, sets.filter((s) => s.has(p)).length]).sort((a, b) => b[1] - a[1] || (attentionRank.get(a[0]) ?? missRank) - (attentionRank.get(b[0]) ?? missRank) || a[0].localeCompare(b[0])).slice(0, options.topK ?? 30);
|
|
3396
3393
|
}
|
|
3397
|
-
async searchCodebase(input
|
|
3394
|
+
async searchCodebase(input) {
|
|
3398
3395
|
const query = String(input.query ?? "").trim();
|
|
3399
3396
|
if (!query) throw new Error("`query` is required");
|
|
3400
3397
|
const scope = String(input.scope ?? "").trim() || void 0;
|
|
3401
3398
|
const detail = ["brief", "normal", "deep"].includes(String(input.detail)) ? String(input.detail) : "normal";
|
|
3402
3399
|
const intent = String(input.intent ?? "auto");
|
|
3403
3400
|
const maxResults = clampInt(input.max_results, 8, 1, 25);
|
|
3404
|
-
const retrievalMode = normalizeRetrievalMode(options.retrievalMode);
|
|
3405
3401
|
const status = this.status();
|
|
3406
3402
|
if (!status.ready) {
|
|
3407
3403
|
return [
|
|
@@ -3416,8 +3412,8 @@ var WorkspaceIndexStore = class {
|
|
|
3416
3412
|
const perSource = Math.max(maxResults, 12);
|
|
3417
3413
|
const termSets = await this.termFileSets(queryTerms(query));
|
|
3418
3414
|
const symbols = this.symbolHitsForQuery(query, perSource, attention, scope);
|
|
3419
|
-
const files =
|
|
3420
|
-
const content = await this.contentHitsForQuery(query, perSource, attention, scope,
|
|
3415
|
+
const files = this.fileHitsForQuery(query, perSource, attention, scope, termSets);
|
|
3416
|
+
const content = await this.contentHitsForQuery(query, perSource, attention, scope, termSets);
|
|
3421
3417
|
const seeds = this.graphExpansionSeeds(symbols, files);
|
|
3422
3418
|
const graph = seeds.length > 0 ? this.graphHitsForQuery(seeds, perSource, scope, queryTerms(query), termSets) : [];
|
|
3423
3419
|
const merged = fuseHits([symbols, files, content, graph], maxResults);
|
|
@@ -3430,7 +3426,7 @@ var WorkspaceIndexStore = class {
|
|
|
3430
3426
|
`- query: ${query}`,
|
|
3431
3427
|
`- intent: ${intent}`,
|
|
3432
3428
|
`- scope: ${scope ?? "."}`,
|
|
3433
|
-
|
|
3429
|
+
"- retrieval_level: normal",
|
|
3434
3430
|
"",
|
|
3435
3431
|
"Top Files"
|
|
3436
3432
|
];
|
|
@@ -3460,21 +3456,19 @@ var WorkspaceIndexStore = class {
|
|
|
3460
3456
|
let cardRank = 0;
|
|
3461
3457
|
for (const [p, cardReasons] of topPaths.slice(0, maxResults)) {
|
|
3462
3458
|
cardRank += 1;
|
|
3463
|
-
lines.push(...this.renderFileCard(p, cardRank, cardReasons, detail,
|
|
3464
|
-
}
|
|
3465
|
-
|
|
3466
|
-
|
|
3467
|
-
|
|
3468
|
-
|
|
3469
|
-
|
|
3470
|
-
|
|
3471
|
-
|
|
3472
|
-
|
|
3473
|
-
|
|
3474
|
-
|
|
3475
|
-
|
|
3476
|
-
lines.push(` Next read: read_file path=${hit.path} start_line=${hit.line} end_line=${hit.end_line} context=dependencies`);
|
|
3477
|
-
}
|
|
3459
|
+
lines.push(...this.renderFileCard(p, cardRank, cardReasons, detail, relatedByPath.get(p)));
|
|
3460
|
+
}
|
|
3461
|
+
const chunkLimit = detailLimit(detail, 3, 6, 10);
|
|
3462
|
+
const chunkHits = content.filter((hit) => hit.result_type === "chunk").slice(0, chunkLimit);
|
|
3463
|
+
if (chunkHits.length > 0) {
|
|
3464
|
+
lines.push("", "Top Matches");
|
|
3465
|
+
for (const hit of chunkHits) {
|
|
3466
|
+
const reasons = Array.isArray(hit.reasons) ? hit.reasons.map(String).join(", ") : "chunk";
|
|
3467
|
+
lines.push(
|
|
3468
|
+
`- ${hit.path}:${hit.line}-${hit.end_line} [${hit.kind}] ${hit.name} (score=${hit.score}; ${reasons})`
|
|
3469
|
+
);
|
|
3470
|
+
if (hit.preview) lines.push(` Preview: ${hit.preview}`);
|
|
3471
|
+
lines.push(` Next read: read_file path=${hit.path} start_line=${hit.line} end_line=${hit.end_line} context=dependencies`);
|
|
3478
3472
|
}
|
|
3479
3473
|
}
|
|
3480
3474
|
const symbolLimit = detailLimit(detail, 3, 6, 10);
|
|
@@ -3515,12 +3509,11 @@ var WorkspaceIndexStore = class {
|
|
|
3515
3509
|
);
|
|
3516
3510
|
return lines.join("\n");
|
|
3517
3511
|
}
|
|
3518
|
-
async traceCodebase(input
|
|
3512
|
+
async traceCodebase(input) {
|
|
3519
3513
|
const target = String(input.target ?? "").trim();
|
|
3520
3514
|
if (!target) throw new Error("`target` is required");
|
|
3521
3515
|
const parsedTarget = parseTraceTarget(target, input.path);
|
|
3522
3516
|
const targetName = parsedTarget.name.trim() || target;
|
|
3523
|
-
const retrievalMode = normalizeRetrievalMode(options.retrievalMode);
|
|
3524
3517
|
const relation = ["auto", "impact", "callers", "importers", "references", "hierarchy", "dependencies"].includes(String(input.relation)) ? String(input.relation) : "auto";
|
|
3525
3518
|
const scope = String(input.scope ?? "").trim() || void 0;
|
|
3526
3519
|
const depth = clampInt(input.depth, 2, 1, 6);
|
|
@@ -3535,7 +3528,7 @@ var WorkspaceIndexStore = class {
|
|
|
3535
3528
|
`Use grep for "${targetName}" until enough files are indexed.`
|
|
3536
3529
|
].join("\n");
|
|
3537
3530
|
}
|
|
3538
|
-
const targets = this.resolveTraceTargets(targetName, scope, 5, parsedTarget.pathHint
|
|
3531
|
+
const targets = this.resolveTraceTargets(targetName, scope, 5, parsedTarget.pathHint);
|
|
3539
3532
|
const selected = targets[0] ?? { name: targetName, path: "", line: 1, kind: "unknown", score: 0 };
|
|
3540
3533
|
const selectedName = String(selected.name || targetName).split(".").pop() ?? targetName;
|
|
3541
3534
|
const selectedPath = String(selected.path || "");
|
|
@@ -3611,7 +3604,7 @@ var WorkspaceIndexStore = class {
|
|
|
3611
3604
|
}
|
|
3612
3605
|
}
|
|
3613
3606
|
if (structuralHitCount === 0) {
|
|
3614
|
-
lines.push("", ...await this.formatTraceFallback(selectedName, selectedPath, scope, detailLimit("normal", 3, 6, 10)
|
|
3607
|
+
lines.push("", ...await this.formatTraceFallback(selectedName, selectedPath, scope, detailLimit("normal", 3, 6, 10)));
|
|
3615
3608
|
}
|
|
3616
3609
|
const suggested = dedupe(
|
|
3617
3610
|
[
|
|
@@ -3638,13 +3631,12 @@ var WorkspaceIndexStore = class {
|
|
|
3638
3631
|
}
|
|
3639
3632
|
return lines.join("\n");
|
|
3640
3633
|
}
|
|
3641
|
-
async readContextHeader(
|
|
3634
|
+
async readContextHeader(path7, startLine, mode) {
|
|
3642
3635
|
if (mode === "none" || !this.status().ready) return "";
|
|
3643
|
-
const
|
|
3644
|
-
const
|
|
3645
|
-
const
|
|
3646
|
-
const
|
|
3647
|
-
const enclosing = this.enclosingSymbol(path5, startLine);
|
|
3636
|
+
const summary = this.fileSummaryFor(path7);
|
|
3637
|
+
const syms = this.listSymbols(path7);
|
|
3638
|
+
const imports = [...this.edgesOutByPath.get(path7) ?? []].filter((e) => e.kind === "imports" && e.target).map((e) => e.target);
|
|
3639
|
+
const enclosing = this.enclosingSymbol(path7, startLine);
|
|
3648
3640
|
let parentClass = null;
|
|
3649
3641
|
if (enclosing && (enclosing[0].kind === "function" || enclosing[0].kind === "method")) {
|
|
3650
3642
|
for (const sym of syms) {
|
|
@@ -3654,7 +3646,7 @@ var WorkspaceIndexStore = class {
|
|
|
3654
3646
|
}
|
|
3655
3647
|
if (!summary && !parentClass && !enclosing && imports.length === 0 && syms.length === 0) return "";
|
|
3656
3648
|
const lines = ["--- codebase context ---"];
|
|
3657
|
-
if (summary) lines.push(`file: ${
|
|
3649
|
+
if (summary) lines.push(`file: ${path7} - ${summary}`);
|
|
3658
3650
|
if (parentClass) lines.push(`class: ${parentClass.path}:${parentClass.line} [${parentClass.kind}] ${parentClass.signature || parentClass.name}`);
|
|
3659
3651
|
if (enclosing) {
|
|
3660
3652
|
const [sym, end] = enclosing;
|
|
@@ -3675,13 +3667,13 @@ var WorkspaceIndexStore = class {
|
|
|
3675
3667
|
}
|
|
3676
3668
|
}
|
|
3677
3669
|
if (["dependencies", "full", "auto"].includes(mode)) {
|
|
3678
|
-
const related = await this.relatedContextForPath(
|
|
3670
|
+
const related = await this.relatedContextForPath(path7, mode === "full" ? 8 : 4);
|
|
3679
3671
|
if (related.dependencies.length > 0) lines.push(`depends on: ${related.dependencies.join(", ")}`);
|
|
3680
3672
|
if (related.dependents.length > 0) lines.push(`used by: ${related.dependents.join(", ")}`);
|
|
3681
3673
|
if (related.tests.length > 0) lines.push(`related tests: ${related.tests.join(", ")}`);
|
|
3682
3674
|
}
|
|
3683
|
-
if (
|
|
3684
|
-
const chunks = this.chunkIndex.bestChunksForPath(
|
|
3675
|
+
if (mode === "full" && this.chunkIndex.size() > 0) {
|
|
3676
|
+
const chunks = this.chunkIndex.bestChunksForPath(path7, 4);
|
|
3685
3677
|
if (chunks.length > 0) {
|
|
3686
3678
|
lines.push(`chunks: ${chunks.map((c) => `${c.title}@${c.startLine}-${c.endLine}`).join(", ")}`);
|
|
3687
3679
|
}
|
|
@@ -3707,34 +3699,28 @@ var WorkspaceIndexStore = class {
|
|
|
3707
3699
|
}
|
|
3708
3700
|
return hits;
|
|
3709
3701
|
}
|
|
3710
|
-
|
|
3711
|
-
return this.fileHitsForQuery(query, limit, attention, scope, true, termSets);
|
|
3712
|
-
}
|
|
3713
|
-
basicFileHitsForQuery(query, limit, attention, scope, termSets) {
|
|
3714
|
-
return this.fileHitsForQuery(query, limit, attention, scope, false, termSets);
|
|
3715
|
-
}
|
|
3716
|
-
fileHitsForQuery(query, limit, attention, scope, includePathIndex, termSets) {
|
|
3702
|
+
fileHitsForQuery(query, limit, attention, scope, termSets) {
|
|
3717
3703
|
const terms = queryTerms(query);
|
|
3718
3704
|
const queryLc = query.toLowerCase().trim();
|
|
3719
3705
|
const hits = [];
|
|
3720
|
-
const pathHits =
|
|
3706
|
+
const pathHits = new Map(
|
|
3721
3707
|
this.pathIndex.search(query, { limit: Math.max(limit * 4, 50), scope, attention, includeDocs: true }).map((hit) => [hit.path, hit])
|
|
3722
|
-
)
|
|
3708
|
+
);
|
|
3723
3709
|
if (/[*?[\]]/.test(query)) {
|
|
3724
|
-
for (const
|
|
3725
|
-
if (scopeFilter(
|
|
3710
|
+
for (const path7 of this.findFiles(query, limit * 2)) {
|
|
3711
|
+
if (scopeFilter(path7, scope)) hits.push([100, path7, ["glob"]]);
|
|
3726
3712
|
}
|
|
3727
3713
|
if (hits.length > 0) {
|
|
3728
|
-
return hits.sort((a, b) => b[0] - a[0] || a[1].localeCompare(b[1])).slice(0, limit).map(([score,
|
|
3714
|
+
return hits.sort((a, b) => b[0] - a[0] || a[1].localeCompare(b[1])).slice(0, limit).map(([score, path7, reasons]) => ({ result_type: "file", path: path7, score, reasons }));
|
|
3729
3715
|
}
|
|
3730
3716
|
}
|
|
3731
|
-
for (const
|
|
3732
|
-
if (!scopeFilter(
|
|
3717
|
+
for (const path7 of this.files) {
|
|
3718
|
+
if (!scopeFilter(path7, scope)) continue;
|
|
3733
3719
|
let score = 0;
|
|
3734
3720
|
const reasons = [];
|
|
3735
|
-
const pathLc =
|
|
3736
|
-
const summaryLc = (this.fileSummaries.get(
|
|
3737
|
-
const pathHit = pathHits.get(
|
|
3721
|
+
const pathLc = path7.toLowerCase();
|
|
3722
|
+
const summaryLc = (this.fileSummaries.get(path7) ?? "").toLowerCase();
|
|
3723
|
+
const pathHit = pathHits.get(path7);
|
|
3738
3724
|
if (pathHit) {
|
|
3739
3725
|
score += pathHit.score;
|
|
3740
3726
|
reasons.push(...pathHit.reasons);
|
|
@@ -3752,24 +3738,24 @@ var WorkspaceIndexStore = class {
|
|
|
3752
3738
|
score += 8;
|
|
3753
3739
|
if (!reasons.includes("summary")) reasons.push("summary");
|
|
3754
3740
|
}
|
|
3755
|
-
if (termSets.get(term)?.has(
|
|
3741
|
+
if (termSets.get(term)?.has(path7)) {
|
|
3756
3742
|
score += 5;
|
|
3757
3743
|
if (!reasons.includes("content")) reasons.push("content");
|
|
3758
3744
|
}
|
|
3759
3745
|
}
|
|
3760
|
-
if (attention?.includes(
|
|
3761
|
-
score += attention.indexOf(
|
|
3746
|
+
if (attention?.includes(path7)) {
|
|
3747
|
+
score += attention.indexOf(path7) === 0 ? 20 : 10;
|
|
3762
3748
|
reasons.push("open/recent");
|
|
3763
3749
|
}
|
|
3764
|
-
const meta = this.fileMeta.get(
|
|
3750
|
+
const meta = this.fileMeta.get(path7);
|
|
3765
3751
|
if (meta?.is_generated) score -= 50;
|
|
3766
3752
|
if (meta?.is_test) score -= 12;
|
|
3767
|
-
if (score > 0) hits.push([score,
|
|
3753
|
+
if (score > 0) hits.push([score, path7, reasons]);
|
|
3768
3754
|
}
|
|
3769
|
-
return hits.sort((a, b) => b[0] - a[0] || a[1].localeCompare(b[1])).slice(0, limit).map(([score,
|
|
3755
|
+
return hits.sort((a, b) => b[0] - a[0] || a[1].localeCompare(b[1])).slice(0, limit).map(([score, path7, reasons]) => ({ result_type: "file", path: path7, score, reasons }));
|
|
3770
3756
|
}
|
|
3771
|
-
async contentHitsForQuery(query, limit, attention, scope,
|
|
3772
|
-
if (
|
|
3757
|
+
async contentHitsForQuery(query, limit, attention, scope, termSets) {
|
|
3758
|
+
if (this.chunkIndex.size() > 0) {
|
|
3773
3759
|
return this.chunkIndex.search(query, { limit, scope, attention, meta: this.fileMeta }).map((hit) => ({
|
|
3774
3760
|
result_type: "chunk",
|
|
3775
3761
|
path: hit.path,
|
|
@@ -3786,21 +3772,21 @@ var WorkspaceIndexStore = class {
|
|
|
3786
3772
|
if (terms.length === 0) return [];
|
|
3787
3773
|
const hits = await this.findFilesMentioning(terms, { topK: limit * 3, attention, termSets });
|
|
3788
3774
|
const out2 = [];
|
|
3789
|
-
for (const [
|
|
3790
|
-
if (!scopeFilter(
|
|
3791
|
-
out2.push({ result_type: "content", path:
|
|
3775
|
+
for (const [path7, count] of hits) {
|
|
3776
|
+
if (!scopeFilter(path7, scope)) continue;
|
|
3777
|
+
out2.push({ result_type: "content", path: path7, hits: count });
|
|
3792
3778
|
if (out2.length >= limit) break;
|
|
3793
3779
|
}
|
|
3794
3780
|
return out2;
|
|
3795
3781
|
}
|
|
3796
|
-
resolveTraceTargets(target, scope, limit, pathHint
|
|
3797
|
-
const scopedFiles = pathHint ? this.matchFilesForPathHint(pathHint, scope, limit * 4
|
|
3782
|
+
resolveTraceTargets(target, scope, limit, pathHint) {
|
|
3783
|
+
const scopedFiles = pathHint ? this.matchFilesForPathHint(pathHint, scope, limit * 4) : [];
|
|
3798
3784
|
if (scopedFiles.length > 0) {
|
|
3799
3785
|
const needle = target.toLowerCase().trim();
|
|
3800
3786
|
const needleTokens = tokenizeName(target);
|
|
3801
3787
|
const symbolHits = [];
|
|
3802
|
-
for (const
|
|
3803
|
-
for (const sym of this.listSymbols(
|
|
3788
|
+
for (const path7 of scopedFiles) {
|
|
3789
|
+
for (const sym of this.listSymbols(path7)) {
|
|
3804
3790
|
const name2 = sym.name.toLowerCase();
|
|
3805
3791
|
const tokens = this.tokensByName.get(name2) ?? tokenizeName(sym.name);
|
|
3806
3792
|
let overlap = 0;
|
|
@@ -3827,15 +3813,13 @@ var WorkspaceIndexStore = class {
|
|
|
3827
3813
|
}
|
|
3828
3814
|
const candidates = this.symbolHitsForQuery(target, limit, void 0, scope);
|
|
3829
3815
|
if (candidates.length > 0) return candidates;
|
|
3830
|
-
return this.matchFilesForPathHint(target, scope, limit
|
|
3816
|
+
return this.matchFilesForPathHint(target, scope, limit).map((p) => ({ path: p, name: (p.split("/").pop() ?? p).split(".")[0], line: 1, kind: "file", score: 0 }));
|
|
3831
3817
|
}
|
|
3832
|
-
matchFilesForPathHint(pathHint, scope, limit
|
|
3818
|
+
matchFilesForPathHint(pathHint, scope, limit) {
|
|
3833
3819
|
const hint = normalizeTracePath(pathHint).toLowerCase();
|
|
3834
3820
|
if (!hint) return [];
|
|
3835
|
-
|
|
3836
|
-
|
|
3837
|
-
if (pathHits.length > 0) return pathHits.slice(0, limit).map((h) => h.path);
|
|
3838
|
-
}
|
|
3821
|
+
const pathHits = this.pathIndex.search(hint, { scope, limit: limit * 2 });
|
|
3822
|
+
if (pathHits.length > 0) return pathHits.slice(0, limit).map((h) => h.path);
|
|
3839
3823
|
return [...this.files].filter((p) => scopeFilter(p, scope)).map((p) => {
|
|
3840
3824
|
const lc = p.toLowerCase();
|
|
3841
3825
|
let score = 0;
|
|
@@ -3846,30 +3830,28 @@ var WorkspaceIndexStore = class {
|
|
|
3846
3830
|
return [p, score];
|
|
3847
3831
|
}).filter(([, score]) => score > 0).sort((a, b) => b[1] - a[1] || a[0].localeCompare(b[0])).slice(0, limit).map(([p]) => p);
|
|
3848
3832
|
}
|
|
3849
|
-
async formatTraceFallback(target, selectedPath, scope, limit
|
|
3850
|
-
|
|
3851
|
-
|
|
3852
|
-
|
|
3853
|
-
|
|
3854
|
-
|
|
3855
|
-
|
|
3856
|
-
|
|
3857
|
-
|
|
3858
|
-
|
|
3859
|
-
|
|
3860
|
-
(hit) => `- ${hit.path}:${hit.startLine}-${hit.endLine} ${hit.title} (score=${hit.score}; ${hit.reasons.join(", ")})
|
|
3833
|
+
async formatTraceFallback(target, selectedPath, scope, limit) {
|
|
3834
|
+
const chunkHits = this.chunkIndex.search(target, { limit, scope, meta: this.fileMeta }).filter((hit) => hit.path !== selectedPath);
|
|
3835
|
+
if (chunkHits.length > 0) {
|
|
3836
|
+
return [
|
|
3837
|
+
"Trace Coverage",
|
|
3838
|
+
"- no structural edges were indexed for this target/relation",
|
|
3839
|
+
"- fallback: showing ranked chunk evidence from the same client index",
|
|
3840
|
+
"",
|
|
3841
|
+
"Possible Indexed Mentions",
|
|
3842
|
+
...chunkHits.map(
|
|
3843
|
+
(hit) => `- ${hit.path}:${hit.startLine}-${hit.endLine} ${hit.title} (score=${hit.score}; ${hit.reasons.join(", ")})
|
|
3861
3844
|
Preview: ${hit.preview}
|
|
3862
3845
|
Exact read if needed: read_file path=${hit.path} start_line=${hit.startLine} end_line=${hit.endLine} context=dependencies`
|
|
3863
|
-
|
|
3864
|
-
|
|
3865
|
-
}
|
|
3846
|
+
)
|
|
3847
|
+
];
|
|
3866
3848
|
}
|
|
3867
3849
|
const terms = queryTerms(target);
|
|
3868
3850
|
const exact = target.toLowerCase().trim();
|
|
3869
3851
|
if (exact && !terms.includes(exact)) terms.unshift(exact);
|
|
3870
3852
|
const compact = exact.replace(/[^a-z0-9]/g, "");
|
|
3871
3853
|
if (compact && !terms.includes(compact)) terms.push(compact);
|
|
3872
|
-
const mentions = (await this.findFilesMentioning(terms, { topK: limit * 4 })).filter(([
|
|
3854
|
+
const mentions = (await this.findFilesMentioning(terms, { topK: limit * 4 })).filter(([path7]) => path7 !== selectedPath && scopeFilter(path7, scope)).slice(0, limit);
|
|
3873
3855
|
const lines = [
|
|
3874
3856
|
"Trace Coverage",
|
|
3875
3857
|
"- no structural edges were indexed for this target/relation",
|
|
@@ -3881,22 +3863,22 @@ var WorkspaceIndexStore = class {
|
|
|
3881
3863
|
lines.push("- none indexed; use grep for exact byte-level search");
|
|
3882
3864
|
return lines;
|
|
3883
3865
|
}
|
|
3884
|
-
for (const [
|
|
3885
|
-
const syms = this.listSymbols(
|
|
3886
|
-
const outgoing = (this.edgesOutByPath.get(
|
|
3866
|
+
for (const [path7, count] of mentions) {
|
|
3867
|
+
const syms = this.listSymbols(path7).slice(0, 3);
|
|
3868
|
+
const outgoing = (this.edgesOutByPath.get(path7) ?? []).filter((e) => e.target === exact || terms.includes(e.target) || e.source_name.toLowerCase().includes(exact)).slice(0, 3);
|
|
3887
3869
|
const details = [`content_hits=${count}`];
|
|
3888
3870
|
if (syms.length > 0) details.push(`symbols=${syms.map((s) => `${s.name}@${s.line}`).join(",")}`);
|
|
3889
3871
|
if (outgoing.length > 0) details.push(`edges=${outgoing.map((e) => `${e.kind}:${e.target}@${e.line}`).join(",")}`);
|
|
3890
3872
|
const firstLine = syms[0]?.line ?? 1;
|
|
3891
|
-
lines.push(`- ${
|
|
3892
|
-
lines.push(` Exact read if needed: read_file path=${
|
|
3873
|
+
lines.push(`- ${path7} (${details.join("; ")})`);
|
|
3874
|
+
lines.push(` Exact read if needed: read_file path=${path7} start_line=${firstLine} context=dependencies`);
|
|
3893
3875
|
}
|
|
3894
3876
|
return lines;
|
|
3895
3877
|
}
|
|
3896
|
-
async relatedContextForPath(
|
|
3897
|
-
const imports = (this.edgesOutByPath.get(
|
|
3898
|
-
const dependencies = (this.edgesOutByPath.get(
|
|
3899
|
-
const syms = this.listSymbols(
|
|
3878
|
+
async relatedContextForPath(path7, limit) {
|
|
3879
|
+
const imports = (this.edgesOutByPath.get(path7) ?? []).filter((e) => e.kind === "imports" && e.target).map((e) => e.target);
|
|
3880
|
+
const dependencies = (this.edgesOutByPath.get(path7) ?? []).filter((e) => e.kind !== "imports" && e.target).map((e) => `${e.kind}:${e.target}`);
|
|
3881
|
+
const syms = this.listSymbols(path7);
|
|
3900
3882
|
const dependentEdges = [];
|
|
3901
3883
|
for (const sym of syms.slice(0, 8)) {
|
|
3902
3884
|
dependentEdges.push(...this.findCallers(sym.name, { limit }));
|
|
@@ -3904,17 +3886,17 @@ var WorkspaceIndexStore = class {
|
|
|
3904
3886
|
dependentEdges.push(...this.findImporters(sym.name, { limit }));
|
|
3905
3887
|
}
|
|
3906
3888
|
const dependentPaths = dedupe(dependentEdges, edgeKey, limit * 2).map((e) => e.source_path);
|
|
3907
|
-
for (const token of pathStems(
|
|
3889
|
+
for (const token of pathStems(path7)) {
|
|
3908
3890
|
dependentPaths.push(...this.findImporters(token, { limit }).map((e) => e.source_path));
|
|
3909
3891
|
}
|
|
3910
3892
|
const symbolNames = new Set(syms.slice(0, 8).map((s) => s.name.toLowerCase()));
|
|
3911
|
-
const stems = new Set(pathStems(
|
|
3893
|
+
const stems = new Set(pathStems(path7));
|
|
3912
3894
|
const symbolSets = new Map(
|
|
3913
3895
|
[...symbolNames].map((n) => [n, this.chunkIndex.filesWithTerm(n)])
|
|
3914
3896
|
);
|
|
3915
3897
|
const tests = [];
|
|
3916
3898
|
for (const [candidate, c] of this.testFileCandidatesFor()) {
|
|
3917
|
-
if (candidate ===
|
|
3899
|
+
if (candidate === path7) continue;
|
|
3918
3900
|
if ([...stems].some((t) => c.includes(t)) || [...symbolNames].some((n) => c.includes(n)) || [...symbolNames].some((n) => symbolSets.get(n)?.has(candidate) ?? false)) {
|
|
3919
3901
|
tests.push(candidate);
|
|
3920
3902
|
}
|
|
@@ -3923,7 +3905,7 @@ var WorkspaceIndexStore = class {
|
|
|
3923
3905
|
imports: dedupe(imports, (p) => p, limit),
|
|
3924
3906
|
dependencies: dedupe(dependencies, (p) => p, limit),
|
|
3925
3907
|
// Self-references (recursion, same-file calls) are not dependents.
|
|
3926
|
-
dependents: dedupe(dependentPaths.filter((p) => p !==
|
|
3908
|
+
dependents: dedupe(dependentPaths.filter((p) => p !== path7), (p) => p, limit),
|
|
3927
3909
|
tests: dedupe(tests, (p) => p, limit)
|
|
3928
3910
|
};
|
|
3929
3911
|
}
|
|
@@ -4001,13 +3983,13 @@ var WorkspaceIndexStore = class {
|
|
|
4001
3983
|
reasons: [c.reason]
|
|
4002
3984
|
}));
|
|
4003
3985
|
}
|
|
4004
|
-
renderFileCard(
|
|
3986
|
+
renderFileCard(path7, rank, reasons, detail, related) {
|
|
4005
3987
|
const maxRelated = detailLimit(detail, 2, 4, 7);
|
|
4006
|
-
const lines = [`${rank}. ${
|
|
3988
|
+
const lines = [`${rank}. ${path7}`];
|
|
4007
3989
|
if (reasons.length > 0) lines.push(` Why: ${dedupe(reasons, (r) => r, 6).join(", ")}`);
|
|
4008
|
-
const summary = this.fileSummaryFor(
|
|
3990
|
+
const summary = this.fileSummaryFor(path7);
|
|
4009
3991
|
if (summary) lines.push(` Summary: ${summary}`);
|
|
4010
|
-
const syms = this.listSymbols(
|
|
3992
|
+
const syms = this.listSymbols(path7);
|
|
4011
3993
|
if (syms.length > 0) {
|
|
4012
3994
|
const shown = syms.slice(0, maxRelated).map((s) => `${s.signature || s.name}@${s.line}`);
|
|
4013
3995
|
const tail = syms.length > shown.length ? ` (+${syms.length - shown.length} more)` : "";
|
|
@@ -4017,7 +3999,7 @@ var WorkspaceIndexStore = class {
|
|
|
4017
3999
|
const dependencies = related.dependencies.slice(0, maxRelated);
|
|
4018
4000
|
const dependents = related.dependents.slice(0, maxRelated);
|
|
4019
4001
|
const relatedTests = related.tests.slice(0, maxRelated);
|
|
4020
|
-
const chunks =
|
|
4002
|
+
const chunks = this.chunkIndex.bestChunksForPath(path7, detail === "deep" ? 3 : 2);
|
|
4021
4003
|
if (chunks.length > 0) {
|
|
4022
4004
|
lines.push(` Chunks: ${chunks.map((c) => `${c.title}@${c.startLine}-${c.endLine}`).join(", ")}`);
|
|
4023
4005
|
}
|
|
@@ -4025,7 +4007,7 @@ var WorkspaceIndexStore = class {
|
|
|
4025
4007
|
if (dependencies.length > 0) lines.push(` Uses: ${dependencies.join(", ")}`);
|
|
4026
4008
|
if (dependents.length > 0) lines.push(` Used by: ${dependents.join(", ")}`);
|
|
4027
4009
|
if (relatedTests.length > 0) lines.push(` Related tests: ${relatedTests.join(", ")}`);
|
|
4028
|
-
lines.push(syms.length > 0 ? ` Exact read if needed: read_file path=${
|
|
4010
|
+
lines.push(syms.length > 0 ? ` Exact read if needed: read_file path=${path7} start_line=${syms[0].line} context=dependencies` : ` Exact read if needed: read_file path=${path7} context=dependencies`);
|
|
4029
4011
|
return lines;
|
|
4030
4012
|
}
|
|
4031
4013
|
formatEdges(title, edges, limit) {
|
|
@@ -4043,10 +4025,10 @@ var WorkspaceIndexStore = class {
|
|
|
4043
4025
|
const s = this.status();
|
|
4044
4026
|
return `ready=${s.ready} state=${s.state} progress=${s.progress_percent}% files=${s.file_count} symbols=${s.symbol_count} edges=${s.edge_count} resolved_edges=${s.resolved_edge_count} chunks=${this.chunkIndex.size()}`;
|
|
4045
4027
|
}
|
|
4046
|
-
fileSummaryFor(
|
|
4047
|
-
const summary = (this.fileSummaries.get(
|
|
4028
|
+
fileSummaryFor(path7) {
|
|
4029
|
+
const summary = (this.fileSummaries.get(path7) ?? "").trim();
|
|
4048
4030
|
if (summary) return summary;
|
|
4049
|
-
const syms = this.listSymbols(
|
|
4031
|
+
const syms = this.listSymbols(path7);
|
|
4050
4032
|
if (syms.length === 0) return "";
|
|
4051
4033
|
const names = syms.map((s) => s.name).filter((n) => !n.startsWith("_"));
|
|
4052
4034
|
const shown = (names.length > 0 ? names : syms.map((s) => s.name)).slice(0, 5);
|
|
@@ -4234,20 +4216,20 @@ var WorkspaceIndexStore = class {
|
|
|
4234
4216
|
}
|
|
4235
4217
|
return null;
|
|
4236
4218
|
}
|
|
4237
|
-
removePath(
|
|
4238
|
-
this.removePathStems(
|
|
4239
|
-
this.pathIndex.remove(
|
|
4240
|
-
this.chunkIndex.removePath(
|
|
4241
|
-
const prev = this.byPath.get(
|
|
4242
|
-
this.byPath.delete(
|
|
4243
|
-
this.removeEdgesFromPath(
|
|
4244
|
-
this.fileMeta.delete(
|
|
4245
|
-
this.fileSummaries.delete(
|
|
4219
|
+
removePath(path7) {
|
|
4220
|
+
this.removePathStems(path7);
|
|
4221
|
+
this.pathIndex.remove(path7);
|
|
4222
|
+
this.chunkIndex.removePath(path7);
|
|
4223
|
+
const prev = this.byPath.get(path7) ?? [];
|
|
4224
|
+
this.byPath.delete(path7);
|
|
4225
|
+
this.removeEdgesFromPath(path7);
|
|
4226
|
+
this.fileMeta.delete(path7);
|
|
4227
|
+
this.fileSummaries.delete(path7);
|
|
4246
4228
|
for (const sym of prev) {
|
|
4247
4229
|
const key = sym.name.toLowerCase();
|
|
4248
4230
|
const bucket = this.byName.get(key);
|
|
4249
4231
|
if (!bucket) continue;
|
|
4250
|
-
const next = bucket.filter((s) => s.path !==
|
|
4232
|
+
const next = bucket.filter((s) => s.path !== path7);
|
|
4251
4233
|
if (next.length > 0) {
|
|
4252
4234
|
this.byName.set(key, next);
|
|
4253
4235
|
} else {
|
|
@@ -4266,9 +4248,9 @@ var WorkspaceIndexStore = class {
|
|
|
4266
4248
|
}
|
|
4267
4249
|
this.totalSymbols = Math.max(0, this.totalSymbols - prev.length);
|
|
4268
4250
|
}
|
|
4269
|
-
removeEdgesFromPath(
|
|
4270
|
-
const outgoing = this.edgesOutByPath.get(
|
|
4271
|
-
this.edgesOutByPath.delete(
|
|
4251
|
+
removeEdgesFromPath(path7) {
|
|
4252
|
+
const outgoing = this.edgesOutByPath.get(path7) ?? [];
|
|
4253
|
+
this.edgesOutByPath.delete(path7);
|
|
4272
4254
|
if (outgoing.length === 0) return;
|
|
4273
4255
|
const dropsByTarget = /* @__PURE__ */ new Map();
|
|
4274
4256
|
for (const edge of outgoing) {
|
|
@@ -4285,48 +4267,48 @@ var WorkspaceIndexStore = class {
|
|
|
4285
4267
|
this.totalEdges = Math.max(0, this.totalEdges - outgoing.length);
|
|
4286
4268
|
this.totalResolvedEdges = Math.max(0, this.totalResolvedEdges - outgoing.filter((e) => (e.confidence || "AMBIGUOUS") !== "AMBIGUOUS").length);
|
|
4287
4269
|
}
|
|
4288
|
-
setMeta(
|
|
4289
|
-
this.fileMeta.set(
|
|
4270
|
+
setMeta(path7, override) {
|
|
4271
|
+
this.fileMeta.set(path7, {
|
|
4290
4272
|
mtime: override?.mtime ?? 0,
|
|
4291
4273
|
size: override?.size ?? 0,
|
|
4292
|
-
is_test: Boolean(override?.is_test) || isTestPath(
|
|
4293
|
-
is_generated: Boolean(override?.is_generated) || isGeneratedPath(
|
|
4274
|
+
is_test: Boolean(override?.is_test) || isTestPath(path7),
|
|
4275
|
+
is_generated: Boolean(override?.is_generated) || isGeneratedPath(path7)
|
|
4294
4276
|
});
|
|
4295
4277
|
}
|
|
4296
4278
|
suggestPaths(query, limit = 5) {
|
|
4297
4279
|
return this.pathIndex.search(query, { limit, includeDocs: true }).map((hit) => hit.path);
|
|
4298
4280
|
}
|
|
4299
|
-
readRangeSuggestions(
|
|
4300
|
-
return this.chunkIndex.bestChunksForPath(
|
|
4281
|
+
readRangeSuggestions(path7, limit = 5) {
|
|
4282
|
+
return this.chunkIndex.bestChunksForPath(path7, limit).map((chunk) => ({
|
|
4301
4283
|
startLine: chunk.startLine,
|
|
4302
4284
|
endLine: chunk.endLine,
|
|
4303
4285
|
title: chunk.title
|
|
4304
4286
|
}));
|
|
4305
4287
|
}
|
|
4306
|
-
indexPathStems(
|
|
4307
|
-
const stems = pathStems(
|
|
4308
|
-
this.pathStemsByFile.set(
|
|
4288
|
+
indexPathStems(path7) {
|
|
4289
|
+
const stems = pathStems(path7);
|
|
4290
|
+
this.pathStemsByFile.set(path7, stems);
|
|
4309
4291
|
const final = stems.at(-1);
|
|
4310
4292
|
if (final) {
|
|
4311
4293
|
if (!this.filesByFinalStem.has(final)) this.filesByFinalStem.set(final, /* @__PURE__ */ new Set());
|
|
4312
|
-
this.filesByFinalStem.get(final).add(
|
|
4294
|
+
this.filesByFinalStem.get(final).add(path7);
|
|
4313
4295
|
}
|
|
4314
4296
|
}
|
|
4315
|
-
removePathStems(
|
|
4316
|
-
const stems = this.pathStemsByFile.get(
|
|
4317
|
-
this.pathStemsByFile.delete(
|
|
4297
|
+
removePathStems(path7) {
|
|
4298
|
+
const stems = this.pathStemsByFile.get(path7);
|
|
4299
|
+
this.pathStemsByFile.delete(path7);
|
|
4318
4300
|
const final = stems?.at(-1);
|
|
4319
4301
|
if (!final) return;
|
|
4320
4302
|
const bucket = this.filesByFinalStem.get(final);
|
|
4321
4303
|
if (!bucket) return;
|
|
4322
|
-
bucket.delete(
|
|
4304
|
+
bucket.delete(path7);
|
|
4323
4305
|
if (bucket.size === 0) this.filesByFinalStem.delete(final);
|
|
4324
4306
|
}
|
|
4325
|
-
stemsForPath(
|
|
4326
|
-
const existing = this.pathStemsByFile.get(
|
|
4307
|
+
stemsForPath(path7) {
|
|
4308
|
+
const existing = this.pathStemsByFile.get(path7);
|
|
4327
4309
|
if (existing) return existing;
|
|
4328
|
-
this.indexPathStems(
|
|
4329
|
-
return this.pathStemsByFile.get(
|
|
4310
|
+
this.indexPathStems(path7);
|
|
4311
|
+
return this.pathStemsByFile.get(path7) ?? [];
|
|
4330
4312
|
}
|
|
4331
4313
|
resolvesInFile(sourcePath, targetName) {
|
|
4332
4314
|
if (!targetName) return true;
|
|
@@ -4810,7 +4792,7 @@ function moduleNameFromSourceLiteral(literal) {
|
|
|
4810
4792
|
function moduleSpecFromSourceLiteral(literal) {
|
|
4811
4793
|
return literal.replace(/^['"]|['"]$/g, "");
|
|
4812
4794
|
}
|
|
4813
|
-
function extractFromMatches(matches,
|
|
4795
|
+
function extractFromMatches(matches, path7, allLines) {
|
|
4814
4796
|
const symbols = [];
|
|
4815
4797
|
const edges = [];
|
|
4816
4798
|
for (const m of matches) {
|
|
@@ -4823,7 +4805,7 @@ function extractFromMatches(matches, path5, allLines) {
|
|
|
4823
4805
|
const name2 = byName["symbol.function.name"]?.[0]?.text;
|
|
4824
4806
|
if (name2) {
|
|
4825
4807
|
symbols.push({
|
|
4826
|
-
path:
|
|
4808
|
+
path: path7,
|
|
4827
4809
|
name: name2,
|
|
4828
4810
|
kind: "function",
|
|
4829
4811
|
line: lineOf(def),
|
|
@@ -4836,7 +4818,7 @@ function extractFromMatches(matches, path5, allLines) {
|
|
|
4836
4818
|
const name2 = byName["symbol.method.name"]?.[0]?.text;
|
|
4837
4819
|
if (name2) {
|
|
4838
4820
|
symbols.push({
|
|
4839
|
-
path:
|
|
4821
|
+
path: path7,
|
|
4840
4822
|
name: name2,
|
|
4841
4823
|
kind: "method",
|
|
4842
4824
|
line: lineOf(def),
|
|
@@ -4849,7 +4831,7 @@ function extractFromMatches(matches, path5, allLines) {
|
|
|
4849
4831
|
const name2 = byName["symbol.class.name"]?.[0]?.text;
|
|
4850
4832
|
if (name2) {
|
|
4851
4833
|
symbols.push({
|
|
4852
|
-
path:
|
|
4834
|
+
path: path7,
|
|
4853
4835
|
name: name2,
|
|
4854
4836
|
kind: "class",
|
|
4855
4837
|
line: lineOf(def),
|
|
@@ -4858,7 +4840,7 @@ function extractFromMatches(matches, path5, allLines) {
|
|
|
4858
4840
|
for (const parent of byName["edge.extends.parent"] ?? []) {
|
|
4859
4841
|
edges.push({
|
|
4860
4842
|
kind: "extends",
|
|
4861
|
-
source_path:
|
|
4843
|
+
source_path: path7,
|
|
4862
4844
|
source_name: name2,
|
|
4863
4845
|
target: parent.text.toLowerCase(),
|
|
4864
4846
|
line: lineOf(parent)
|
|
@@ -4871,7 +4853,7 @@ function extractFromMatches(matches, path5, allLines) {
|
|
|
4871
4853
|
const name2 = byName["symbol.interface.name"]?.[0]?.text;
|
|
4872
4854
|
if (name2) {
|
|
4873
4855
|
symbols.push({
|
|
4874
|
-
path:
|
|
4856
|
+
path: path7,
|
|
4875
4857
|
name: name2,
|
|
4876
4858
|
kind: "interface",
|
|
4877
4859
|
line: lineOf(def),
|
|
@@ -4884,7 +4866,7 @@ function extractFromMatches(matches, path5, allLines) {
|
|
|
4884
4866
|
const name2 = byName["symbol.type.name"]?.[0]?.text;
|
|
4885
4867
|
if (name2) {
|
|
4886
4868
|
symbols.push({
|
|
4887
|
-
path:
|
|
4869
|
+
path: path7,
|
|
4888
4870
|
name: name2,
|
|
4889
4871
|
kind: "type",
|
|
4890
4872
|
line: lineOf(def),
|
|
@@ -4897,7 +4879,7 @@ function extractFromMatches(matches, path5, allLines) {
|
|
|
4897
4879
|
const name2 = byName["symbol.enum.name"]?.[0]?.text;
|
|
4898
4880
|
if (name2) {
|
|
4899
4881
|
symbols.push({
|
|
4900
|
-
path:
|
|
4882
|
+
path: path7,
|
|
4901
4883
|
name: name2,
|
|
4902
4884
|
kind: "enum",
|
|
4903
4885
|
line: lineOf(def),
|
|
@@ -4910,7 +4892,7 @@ function extractFromMatches(matches, path5, allLines) {
|
|
|
4910
4892
|
const last = dotted.split(".").pop() ?? dotted;
|
|
4911
4893
|
edges.push({
|
|
4912
4894
|
kind: "imports",
|
|
4913
|
-
source_path:
|
|
4895
|
+
source_path: path7,
|
|
4914
4896
|
source_name: "",
|
|
4915
4897
|
target: last.toLowerCase(),
|
|
4916
4898
|
line: lineOf(targetNode)
|
|
@@ -4921,7 +4903,7 @@ function extractFromMatches(matches, path5, allLines) {
|
|
|
4921
4903
|
if (modName) {
|
|
4922
4904
|
edges.push({
|
|
4923
4905
|
kind: "imports",
|
|
4924
|
-
source_path:
|
|
4906
|
+
source_path: path7,
|
|
4925
4907
|
source_name: "",
|
|
4926
4908
|
target: modName.toLowerCase(),
|
|
4927
4909
|
line: lineOf(sourceLit),
|
|
@@ -4933,7 +4915,7 @@ function extractFromMatches(matches, path5, allLines) {
|
|
|
4933
4915
|
const sourceName = enclosingSymbolName(callTarget);
|
|
4934
4916
|
edges.push({
|
|
4935
4917
|
kind: "calls",
|
|
4936
|
-
source_path:
|
|
4918
|
+
source_path: path7,
|
|
4937
4919
|
source_name: sourceName,
|
|
4938
4920
|
target: callTarget.text.toLowerCase(),
|
|
4939
4921
|
line: lineOf(callTarget)
|
|
@@ -4945,7 +4927,7 @@ function extractFromMatches(matches, path5, allLines) {
|
|
|
4945
4927
|
if (childName) {
|
|
4946
4928
|
edges.push({
|
|
4947
4929
|
kind: "extends",
|
|
4948
|
-
source_path:
|
|
4930
|
+
source_path: path7,
|
|
4949
4931
|
source_name: childName,
|
|
4950
4932
|
target: parent.text.toLowerCase(),
|
|
4951
4933
|
line: lineOf(parent)
|
|
@@ -4957,7 +4939,7 @@ function extractFromMatches(matches, path5, allLines) {
|
|
|
4957
4939
|
if (childName) {
|
|
4958
4940
|
edges.push({
|
|
4959
4941
|
kind: "implements",
|
|
4960
|
-
source_path:
|
|
4942
|
+
source_path: path7,
|
|
4961
4943
|
source_name: childName,
|
|
4962
4944
|
target: parent.text.toLowerCase(),
|
|
4963
4945
|
line: lineOf(parent)
|
|
@@ -4967,7 +4949,7 @@ function extractFromMatches(matches, path5, allLines) {
|
|
|
4967
4949
|
}
|
|
4968
4950
|
return { symbols, edges };
|
|
4969
4951
|
}
|
|
4970
|
-
function extractWithTreeSitter(handle4, lang,
|
|
4952
|
+
function extractWithTreeSitter(handle4, lang, path7, content) {
|
|
4971
4953
|
const querySource = queryFor(lang);
|
|
4972
4954
|
if (!querySource) return null;
|
|
4973
4955
|
const tree = handle4.parse(lang, content);
|
|
@@ -4977,7 +4959,7 @@ function extractWithTreeSitter(handle4, lang, path5, content) {
|
|
|
4977
4959
|
if (!query) return null;
|
|
4978
4960
|
const matches = query.matches(tree.rootNode);
|
|
4979
4961
|
const allLines = content.split("\n");
|
|
4980
|
-
return extractFromMatches(matches,
|
|
4962
|
+
return extractFromMatches(matches, path7, allLines);
|
|
4981
4963
|
} finally {
|
|
4982
4964
|
try {
|
|
4983
4965
|
tree.delete();
|
|
@@ -5176,10 +5158,10 @@ function langFromExt(ext) {
|
|
|
5176
5158
|
return null;
|
|
5177
5159
|
}
|
|
5178
5160
|
}
|
|
5179
|
-
function languageForPath(
|
|
5180
|
-
const dot =
|
|
5161
|
+
function languageForPath(path7) {
|
|
5162
|
+
const dot = path7.lastIndexOf(".");
|
|
5181
5163
|
if (dot < 0) return null;
|
|
5182
|
-
return langFromExt(
|
|
5164
|
+
return langFromExt(path7.slice(dot));
|
|
5183
5165
|
}
|
|
5184
5166
|
async function tryLoad(grammarDir) {
|
|
5185
5167
|
if (handle2) return handle2;
|
|
@@ -5278,9 +5260,9 @@ async function ensureGrammar(h, lang) {
|
|
|
5278
5260
|
|
|
5279
5261
|
// ../packages/orion-client-core/src/summaries.ts
|
|
5280
5262
|
var SUMMARY_MAX_CHARS = 200;
|
|
5281
|
-
function familyFor(
|
|
5282
|
-
const dot =
|
|
5283
|
-
const ext = dot >= 0 ?
|
|
5263
|
+
function familyFor(path7) {
|
|
5264
|
+
const dot = path7.lastIndexOf(".");
|
|
5265
|
+
const ext = dot >= 0 ? path7.slice(dot).toLowerCase() : "";
|
|
5284
5266
|
switch (ext) {
|
|
5285
5267
|
case ".py":
|
|
5286
5268
|
return "python";
|
|
@@ -5333,10 +5315,10 @@ function clean(text) {
|
|
|
5333
5315
|
function stripDocstringQuotes(raw) {
|
|
5334
5316
|
return raw.trim().replace(/^[rbRBuUfF]*("""|'''|"|')/, "").replace(/("""|'''|"|')$/, "");
|
|
5335
5317
|
}
|
|
5336
|
-
function extractFileSummary(
|
|
5318
|
+
function extractFileSummary(path7, content, opts) {
|
|
5337
5319
|
if (!opts.shipDocstrings) return "";
|
|
5338
5320
|
const lines = content.split("\n");
|
|
5339
|
-
const raw = familyFor(
|
|
5321
|
+
const raw = familyFor(path7) === "python" ? pythonModuleDocstring(lines) : leadingCommentBlock(lines, familyFor(path7));
|
|
5340
5322
|
return clean(raw);
|
|
5341
5323
|
}
|
|
5342
5324
|
function pythonModuleDocstring(lines) {
|
|
@@ -5391,10 +5373,10 @@ function leadingCommentBlock(lines, fam) {
|
|
|
5391
5373
|
}
|
|
5392
5374
|
return collected.filter((l) => l && !isLicenseNoise(l)).join(" ");
|
|
5393
5375
|
}
|
|
5394
|
-
function extractSymbolSummaries(
|
|
5376
|
+
function extractSymbolSummaries(path7, content, symbols, opts) {
|
|
5395
5377
|
const out2 = /* @__PURE__ */ new Map();
|
|
5396
5378
|
if (!opts.shipDocstrings || symbols.length === 0) return out2;
|
|
5397
|
-
const fam = familyFor(
|
|
5379
|
+
const fam = familyFor(path7);
|
|
5398
5380
|
const lines = content.split("\n");
|
|
5399
5381
|
for (const s of symbols) {
|
|
5400
5382
|
const raw = fam === "python" ? pythonSymbolDocstring(lines, s.line) : precedingCommentSummary(lines, s.line, fam);
|
|
@@ -6190,9 +6172,9 @@ var SWIFT_RULES = [
|
|
|
6190
6172
|
{ match: /^\s*extension\s+(\w+)/, kind: "type", nameGroup: 1 },
|
|
6191
6173
|
{ match: /^\s*(?:(?:public|private|internal|fileprivate|open|static|class|final|override|mutating)\s+)*func\s+(\w+)/, kind: "function", nameGroup: 1 }
|
|
6192
6174
|
];
|
|
6193
|
-
function languageFor(
|
|
6194
|
-
const dot =
|
|
6195
|
-
const ext = dot >= 0 ?
|
|
6175
|
+
function languageFor(path7) {
|
|
6176
|
+
const dot = path7.lastIndexOf(".");
|
|
6177
|
+
const ext = dot >= 0 ? path7.slice(dot).toLowerCase() : "";
|
|
6196
6178
|
switch (ext) {
|
|
6197
6179
|
case ".py":
|
|
6198
6180
|
return { family: "python", rules: PYTHON_RULES };
|
|
@@ -6328,8 +6310,8 @@ function isProbablyGeneratedPath(p) {
|
|
|
6328
6310
|
const lc = p.toLowerCase();
|
|
6329
6311
|
return lc.includes("/generated/") || lc.includes("/__generated__/") || lc.includes("/build/") || lc.includes("/dist/") || lc.endsWith(".min.js") || lc.endsWith(".bundle.js");
|
|
6330
6312
|
}
|
|
6331
|
-
function extractSymbols(
|
|
6332
|
-
const { rules } = languageFor(
|
|
6313
|
+
function extractSymbols(path7, content) {
|
|
6314
|
+
const { rules } = languageFor(path7);
|
|
6333
6315
|
if (rules.length === 0) return [];
|
|
6334
6316
|
const out2 = [];
|
|
6335
6317
|
const lines = content.split("\n");
|
|
@@ -6346,7 +6328,7 @@ function extractSymbols(path5, content) {
|
|
|
6346
6328
|
if (!name2) continue;
|
|
6347
6329
|
const sig = trimmed.length > 160 ? trimmed.slice(0, 160) + "\u2026" : trimmed;
|
|
6348
6330
|
out2.push({
|
|
6349
|
-
path:
|
|
6331
|
+
path: path7,
|
|
6350
6332
|
name: name2,
|
|
6351
6333
|
kind: rule.kind,
|
|
6352
6334
|
line: i2 + 1,
|
|
@@ -6368,7 +6350,7 @@ function pathBasename(s) {
|
|
|
6368
6350
|
function jsModuleTarget(spec) {
|
|
6369
6351
|
return pathBasename(spec).replace(/\.(d\.)?ts$/, "").replace(/\.js$/, "");
|
|
6370
6352
|
}
|
|
6371
|
-
function extractEdgesPython(
|
|
6353
|
+
function extractEdgesPython(path7, lines) {
|
|
6372
6354
|
const edges = [];
|
|
6373
6355
|
const scope = [];
|
|
6374
6356
|
const indentOf = (s) => {
|
|
@@ -6397,7 +6379,7 @@ function extractEdgesPython(path5, lines) {
|
|
|
6397
6379
|
if (name2 && name2 !== "object") {
|
|
6398
6380
|
edges.push({
|
|
6399
6381
|
kind: "extends",
|
|
6400
|
-
source_path:
|
|
6382
|
+
source_path: path7,
|
|
6401
6383
|
source_name: child,
|
|
6402
6384
|
target: name2.toLowerCase(),
|
|
6403
6385
|
line: i2 + 1
|
|
@@ -6418,7 +6400,7 @@ function extractEdgesPython(path5, lines) {
|
|
|
6418
6400
|
if (tgt) {
|
|
6419
6401
|
edges.push({
|
|
6420
6402
|
kind: "imports",
|
|
6421
|
-
source_path:
|
|
6403
|
+
source_path: path7,
|
|
6422
6404
|
source_name: "",
|
|
6423
6405
|
target: tgt.toLowerCase(),
|
|
6424
6406
|
line: i2 + 1
|
|
@@ -6434,7 +6416,7 @@ function extractEdgesPython(path5, lines) {
|
|
|
6434
6416
|
if (tgt && tgt !== "*") {
|
|
6435
6417
|
edges.push({
|
|
6436
6418
|
kind: "imports",
|
|
6437
|
-
source_path:
|
|
6419
|
+
source_path: path7,
|
|
6438
6420
|
source_name: "",
|
|
6439
6421
|
target: tgt.toLowerCase(),
|
|
6440
6422
|
line: i2 + 1
|
|
@@ -6452,7 +6434,7 @@ function extractEdgesPython(path5, lines) {
|
|
|
6452
6434
|
if (CALL_NOISE.has(target)) continue;
|
|
6453
6435
|
edges.push({
|
|
6454
6436
|
kind: "calls",
|
|
6455
|
-
source_path:
|
|
6437
|
+
source_path: path7,
|
|
6456
6438
|
source_name: source,
|
|
6457
6439
|
target: target.toLowerCase(),
|
|
6458
6440
|
line: i2 + 1
|
|
@@ -6462,7 +6444,7 @@ function extractEdgesPython(path5, lines) {
|
|
|
6462
6444
|
}
|
|
6463
6445
|
return edges;
|
|
6464
6446
|
}
|
|
6465
|
-
function extractEdgesJsTs(
|
|
6447
|
+
function extractEdgesJsTs(path7, lines) {
|
|
6466
6448
|
const edges = [];
|
|
6467
6449
|
const scope = [];
|
|
6468
6450
|
let braceDepth = 0;
|
|
@@ -6481,7 +6463,7 @@ function extractEdgesJsTs(path5, lines) {
|
|
|
6481
6463
|
if (tgt) {
|
|
6482
6464
|
edges.push({
|
|
6483
6465
|
kind: "imports",
|
|
6484
|
-
source_path:
|
|
6466
|
+
source_path: path7,
|
|
6485
6467
|
source_name: "",
|
|
6486
6468
|
target: tgt.toLowerCase(),
|
|
6487
6469
|
line: i2 + 1,
|
|
@@ -6497,7 +6479,7 @@ function extractEdgesJsTs(path5, lines) {
|
|
|
6497
6479
|
if (cleaned) {
|
|
6498
6480
|
edges.push({
|
|
6499
6481
|
kind: "imports",
|
|
6500
|
-
source_path:
|
|
6482
|
+
source_path: path7,
|
|
6501
6483
|
source_name: "",
|
|
6502
6484
|
target: cleaned.toLowerCase(),
|
|
6503
6485
|
line: i2 + 1,
|
|
@@ -6515,7 +6497,7 @@ function extractEdgesJsTs(path5, lines) {
|
|
|
6515
6497
|
if (parent) {
|
|
6516
6498
|
edges.push({
|
|
6517
6499
|
kind: "extends",
|
|
6518
|
-
source_path:
|
|
6500
|
+
source_path: path7,
|
|
6519
6501
|
source_name: child,
|
|
6520
6502
|
target: parent.toLowerCase(),
|
|
6521
6503
|
line: i2 + 1
|
|
@@ -6527,7 +6509,7 @@ function extractEdgesJsTs(path5, lines) {
|
|
|
6527
6509
|
if (cleaned) {
|
|
6528
6510
|
edges.push({
|
|
6529
6511
|
kind: "implements",
|
|
6530
|
-
source_path:
|
|
6512
|
+
source_path: path7,
|
|
6531
6513
|
source_name: child,
|
|
6532
6514
|
target: cleaned.toLowerCase(),
|
|
6533
6515
|
line: i2 + 1
|
|
@@ -6550,7 +6532,7 @@ function extractEdgesJsTs(path5, lines) {
|
|
|
6550
6532
|
if (CALL_NOISE.has(target)) continue;
|
|
6551
6533
|
edges.push({
|
|
6552
6534
|
kind: "calls",
|
|
6553
|
-
source_path:
|
|
6535
|
+
source_path: path7,
|
|
6554
6536
|
source_name: source,
|
|
6555
6537
|
target: target.toLowerCase(),
|
|
6556
6538
|
line: i2 + 1
|
|
@@ -6564,7 +6546,7 @@ function extractEdgesJsTs(path5, lines) {
|
|
|
6564
6546
|
}
|
|
6565
6547
|
return edges;
|
|
6566
6548
|
}
|
|
6567
|
-
function extractEdgesGo(
|
|
6549
|
+
function extractEdgesGo(path7, lines) {
|
|
6568
6550
|
const edges = [];
|
|
6569
6551
|
let inImportBlock = false;
|
|
6570
6552
|
for (let i2 = 0; i2 < lines.length; i2++) {
|
|
@@ -6583,7 +6565,7 @@ function extractEdgesGo(path5, lines) {
|
|
|
6583
6565
|
const tgt = lastWord(m[1].replace(/\//g, "."));
|
|
6584
6566
|
edges.push({
|
|
6585
6567
|
kind: "imports",
|
|
6586
|
-
source_path:
|
|
6568
|
+
source_path: path7,
|
|
6587
6569
|
source_name: "",
|
|
6588
6570
|
target: tgt.toLowerCase(),
|
|
6589
6571
|
line: i2 + 1
|
|
@@ -6596,7 +6578,7 @@ function extractEdgesGo(path5, lines) {
|
|
|
6596
6578
|
const tgt = lastWord(im[1].replace(/\//g, "."));
|
|
6597
6579
|
edges.push({
|
|
6598
6580
|
kind: "imports",
|
|
6599
|
-
source_path:
|
|
6581
|
+
source_path: path7,
|
|
6600
6582
|
source_name: "",
|
|
6601
6583
|
target: tgt.toLowerCase(),
|
|
6602
6584
|
line: i2 + 1
|
|
@@ -6605,7 +6587,7 @@ function extractEdgesGo(path5, lines) {
|
|
|
6605
6587
|
}
|
|
6606
6588
|
return edges;
|
|
6607
6589
|
}
|
|
6608
|
-
function extractEdgesRust(
|
|
6590
|
+
function extractEdgesRust(path7, lines) {
|
|
6609
6591
|
const edges = [];
|
|
6610
6592
|
for (let i2 = 0; i2 < lines.length; i2++) {
|
|
6611
6593
|
const line = lines[i2];
|
|
@@ -6616,7 +6598,7 @@ function extractEdgesRust(path5, lines) {
|
|
|
6616
6598
|
if (tgt) {
|
|
6617
6599
|
edges.push({
|
|
6618
6600
|
kind: "imports",
|
|
6619
|
-
source_path:
|
|
6601
|
+
source_path: path7,
|
|
6620
6602
|
source_name: "",
|
|
6621
6603
|
target: tgt.toLowerCase(),
|
|
6622
6604
|
line: i2 + 1
|
|
@@ -6629,7 +6611,7 @@ function extractEdgesRust(path5, lines) {
|
|
|
6629
6611
|
if (cleaned && cleaned !== "*" && cleaned !== "self") {
|
|
6630
6612
|
edges.push({
|
|
6631
6613
|
kind: "imports",
|
|
6632
|
-
source_path:
|
|
6614
|
+
source_path: path7,
|
|
6633
6615
|
source_name: "",
|
|
6634
6616
|
target: cleaned.toLowerCase(),
|
|
6635
6617
|
line: i2 + 1
|
|
@@ -6642,7 +6624,7 @@ function extractEdgesRust(path5, lines) {
|
|
|
6642
6624
|
if (implMatch) {
|
|
6643
6625
|
edges.push({
|
|
6644
6626
|
kind: "implements",
|
|
6645
|
-
source_path:
|
|
6627
|
+
source_path: path7,
|
|
6646
6628
|
source_name: implMatch[2],
|
|
6647
6629
|
target: implMatch[1].toLowerCase(),
|
|
6648
6630
|
line: i2 + 1
|
|
@@ -6651,7 +6633,7 @@ function extractEdgesRust(path5, lines) {
|
|
|
6651
6633
|
}
|
|
6652
6634
|
return edges;
|
|
6653
6635
|
}
|
|
6654
|
-
function extractEdgesJava(
|
|
6636
|
+
function extractEdgesJava(path7, lines) {
|
|
6655
6637
|
const edges = [];
|
|
6656
6638
|
for (let i2 = 0; i2 < lines.length; i2++) {
|
|
6657
6639
|
const line = lines[i2];
|
|
@@ -6660,7 +6642,7 @@ function extractEdgesJava(path5, lines) {
|
|
|
6660
6642
|
const tgt = lastWord(importMatch[1]);
|
|
6661
6643
|
edges.push({
|
|
6662
6644
|
kind: "imports",
|
|
6663
|
-
source_path:
|
|
6645
|
+
source_path: path7,
|
|
6664
6646
|
source_name: "",
|
|
6665
6647
|
target: tgt.toLowerCase(),
|
|
6666
6648
|
line: i2 + 1
|
|
@@ -6672,7 +6654,7 @@ function extractEdgesJava(path5, lines) {
|
|
|
6672
6654
|
if (classMatch[2]) {
|
|
6673
6655
|
edges.push({
|
|
6674
6656
|
kind: "extends",
|
|
6675
|
-
source_path:
|
|
6657
|
+
source_path: path7,
|
|
6676
6658
|
source_name: child,
|
|
6677
6659
|
target: classMatch[2].toLowerCase(),
|
|
6678
6660
|
line: i2 + 1
|
|
@@ -6684,7 +6666,7 @@ function extractEdgesJava(path5, lines) {
|
|
|
6684
6666
|
if (cleaned) {
|
|
6685
6667
|
edges.push({
|
|
6686
6668
|
kind: "implements",
|
|
6687
|
-
source_path:
|
|
6669
|
+
source_path: path7,
|
|
6688
6670
|
source_name: child,
|
|
6689
6671
|
target: cleaned.toLowerCase(),
|
|
6690
6672
|
line: i2 + 1
|
|
@@ -6696,7 +6678,7 @@ function extractEdgesJava(path5, lines) {
|
|
|
6696
6678
|
}
|
|
6697
6679
|
return edges;
|
|
6698
6680
|
}
|
|
6699
|
-
function extractEdgesRuby(
|
|
6681
|
+
function extractEdgesRuby(path7, lines) {
|
|
6700
6682
|
const edges = [];
|
|
6701
6683
|
for (let i2 = 0; i2 < lines.length; i2++) {
|
|
6702
6684
|
const line = lines[i2];
|
|
@@ -6705,7 +6687,7 @@ function extractEdgesRuby(path5, lines) {
|
|
|
6705
6687
|
const tgt = pathBasename(requireMatch[1]).replace(/\.rb$/, "");
|
|
6706
6688
|
edges.push({
|
|
6707
6689
|
kind: "imports",
|
|
6708
|
-
source_path:
|
|
6690
|
+
source_path: path7,
|
|
6709
6691
|
source_name: "",
|
|
6710
6692
|
target: tgt.toLowerCase(),
|
|
6711
6693
|
line: i2 + 1
|
|
@@ -6715,7 +6697,7 @@ function extractEdgesRuby(path5, lines) {
|
|
|
6715
6697
|
if (classMatch) {
|
|
6716
6698
|
edges.push({
|
|
6717
6699
|
kind: "extends",
|
|
6718
|
-
source_path:
|
|
6700
|
+
source_path: path7,
|
|
6719
6701
|
source_name: classMatch[1],
|
|
6720
6702
|
target: classMatch[2].toLowerCase(),
|
|
6721
6703
|
line: i2 + 1
|
|
@@ -6743,7 +6725,7 @@ function declRegexFor(keywords) {
|
|
|
6743
6725
|
}
|
|
6744
6726
|
return re;
|
|
6745
6727
|
}
|
|
6746
|
-
function extractEdgesColonInherit(
|
|
6728
|
+
function extractEdgesColonInherit(path7, lines, opts) {
|
|
6747
6729
|
const edges = [];
|
|
6748
6730
|
const declRe = declRegexFor(opts.declKeywords);
|
|
6749
6731
|
for (let i2 = 0; i2 < lines.length; i2++) {
|
|
@@ -6754,7 +6736,7 @@ function extractEdgesColonInherit(path5, lines, opts) {
|
|
|
6754
6736
|
if (target) {
|
|
6755
6737
|
edges.push({
|
|
6756
6738
|
kind: "imports",
|
|
6757
|
-
source_path:
|
|
6739
|
+
source_path: path7,
|
|
6758
6740
|
source_name: "",
|
|
6759
6741
|
target: target.toLowerCase(),
|
|
6760
6742
|
line: i2 + 1
|
|
@@ -6775,7 +6757,7 @@ function extractEdgesColonInherit(path5, lines, opts) {
|
|
|
6775
6757
|
if (/^\w+$/.test(name2) && name2 !== child) {
|
|
6776
6758
|
edges.push({
|
|
6777
6759
|
kind: "extends",
|
|
6778
|
-
source_path:
|
|
6760
|
+
source_path: path7,
|
|
6779
6761
|
source_name: child,
|
|
6780
6762
|
target: name2.toLowerCase(),
|
|
6781
6763
|
line: i2 + 1
|
|
@@ -6786,7 +6768,7 @@ function extractEdgesColonInherit(path5, lines, opts) {
|
|
|
6786
6768
|
}
|
|
6787
6769
|
return edges;
|
|
6788
6770
|
}
|
|
6789
|
-
function extractEdgesPhp(
|
|
6771
|
+
function extractEdgesPhp(path7, lines) {
|
|
6790
6772
|
const edges = [];
|
|
6791
6773
|
for (let i2 = 0; i2 < lines.length; i2++) {
|
|
6792
6774
|
const line = lines[i2];
|
|
@@ -6794,7 +6776,7 @@ function extractEdgesPhp(path5, lines) {
|
|
|
6794
6776
|
if (use) {
|
|
6795
6777
|
edges.push({
|
|
6796
6778
|
kind: "imports",
|
|
6797
|
-
source_path:
|
|
6779
|
+
source_path: path7,
|
|
6798
6780
|
source_name: "",
|
|
6799
6781
|
target: lastWord(use[1].replace(/\\/g, ".")).toLowerCase(),
|
|
6800
6782
|
line: i2 + 1
|
|
@@ -6804,7 +6786,7 @@ function extractEdgesPhp(path5, lines) {
|
|
|
6804
6786
|
if (req) {
|
|
6805
6787
|
edges.push({
|
|
6806
6788
|
kind: "imports",
|
|
6807
|
-
source_path:
|
|
6789
|
+
source_path: path7,
|
|
6808
6790
|
source_name: "",
|
|
6809
6791
|
target: pathBasename(req[1]).toLowerCase(),
|
|
6810
6792
|
line: i2 + 1
|
|
@@ -6816,7 +6798,7 @@ function extractEdgesPhp(path5, lines) {
|
|
|
6816
6798
|
if (decl[2]) {
|
|
6817
6799
|
edges.push({
|
|
6818
6800
|
kind: "extends",
|
|
6819
|
-
source_path:
|
|
6801
|
+
source_path: path7,
|
|
6820
6802
|
source_name: child,
|
|
6821
6803
|
target: lastWord(decl[2].replace(/\\/g, ".")).toLowerCase(),
|
|
6822
6804
|
line: i2 + 1
|
|
@@ -6828,7 +6810,7 @@ function extractEdgesPhp(path5, lines) {
|
|
|
6828
6810
|
if (name2) {
|
|
6829
6811
|
edges.push({
|
|
6830
6812
|
kind: "implements",
|
|
6831
|
-
source_path:
|
|
6813
|
+
source_path: path7,
|
|
6832
6814
|
source_name: child,
|
|
6833
6815
|
target: name2.toLowerCase(),
|
|
6834
6816
|
line: i2 + 1
|
|
@@ -6840,24 +6822,24 @@ function extractEdgesPhp(path5, lines) {
|
|
|
6840
6822
|
}
|
|
6841
6823
|
return edges;
|
|
6842
6824
|
}
|
|
6843
|
-
function extractEdges(
|
|
6844
|
-
const { family } = languageFor(
|
|
6825
|
+
function extractEdges(path7, content) {
|
|
6826
|
+
const { family } = languageFor(path7);
|
|
6845
6827
|
const lines = content.split("\n");
|
|
6846
6828
|
switch (family) {
|
|
6847
6829
|
case "python":
|
|
6848
|
-
return extractEdgesPython(
|
|
6830
|
+
return extractEdgesPython(path7, lines);
|
|
6849
6831
|
case "jsts":
|
|
6850
|
-
return extractEdgesJsTs(
|
|
6832
|
+
return extractEdgesJsTs(path7, lines);
|
|
6851
6833
|
case "go":
|
|
6852
|
-
return extractEdgesGo(
|
|
6834
|
+
return extractEdgesGo(path7, lines);
|
|
6853
6835
|
case "rust":
|
|
6854
|
-
return extractEdgesRust(
|
|
6836
|
+
return extractEdgesRust(path7, lines);
|
|
6855
6837
|
case "java":
|
|
6856
|
-
return extractEdgesJava(
|
|
6838
|
+
return extractEdgesJava(path7, lines);
|
|
6857
6839
|
case "ruby":
|
|
6858
|
-
return extractEdgesRuby(
|
|
6840
|
+
return extractEdgesRuby(path7, lines);
|
|
6859
6841
|
case "cfamily":
|
|
6860
|
-
return extractEdgesColonInherit(
|
|
6842
|
+
return extractEdgesColonInherit(path7, lines, {
|
|
6861
6843
|
importRe: /^\s*#\s*include\s+"([^"]+)"/,
|
|
6862
6844
|
importTarget: pathBasename,
|
|
6863
6845
|
// C++ `enum class Foo : int` names a storage type, not a base — excluded (see declKeywords).
|
|
@@ -6865,21 +6847,21 @@ function extractEdges(path5, content) {
|
|
|
6865
6847
|
baseNoise: /\b(?:public|private|protected|virtual)\b/g
|
|
6866
6848
|
});
|
|
6867
6849
|
case "csharp":
|
|
6868
|
-
return extractEdgesColonInherit(
|
|
6850
|
+
return extractEdgesColonInherit(path7, lines, {
|
|
6869
6851
|
importRe: /^\s*(?:global\s+)?using\s+(?:static\s+)?([\w.]+)\s*;/,
|
|
6870
6852
|
importTarget: lastWord,
|
|
6871
6853
|
// `enum Color : byte` is a storage type, not a base — excluded (see declKeywords).
|
|
6872
6854
|
declKeywords: ["class", "struct", "interface"]
|
|
6873
6855
|
});
|
|
6874
6856
|
case "swift":
|
|
6875
|
-
return extractEdgesColonInherit(
|
|
6857
|
+
return extractEdgesColonInherit(path7, lines, {
|
|
6876
6858
|
importRe: /^\s*import\s+([\w.]+)/,
|
|
6877
6859
|
importTarget: lastWord,
|
|
6878
6860
|
// Swift DOES carry real conformance on an enum, and its query emits those edges.
|
|
6879
6861
|
declKeywords: ["class", "struct", "enum", "protocol"]
|
|
6880
6862
|
});
|
|
6881
6863
|
case "php":
|
|
6882
|
-
return extractEdgesPhp(
|
|
6864
|
+
return extractEdgesPhp(path7, lines);
|
|
6883
6865
|
default:
|
|
6884
6866
|
return [];
|
|
6885
6867
|
}
|
|
@@ -7116,16 +7098,16 @@ var WorkspaceIndexer = class {
|
|
|
7116
7098
|
this.cachedRemovals.delete(r.relPath);
|
|
7117
7099
|
this.cachedUpdates.set(r.relPath, r);
|
|
7118
7100
|
}
|
|
7119
|
-
rememberRemoval(
|
|
7101
|
+
rememberRemoval(path7) {
|
|
7120
7102
|
if (!this.building) return;
|
|
7121
|
-
this.cachedUpdates.delete(
|
|
7122
|
-
this.cachedRemovals.add(
|
|
7103
|
+
this.cachedUpdates.delete(path7);
|
|
7104
|
+
this.cachedRemovals.add(path7);
|
|
7123
7105
|
}
|
|
7124
|
-
shouldSkipStaleBuildResult(
|
|
7125
|
-
if (this.cachedUpdates.has(
|
|
7106
|
+
shouldSkipStaleBuildResult(path7) {
|
|
7107
|
+
if (this.cachedUpdates.has(path7)) return true;
|
|
7126
7108
|
for (const removed of this.cachedRemovals) {
|
|
7127
7109
|
const prefix = removed.endsWith("/") ? removed : removed + "/";
|
|
7128
|
-
if (
|
|
7110
|
+
if (path7 === removed || path7.startsWith(prefix)) return true;
|
|
7129
7111
|
}
|
|
7130
7112
|
return false;
|
|
7131
7113
|
}
|
|
@@ -7831,18 +7813,18 @@ var WorkspaceIndexer = class {
|
|
|
7831
7813
|
chunks: buildChunksForFile(file.relPath, text, file.symbols, file.fileSummary)
|
|
7832
7814
|
};
|
|
7833
7815
|
}
|
|
7834
|
-
async tryTreeSitter(
|
|
7816
|
+
async tryTreeSitter(path7, content, sizeBytes) {
|
|
7835
7817
|
const enabled = this.indexConfig.useTreeSitter();
|
|
7836
7818
|
const maxBytes = this.indexConfig.treeSitterMaxFileBytes();
|
|
7837
7819
|
if (!shouldExtractWithTreeSitter(sizeBytes, { enabled, maxBytes })) {
|
|
7838
7820
|
return null;
|
|
7839
7821
|
}
|
|
7840
|
-
const lang = languageForPath(
|
|
7822
|
+
const lang = languageForPath(path7);
|
|
7841
7823
|
if (!lang) return null;
|
|
7842
7824
|
const pool = this.getWorkerPool();
|
|
7843
7825
|
if (pool) {
|
|
7844
7826
|
try {
|
|
7845
|
-
return await pool.extract(lang,
|
|
7827
|
+
return await pool.extract(lang, path7, content);
|
|
7846
7828
|
} catch (e) {
|
|
7847
7829
|
console.warn("orion: tree-sitter worker failed, falling back inline", e);
|
|
7848
7830
|
}
|
|
@@ -7852,7 +7834,7 @@ var WorkspaceIndexer = class {
|
|
|
7852
7834
|
if (!handle4) return null;
|
|
7853
7835
|
const ready = await ensureGrammar(handle4, lang);
|
|
7854
7836
|
if (!ready) return null;
|
|
7855
|
-
return extractWithTreeSitter(handle4, lang,
|
|
7837
|
+
return extractWithTreeSitter(handle4, lang, path7, content);
|
|
7856
7838
|
} catch (e) {
|
|
7857
7839
|
console.warn("orion: tree-sitter extraction failed, using regex fallback", e);
|
|
7858
7840
|
return null;
|
|
@@ -7927,9 +7909,9 @@ function changedLineRanges(before, after) {
|
|
|
7927
7909
|
}
|
|
7928
7910
|
return ranges;
|
|
7929
7911
|
}
|
|
7930
|
-
function changedSymbolNames(
|
|
7931
|
-
const postSyms = extractSymbols(
|
|
7932
|
-
const preSyms = extractSymbols(
|
|
7912
|
+
function changedSymbolNames(path7, before, after) {
|
|
7913
|
+
const postSyms = extractSymbols(path7, after);
|
|
7914
|
+
const preSyms = extractSymbols(path7, before);
|
|
7933
7915
|
const ranges = changedLineRanges(before, after);
|
|
7934
7916
|
const inChangedRange = (line) => ranges.some(([s, e]) => s <= line && line <= e);
|
|
7935
7917
|
const names = /* @__PURE__ */ new Set();
|
|
@@ -7942,22 +7924,22 @@ function changedSymbolNames(path5, before, after) {
|
|
|
7942
7924
|
}
|
|
7943
7925
|
return names;
|
|
7944
7926
|
}
|
|
7945
|
-
function moduleStem(
|
|
7946
|
-
const base =
|
|
7927
|
+
function moduleStem(path7) {
|
|
7928
|
+
const base = path7.split("/").pop() ?? "";
|
|
7947
7929
|
const dot = base.lastIndexOf(".");
|
|
7948
7930
|
return dot > 0 ? base.slice(0, dot) : base;
|
|
7949
7931
|
}
|
|
7950
|
-
function buildDependencyAdvisory(
|
|
7951
|
-
if (!
|
|
7932
|
+
function buildDependencyAdvisory(path7, before, after, graph, options = {}) {
|
|
7933
|
+
if (!path7 || after === null) return null;
|
|
7952
7934
|
if (!graph.status().ready) return null;
|
|
7953
7935
|
const maxFiles = Math.max(1, options.maxFiles ?? DEPENDENCY_ADVISORY_MAX_FILES);
|
|
7954
7936
|
const maxSymbols = Math.max(1, options.maxSymbols ?? DEPENDENCY_ADVISORY_MAX_SYMBOLS);
|
|
7955
7937
|
const isNew = before === null;
|
|
7956
7938
|
let changed;
|
|
7957
7939
|
if (isNew) {
|
|
7958
|
-
changed = new Set(extractSymbols(
|
|
7940
|
+
changed = new Set(extractSymbols(path7, after).map((s) => s.name).filter(Boolean));
|
|
7959
7941
|
} else {
|
|
7960
|
-
changed = changedSymbolNames(
|
|
7942
|
+
changed = changedSymbolNames(path7, before, after);
|
|
7961
7943
|
if (changed.size === 0) return null;
|
|
7962
7944
|
}
|
|
7963
7945
|
const affected = /* @__PURE__ */ new Map();
|
|
@@ -7972,7 +7954,7 @@ function buildDependencyAdvisory(path5, before, after, graph, options = {}) {
|
|
|
7972
7954
|
return names.has(name2.toLowerCase());
|
|
7973
7955
|
};
|
|
7974
7956
|
const add = (sourcePath, name2) => {
|
|
7975
|
-
if (!sourcePath || sourcePath ===
|
|
7957
|
+
if (!sourcePath || sourcePath === path7) return;
|
|
7976
7958
|
if (definesLocally(sourcePath, name2)) return;
|
|
7977
7959
|
let names = affected.get(sourcePath);
|
|
7978
7960
|
if (!names) affected.set(sourcePath, names = /* @__PURE__ */ new Set());
|
|
@@ -7986,7 +7968,7 @@ function buildDependencyAdvisory(path5, before, after, graph, options = {}) {
|
|
|
7986
7968
|
add(edge.source_path, name2);
|
|
7987
7969
|
}
|
|
7988
7970
|
}
|
|
7989
|
-
const stem = moduleStem(
|
|
7971
|
+
const stem = moduleStem(path7);
|
|
7990
7972
|
if (stem) {
|
|
7991
7973
|
for (const edge of graph.findImporters(stem, { strictReachable: true })) {
|
|
7992
7974
|
add(edge.source_path, stem);
|
|
@@ -7999,15 +7981,702 @@ function buildDependencyAdvisory(path5, before, after, graph, options = {}) {
|
|
|
7999
7981
|
const symbolNames = [...changed].sort();
|
|
8000
7982
|
let symStr = symbolNames.slice(0, maxSymbols).join(", ");
|
|
8001
7983
|
if (symbolNames.length > maxSymbols) symStr += ", \u2026";
|
|
8002
|
-
const lead = isNew ? `${files.length} existing file(s) already import or reference ${
|
|
7984
|
+
const lead = isNew ? `${files.length} existing file(s) already import or reference ${path7}` : `${files.length} other file(s) import or use what you changed in ${path7} (${symStr})`;
|
|
8003
7985
|
let note = `${lead}. Affected (best-effort, by name \u2014 verify before relying): ${shown.join(", ")}`;
|
|
8004
7986
|
if (extra > 0) {
|
|
8005
|
-
note += `. +${extra} more \u2014 use trace_codebase on ${
|
|
7987
|
+
note += `. +${extra} more \u2014 use trace_codebase on ${path7} for the full set`;
|
|
8006
7988
|
}
|
|
8007
7989
|
note += ".";
|
|
8008
7990
|
return { files, note };
|
|
8009
7991
|
}
|
|
8010
7992
|
|
|
7993
|
+
// ../packages/orion-client-core/src/vectorStore.ts
|
|
7994
|
+
var path5 = __toESM(require("path"));
|
|
7995
|
+
var import_crypto2 = require("crypto");
|
|
7996
|
+
var import_fs3 = require("fs");
|
|
7997
|
+
var VECTOR_STORE_VERSION = 1;
|
|
7998
|
+
var VECTOR_CHECKPOINT_ROWS = 1024;
|
|
7999
|
+
var VECTOR_SCAN_BLOCK_ROWS = 1024;
|
|
8000
|
+
var VECTOR_LOCK_STALE_MS = 15 * 6e4;
|
|
8001
|
+
var VECTOR_LAYER_BUSY_PREFIX = "vector layer busy:";
|
|
8002
|
+
var BYTES_PER_FLOAT = 4;
|
|
8003
|
+
var VectorLayerBusyError = class extends Error {
|
|
8004
|
+
constructor(lockPath, holderPid) {
|
|
8005
|
+
super(`${VECTOR_LAYER_BUSY_PREFIX} another Orion process (pid ${holderPid}) is embedding this workspace`);
|
|
8006
|
+
this.lockPath = lockPath;
|
|
8007
|
+
this.holderPid = holderPid;
|
|
8008
|
+
this.name = "VectorLayerBusyError";
|
|
8009
|
+
}
|
|
8010
|
+
};
|
|
8011
|
+
function processAlive(pid) {
|
|
8012
|
+
try {
|
|
8013
|
+
process.kill(pid, 0);
|
|
8014
|
+
return true;
|
|
8015
|
+
} catch (error) {
|
|
8016
|
+
return error.code === "EPERM";
|
|
8017
|
+
}
|
|
8018
|
+
}
|
|
8019
|
+
var realFs2 = {
|
|
8020
|
+
readText: (p) => import_fs3.promises.readFile(p, "utf8"),
|
|
8021
|
+
writeTextAtomic: (p, content) => atomicWriteFile(p, content),
|
|
8022
|
+
writeBytesAtomic: (p, bytes) => atomicWriteFile(p, Buffer.from(bytes)),
|
|
8023
|
+
appendBytes: (p, bytes) => import_fs3.promises.appendFile(p, bytes),
|
|
8024
|
+
readBytesAt: async (p, offset, length) => {
|
|
8025
|
+
const handle4 = await import_fs3.promises.open(p, "r");
|
|
8026
|
+
try {
|
|
8027
|
+
const buffer = new Uint8Array(length);
|
|
8028
|
+
let read = 0;
|
|
8029
|
+
while (read < length) {
|
|
8030
|
+
const { bytesRead } = await handle4.read(buffer, read, length - read, offset + read);
|
|
8031
|
+
if (bytesRead === 0) break;
|
|
8032
|
+
read += bytesRead;
|
|
8033
|
+
}
|
|
8034
|
+
return read === length ? buffer : buffer.subarray(0, read);
|
|
8035
|
+
} finally {
|
|
8036
|
+
await handle4.close();
|
|
8037
|
+
}
|
|
8038
|
+
},
|
|
8039
|
+
fileSize: async (p) => {
|
|
8040
|
+
try {
|
|
8041
|
+
return (await import_fs3.promises.stat(p)).size;
|
|
8042
|
+
} catch {
|
|
8043
|
+
return null;
|
|
8044
|
+
}
|
|
8045
|
+
},
|
|
8046
|
+
truncate: (p, size) => import_fs3.promises.truncate(p, size),
|
|
8047
|
+
rename: (from, to) => import_fs3.promises.rename(from, to),
|
|
8048
|
+
mkdir: async (p) => {
|
|
8049
|
+
await import_fs3.promises.mkdir(p, { recursive: true });
|
|
8050
|
+
},
|
|
8051
|
+
rm: (p) => import_fs3.promises.rm(p, { force: true }),
|
|
8052
|
+
createExclusive: async (p, content) => {
|
|
8053
|
+
try {
|
|
8054
|
+
await import_fs3.promises.writeFile(p, content, { flag: "wx" });
|
|
8055
|
+
return true;
|
|
8056
|
+
} catch (error) {
|
|
8057
|
+
if (error.code === "EEXIST") return false;
|
|
8058
|
+
throw error;
|
|
8059
|
+
}
|
|
8060
|
+
}
|
|
8061
|
+
};
|
|
8062
|
+
function vectorContentHash(text) {
|
|
8063
|
+
return (0, import_crypto2.createHash)("sha256").update(text, "utf8").digest("hex").slice(0, 32);
|
|
8064
|
+
}
|
|
8065
|
+
function vectorModelSlug(model) {
|
|
8066
|
+
const slug = model.toLowerCase().replace(/[^a-z0-9.]+/g, "-").replace(/^-+|-+$/g, "");
|
|
8067
|
+
return slug || "model";
|
|
8068
|
+
}
|
|
8069
|
+
function encodeManifest(root, model, manifest) {
|
|
8070
|
+
const rows = manifest.rows.map((r) => [r.hash, r.path, r.startLine, r.endLine, r.sig]);
|
|
8071
|
+
return JSON.stringify({ v: VECTOR_STORE_VERSION, root, model, dims: manifest.dims, rows });
|
|
8072
|
+
}
|
|
8073
|
+
function decodeManifest(raw, expected) {
|
|
8074
|
+
let parsed;
|
|
8075
|
+
try {
|
|
8076
|
+
parsed = JSON.parse(raw);
|
|
8077
|
+
} catch {
|
|
8078
|
+
return null;
|
|
8079
|
+
}
|
|
8080
|
+
if (!parsed || typeof parsed !== "object") return null;
|
|
8081
|
+
const m = parsed;
|
|
8082
|
+
if (m.v !== VECTOR_STORE_VERSION || m.root !== expected.root || m.model !== expected.model) return null;
|
|
8083
|
+
const dims = m.dims;
|
|
8084
|
+
if (typeof dims !== "number" || !Number.isInteger(dims) || dims <= 0) return null;
|
|
8085
|
+
if (!Array.isArray(m.rows)) return null;
|
|
8086
|
+
const rows = [];
|
|
8087
|
+
for (const entry of m.rows) {
|
|
8088
|
+
if (!Array.isArray(entry) || entry.length !== 5) return null;
|
|
8089
|
+
const [hash, p, startLine, endLine, sig] = entry;
|
|
8090
|
+
if (typeof hash !== "string" || typeof p !== "string" || typeof sig !== "string") return null;
|
|
8091
|
+
if (typeof startLine !== "number" || typeof endLine !== "number") return null;
|
|
8092
|
+
rows.push({ hash, path: p, startLine, endLine, sig });
|
|
8093
|
+
}
|
|
8094
|
+
return { dims, rows };
|
|
8095
|
+
}
|
|
8096
|
+
var VectorStore = class {
|
|
8097
|
+
root;
|
|
8098
|
+
model;
|
|
8099
|
+
fsOps;
|
|
8100
|
+
log;
|
|
8101
|
+
now;
|
|
8102
|
+
pidAlive;
|
|
8103
|
+
dir;
|
|
8104
|
+
slug;
|
|
8105
|
+
dimsValue = 0;
|
|
8106
|
+
rowsValue = [];
|
|
8107
|
+
/** Rows the manifest on disk describes; rows past this are appended but uncommitted. */
|
|
8108
|
+
committedRows = 0;
|
|
8109
|
+
loaded = false;
|
|
8110
|
+
lockHeld = false;
|
|
8111
|
+
constructor(options) {
|
|
8112
|
+
this.root = options.root;
|
|
8113
|
+
this.model = options.model;
|
|
8114
|
+
this.fsOps = options.fsOps ?? realFs2;
|
|
8115
|
+
this.log = options.log ?? (() => void 0);
|
|
8116
|
+
this.now = options.now ?? Date.now;
|
|
8117
|
+
this.pidAlive = options.pidAlive ?? processAlive;
|
|
8118
|
+
this.dir = path5.join(options.baseDir ?? defaultIndexCacheBaseDir(), indexCacheFingerprint(options.root));
|
|
8119
|
+
this.slug = vectorModelSlug(options.model);
|
|
8120
|
+
}
|
|
8121
|
+
binPath() {
|
|
8122
|
+
return path5.join(this.dir, `vectors.${this.slug}.bin`);
|
|
8123
|
+
}
|
|
8124
|
+
manifestPath() {
|
|
8125
|
+
return path5.join(this.dir, `vectors.${this.slug}.json`);
|
|
8126
|
+
}
|
|
8127
|
+
lockPath() {
|
|
8128
|
+
return path5.join(this.dir, `vectors.${this.slug}.lock`);
|
|
8129
|
+
}
|
|
8130
|
+
/** Take the layer's writer lock: create the lock file exclusively; break a
|
|
8131
|
+
* stale one (dead holder, or older than VECTOR_LOCK_STALE_MS) once and retry;
|
|
8132
|
+
* throw VectorLayerBusyError for a live holder. */
|
|
8133
|
+
async acquireLock() {
|
|
8134
|
+
await this.fsOps.mkdir(this.dir);
|
|
8135
|
+
const record = { pid: process.pid, startedAt: this.now() };
|
|
8136
|
+
for (let attempt = 0; attempt < 2; attempt++) {
|
|
8137
|
+
if (await this.fsOps.createExclusive(this.lockPath(), JSON.stringify(record))) {
|
|
8138
|
+
this.lockHeld = true;
|
|
8139
|
+
return;
|
|
8140
|
+
}
|
|
8141
|
+
const holder = await this.readLock();
|
|
8142
|
+
const stale = holder === null || holder.pid === process.pid || !this.pidAlive(holder.pid) || this.now() - holder.startedAt > VECTOR_LOCK_STALE_MS;
|
|
8143
|
+
if (!stale) throw new VectorLayerBusyError(this.lockPath(), holder.pid);
|
|
8144
|
+
this.log(`orion: vector layer for ${this.model} \u2014 breaking a stale lock (pid ${holder?.pid ?? "?"})`);
|
|
8145
|
+
await this.fsOps.rm(this.lockPath());
|
|
8146
|
+
}
|
|
8147
|
+
throw new VectorLayerBusyError(this.lockPath(), 0);
|
|
8148
|
+
}
|
|
8149
|
+
async readLock() {
|
|
8150
|
+
try {
|
|
8151
|
+
const parsed = JSON.parse(await this.fsOps.readText(this.lockPath()));
|
|
8152
|
+
if (typeof parsed.pid !== "number" || typeof parsed.startedAt !== "number") return null;
|
|
8153
|
+
return { pid: parsed.pid, startedAt: parsed.startedAt };
|
|
8154
|
+
} catch {
|
|
8155
|
+
return null;
|
|
8156
|
+
}
|
|
8157
|
+
}
|
|
8158
|
+
/** Release the writer lock. Safe to call more than once, and without `load()`. */
|
|
8159
|
+
async close() {
|
|
8160
|
+
if (!this.lockHeld) return;
|
|
8161
|
+
this.lockHeld = false;
|
|
8162
|
+
await this.fsOps.rm(this.lockPath());
|
|
8163
|
+
}
|
|
8164
|
+
dims() {
|
|
8165
|
+
return this.dimsValue;
|
|
8166
|
+
}
|
|
8167
|
+
size() {
|
|
8168
|
+
return this.rowsValue.length;
|
|
8169
|
+
}
|
|
8170
|
+
rows() {
|
|
8171
|
+
return this.rowsValue;
|
|
8172
|
+
}
|
|
8173
|
+
/** Take the lock, then read the manifest and reconcile it with the .bin: an
|
|
8174
|
+
* absent layer starts empty; a rejected manifest or a .bin shorter than its
|
|
8175
|
+
* manifest discards the layer (a wrong vector is structurally impossible —
|
|
8176
|
+
* the worst case is re-embedding once); a .bin longer than its manifest is a
|
|
8177
|
+
* crashed append and its tail is truncated. */
|
|
8178
|
+
async load() {
|
|
8179
|
+
await this.acquireLock();
|
|
8180
|
+
try {
|
|
8181
|
+
await this.reconcile();
|
|
8182
|
+
} catch (error) {
|
|
8183
|
+
await this.close();
|
|
8184
|
+
throw error;
|
|
8185
|
+
}
|
|
8186
|
+
}
|
|
8187
|
+
/** The manifest ↔ .bin reconcile `load()` runs under the lock. */
|
|
8188
|
+
async reconcile() {
|
|
8189
|
+
this.loaded = true;
|
|
8190
|
+
this.rowsValue = [];
|
|
8191
|
+
this.dimsValue = 0;
|
|
8192
|
+
this.committedRows = 0;
|
|
8193
|
+
let raw;
|
|
8194
|
+
try {
|
|
8195
|
+
raw = await this.fsOps.readText(this.manifestPath());
|
|
8196
|
+
} catch {
|
|
8197
|
+
return;
|
|
8198
|
+
}
|
|
8199
|
+
const manifest = decodeManifest(raw, { root: this.root, model: this.model });
|
|
8200
|
+
if (!manifest) {
|
|
8201
|
+
this.log(`orion: vector layer for ${this.model} rejected (version/identity/shape) \u2014 re-embedding`);
|
|
8202
|
+
await this.discard();
|
|
8203
|
+
return;
|
|
8204
|
+
}
|
|
8205
|
+
const binSize = await this.fsOps.fileSize(this.binPath());
|
|
8206
|
+
const committedBytes = manifest.rows.length * manifest.dims * BYTES_PER_FLOAT;
|
|
8207
|
+
if (binSize === null || binSize < committedBytes) {
|
|
8208
|
+
this.log(`orion: vector file for ${this.model} is shorter than its manifest \u2014 re-embedding`);
|
|
8209
|
+
await this.discard();
|
|
8210
|
+
return;
|
|
8211
|
+
}
|
|
8212
|
+
if (binSize > committedBytes) {
|
|
8213
|
+
await this.fsOps.truncate(this.binPath(), committedBytes);
|
|
8214
|
+
this.log(`orion: vector layer for ${this.model} dropped an uncommitted tail (${binSize - committedBytes} bytes)`);
|
|
8215
|
+
}
|
|
8216
|
+
this.dimsValue = manifest.dims;
|
|
8217
|
+
this.rowsValue = manifest.rows;
|
|
8218
|
+
this.committedRows = manifest.rows.length;
|
|
8219
|
+
}
|
|
8220
|
+
async discard() {
|
|
8221
|
+
await this.fsOps.rm(this.binPath());
|
|
8222
|
+
await this.fsOps.rm(this.manifestPath());
|
|
8223
|
+
this.rowsValue = [];
|
|
8224
|
+
this.dimsValue = 0;
|
|
8225
|
+
this.committedRows = 0;
|
|
8226
|
+
}
|
|
8227
|
+
/** Append rows with their vectors (same length, every vector `dims` wide —
|
|
8228
|
+
* the first append of an empty layer fixes `dims`). Rows land in the .bin at
|
|
8229
|
+
* once; the manifest checkpoints every VECTOR_CHECKPOINT_ROWS rows and on
|
|
8230
|
+
* `flush()`, so a run's progress survives a crash in bounded pieces. */
|
|
8231
|
+
async append(rows, vectors) {
|
|
8232
|
+
this.assertLoaded();
|
|
8233
|
+
if (rows.length !== vectors.length) throw new Error("vector store: rows and vectors differ in length");
|
|
8234
|
+
if (rows.length === 0) return;
|
|
8235
|
+
const dims = vectors[0].length;
|
|
8236
|
+
if (dims === 0) throw new Error("vector store: an empty vector");
|
|
8237
|
+
if (this.dimsValue === 0) {
|
|
8238
|
+
this.dimsValue = dims;
|
|
8239
|
+
await this.fsOps.mkdir(this.dir);
|
|
8240
|
+
await this.fsOps.writeBytesAtomic(this.binPath(), new Uint8Array(0));
|
|
8241
|
+
} else if (dims !== this.dimsValue) {
|
|
8242
|
+
throw new Error(`vector store: width ${dims} does not match the layer's ${this.dimsValue}`);
|
|
8243
|
+
}
|
|
8244
|
+
const block = new Float32Array(rows.length * dims);
|
|
8245
|
+
for (let i2 = 0; i2 < vectors.length; i2++) {
|
|
8246
|
+
if (vectors[i2].length !== dims) throw new Error("vector store: vectors of differing width");
|
|
8247
|
+
block.set(vectors[i2], i2 * dims);
|
|
8248
|
+
}
|
|
8249
|
+
await this.fsOps.appendBytes(this.binPath(), new Uint8Array(block.buffer, block.byteOffset, block.byteLength));
|
|
8250
|
+
for (const row of rows) this.rowsValue.push(row);
|
|
8251
|
+
if (this.rowsValue.length - this.committedRows >= VECTOR_CHECKPOINT_ROWS) await this.flush();
|
|
8252
|
+
}
|
|
8253
|
+
/** Commit every appended row to the manifest (a no-op when nothing is pending). */
|
|
8254
|
+
async flush() {
|
|
8255
|
+
this.assertLoaded();
|
|
8256
|
+
if (this.rowsValue.length === this.committedRows) return;
|
|
8257
|
+
await this.fsOps.mkdir(this.dir);
|
|
8258
|
+
await this.fsOps.writeTextAtomic(
|
|
8259
|
+
this.manifestPath(),
|
|
8260
|
+
encodeManifest(this.root, this.model, { dims: this.dimsValue, rows: this.rowsValue })
|
|
8261
|
+
);
|
|
8262
|
+
this.committedRows = this.rowsValue.length;
|
|
8263
|
+
}
|
|
8264
|
+
/** Stream every row's vector, in row order, through a reusable block buffer:
|
|
8265
|
+
* `visit` must not retain `vector` past the call. `include` skips rows
|
|
8266
|
+
* without reading them into the visit (dead rows still cost the block read). */
|
|
8267
|
+
async scan(visit, include) {
|
|
8268
|
+
this.assertLoaded();
|
|
8269
|
+
const total = this.rowsValue.length;
|
|
8270
|
+
if (total === 0) return;
|
|
8271
|
+
const dims = this.dimsValue;
|
|
8272
|
+
const rowBytes = dims * BYTES_PER_FLOAT;
|
|
8273
|
+
for (let start2 = 0; start2 < total; start2 += VECTOR_SCAN_BLOCK_ROWS) {
|
|
8274
|
+
const count = Math.min(VECTOR_SCAN_BLOCK_ROWS, total - start2);
|
|
8275
|
+
const bytes = await this.fsOps.readBytesAt(this.binPath(), start2 * rowBytes, count * rowBytes);
|
|
8276
|
+
if (bytes.length < count * rowBytes) {
|
|
8277
|
+
throw new Error("vector store: the vector file is shorter than its manifest");
|
|
8278
|
+
}
|
|
8279
|
+
const floats = new Float32Array(bytes.buffer.slice(bytes.byteOffset, bytes.byteOffset + count * rowBytes));
|
|
8280
|
+
for (let i2 = 0; i2 < count; i2++) {
|
|
8281
|
+
const rowIndex = start2 + i2;
|
|
8282
|
+
if (include && !include(rowIndex)) continue;
|
|
8283
|
+
visit(rowIndex, floats.subarray(i2 * dims, (i2 + 1) * dims));
|
|
8284
|
+
}
|
|
8285
|
+
}
|
|
8286
|
+
}
|
|
8287
|
+
/** Rewrite the layer with only the rows `keep` selects — the dead-row sweep
|
|
8288
|
+
* after a reconcile. Streams the old .bin block by block into a sibling file
|
|
8289
|
+
* and renames it over, then commits the surviving rows' manifest. */
|
|
8290
|
+
async compact(keep) {
|
|
8291
|
+
this.assertLoaded();
|
|
8292
|
+
const total = this.rowsValue.length;
|
|
8293
|
+
const survivors = [];
|
|
8294
|
+
if (total === 0) return { kept: 0, dropped: 0 };
|
|
8295
|
+
const dims = this.dimsValue;
|
|
8296
|
+
const rowBytes = dims * BYTES_PER_FLOAT;
|
|
8297
|
+
const tmp = `${this.binPath()}.compact`;
|
|
8298
|
+
await this.fsOps.writeBytesAtomic(tmp, new Uint8Array(0));
|
|
8299
|
+
for (let start2 = 0; start2 < total; start2 += VECTOR_SCAN_BLOCK_ROWS) {
|
|
8300
|
+
const count = Math.min(VECTOR_SCAN_BLOCK_ROWS, total - start2);
|
|
8301
|
+
const bytes = await this.fsOps.readBytesAt(this.binPath(), start2 * rowBytes, count * rowBytes);
|
|
8302
|
+
const keptBytes = [];
|
|
8303
|
+
for (let i2 = 0; i2 < count; i2++) {
|
|
8304
|
+
const rowIndex = start2 + i2;
|
|
8305
|
+
const row = this.rowsValue[rowIndex];
|
|
8306
|
+
if (!keep(row, rowIndex)) continue;
|
|
8307
|
+
survivors.push(row);
|
|
8308
|
+
keptBytes.push(bytes.subarray(i2 * rowBytes, (i2 + 1) * rowBytes));
|
|
8309
|
+
}
|
|
8310
|
+
if (keptBytes.length > 0) {
|
|
8311
|
+
const merged = new Uint8Array(keptBytes.length * rowBytes);
|
|
8312
|
+
keptBytes.forEach((chunk, i2) => merged.set(chunk, i2 * rowBytes));
|
|
8313
|
+
await this.fsOps.appendBytes(tmp, merged);
|
|
8314
|
+
}
|
|
8315
|
+
}
|
|
8316
|
+
await this.fsOps.rename(tmp, this.binPath());
|
|
8317
|
+
const dropped = total - survivors.length;
|
|
8318
|
+
this.rowsValue = survivors;
|
|
8319
|
+
this.committedRows = -1;
|
|
8320
|
+
await this.fsOps.writeTextAtomic(
|
|
8321
|
+
this.manifestPath(),
|
|
8322
|
+
encodeManifest(this.root, this.model, { dims, rows: survivors })
|
|
8323
|
+
);
|
|
8324
|
+
this.committedRows = survivors.length;
|
|
8325
|
+
return { kept: survivors.length, dropped };
|
|
8326
|
+
}
|
|
8327
|
+
assertLoaded() {
|
|
8328
|
+
if (!this.loaded) throw new Error("vector store: load() first");
|
|
8329
|
+
}
|
|
8330
|
+
};
|
|
8331
|
+
|
|
8332
|
+
// ../packages/orion-client-core/src/enhancedRetrieval.ts
|
|
8333
|
+
var ENHANCED_TEST_DIRS = /* @__PURE__ */ new Set(["test", "tests", "testing"]);
|
|
8334
|
+
var ENHANCED_CHUNK_SOURCE_CHARS = 1e4;
|
|
8335
|
+
var ENHANCED_EMBED_BATCH_SIZE = 16;
|
|
8336
|
+
var ENHANCED_EMBED_MAX_RETRIES = 2;
|
|
8337
|
+
var ENHANCED_PAYLOAD_BUDGET_BYTES = 8 * 1024 * 1024;
|
|
8338
|
+
var COMPACT_MIN_DEAD_ROWS = 1e3;
|
|
8339
|
+
var COMPACT_DEAD_RATIO = 0.25;
|
|
8340
|
+
var CODE_CHUNK_KINDS = /* @__PURE__ */ new Set(["function", "method", "class", "module", "window"]);
|
|
8341
|
+
var CLASS_LIKE_SYMBOL_KINDS = /* @__PURE__ */ new Set(["class", "interface", "struct", "trait", "enum"]);
|
|
8342
|
+
function retrievalChunkType(kind) {
|
|
8343
|
+
if (kind === "function" || kind === "method") return "function";
|
|
8344
|
+
if (kind === "class") return "class";
|
|
8345
|
+
return "file";
|
|
8346
|
+
}
|
|
8347
|
+
function isTestDirectoryPath(relPath) {
|
|
8348
|
+
const parts2 = relPath.replace(/\\/g, "/").split("/");
|
|
8349
|
+
return parts2.slice(0, -1).some((part) => ENHANCED_TEST_DIRS.has(part.toLowerCase()));
|
|
8350
|
+
}
|
|
8351
|
+
function chunkSource(lines, startLine, endLine) {
|
|
8352
|
+
return lines.slice(Math.max(0, startLine - 1), Math.max(0, endLine)).join("\n");
|
|
8353
|
+
}
|
|
8354
|
+
function embeddingText(relPath, type, source) {
|
|
8355
|
+
return `File Path: ${relPath}
|
|
8356
|
+
File Type: ${type}
|
|
8357
|
+
|
|
8358
|
+
${source.slice(0, ENHANCED_CHUNK_SOURCE_CHARS)}`;
|
|
8359
|
+
}
|
|
8360
|
+
function fileSignature(stat) {
|
|
8361
|
+
return `${stat.size}:${stat.mtimeMs}`;
|
|
8362
|
+
}
|
|
8363
|
+
function chunkIdentity(chunk, symbols) {
|
|
8364
|
+
let name2 = chunk.title;
|
|
8365
|
+
let parent = null;
|
|
8366
|
+
if (chunk.kind === "function" || chunk.kind === "method" || chunk.kind === "class") {
|
|
8367
|
+
const own = symbols.find((s) => s.line === chunk.startLine);
|
|
8368
|
+
if (own) name2 = own.name;
|
|
8369
|
+
if (chunk.kind === "method") {
|
|
8370
|
+
for (const s of symbols) {
|
|
8371
|
+
if (s.line >= chunk.startLine) break;
|
|
8372
|
+
if (CLASS_LIKE_SYMBOL_KINDS.has(s.kind)) parent = s.name;
|
|
8373
|
+
}
|
|
8374
|
+
}
|
|
8375
|
+
}
|
|
8376
|
+
return { name: name2, parent };
|
|
8377
|
+
}
|
|
8378
|
+
function normalizeInPlace(vector) {
|
|
8379
|
+
let sum = 0;
|
|
8380
|
+
for (let i2 = 0; i2 < vector.length; i2++) sum += vector[i2] * vector[i2];
|
|
8381
|
+
const norm = Math.sqrt(sum);
|
|
8382
|
+
if (norm > 0) for (let i2 = 0; i2 < vector.length; i2++) vector[i2] /= norm;
|
|
8383
|
+
return vector;
|
|
8384
|
+
}
|
|
8385
|
+
function cosineAgainstNormalized(query, row) {
|
|
8386
|
+
let dot = 0;
|
|
8387
|
+
let sum = 0;
|
|
8388
|
+
for (let i2 = 0; i2 < query.length; i2++) {
|
|
8389
|
+
dot += query[i2] * row[i2];
|
|
8390
|
+
sum += row[i2] * row[i2];
|
|
8391
|
+
}
|
|
8392
|
+
const norm = Math.sqrt(sum);
|
|
8393
|
+
return norm > 0 ? dot / norm : 0;
|
|
8394
|
+
}
|
|
8395
|
+
var TopK = class {
|
|
8396
|
+
constructor(k) {
|
|
8397
|
+
this.k = k;
|
|
8398
|
+
}
|
|
8399
|
+
rows = [];
|
|
8400
|
+
scores = [];
|
|
8401
|
+
offer(rowIndex, score) {
|
|
8402
|
+
if (this.k <= 0) return;
|
|
8403
|
+
const full = this.rows.length >= this.k;
|
|
8404
|
+
if (full && score <= this.scores[this.scores.length - 1]) return;
|
|
8405
|
+
let lo = 0;
|
|
8406
|
+
let hi = this.scores.length;
|
|
8407
|
+
while (lo < hi) {
|
|
8408
|
+
const mid = lo + hi >> 1;
|
|
8409
|
+
if (this.scores[mid] >= score) lo = mid + 1;
|
|
8410
|
+
else hi = mid;
|
|
8411
|
+
}
|
|
8412
|
+
this.rows.splice(lo, 0, rowIndex);
|
|
8413
|
+
this.scores.splice(lo, 0, score);
|
|
8414
|
+
if (full) {
|
|
8415
|
+
this.rows.pop();
|
|
8416
|
+
this.scores.pop();
|
|
8417
|
+
}
|
|
8418
|
+
}
|
|
8419
|
+
entries() {
|
|
8420
|
+
return this.rows.map((rowIndex, i2) => ({ rowIndex, score: this.scores[i2] }));
|
|
8421
|
+
}
|
|
8422
|
+
};
|
|
8423
|
+
var inFlight = /* @__PURE__ */ new Map();
|
|
8424
|
+
async function serialized(key, run2) {
|
|
8425
|
+
const prior = inFlight.get(key) ?? Promise.resolve();
|
|
8426
|
+
const next = prior.catch(() => void 0).then(run2);
|
|
8427
|
+
inFlight.set(key, next);
|
|
8428
|
+
try {
|
|
8429
|
+
return await next;
|
|
8430
|
+
} finally {
|
|
8431
|
+
if (inFlight.get(key) === next) inFlight.delete(key);
|
|
8432
|
+
}
|
|
8433
|
+
}
|
|
8434
|
+
var defaultSleep = (ms) => new Promise((resolve5) => setTimeout(resolve5, ms));
|
|
8435
|
+
async function enhancedRetrieve(request, deps) {
|
|
8436
|
+
return await serialized(`${deps.baseDir ?? ""}\0${deps.root}`, () => runEnhancedRetrieve(request, deps));
|
|
8437
|
+
}
|
|
8438
|
+
async function runEnhancedRetrieve(request, deps) {
|
|
8439
|
+
const now = deps.now ?? Date.now;
|
|
8440
|
+
const started = now();
|
|
8441
|
+
const log = deps.log ?? (() => void 0);
|
|
8442
|
+
const sleep = deps.sleep ?? defaultSleep;
|
|
8443
|
+
const batchSize = Math.max(1, deps.batchSize ?? ENHANCED_EMBED_BATCH_SIZE);
|
|
8444
|
+
const maxRetries = Math.max(1, deps.maxRetries ?? ENHANCED_EMBED_MAX_RETRIES);
|
|
8445
|
+
const payloadBudget = deps.payloadBudgetBytes ?? ENHANCED_PAYLOAD_BUDGET_BYTES;
|
|
8446
|
+
const scope = normalizeScope(request.scope);
|
|
8447
|
+
const inventory = [];
|
|
8448
|
+
for (const chunk of deps.chunks()) {
|
|
8449
|
+
if (!CODE_CHUNK_KINDS.has(chunk.kind)) continue;
|
|
8450
|
+
if (isTestDirectoryPath(chunk.path)) continue;
|
|
8451
|
+
if (scope && !inScope(chunk.path, scope)) continue;
|
|
8452
|
+
inventory.push({ chunk, type: retrievalChunkType(chunk.kind), rowIndex: -1 });
|
|
8453
|
+
}
|
|
8454
|
+
const byPath = /* @__PURE__ */ new Map();
|
|
8455
|
+
for (const entry of inventory) {
|
|
8456
|
+
const list = byPath.get(entry.chunk.path);
|
|
8457
|
+
if (list) list.push(entry);
|
|
8458
|
+
else byPath.set(entry.chunk.path, [entry]);
|
|
8459
|
+
}
|
|
8460
|
+
const queryResponse = await deps.embeddings.embed({
|
|
8461
|
+
texts: [request.queryText],
|
|
8462
|
+
inputType: "query",
|
|
8463
|
+
sessionId: request.sessionId
|
|
8464
|
+
});
|
|
8465
|
+
const model = queryResponse.model;
|
|
8466
|
+
const provider = queryResponse.provider;
|
|
8467
|
+
const query = normalizeInPlace(Float32Array.from(queryResponse.vectors[0] ?? []));
|
|
8468
|
+
const stats = {
|
|
8469
|
+
files_considered: byPath.size,
|
|
8470
|
+
chunks_considered: inventory.length,
|
|
8471
|
+
chunks_embedded: 0,
|
|
8472
|
+
cache_hits: 0,
|
|
8473
|
+
failed_chunks: 0,
|
|
8474
|
+
files_sent: 0,
|
|
8475
|
+
files_truncated: 0,
|
|
8476
|
+
elapsed_ms: 0
|
|
8477
|
+
};
|
|
8478
|
+
const store2 = new VectorStore({ root: deps.root, model, baseDir: deps.baseDir, fsOps: deps.fsOps, log });
|
|
8479
|
+
await store2.load();
|
|
8480
|
+
try {
|
|
8481
|
+
const rowByHash = /* @__PURE__ */ new Map();
|
|
8482
|
+
const rowBySpan = /* @__PURE__ */ new Map();
|
|
8483
|
+
store2.rows().forEach((row, i2) => {
|
|
8484
|
+
rowByHash.set(row.hash, i2);
|
|
8485
|
+
rowBySpan.set(spanKey(row.path, row.sig, row.startLine, row.endLine), i2);
|
|
8486
|
+
});
|
|
8487
|
+
const signatures = /* @__PURE__ */ new Map();
|
|
8488
|
+
const embedBatch = async (batch) => {
|
|
8489
|
+
let vectors = null;
|
|
8490
|
+
for (let attempt = 0; attempt < maxRetries; attempt++) {
|
|
8491
|
+
try {
|
|
8492
|
+
const response = await deps.embeddings.embed({
|
|
8493
|
+
texts: batch.map((m) => m.text),
|
|
8494
|
+
inputType: "passage",
|
|
8495
|
+
model,
|
|
8496
|
+
sessionId: request.sessionId
|
|
8497
|
+
});
|
|
8498
|
+
if (response.vectors.length !== batch.length) {
|
|
8499
|
+
throw new Error(`embedding batch answered ${response.vectors.length} vectors for ${batch.length} texts`);
|
|
8500
|
+
}
|
|
8501
|
+
vectors = response.vectors;
|
|
8502
|
+
break;
|
|
8503
|
+
} catch (error) {
|
|
8504
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
8505
|
+
if (attempt < maxRetries - 1) {
|
|
8506
|
+
const waitMs = 2 ** attempt * 1e3;
|
|
8507
|
+
log(`orion: embedding batch failed (attempt ${attempt + 1}), retrying in ${waitMs / 1e3}s: ${message}`);
|
|
8508
|
+
await sleep(waitMs);
|
|
8509
|
+
} else {
|
|
8510
|
+
log(`orion: embedding batch failed after ${maxRetries} attempts: ${message}`);
|
|
8511
|
+
}
|
|
8512
|
+
}
|
|
8513
|
+
}
|
|
8514
|
+
deps.onProgress?.();
|
|
8515
|
+
if (!vectors) {
|
|
8516
|
+
stats.failed_chunks += batch.length;
|
|
8517
|
+
return;
|
|
8518
|
+
}
|
|
8519
|
+
const rows = [];
|
|
8520
|
+
const rowVectors = [];
|
|
8521
|
+
for (let i2 = 0; i2 < batch.length; i2++) {
|
|
8522
|
+
const miss = batch[i2];
|
|
8523
|
+
const known = rowByHash.get(miss.hash);
|
|
8524
|
+
if (known !== void 0) {
|
|
8525
|
+
miss.entry.rowIndex = known;
|
|
8526
|
+
continue;
|
|
8527
|
+
}
|
|
8528
|
+
const rowIndex = store2.size() + rows.length;
|
|
8529
|
+
rowByHash.set(miss.hash, rowIndex);
|
|
8530
|
+
miss.entry.rowIndex = rowIndex;
|
|
8531
|
+
rows.push({
|
|
8532
|
+
hash: miss.hash,
|
|
8533
|
+
path: miss.entry.chunk.path,
|
|
8534
|
+
startLine: miss.entry.chunk.startLine,
|
|
8535
|
+
endLine: miss.entry.chunk.endLine,
|
|
8536
|
+
sig: signatures.get(miss.entry.chunk.path) ?? ""
|
|
8537
|
+
});
|
|
8538
|
+
rowVectors.push(Float32Array.from(vectors[i2]));
|
|
8539
|
+
}
|
|
8540
|
+
if (rows.length > 0) await store2.append(rows, rowVectors);
|
|
8541
|
+
stats.chunks_embedded += batch.length;
|
|
8542
|
+
};
|
|
8543
|
+
let pending = [];
|
|
8544
|
+
const embedPending = async () => {
|
|
8545
|
+
if (pending.length === 0) return;
|
|
8546
|
+
const batch = pending;
|
|
8547
|
+
pending = [];
|
|
8548
|
+
await embedBatch(batch);
|
|
8549
|
+
};
|
|
8550
|
+
for (const [relPath, entries] of byPath) {
|
|
8551
|
+
const stat = await deps.stat(relPath);
|
|
8552
|
+
if (!stat) continue;
|
|
8553
|
+
const sig = fileSignature(stat);
|
|
8554
|
+
signatures.set(relPath, sig);
|
|
8555
|
+
const trusted = entries.every((entry) => {
|
|
8556
|
+
const row = rowBySpan.get(spanKey(relPath, sig, entry.chunk.startLine, entry.chunk.endLine));
|
|
8557
|
+
if (row === void 0) return false;
|
|
8558
|
+
entry.rowIndex = row;
|
|
8559
|
+
return true;
|
|
8560
|
+
});
|
|
8561
|
+
if (trusted) {
|
|
8562
|
+
stats.cache_hits += entries.length;
|
|
8563
|
+
continue;
|
|
8564
|
+
}
|
|
8565
|
+
const text = await deps.readFile(relPath);
|
|
8566
|
+
if (text === null) continue;
|
|
8567
|
+
const lines = text.split("\n");
|
|
8568
|
+
for (const entry of entries) {
|
|
8569
|
+
const rendered = embeddingText(relPath, entry.type, chunkSource(lines, entry.chunk.startLine, entry.chunk.endLine));
|
|
8570
|
+
const hash = vectorContentHash(rendered);
|
|
8571
|
+
const row = rowByHash.get(hash);
|
|
8572
|
+
if (row !== void 0) {
|
|
8573
|
+
entry.rowIndex = row;
|
|
8574
|
+
stats.cache_hits += 1;
|
|
8575
|
+
continue;
|
|
8576
|
+
}
|
|
8577
|
+
pending.push({ entry, text: rendered, hash });
|
|
8578
|
+
if (pending.length >= batchSize) await embedPending();
|
|
8579
|
+
}
|
|
8580
|
+
}
|
|
8581
|
+
await embedPending();
|
|
8582
|
+
await store2.flush();
|
|
8583
|
+
const liveRows = /* @__PURE__ */ new Map();
|
|
8584
|
+
for (const entry of inventory) {
|
|
8585
|
+
if (entry.rowIndex < 0) continue;
|
|
8586
|
+
const list = liveRows.get(entry.rowIndex);
|
|
8587
|
+
if (list) list.push(entry);
|
|
8588
|
+
else liveRows.set(entry.rowIndex, [entry]);
|
|
8589
|
+
}
|
|
8590
|
+
const top = new TopK(Math.max(0, Math.min(request.topK, liveRows.size)));
|
|
8591
|
+
if (query.length === store2.dims() && liveRows.size > 0) {
|
|
8592
|
+
await store2.scan(
|
|
8593
|
+
(rowIndex, vector) => top.offer(rowIndex, cosineAgainstNormalized(query, vector)),
|
|
8594
|
+
(rowIndex) => liveRows.has(rowIndex)
|
|
8595
|
+
);
|
|
8596
|
+
} else if (liveRows.size > 0) {
|
|
8597
|
+
log(`orion: query vector width ${query.length} does not match the layer's ${store2.dims()} \u2014 no ranking`);
|
|
8598
|
+
}
|
|
8599
|
+
const hits = [];
|
|
8600
|
+
for (const { rowIndex, score } of top.entries()) {
|
|
8601
|
+
for (const entry of liveRows.get(rowIndex) ?? []) {
|
|
8602
|
+
hits.push({ ...describeChunk(entry, deps.symbolsFor(entry.chunk.path)), score });
|
|
8603
|
+
}
|
|
8604
|
+
}
|
|
8605
|
+
hits.splice(request.topK);
|
|
8606
|
+
const candidateFiles = [];
|
|
8607
|
+
const seen = /* @__PURE__ */ new Set();
|
|
8608
|
+
for (const hit of hits) {
|
|
8609
|
+
if (seen.has(hit.path)) continue;
|
|
8610
|
+
seen.add(hit.path);
|
|
8611
|
+
candidateFiles.push(hit.path);
|
|
8612
|
+
}
|
|
8613
|
+
const files = [];
|
|
8614
|
+
const fileChunks = {};
|
|
8615
|
+
let sentBytes = 0;
|
|
8616
|
+
let sentChars = 0;
|
|
8617
|
+
for (const relPath of candidateFiles) {
|
|
8618
|
+
const symbols = deps.symbolsFor(relPath);
|
|
8619
|
+
fileChunks[relPath] = (byPath.get(relPath) ?? []).map((entry) => describeChunk(entry, symbols));
|
|
8620
|
+
const content = await deps.readFile(relPath);
|
|
8621
|
+
if (content === null) {
|
|
8622
|
+
stats.files_truncated += 1;
|
|
8623
|
+
continue;
|
|
8624
|
+
}
|
|
8625
|
+
const bytes = Buffer.byteLength(content, "utf8");
|
|
8626
|
+
const overBudget = files.length > 0 && sentBytes + bytes > payloadBudget;
|
|
8627
|
+
if (overBudget && sentChars >= request.rerankSourceChars) {
|
|
8628
|
+
stats.files_truncated += 1;
|
|
8629
|
+
continue;
|
|
8630
|
+
}
|
|
8631
|
+
files.push({ path: relPath, content });
|
|
8632
|
+
sentBytes += bytes;
|
|
8633
|
+
sentChars += content.length;
|
|
8634
|
+
}
|
|
8635
|
+
stats.files_sent = files.length;
|
|
8636
|
+
const dead = store2.size() - liveRows.size;
|
|
8637
|
+
if (dead >= COMPACT_MIN_DEAD_ROWS && dead >= store2.size() * COMPACT_DEAD_RATIO) {
|
|
8638
|
+
const swept = await store2.compact((_row, rowIndex) => liveRows.has(rowIndex));
|
|
8639
|
+
log(`orion: vector layer for ${model} compacted \u2014 kept ${swept.kept}, dropped ${swept.dropped}`);
|
|
8640
|
+
}
|
|
8641
|
+
stats.elapsed_ms = Math.max(0, now() - started);
|
|
8642
|
+
return {
|
|
8643
|
+
version: 1,
|
|
8644
|
+
provider,
|
|
8645
|
+
model,
|
|
8646
|
+
dims: store2.dims() || query.length,
|
|
8647
|
+
query_text: request.queryText,
|
|
8648
|
+
hits,
|
|
8649
|
+
candidate_files: candidateFiles,
|
|
8650
|
+
files,
|
|
8651
|
+
file_chunks: fileChunks,
|
|
8652
|
+
stats
|
|
8653
|
+
};
|
|
8654
|
+
} finally {
|
|
8655
|
+
await store2.close();
|
|
8656
|
+
}
|
|
8657
|
+
}
|
|
8658
|
+
function describeChunk(entry, symbols) {
|
|
8659
|
+
const { name: name2, parent } = chunkIdentity(entry.chunk, symbols);
|
|
8660
|
+
return {
|
|
8661
|
+
path: entry.chunk.path,
|
|
8662
|
+
type: entry.type,
|
|
8663
|
+
name: name2,
|
|
8664
|
+
parent,
|
|
8665
|
+
start_line: entry.chunk.startLine,
|
|
8666
|
+
end_line: entry.chunk.endLine
|
|
8667
|
+
};
|
|
8668
|
+
}
|
|
8669
|
+
function spanKey(relPath, sig, startLine, endLine) {
|
|
8670
|
+
return `${relPath}\0${sig}\0${startLine}-${endLine}`;
|
|
8671
|
+
}
|
|
8672
|
+
function normalizeScope(scope) {
|
|
8673
|
+
const trimmed = (scope ?? "").trim().replace(/\\/g, "/").replace(/^\.\/+/, "").replace(/\/+$/, "");
|
|
8674
|
+
return trimmed === "." ? "" : trimmed;
|
|
8675
|
+
}
|
|
8676
|
+
function inScope(relPath, scope) {
|
|
8677
|
+
return relPath === scope || relPath.startsWith(`${scope}/`);
|
|
8678
|
+
}
|
|
8679
|
+
|
|
8011
8680
|
// ../packages/orion-client-core/src/shims/fileSource.ts
|
|
8012
8681
|
function emptyIndexStatusDetail() {
|
|
8013
8682
|
return {
|
|
@@ -8047,6 +8716,31 @@ var WorkerWorkspaceIndexer = class extends WorkspaceIndexer {
|
|
|
8047
8716
|
return adaptiveIndexHeapBudgetBytes();
|
|
8048
8717
|
}
|
|
8049
8718
|
};
|
|
8719
|
+
var hostNextId = 1;
|
|
8720
|
+
var hostPending = /* @__PURE__ */ new Map();
|
|
8721
|
+
function callHost(method, params) {
|
|
8722
|
+
const id = hostNextId++;
|
|
8723
|
+
return new Promise((resolve5, reject) => {
|
|
8724
|
+
if (typeof process.send !== "function") {
|
|
8725
|
+
reject(new Error("embeddings are unavailable: no IPC channel to the host"));
|
|
8726
|
+
return;
|
|
8727
|
+
}
|
|
8728
|
+
hostPending.set(id, { resolve: resolve5, reject });
|
|
8729
|
+
const msg = { hostRequest: id, method, params };
|
|
8730
|
+
process.send(msg, (error) => {
|
|
8731
|
+
if (!error) return;
|
|
8732
|
+
hostPending.delete(id);
|
|
8733
|
+
reject(error);
|
|
8734
|
+
});
|
|
8735
|
+
});
|
|
8736
|
+
}
|
|
8737
|
+
function settleHostResponse(msg) {
|
|
8738
|
+
const pending = hostPending.get(msg.hostResponse);
|
|
8739
|
+
if (!pending) return;
|
|
8740
|
+
hostPending.delete(msg.hostResponse);
|
|
8741
|
+
if (msg.ok) pending.resolve(msg.result);
|
|
8742
|
+
else pending.reject(new Error(msg.error));
|
|
8743
|
+
}
|
|
8050
8744
|
var config = {
|
|
8051
8745
|
root: null,
|
|
8052
8746
|
grammarDir: null,
|
|
@@ -8170,8 +8864,52 @@ var READ_METHODS = /* @__PURE__ */ new Set([
|
|
|
8170
8864
|
"readContextHeader",
|
|
8171
8865
|
"searchCodebase",
|
|
8172
8866
|
"traceCodebase",
|
|
8867
|
+
"enhancedRetrieve",
|
|
8173
8868
|
"dependencyAdvisory"
|
|
8174
8869
|
]);
|
|
8870
|
+
async function runEnhancedRetrieve2(input) {
|
|
8871
|
+
const root = config.root;
|
|
8872
|
+
if (!root) return null;
|
|
8873
|
+
const absolute = (rel) => path6.join(root, rel);
|
|
8874
|
+
return await enhancedRetrieve(
|
|
8875
|
+
{
|
|
8876
|
+
queryText: String(input.query_text ?? ""),
|
|
8877
|
+
topK: Number(input.top_k ?? 0),
|
|
8878
|
+
rerankSourceChars: Number(input.rerank_source_chars ?? 0),
|
|
8879
|
+
scope: input.scope,
|
|
8880
|
+
sessionId: input.sessionId
|
|
8881
|
+
},
|
|
8882
|
+
{
|
|
8883
|
+
root,
|
|
8884
|
+
chunks: () => store.chunkIndex.collect(),
|
|
8885
|
+
symbolsFor: (rel) => store.listSymbols(rel),
|
|
8886
|
+
readFile: async (rel) => {
|
|
8887
|
+
try {
|
|
8888
|
+
return await import_fs4.promises.readFile(absolute(rel), "utf8");
|
|
8889
|
+
} catch {
|
|
8890
|
+
return null;
|
|
8891
|
+
}
|
|
8892
|
+
},
|
|
8893
|
+
stat: async (rel) => {
|
|
8894
|
+
try {
|
|
8895
|
+
const s = await import_fs4.promises.stat(absolute(rel));
|
|
8896
|
+
return { size: s.size, mtimeMs: s.mtimeMs };
|
|
8897
|
+
} catch {
|
|
8898
|
+
return null;
|
|
8899
|
+
}
|
|
8900
|
+
},
|
|
8901
|
+
embeddings: {
|
|
8902
|
+
embed: (request) => callHost("embed", request)
|
|
8903
|
+
},
|
|
8904
|
+
...config.cacheBaseDir ? { baseDir: config.cacheBaseDir } : {},
|
|
8905
|
+
log: (message) => console.log(message),
|
|
8906
|
+
onProgress: () => {
|
|
8907
|
+
lastActivityAt = Date.now();
|
|
8908
|
+
send({ event: "progress", kind: "heartbeat" });
|
|
8909
|
+
}
|
|
8910
|
+
}
|
|
8911
|
+
);
|
|
8912
|
+
}
|
|
8175
8913
|
var WAKE_READ_WARM_WAIT_MS = 15e3;
|
|
8176
8914
|
async function handle3(method, params) {
|
|
8177
8915
|
if (READ_METHODS.has(method)) {
|
|
@@ -8201,19 +8939,14 @@ async function handle3(method, params) {
|
|
|
8201
8939
|
return store.readContextHeader(
|
|
8202
8940
|
String(params.path ?? ""),
|
|
8203
8941
|
Number(params.line ?? 1),
|
|
8204
|
-
String(params.mode ?? "full")
|
|
8205
|
-
params.options ?? {}
|
|
8942
|
+
String(params.mode ?? "full")
|
|
8206
8943
|
);
|
|
8207
8944
|
case "searchCodebase":
|
|
8208
|
-
return store.searchCodebase(
|
|
8209
|
-
params.input ?? {},
|
|
8210
|
-
params.options ?? {}
|
|
8211
|
-
);
|
|
8945
|
+
return store.searchCodebase(params.input ?? {});
|
|
8212
8946
|
case "traceCodebase":
|
|
8213
|
-
return store.traceCodebase(
|
|
8214
|
-
|
|
8215
|
-
|
|
8216
|
-
);
|
|
8947
|
+
return store.traceCodebase(params.input ?? {});
|
|
8948
|
+
case "enhancedRetrieve":
|
|
8949
|
+
return await runEnhancedRetrieve2(params.input ?? {});
|
|
8217
8950
|
case "dependencyAdvisory":
|
|
8218
8951
|
return buildDependencyAdvisory(
|
|
8219
8952
|
String(params.path ?? ""),
|
|
@@ -8231,6 +8964,10 @@ async function handle3(method, params) {
|
|
|
8231
8964
|
}
|
|
8232
8965
|
}
|
|
8233
8966
|
process.on("message", (msg) => {
|
|
8967
|
+
if (msg && typeof msg === "object" && "hostResponse" in msg) {
|
|
8968
|
+
settleHostResponse(msg);
|
|
8969
|
+
return;
|
|
8970
|
+
}
|
|
8234
8971
|
if (!msg || typeof msg.id !== "number" || typeof msg.method !== "string") return;
|
|
8235
8972
|
activeRequests += 1;
|
|
8236
8973
|
lastActivityAt = Date.now();
|