@wrongstack/tools 0.307.0 → 0.307.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/builtin.js +564 -396
- package/dist/codebase-index/codebase-impact-analysis-tool.d.ts +2 -0
- package/dist/codebase-index/index.js +134 -49
- package/dist/codebase-index/project-server.js +87 -43
- package/dist/codebase-index/worker.js +87 -43
- package/dist/codebase-index/writer-graph-helpers.d.ts +1 -1
- package/dist/codebase-index/writer-helpers.d.ts +12 -0
- package/dist/edit.js +87 -43
- package/dist/index.d.ts +1 -1
- package/dist/index.js +583 -412
- package/dist/pack.js +563 -396
- package/dist/patch.js +87 -43
- package/dist/read.js +91 -47
- package/dist/replace.js +87 -43
- package/dist/tool-tier.js +564 -396
- package/dist/write.js +87 -43
- package/package.json +4 -4
package/dist/patch.js
CHANGED
|
@@ -4427,10 +4427,16 @@ function buildFileGraphNodeState(pkgSyms, localFiles, packageOf) {
|
|
|
4427
4427
|
}
|
|
4428
4428
|
return { fileNodes, symToFile, fileStats, ensureFileNode };
|
|
4429
4429
|
}
|
|
4430
|
-
function buildSymbolGraphNodes(symById, relatedIds,
|
|
4430
|
+
function buildSymbolGraphNodes(symById, relatedIds, localFiles, packageOf) {
|
|
4431
|
+
const local = new Set(
|
|
4432
|
+
[...typeof localFiles === "string" ? [localFiles] : localFiles].map(
|
|
4433
|
+
(file) => file.replace(/\\/g, "/")
|
|
4434
|
+
)
|
|
4435
|
+
);
|
|
4436
|
+
const isLocal = (file) => local.has(file.replace(/\\/g, "/"));
|
|
4431
4437
|
return [...relatedIds].map((id) => symById.get(id)).filter((symbol) => symbol !== void 0).sort((a, b) => {
|
|
4432
|
-
const aExternal = a.file
|
|
4433
|
-
const bExternal = b.file
|
|
4438
|
+
const aExternal = isLocal(a.file) ? 0 : 1;
|
|
4439
|
+
const bExternal = isLocal(b.file) ? 0 : 1;
|
|
4434
4440
|
return aExternal - bExternal || a.file.localeCompare(b.file) || a.line - b.line || a.id - b.id;
|
|
4435
4441
|
}).map((s) => ({
|
|
4436
4442
|
id: `sym:${s.id}`,
|
|
@@ -4444,7 +4450,7 @@ function buildSymbolGraphNodes(symById, relatedIds, fileFilter, packageOf) {
|
|
|
4444
4450
|
line: s.line,
|
|
4445
4451
|
signature: s.signature,
|
|
4446
4452
|
scope: s.scope,
|
|
4447
|
-
external: s.file
|
|
4453
|
+
external: !isLocal(s.file)
|
|
4448
4454
|
}));
|
|
4449
4455
|
}
|
|
4450
4456
|
function addWeightedEdge(edgeMap, source, target, callType, weight) {
|
|
@@ -4479,6 +4485,52 @@ function materializeWeightedEdges(edgeMap, idPrefix) {
|
|
|
4479
4485
|
return edges;
|
|
4480
4486
|
}
|
|
4481
4487
|
|
|
4488
|
+
// src/codebase-index/writer-helpers.ts
|
|
4489
|
+
import { resolveWstackPaths } from "@wrongstack/core/utils";
|
|
4490
|
+
function escapeLike(value) {
|
|
4491
|
+
return value.replace(/[\\%_]/g, (char) => `\\${char}`);
|
|
4492
|
+
}
|
|
4493
|
+
function posixIndexPath(file) {
|
|
4494
|
+
return file.replace(/\\/g, "/").replace(/^\.\//, "");
|
|
4495
|
+
}
|
|
4496
|
+
function indexedFileMatchSql(column = "file") {
|
|
4497
|
+
return `(${column} = ? OR replace(${column}, '\\', '/') = ? OR replace(${column}, '\\', '/') LIKE ? ESCAPE '\\')`;
|
|
4498
|
+
}
|
|
4499
|
+
function indexedFileMatchArgs(file) {
|
|
4500
|
+
const posix4 = posixIndexPath(file.trim());
|
|
4501
|
+
return [file, posix4, `%/${escapeLike(posix4)}`];
|
|
4502
|
+
}
|
|
4503
|
+
function matchesIndexedPackageFilter(storedFile, packageLabel, filter) {
|
|
4504
|
+
if (packageLabel === filter) return true;
|
|
4505
|
+
const posixFile = posixIndexPath(storedFile);
|
|
4506
|
+
const posixFilter = posixIndexPath(filter.trim());
|
|
4507
|
+
if (!posixFilter) return false;
|
|
4508
|
+
return posixFile === posixFilter || posixFile.endsWith(`/${posixFilter}`) || posixFile.includes(`/${posixFilter}/`);
|
|
4509
|
+
}
|
|
4510
|
+
function assignRefsToSymbols(refs, symbols) {
|
|
4511
|
+
if (refs.length === 0 || symbols.length === 0) return [];
|
|
4512
|
+
const ordered = [...symbols].sort((a, b) => a.line - b.line || a.col - b.col || a.id - b.id);
|
|
4513
|
+
const seen = /* @__PURE__ */ new Set();
|
|
4514
|
+
const assigned = [];
|
|
4515
|
+
for (const ref of refs) {
|
|
4516
|
+
let owner;
|
|
4517
|
+
for (const symbol of ordered) {
|
|
4518
|
+
if (symbol.line > ref.line) break;
|
|
4519
|
+
owner = symbol;
|
|
4520
|
+
}
|
|
4521
|
+
if (!owner && ref.callType === "import") owner = ordered[0];
|
|
4522
|
+
if (!owner || owner.id <= 0) continue;
|
|
4523
|
+
const key = `${owner.id}:${ref.toName}:${ref.callType}:${ref.module ?? ""}`;
|
|
4524
|
+
if (seen.has(key)) continue;
|
|
4525
|
+
seen.add(key);
|
|
4526
|
+
assigned.push({ ...ref, fromId: owner.id });
|
|
4527
|
+
}
|
|
4528
|
+
return assigned;
|
|
4529
|
+
}
|
|
4530
|
+
function resolveIndexDir(projectRoot, override) {
|
|
4531
|
+
return override ?? resolveWstackPaths({ projectRoot }).projectCodebaseIndex;
|
|
4532
|
+
}
|
|
4533
|
+
|
|
4482
4534
|
// src/codebase-index/writer-ref-mapper.ts
|
|
4483
4535
|
function mapWriterRefRow(row) {
|
|
4484
4536
|
return {
|
|
@@ -4534,10 +4586,23 @@ function mapCallSiteRow(row) {
|
|
|
4534
4586
|
line: row.ref_line
|
|
4535
4587
|
};
|
|
4536
4588
|
}
|
|
4589
|
+
function resolveIndexedFiles(stmt, file) {
|
|
4590
|
+
const rows = stmt(
|
|
4591
|
+
`SELECT DISTINCT file FROM symbols WHERE ${indexedFileMatchSql("file")} ORDER BY length(file), file`
|
|
4592
|
+
).all(...indexedFileMatchArgs(file));
|
|
4593
|
+
return rows.map((row) => row.file);
|
|
4594
|
+
}
|
|
4537
4595
|
function resolveSymbolIds(stmt, symbolName, file) {
|
|
4538
|
-
|
|
4539
|
-
|
|
4540
|
-
|
|
4596
|
+
if (!file) {
|
|
4597
|
+
const rows2 = stmt("SELECT id FROM symbols WHERE name = ? ORDER BY id").all(symbolName);
|
|
4598
|
+
return rows2.map((r) => r.id);
|
|
4599
|
+
}
|
|
4600
|
+
const indexedFiles = resolveIndexedFiles(stmt, file);
|
|
4601
|
+
if (indexedFiles.length === 0) return [];
|
|
4602
|
+
const placeholders = indexedFiles.map(() => "?").join(",");
|
|
4603
|
+
const rows = stmt(
|
|
4604
|
+
`SELECT id FROM symbols WHERE name = ? AND file IN (${placeholders}) ORDER BY id`
|
|
4605
|
+
).all(symbolName, ...indexedFiles);
|
|
4541
4606
|
return rows.map((r) => r.id);
|
|
4542
4607
|
}
|
|
4543
4608
|
function findIncomingCallsByName(stmt, symbolName, file, limit) {
|
|
@@ -4859,7 +4924,7 @@ function getFileGraphWithStatement(stmt, packageFilter) {
|
|
|
4859
4924
|
const allFiles = stmt("SELECT DISTINCT file FROM symbols").all();
|
|
4860
4925
|
const packageOf = readPackageLabeller(stmt);
|
|
4861
4926
|
const langOf = (file) => detectLang(file) ?? "other";
|
|
4862
|
-
const pkgFilePaths = allFiles.filter((f) => packageOf(f.file)
|
|
4927
|
+
const pkgFilePaths = allFiles.filter((f) => matchesIndexedPackageFilter(f.file, packageOf(f.file), packageFilter)).map((f) => f.file);
|
|
4863
4928
|
const localFiles = new Set(pkgFilePaths);
|
|
4864
4929
|
if (localFiles.size === 0) return { nodes: [], edges: [] };
|
|
4865
4930
|
const filePlaceholders = [...localFiles].map(() => "?").join(",");
|
|
@@ -4935,9 +5000,12 @@ function getFileGraphWithStatement(stmt, packageFilter) {
|
|
|
4935
5000
|
return { nodes: [...fileNodes.values()], edges };
|
|
4936
5001
|
}
|
|
4937
5002
|
function getSymbolGraphWithStatement(stmt, fileFilter) {
|
|
5003
|
+
const indexedFiles = resolveIndexedFiles(stmt, fileFilter);
|
|
5004
|
+
if (indexedFiles.length === 0) return { nodes: [], edges: [] };
|
|
5005
|
+
const filePlaceholders = indexedFiles.map(() => "?").join(",");
|
|
4938
5006
|
const syms = stmt(
|
|
4939
|
-
|
|
4940
|
-
).all(
|
|
5007
|
+
`SELECT id, name, kind, lang, file, line, signature, scope FROM symbols WHERE file IN (${filePlaceholders}) ORDER BY line, id`
|
|
5008
|
+
).all(...indexedFiles);
|
|
4941
5009
|
if (syms.length === 0) return { nodes: [], edges: [] };
|
|
4942
5010
|
const symById = new Map(syms.map((symbol) => [symbol.id, symbol]));
|
|
4943
5011
|
const relatedIds = new Set(syms.map((symbol) => symbol.id));
|
|
@@ -4947,16 +5015,16 @@ function getSymbolGraphWithStatement(stmt, fileFilter) {
|
|
|
4947
5015
|
SELECT r.from_id, r.to_id, r.to_name, r.call_type, r.line
|
|
4948
5016
|
FROM refs r
|
|
4949
5017
|
JOIN symbols s ON s.id = r.from_id
|
|
4950
|
-
WHERE s.file
|
|
5018
|
+
WHERE s.file IN (${filePlaceholders})
|
|
4951
5019
|
UNION
|
|
4952
5020
|
SELECT r.from_id, r.to_id, r.to_name, r.call_type, r.line
|
|
4953
5021
|
FROM refs r
|
|
4954
5022
|
JOIN symbols s ON s.id = r.to_id
|
|
4955
|
-
WHERE s.file
|
|
5023
|
+
WHERE s.file IN (${filePlaceholders})
|
|
4956
5024
|
)
|
|
4957
5025
|
WHERE to_id IS NOT NULL
|
|
4958
5026
|
GROUP BY from_id, to_id, call_type`
|
|
4959
|
-
).all(
|
|
5027
|
+
).all(...indexedFiles, ...indexedFiles);
|
|
4960
5028
|
const edgeMap = /* @__PURE__ */ new Map();
|
|
4961
5029
|
for (const r of refRows) {
|
|
4962
5030
|
if (r.to_id == null) continue;
|
|
@@ -4975,39 +5043,15 @@ function getSymbolGraphWithStatement(stmt, fileFilter) {
|
|
|
4975
5043
|
).all(...missingIds);
|
|
4976
5044
|
for (const s of extras) symById.set(s.id, s);
|
|
4977
5045
|
}
|
|
4978
|
-
const nodes = buildSymbolGraphNodes(
|
|
5046
|
+
const nodes = buildSymbolGraphNodes(
|
|
5047
|
+
symById,
|
|
5048
|
+
relatedIds,
|
|
5049
|
+
new Set(syms.map((symbol) => symbol.file)),
|
|
5050
|
+
readPackageLabeller(stmt)
|
|
5051
|
+
);
|
|
4979
5052
|
return { nodes, edges };
|
|
4980
5053
|
}
|
|
4981
5054
|
|
|
4982
|
-
// src/codebase-index/writer-helpers.ts
|
|
4983
|
-
import { resolveWstackPaths } from "@wrongstack/core/utils";
|
|
4984
|
-
function escapeLike(value) {
|
|
4985
|
-
return value.replace(/[\\%_]/g, (char) => `\\${char}`);
|
|
4986
|
-
}
|
|
4987
|
-
function assignRefsToSymbols(refs, symbols) {
|
|
4988
|
-
if (refs.length === 0 || symbols.length === 0) return [];
|
|
4989
|
-
const ordered = [...symbols].sort((a, b) => a.line - b.line || a.col - b.col || a.id - b.id);
|
|
4990
|
-
const seen = /* @__PURE__ */ new Set();
|
|
4991
|
-
const assigned = [];
|
|
4992
|
-
for (const ref of refs) {
|
|
4993
|
-
let owner;
|
|
4994
|
-
for (const symbol of ordered) {
|
|
4995
|
-
if (symbol.line > ref.line) break;
|
|
4996
|
-
owner = symbol;
|
|
4997
|
-
}
|
|
4998
|
-
if (!owner && ref.callType === "import") owner = ordered[0];
|
|
4999
|
-
if (!owner || owner.id <= 0) continue;
|
|
5000
|
-
const key = `${owner.id}:${ref.toName}:${ref.callType}:${ref.module ?? ""}`;
|
|
5001
|
-
if (seen.has(key)) continue;
|
|
5002
|
-
seen.add(key);
|
|
5003
|
-
assigned.push({ ...ref, fromId: owner.id });
|
|
5004
|
-
}
|
|
5005
|
-
return assigned;
|
|
5006
|
-
}
|
|
5007
|
-
function resolveIndexDir(projectRoot, override) {
|
|
5008
|
-
return override ?? resolveWstackPaths({ projectRoot }).projectCodebaseIndex;
|
|
5009
|
-
}
|
|
5010
|
-
|
|
5011
5055
|
// src/codebase-index/vector-search.ts
|
|
5012
5056
|
var RRF_K = 60;
|
|
5013
5057
|
var VECTOR_DIMENSIONS = 384;
|
package/dist/read.js
CHANGED
|
@@ -4426,10 +4426,16 @@ function buildFileGraphNodeState(pkgSyms, localFiles, packageOf) {
|
|
|
4426
4426
|
}
|
|
4427
4427
|
return { fileNodes, symToFile, fileStats, ensureFileNode };
|
|
4428
4428
|
}
|
|
4429
|
-
function buildSymbolGraphNodes(symById, relatedIds,
|
|
4429
|
+
function buildSymbolGraphNodes(symById, relatedIds, localFiles, packageOf) {
|
|
4430
|
+
const local = new Set(
|
|
4431
|
+
[...typeof localFiles === "string" ? [localFiles] : localFiles].map(
|
|
4432
|
+
(file) => file.replace(/\\/g, "/")
|
|
4433
|
+
)
|
|
4434
|
+
);
|
|
4435
|
+
const isLocal = (file) => local.has(file.replace(/\\/g, "/"));
|
|
4430
4436
|
return [...relatedIds].map((id) => symById.get(id)).filter((symbol) => symbol !== void 0).sort((a, b) => {
|
|
4431
|
-
const aExternal = a.file
|
|
4432
|
-
const bExternal = b.file
|
|
4437
|
+
const aExternal = isLocal(a.file) ? 0 : 1;
|
|
4438
|
+
const bExternal = isLocal(b.file) ? 0 : 1;
|
|
4433
4439
|
return aExternal - bExternal || a.file.localeCompare(b.file) || a.line - b.line || a.id - b.id;
|
|
4434
4440
|
}).map((s) => ({
|
|
4435
4441
|
id: `sym:${s.id}`,
|
|
@@ -4443,7 +4449,7 @@ function buildSymbolGraphNodes(symById, relatedIds, fileFilter, packageOf) {
|
|
|
4443
4449
|
line: s.line,
|
|
4444
4450
|
signature: s.signature,
|
|
4445
4451
|
scope: s.scope,
|
|
4446
|
-
external: s.file
|
|
4452
|
+
external: !isLocal(s.file)
|
|
4447
4453
|
}));
|
|
4448
4454
|
}
|
|
4449
4455
|
function addWeightedEdge(edgeMap, source, target, callType, weight) {
|
|
@@ -4478,6 +4484,56 @@ function materializeWeightedEdges(edgeMap, idPrefix) {
|
|
|
4478
4484
|
return edges;
|
|
4479
4485
|
}
|
|
4480
4486
|
|
|
4487
|
+
// src/codebase-index/writer-helpers.ts
|
|
4488
|
+
import { resolveWstackPaths } from "@wrongstack/core/utils";
|
|
4489
|
+
function escapeLike(value) {
|
|
4490
|
+
return value.replace(/[\\%_]/g, (char) => `\\${char}`);
|
|
4491
|
+
}
|
|
4492
|
+
function posixIndexPath(file) {
|
|
4493
|
+
return file.replace(/\\/g, "/").replace(/^\.\//, "");
|
|
4494
|
+
}
|
|
4495
|
+
function indexedFileMatchSql(column = "file") {
|
|
4496
|
+
return `(${column} = ? OR replace(${column}, '\\', '/') = ? OR replace(${column}, '\\', '/') LIKE ? ESCAPE '\\')`;
|
|
4497
|
+
}
|
|
4498
|
+
function indexedFileMatchArgs(file) {
|
|
4499
|
+
const posix4 = posixIndexPath(file.trim());
|
|
4500
|
+
return [file, posix4, `%/${escapeLike(posix4)}`];
|
|
4501
|
+
}
|
|
4502
|
+
function matchesIndexedPackageFilter(storedFile, packageLabel, filter) {
|
|
4503
|
+
if (packageLabel === filter) return true;
|
|
4504
|
+
const posixFile = posixIndexPath(storedFile);
|
|
4505
|
+
const posixFilter = posixIndexPath(filter.trim());
|
|
4506
|
+
if (!posixFilter) return false;
|
|
4507
|
+
return posixFile === posixFilter || posixFile.endsWith(`/${posixFilter}`) || posixFile.includes(`/${posixFilter}/`);
|
|
4508
|
+
}
|
|
4509
|
+
function assignRefsToSymbols(refs, symbols) {
|
|
4510
|
+
if (refs.length === 0 || symbols.length === 0) return [];
|
|
4511
|
+
const ordered = [...symbols].sort((a, b) => a.line - b.line || a.col - b.col || a.id - b.id);
|
|
4512
|
+
const seen = /* @__PURE__ */ new Set();
|
|
4513
|
+
const assigned = [];
|
|
4514
|
+
for (const ref of refs) {
|
|
4515
|
+
let owner;
|
|
4516
|
+
for (const symbol of ordered) {
|
|
4517
|
+
if (symbol.line > ref.line) break;
|
|
4518
|
+
owner = symbol;
|
|
4519
|
+
}
|
|
4520
|
+
if (!owner && ref.callType === "import") owner = ordered[0];
|
|
4521
|
+
if (!owner || owner.id <= 0) continue;
|
|
4522
|
+
const key = `${owner.id}:${ref.toName}:${ref.callType}:${ref.module ?? ""}`;
|
|
4523
|
+
if (seen.has(key)) continue;
|
|
4524
|
+
seen.add(key);
|
|
4525
|
+
assigned.push({ ...ref, fromId: owner.id });
|
|
4526
|
+
}
|
|
4527
|
+
return assigned;
|
|
4528
|
+
}
|
|
4529
|
+
function resolveIndexDir(projectRoot, override) {
|
|
4530
|
+
return override ?? resolveWstackPaths({ projectRoot }).projectCodebaseIndex;
|
|
4531
|
+
}
|
|
4532
|
+
function codebaseIndexDirOverride(ctx) {
|
|
4533
|
+
const v = ctx.meta?.["codebaseIndexDir"];
|
|
4534
|
+
return typeof v === "string" ? v : void 0;
|
|
4535
|
+
}
|
|
4536
|
+
|
|
4481
4537
|
// src/codebase-index/writer-ref-mapper.ts
|
|
4482
4538
|
function mapWriterRefRow(row) {
|
|
4483
4539
|
return {
|
|
@@ -4533,10 +4589,23 @@ function mapCallSiteRow(row) {
|
|
|
4533
4589
|
line: row.ref_line
|
|
4534
4590
|
};
|
|
4535
4591
|
}
|
|
4592
|
+
function resolveIndexedFiles(stmt, file) {
|
|
4593
|
+
const rows = stmt(
|
|
4594
|
+
`SELECT DISTINCT file FROM symbols WHERE ${indexedFileMatchSql("file")} ORDER BY length(file), file`
|
|
4595
|
+
).all(...indexedFileMatchArgs(file));
|
|
4596
|
+
return rows.map((row) => row.file);
|
|
4597
|
+
}
|
|
4536
4598
|
function resolveSymbolIds(stmt, symbolName, file) {
|
|
4537
|
-
|
|
4538
|
-
|
|
4539
|
-
|
|
4599
|
+
if (!file) {
|
|
4600
|
+
const rows2 = stmt("SELECT id FROM symbols WHERE name = ? ORDER BY id").all(symbolName);
|
|
4601
|
+
return rows2.map((r) => r.id);
|
|
4602
|
+
}
|
|
4603
|
+
const indexedFiles = resolveIndexedFiles(stmt, file);
|
|
4604
|
+
if (indexedFiles.length === 0) return [];
|
|
4605
|
+
const placeholders = indexedFiles.map(() => "?").join(",");
|
|
4606
|
+
const rows = stmt(
|
|
4607
|
+
`SELECT id FROM symbols WHERE name = ? AND file IN (${placeholders}) ORDER BY id`
|
|
4608
|
+
).all(symbolName, ...indexedFiles);
|
|
4540
4609
|
return rows.map((r) => r.id);
|
|
4541
4610
|
}
|
|
4542
4611
|
function findIncomingCallsByName(stmt, symbolName, file, limit) {
|
|
@@ -4858,7 +4927,7 @@ function getFileGraphWithStatement(stmt, packageFilter) {
|
|
|
4858
4927
|
const allFiles = stmt("SELECT DISTINCT file FROM symbols").all();
|
|
4859
4928
|
const packageOf = readPackageLabeller(stmt);
|
|
4860
4929
|
const langOf = (file) => detectLang(file) ?? "other";
|
|
4861
|
-
const pkgFilePaths = allFiles.filter((f) => packageOf(f.file)
|
|
4930
|
+
const pkgFilePaths = allFiles.filter((f) => matchesIndexedPackageFilter(f.file, packageOf(f.file), packageFilter)).map((f) => f.file);
|
|
4862
4931
|
const localFiles = new Set(pkgFilePaths);
|
|
4863
4932
|
if (localFiles.size === 0) return { nodes: [], edges: [] };
|
|
4864
4933
|
const filePlaceholders = [...localFiles].map(() => "?").join(",");
|
|
@@ -4934,9 +5003,12 @@ function getFileGraphWithStatement(stmt, packageFilter) {
|
|
|
4934
5003
|
return { nodes: [...fileNodes.values()], edges };
|
|
4935
5004
|
}
|
|
4936
5005
|
function getSymbolGraphWithStatement(stmt, fileFilter) {
|
|
5006
|
+
const indexedFiles = resolveIndexedFiles(stmt, fileFilter);
|
|
5007
|
+
if (indexedFiles.length === 0) return { nodes: [], edges: [] };
|
|
5008
|
+
const filePlaceholders = indexedFiles.map(() => "?").join(",");
|
|
4937
5009
|
const syms = stmt(
|
|
4938
|
-
|
|
4939
|
-
).all(
|
|
5010
|
+
`SELECT id, name, kind, lang, file, line, signature, scope FROM symbols WHERE file IN (${filePlaceholders}) ORDER BY line, id`
|
|
5011
|
+
).all(...indexedFiles);
|
|
4940
5012
|
if (syms.length === 0) return { nodes: [], edges: [] };
|
|
4941
5013
|
const symById = new Map(syms.map((symbol) => [symbol.id, symbol]));
|
|
4942
5014
|
const relatedIds = new Set(syms.map((symbol) => symbol.id));
|
|
@@ -4946,16 +5018,16 @@ function getSymbolGraphWithStatement(stmt, fileFilter) {
|
|
|
4946
5018
|
SELECT r.from_id, r.to_id, r.to_name, r.call_type, r.line
|
|
4947
5019
|
FROM refs r
|
|
4948
5020
|
JOIN symbols s ON s.id = r.from_id
|
|
4949
|
-
WHERE s.file
|
|
5021
|
+
WHERE s.file IN (${filePlaceholders})
|
|
4950
5022
|
UNION
|
|
4951
5023
|
SELECT r.from_id, r.to_id, r.to_name, r.call_type, r.line
|
|
4952
5024
|
FROM refs r
|
|
4953
5025
|
JOIN symbols s ON s.id = r.to_id
|
|
4954
|
-
WHERE s.file
|
|
5026
|
+
WHERE s.file IN (${filePlaceholders})
|
|
4955
5027
|
)
|
|
4956
5028
|
WHERE to_id IS NOT NULL
|
|
4957
5029
|
GROUP BY from_id, to_id, call_type`
|
|
4958
|
-
).all(
|
|
5030
|
+
).all(...indexedFiles, ...indexedFiles);
|
|
4959
5031
|
const edgeMap = /* @__PURE__ */ new Map();
|
|
4960
5032
|
for (const r of refRows) {
|
|
4961
5033
|
if (r.to_id == null) continue;
|
|
@@ -4974,43 +5046,15 @@ function getSymbolGraphWithStatement(stmt, fileFilter) {
|
|
|
4974
5046
|
).all(...missingIds);
|
|
4975
5047
|
for (const s of extras) symById.set(s.id, s);
|
|
4976
5048
|
}
|
|
4977
|
-
const nodes = buildSymbolGraphNodes(
|
|
5049
|
+
const nodes = buildSymbolGraphNodes(
|
|
5050
|
+
symById,
|
|
5051
|
+
relatedIds,
|
|
5052
|
+
new Set(syms.map((symbol) => symbol.file)),
|
|
5053
|
+
readPackageLabeller(stmt)
|
|
5054
|
+
);
|
|
4978
5055
|
return { nodes, edges };
|
|
4979
5056
|
}
|
|
4980
5057
|
|
|
4981
|
-
// src/codebase-index/writer-helpers.ts
|
|
4982
|
-
import { resolveWstackPaths } from "@wrongstack/core/utils";
|
|
4983
|
-
function escapeLike(value) {
|
|
4984
|
-
return value.replace(/[\\%_]/g, (char) => `\\${char}`);
|
|
4985
|
-
}
|
|
4986
|
-
function assignRefsToSymbols(refs, symbols) {
|
|
4987
|
-
if (refs.length === 0 || symbols.length === 0) return [];
|
|
4988
|
-
const ordered = [...symbols].sort((a, b) => a.line - b.line || a.col - b.col || a.id - b.id);
|
|
4989
|
-
const seen = /* @__PURE__ */ new Set();
|
|
4990
|
-
const assigned = [];
|
|
4991
|
-
for (const ref of refs) {
|
|
4992
|
-
let owner;
|
|
4993
|
-
for (const symbol of ordered) {
|
|
4994
|
-
if (symbol.line > ref.line) break;
|
|
4995
|
-
owner = symbol;
|
|
4996
|
-
}
|
|
4997
|
-
if (!owner && ref.callType === "import") owner = ordered[0];
|
|
4998
|
-
if (!owner || owner.id <= 0) continue;
|
|
4999
|
-
const key = `${owner.id}:${ref.toName}:${ref.callType}:${ref.module ?? ""}`;
|
|
5000
|
-
if (seen.has(key)) continue;
|
|
5001
|
-
seen.add(key);
|
|
5002
|
-
assigned.push({ ...ref, fromId: owner.id });
|
|
5003
|
-
}
|
|
5004
|
-
return assigned;
|
|
5005
|
-
}
|
|
5006
|
-
function resolveIndexDir(projectRoot, override) {
|
|
5007
|
-
return override ?? resolveWstackPaths({ projectRoot }).projectCodebaseIndex;
|
|
5008
|
-
}
|
|
5009
|
-
function codebaseIndexDirOverride(ctx) {
|
|
5010
|
-
const v = ctx.meta?.["codebaseIndexDir"];
|
|
5011
|
-
return typeof v === "string" ? v : void 0;
|
|
5012
|
-
}
|
|
5013
|
-
|
|
5014
5058
|
// src/codebase-index/vector-search.ts
|
|
5015
5059
|
var RRF_K = 60;
|
|
5016
5060
|
var VECTOR_DIMENSIONS = 384;
|
package/dist/replace.js
CHANGED
|
@@ -4592,10 +4592,16 @@ function buildFileGraphNodeState(pkgSyms, localFiles, packageOf) {
|
|
|
4592
4592
|
}
|
|
4593
4593
|
return { fileNodes, symToFile, fileStats, ensureFileNode };
|
|
4594
4594
|
}
|
|
4595
|
-
function buildSymbolGraphNodes(symById, relatedIds,
|
|
4595
|
+
function buildSymbolGraphNodes(symById, relatedIds, localFiles, packageOf) {
|
|
4596
|
+
const local = new Set(
|
|
4597
|
+
[...typeof localFiles === "string" ? [localFiles] : localFiles].map(
|
|
4598
|
+
(file) => file.replace(/\\/g, "/")
|
|
4599
|
+
)
|
|
4600
|
+
);
|
|
4601
|
+
const isLocal = (file) => local.has(file.replace(/\\/g, "/"));
|
|
4596
4602
|
return [...relatedIds].map((id) => symById.get(id)).filter((symbol) => symbol !== void 0).sort((a, b) => {
|
|
4597
|
-
const aExternal = a.file
|
|
4598
|
-
const bExternal = b.file
|
|
4603
|
+
const aExternal = isLocal(a.file) ? 0 : 1;
|
|
4604
|
+
const bExternal = isLocal(b.file) ? 0 : 1;
|
|
4599
4605
|
return aExternal - bExternal || a.file.localeCompare(b.file) || a.line - b.line || a.id - b.id;
|
|
4600
4606
|
}).map((s) => ({
|
|
4601
4607
|
id: `sym:${s.id}`,
|
|
@@ -4609,7 +4615,7 @@ function buildSymbolGraphNodes(symById, relatedIds, fileFilter, packageOf) {
|
|
|
4609
4615
|
line: s.line,
|
|
4610
4616
|
signature: s.signature,
|
|
4611
4617
|
scope: s.scope,
|
|
4612
|
-
external: s.file
|
|
4618
|
+
external: !isLocal(s.file)
|
|
4613
4619
|
}));
|
|
4614
4620
|
}
|
|
4615
4621
|
function addWeightedEdge(edgeMap, source, target, callType, weight) {
|
|
@@ -4644,6 +4650,52 @@ function materializeWeightedEdges(edgeMap, idPrefix) {
|
|
|
4644
4650
|
return edges;
|
|
4645
4651
|
}
|
|
4646
4652
|
|
|
4653
|
+
// src/codebase-index/writer-helpers.ts
|
|
4654
|
+
import { resolveWstackPaths } from "@wrongstack/core/utils";
|
|
4655
|
+
function escapeLike(value) {
|
|
4656
|
+
return value.replace(/[\\%_]/g, (char) => `\\${char}`);
|
|
4657
|
+
}
|
|
4658
|
+
function posixIndexPath(file) {
|
|
4659
|
+
return file.replace(/\\/g, "/").replace(/^\.\//, "");
|
|
4660
|
+
}
|
|
4661
|
+
function indexedFileMatchSql(column = "file") {
|
|
4662
|
+
return `(${column} = ? OR replace(${column}, '\\', '/') = ? OR replace(${column}, '\\', '/') LIKE ? ESCAPE '\\')`;
|
|
4663
|
+
}
|
|
4664
|
+
function indexedFileMatchArgs(file) {
|
|
4665
|
+
const posix4 = posixIndexPath(file.trim());
|
|
4666
|
+
return [file, posix4, `%/${escapeLike(posix4)}`];
|
|
4667
|
+
}
|
|
4668
|
+
function matchesIndexedPackageFilter(storedFile, packageLabel, filter) {
|
|
4669
|
+
if (packageLabel === filter) return true;
|
|
4670
|
+
const posixFile = posixIndexPath(storedFile);
|
|
4671
|
+
const posixFilter = posixIndexPath(filter.trim());
|
|
4672
|
+
if (!posixFilter) return false;
|
|
4673
|
+
return posixFile === posixFilter || posixFile.endsWith(`/${posixFilter}`) || posixFile.includes(`/${posixFilter}/`);
|
|
4674
|
+
}
|
|
4675
|
+
function assignRefsToSymbols(refs, symbols) {
|
|
4676
|
+
if (refs.length === 0 || symbols.length === 0) return [];
|
|
4677
|
+
const ordered = [...symbols].sort((a, b) => a.line - b.line || a.col - b.col || a.id - b.id);
|
|
4678
|
+
const seen = /* @__PURE__ */ new Set();
|
|
4679
|
+
const assigned = [];
|
|
4680
|
+
for (const ref of refs) {
|
|
4681
|
+
let owner;
|
|
4682
|
+
for (const symbol of ordered) {
|
|
4683
|
+
if (symbol.line > ref.line) break;
|
|
4684
|
+
owner = symbol;
|
|
4685
|
+
}
|
|
4686
|
+
if (!owner && ref.callType === "import") owner = ordered[0];
|
|
4687
|
+
if (!owner || owner.id <= 0) continue;
|
|
4688
|
+
const key = `${owner.id}:${ref.toName}:${ref.callType}:${ref.module ?? ""}`;
|
|
4689
|
+
if (seen.has(key)) continue;
|
|
4690
|
+
seen.add(key);
|
|
4691
|
+
assigned.push({ ...ref, fromId: owner.id });
|
|
4692
|
+
}
|
|
4693
|
+
return assigned;
|
|
4694
|
+
}
|
|
4695
|
+
function resolveIndexDir(projectRoot, override) {
|
|
4696
|
+
return override ?? resolveWstackPaths({ projectRoot }).projectCodebaseIndex;
|
|
4697
|
+
}
|
|
4698
|
+
|
|
4647
4699
|
// src/codebase-index/writer-ref-mapper.ts
|
|
4648
4700
|
function mapWriterRefRow(row) {
|
|
4649
4701
|
return {
|
|
@@ -4699,10 +4751,23 @@ function mapCallSiteRow(row) {
|
|
|
4699
4751
|
line: row.ref_line
|
|
4700
4752
|
};
|
|
4701
4753
|
}
|
|
4754
|
+
function resolveIndexedFiles(stmt, file) {
|
|
4755
|
+
const rows = stmt(
|
|
4756
|
+
`SELECT DISTINCT file FROM symbols WHERE ${indexedFileMatchSql("file")} ORDER BY length(file), file`
|
|
4757
|
+
).all(...indexedFileMatchArgs(file));
|
|
4758
|
+
return rows.map((row) => row.file);
|
|
4759
|
+
}
|
|
4702
4760
|
function resolveSymbolIds(stmt, symbolName, file) {
|
|
4703
|
-
|
|
4704
|
-
|
|
4705
|
-
|
|
4761
|
+
if (!file) {
|
|
4762
|
+
const rows2 = stmt("SELECT id FROM symbols WHERE name = ? ORDER BY id").all(symbolName);
|
|
4763
|
+
return rows2.map((r) => r.id);
|
|
4764
|
+
}
|
|
4765
|
+
const indexedFiles = resolveIndexedFiles(stmt, file);
|
|
4766
|
+
if (indexedFiles.length === 0) return [];
|
|
4767
|
+
const placeholders = indexedFiles.map(() => "?").join(",");
|
|
4768
|
+
const rows = stmt(
|
|
4769
|
+
`SELECT id FROM symbols WHERE name = ? AND file IN (${placeholders}) ORDER BY id`
|
|
4770
|
+
).all(symbolName, ...indexedFiles);
|
|
4706
4771
|
return rows.map((r) => r.id);
|
|
4707
4772
|
}
|
|
4708
4773
|
function findIncomingCallsByName(stmt, symbolName, file, limit) {
|
|
@@ -5024,7 +5089,7 @@ function getFileGraphWithStatement(stmt, packageFilter) {
|
|
|
5024
5089
|
const allFiles = stmt("SELECT DISTINCT file FROM symbols").all();
|
|
5025
5090
|
const packageOf = readPackageLabeller(stmt);
|
|
5026
5091
|
const langOf = (file) => detectLang(file) ?? "other";
|
|
5027
|
-
const pkgFilePaths = allFiles.filter((f) => packageOf(f.file)
|
|
5092
|
+
const pkgFilePaths = allFiles.filter((f) => matchesIndexedPackageFilter(f.file, packageOf(f.file), packageFilter)).map((f) => f.file);
|
|
5028
5093
|
const localFiles = new Set(pkgFilePaths);
|
|
5029
5094
|
if (localFiles.size === 0) return { nodes: [], edges: [] };
|
|
5030
5095
|
const filePlaceholders = [...localFiles].map(() => "?").join(",");
|
|
@@ -5100,9 +5165,12 @@ function getFileGraphWithStatement(stmt, packageFilter) {
|
|
|
5100
5165
|
return { nodes: [...fileNodes.values()], edges };
|
|
5101
5166
|
}
|
|
5102
5167
|
function getSymbolGraphWithStatement(stmt, fileFilter) {
|
|
5168
|
+
const indexedFiles = resolveIndexedFiles(stmt, fileFilter);
|
|
5169
|
+
if (indexedFiles.length === 0) return { nodes: [], edges: [] };
|
|
5170
|
+
const filePlaceholders = indexedFiles.map(() => "?").join(",");
|
|
5103
5171
|
const syms = stmt(
|
|
5104
|
-
|
|
5105
|
-
).all(
|
|
5172
|
+
`SELECT id, name, kind, lang, file, line, signature, scope FROM symbols WHERE file IN (${filePlaceholders}) ORDER BY line, id`
|
|
5173
|
+
).all(...indexedFiles);
|
|
5106
5174
|
if (syms.length === 0) return { nodes: [], edges: [] };
|
|
5107
5175
|
const symById = new Map(syms.map((symbol) => [symbol.id, symbol]));
|
|
5108
5176
|
const relatedIds = new Set(syms.map((symbol) => symbol.id));
|
|
@@ -5112,16 +5180,16 @@ function getSymbolGraphWithStatement(stmt, fileFilter) {
|
|
|
5112
5180
|
SELECT r.from_id, r.to_id, r.to_name, r.call_type, r.line
|
|
5113
5181
|
FROM refs r
|
|
5114
5182
|
JOIN symbols s ON s.id = r.from_id
|
|
5115
|
-
WHERE s.file
|
|
5183
|
+
WHERE s.file IN (${filePlaceholders})
|
|
5116
5184
|
UNION
|
|
5117
5185
|
SELECT r.from_id, r.to_id, r.to_name, r.call_type, r.line
|
|
5118
5186
|
FROM refs r
|
|
5119
5187
|
JOIN symbols s ON s.id = r.to_id
|
|
5120
|
-
WHERE s.file
|
|
5188
|
+
WHERE s.file IN (${filePlaceholders})
|
|
5121
5189
|
)
|
|
5122
5190
|
WHERE to_id IS NOT NULL
|
|
5123
5191
|
GROUP BY from_id, to_id, call_type`
|
|
5124
|
-
).all(
|
|
5192
|
+
).all(...indexedFiles, ...indexedFiles);
|
|
5125
5193
|
const edgeMap = /* @__PURE__ */ new Map();
|
|
5126
5194
|
for (const r of refRows) {
|
|
5127
5195
|
if (r.to_id == null) continue;
|
|
@@ -5140,39 +5208,15 @@ function getSymbolGraphWithStatement(stmt, fileFilter) {
|
|
|
5140
5208
|
).all(...missingIds);
|
|
5141
5209
|
for (const s of extras) symById.set(s.id, s);
|
|
5142
5210
|
}
|
|
5143
|
-
const nodes = buildSymbolGraphNodes(
|
|
5211
|
+
const nodes = buildSymbolGraphNodes(
|
|
5212
|
+
symById,
|
|
5213
|
+
relatedIds,
|
|
5214
|
+
new Set(syms.map((symbol) => symbol.file)),
|
|
5215
|
+
readPackageLabeller(stmt)
|
|
5216
|
+
);
|
|
5144
5217
|
return { nodes, edges };
|
|
5145
5218
|
}
|
|
5146
5219
|
|
|
5147
|
-
// src/codebase-index/writer-helpers.ts
|
|
5148
|
-
import { resolveWstackPaths } from "@wrongstack/core/utils";
|
|
5149
|
-
function escapeLike(value) {
|
|
5150
|
-
return value.replace(/[\\%_]/g, (char) => `\\${char}`);
|
|
5151
|
-
}
|
|
5152
|
-
function assignRefsToSymbols(refs, symbols) {
|
|
5153
|
-
if (refs.length === 0 || symbols.length === 0) return [];
|
|
5154
|
-
const ordered = [...symbols].sort((a, b) => a.line - b.line || a.col - b.col || a.id - b.id);
|
|
5155
|
-
const seen = /* @__PURE__ */ new Set();
|
|
5156
|
-
const assigned = [];
|
|
5157
|
-
for (const ref of refs) {
|
|
5158
|
-
let owner;
|
|
5159
|
-
for (const symbol of ordered) {
|
|
5160
|
-
if (symbol.line > ref.line) break;
|
|
5161
|
-
owner = symbol;
|
|
5162
|
-
}
|
|
5163
|
-
if (!owner && ref.callType === "import") owner = ordered[0];
|
|
5164
|
-
if (!owner || owner.id <= 0) continue;
|
|
5165
|
-
const key = `${owner.id}:${ref.toName}:${ref.callType}:${ref.module ?? ""}`;
|
|
5166
|
-
if (seen.has(key)) continue;
|
|
5167
|
-
seen.add(key);
|
|
5168
|
-
assigned.push({ ...ref, fromId: owner.id });
|
|
5169
|
-
}
|
|
5170
|
-
return assigned;
|
|
5171
|
-
}
|
|
5172
|
-
function resolveIndexDir(projectRoot, override) {
|
|
5173
|
-
return override ?? resolveWstackPaths({ projectRoot }).projectCodebaseIndex;
|
|
5174
|
-
}
|
|
5175
|
-
|
|
5176
5220
|
// src/codebase-index/vector-search.ts
|
|
5177
5221
|
var RRF_K = 60;
|
|
5178
5222
|
var VECTOR_DIMENSIONS = 384;
|