@wrongstack/tools 0.307.0 → 0.308.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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/pack.js
CHANGED
|
@@ -1031,8 +1031,8 @@ async function* spawnStream(opts) {
|
|
|
1031
1031
|
try {
|
|
1032
1032
|
for (; ; ) {
|
|
1033
1033
|
while (queue.length === 0) {
|
|
1034
|
-
await new Promise((
|
|
1035
|
-
waiter =
|
|
1034
|
+
await new Promise((resolve23) => {
|
|
1035
|
+
waiter = resolve23;
|
|
1036
1036
|
});
|
|
1037
1037
|
}
|
|
1038
1038
|
const chunk = queue.shift();
|
|
@@ -1135,9 +1135,9 @@ async function detectPackageManager(cwd, stopAt) {
|
|
|
1135
1135
|
return "npm";
|
|
1136
1136
|
}
|
|
1137
1137
|
async function detectPackageManagerInDir(dir) {
|
|
1138
|
-
const
|
|
1138
|
+
const fs43 = await import("node:fs/promises");
|
|
1139
1139
|
try {
|
|
1140
|
-
const raw = await
|
|
1140
|
+
const raw = await fs43.readFile(path3.join(dir, "package.json"), "utf8");
|
|
1141
1141
|
const declared = JSON.parse(raw).packageManager;
|
|
1142
1142
|
if (typeof declared === "string") {
|
|
1143
1143
|
const name = declared.split("@")[0] ?? "";
|
|
@@ -1156,7 +1156,7 @@ async function detectPackageManagerInDir(dir) {
|
|
|
1156
1156
|
];
|
|
1157
1157
|
for (const [file, manager] of lockfiles) {
|
|
1158
1158
|
try {
|
|
1159
|
-
await
|
|
1159
|
+
await fs43.stat(`${dir}/${file}`);
|
|
1160
1160
|
return manager;
|
|
1161
1161
|
} catch {
|
|
1162
1162
|
}
|
|
@@ -4137,15 +4137,15 @@ async function changedPaths(before, after, beforeSizes, afterSizes) {
|
|
|
4137
4137
|
const beforeSet = new Set(before);
|
|
4138
4138
|
const afterSet = new Set(after);
|
|
4139
4139
|
const changed = /* @__PURE__ */ new Set();
|
|
4140
|
-
for (const
|
|
4141
|
-
if (!beforeSet.has(
|
|
4140
|
+
for (const path49 of after) {
|
|
4141
|
+
if (!beforeSet.has(path49)) changed.add(path49);
|
|
4142
4142
|
}
|
|
4143
|
-
for (const
|
|
4144
|
-
if (!afterSet.has(
|
|
4143
|
+
for (const path49 of before) {
|
|
4144
|
+
if (!afterSet.has(path49)) changed.add(path49);
|
|
4145
4145
|
}
|
|
4146
4146
|
if (beforeSizes && afterSizes) {
|
|
4147
|
-
for (const
|
|
4148
|
-
if (beforeSizes.get(
|
|
4147
|
+
for (const path49 of after) {
|
|
4148
|
+
if (beforeSizes.get(path49) !== afterSizes.get(path49)) changed.add(path49);
|
|
4149
4149
|
}
|
|
4150
4150
|
}
|
|
4151
4151
|
return [...changed].sort();
|
|
@@ -5640,7 +5640,7 @@ async function syncGoParse(filePath, content, lang) {
|
|
|
5640
5640
|
}
|
|
5641
5641
|
const goBinary = resolveWin32Command("go");
|
|
5642
5642
|
const goResult = await new Promise(
|
|
5643
|
-
(
|
|
5643
|
+
(resolve23, reject) => {
|
|
5644
5644
|
let settled = false;
|
|
5645
5645
|
const proc = spawn5(goBinary, ["run", scriptPath], {
|
|
5646
5646
|
stdio: ["pipe", "pipe", "pipe"],
|
|
@@ -5669,7 +5669,7 @@ async function syncGoParse(filePath, content, lang) {
|
|
|
5669
5669
|
if (settled) return;
|
|
5670
5670
|
settled = true;
|
|
5671
5671
|
clearTimeout(timer);
|
|
5672
|
-
|
|
5672
|
+
resolve23({ code: code2, stdout: stdout2 });
|
|
5673
5673
|
});
|
|
5674
5674
|
}
|
|
5675
5675
|
);
|
|
@@ -6345,7 +6345,7 @@ async function resolvePython() {
|
|
|
6345
6345
|
return null;
|
|
6346
6346
|
}
|
|
6347
6347
|
function commandIsAvailable(command) {
|
|
6348
|
-
return new Promise((
|
|
6348
|
+
return new Promise((resolve23) => {
|
|
6349
6349
|
let settled = false;
|
|
6350
6350
|
const proc = spawn6(command, ["--version"], {
|
|
6351
6351
|
stdio: "ignore",
|
|
@@ -6355,7 +6355,7 @@ function commandIsAvailable(command) {
|
|
|
6355
6355
|
if (settled) return;
|
|
6356
6356
|
settled = true;
|
|
6357
6357
|
clearTimeout(timer);
|
|
6358
|
-
|
|
6358
|
+
resolve23(available);
|
|
6359
6359
|
};
|
|
6360
6360
|
const timer = setTimeout(() => {
|
|
6361
6361
|
proc.kill("SIGKILL");
|
|
@@ -6367,7 +6367,7 @@ function commandIsAvailable(command) {
|
|
|
6367
6367
|
});
|
|
6368
6368
|
}
|
|
6369
6369
|
function spawnPyParser(pyBinary, scriptPath, filePath, content) {
|
|
6370
|
-
return new Promise((
|
|
6370
|
+
return new Promise((resolve23, reject) => {
|
|
6371
6371
|
let settled = false;
|
|
6372
6372
|
const proc = spawn6(pyBinary, [scriptPath, filePath], {
|
|
6373
6373
|
stdio: ["pipe", "pipe", "pipe"],
|
|
@@ -6396,7 +6396,7 @@ function spawnPyParser(pyBinary, scriptPath, filePath, content) {
|
|
|
6396
6396
|
if (settled) return;
|
|
6397
6397
|
settled = true;
|
|
6398
6398
|
clearTimeout(timer);
|
|
6399
|
-
|
|
6399
|
+
resolve23({ code, stdout });
|
|
6400
6400
|
});
|
|
6401
6401
|
});
|
|
6402
6402
|
}
|
|
@@ -9230,10 +9230,10 @@ var bashTool = {
|
|
|
9230
9230
|
queue.push(c);
|
|
9231
9231
|
}
|
|
9232
9232
|
};
|
|
9233
|
-
const next = () => new Promise((
|
|
9233
|
+
const next = () => new Promise((resolve23) => {
|
|
9234
9234
|
const c = queue.shift();
|
|
9235
|
-
if (c)
|
|
9236
|
-
else resolveNext =
|
|
9235
|
+
if (c) resolve23(c);
|
|
9236
|
+
else resolveNext = resolve23;
|
|
9237
9237
|
});
|
|
9238
9238
|
let lastFlush = Date.now();
|
|
9239
9239
|
const flush = () => {
|
|
@@ -9696,11 +9696,11 @@ var BrowserArtifactStore = class {
|
|
|
9696
9696
|
};
|
|
9697
9697
|
async function hashFile(target) {
|
|
9698
9698
|
const hash = createHash3("sha256");
|
|
9699
|
-
await new Promise((
|
|
9699
|
+
await new Promise((resolve23, reject) => {
|
|
9700
9700
|
const stream = createReadStream(target);
|
|
9701
9701
|
stream.on("data", (chunk) => hash.update(chunk));
|
|
9702
9702
|
stream.once("error", reject);
|
|
9703
|
-
stream.once("end",
|
|
9703
|
+
stream.once("end", resolve23);
|
|
9704
9704
|
});
|
|
9705
9705
|
return hash.digest("hex");
|
|
9706
9706
|
}
|
|
@@ -9850,7 +9850,7 @@ var BrowserNetworkGuardProxy = class {
|
|
|
9850
9850
|
async start() {
|
|
9851
9851
|
if (this.url) return this.url;
|
|
9852
9852
|
if (this.startPromise) return this.startPromise;
|
|
9853
|
-
this.startPromise = new Promise((
|
|
9853
|
+
this.startPromise = new Promise((resolve23, reject) => {
|
|
9854
9854
|
const onError = (error) => {
|
|
9855
9855
|
this.server.off("listening", onListening);
|
|
9856
9856
|
reject(error);
|
|
@@ -9863,7 +9863,7 @@ var BrowserNetworkGuardProxy = class {
|
|
|
9863
9863
|
return;
|
|
9864
9864
|
}
|
|
9865
9865
|
this.url = `http://127.0.0.1:${address.port}`;
|
|
9866
|
-
|
|
9866
|
+
resolve23(this.url);
|
|
9867
9867
|
};
|
|
9868
9868
|
this.server.once("error", onError);
|
|
9869
9869
|
this.server.once("listening", onListening);
|
|
@@ -9878,7 +9878,7 @@ var BrowserNetworkGuardProxy = class {
|
|
|
9878
9878
|
for (const socket of this.sockets) socket.destroy();
|
|
9879
9879
|
this.sockets.clear();
|
|
9880
9880
|
if (!this.server.listening) return;
|
|
9881
|
-
await new Promise((
|
|
9881
|
+
await new Promise((resolve23) => this.server.close(() => resolve23()));
|
|
9882
9882
|
}
|
|
9883
9883
|
async forwardHttp(request2, response) {
|
|
9884
9884
|
try {
|
|
@@ -10451,7 +10451,7 @@ function pushBounded(target, value, limit) {
|
|
|
10451
10451
|
}
|
|
10452
10452
|
async function abortable(signal, operation, onAbort) {
|
|
10453
10453
|
signal.throwIfAborted();
|
|
10454
|
-
return new Promise((
|
|
10454
|
+
return new Promise((resolve23, reject) => {
|
|
10455
10455
|
let settled = false;
|
|
10456
10456
|
let aborting = false;
|
|
10457
10457
|
const finish = (fn) => {
|
|
@@ -10469,7 +10469,7 @@ async function abortable(signal, operation, onAbort) {
|
|
|
10469
10469
|
signal.addEventListener("abort", abort, { once: true });
|
|
10470
10470
|
operation().then(
|
|
10471
10471
|
(value) => {
|
|
10472
|
-
if (!aborting) finish(() =>
|
|
10472
|
+
if (!aborting) finish(() => resolve23(value));
|
|
10473
10473
|
},
|
|
10474
10474
|
(err) => {
|
|
10475
10475
|
if (!aborting) finish(() => reject(err));
|
|
@@ -11725,10 +11725,16 @@ function buildFileGraphNodeState(pkgSyms, localFiles, packageOf) {
|
|
|
11725
11725
|
}
|
|
11726
11726
|
return { fileNodes, symToFile, fileStats, ensureFileNode };
|
|
11727
11727
|
}
|
|
11728
|
-
function buildSymbolGraphNodes(symById, relatedIds,
|
|
11728
|
+
function buildSymbolGraphNodes(symById, relatedIds, localFiles, packageOf) {
|
|
11729
|
+
const local = new Set(
|
|
11730
|
+
[...typeof localFiles === "string" ? [localFiles] : localFiles].map(
|
|
11731
|
+
(file) => file.replace(/\\/g, "/")
|
|
11732
|
+
)
|
|
11733
|
+
);
|
|
11734
|
+
const isLocal = (file) => local.has(file.replace(/\\/g, "/"));
|
|
11729
11735
|
return [...relatedIds].map((id) => symById.get(id)).filter((symbol) => symbol !== void 0).sort((a, b) => {
|
|
11730
|
-
const aExternal = a.file
|
|
11731
|
-
const bExternal = b.file
|
|
11736
|
+
const aExternal = isLocal(a.file) ? 0 : 1;
|
|
11737
|
+
const bExternal = isLocal(b.file) ? 0 : 1;
|
|
11732
11738
|
return aExternal - bExternal || a.file.localeCompare(b.file) || a.line - b.line || a.id - b.id;
|
|
11733
11739
|
}).map((s) => ({
|
|
11734
11740
|
id: `sym:${s.id}`,
|
|
@@ -11742,7 +11748,7 @@ function buildSymbolGraphNodes(symById, relatedIds, fileFilter, packageOf) {
|
|
|
11742
11748
|
line: s.line,
|
|
11743
11749
|
signature: s.signature,
|
|
11744
11750
|
scope: s.scope,
|
|
11745
|
-
external: s.file
|
|
11751
|
+
external: !isLocal(s.file)
|
|
11746
11752
|
}));
|
|
11747
11753
|
}
|
|
11748
11754
|
function addWeightedEdge(edgeMap, source, target, callType, weight) {
|
|
@@ -11777,6 +11783,56 @@ function materializeWeightedEdges(edgeMap, idPrefix) {
|
|
|
11777
11783
|
return edges;
|
|
11778
11784
|
}
|
|
11779
11785
|
|
|
11786
|
+
// src/codebase-index/writer-helpers.ts
|
|
11787
|
+
import { resolveWstackPaths as resolveWstackPaths2 } from "@wrongstack/core/utils";
|
|
11788
|
+
function escapeLike(value) {
|
|
11789
|
+
return value.replace(/[\\%_]/g, (char) => `\\${char}`);
|
|
11790
|
+
}
|
|
11791
|
+
function posixIndexPath(file) {
|
|
11792
|
+
return file.replace(/\\/g, "/").replace(/^\.\//, "");
|
|
11793
|
+
}
|
|
11794
|
+
function indexedFileMatchSql(column = "file") {
|
|
11795
|
+
return `(${column} = ? OR replace(${column}, '\\', '/') = ? OR replace(${column}, '\\', '/') LIKE ? ESCAPE '\\')`;
|
|
11796
|
+
}
|
|
11797
|
+
function indexedFileMatchArgs(file) {
|
|
11798
|
+
const posix4 = posixIndexPath(file.trim());
|
|
11799
|
+
return [file, posix4, `%/${escapeLike(posix4)}`];
|
|
11800
|
+
}
|
|
11801
|
+
function matchesIndexedPackageFilter(storedFile, packageLabel, filter) {
|
|
11802
|
+
if (packageLabel === filter) return true;
|
|
11803
|
+
const posixFile = posixIndexPath(storedFile);
|
|
11804
|
+
const posixFilter = posixIndexPath(filter.trim());
|
|
11805
|
+
if (!posixFilter) return false;
|
|
11806
|
+
return posixFile === posixFilter || posixFile.endsWith(`/${posixFilter}`) || posixFile.includes(`/${posixFilter}/`);
|
|
11807
|
+
}
|
|
11808
|
+
function assignRefsToSymbols(refs, symbols) {
|
|
11809
|
+
if (refs.length === 0 || symbols.length === 0) return [];
|
|
11810
|
+
const ordered = [...symbols].sort((a, b) => a.line - b.line || a.col - b.col || a.id - b.id);
|
|
11811
|
+
const seen = /* @__PURE__ */ new Set();
|
|
11812
|
+
const assigned = [];
|
|
11813
|
+
for (const ref of refs) {
|
|
11814
|
+
let owner2;
|
|
11815
|
+
for (const symbol of ordered) {
|
|
11816
|
+
if (symbol.line > ref.line) break;
|
|
11817
|
+
owner2 = symbol;
|
|
11818
|
+
}
|
|
11819
|
+
if (!owner2 && ref.callType === "import") owner2 = ordered[0];
|
|
11820
|
+
if (!owner2 || owner2.id <= 0) continue;
|
|
11821
|
+
const key = `${owner2.id}:${ref.toName}:${ref.callType}:${ref.module ?? ""}`;
|
|
11822
|
+
if (seen.has(key)) continue;
|
|
11823
|
+
seen.add(key);
|
|
11824
|
+
assigned.push({ ...ref, fromId: owner2.id });
|
|
11825
|
+
}
|
|
11826
|
+
return assigned;
|
|
11827
|
+
}
|
|
11828
|
+
function resolveIndexDir(projectRoot, override) {
|
|
11829
|
+
return override ?? resolveWstackPaths2({ projectRoot }).projectCodebaseIndex;
|
|
11830
|
+
}
|
|
11831
|
+
function codebaseIndexDirOverride(ctx) {
|
|
11832
|
+
const v = ctx.meta?.["codebaseIndexDir"];
|
|
11833
|
+
return typeof v === "string" ? v : void 0;
|
|
11834
|
+
}
|
|
11835
|
+
|
|
11780
11836
|
// src/codebase-index/writer-ref-mapper.ts
|
|
11781
11837
|
function mapWriterRefRow(row) {
|
|
11782
11838
|
return {
|
|
@@ -11832,10 +11888,23 @@ function mapCallSiteRow(row) {
|
|
|
11832
11888
|
line: row.ref_line
|
|
11833
11889
|
};
|
|
11834
11890
|
}
|
|
11891
|
+
function resolveIndexedFiles(stmt, file) {
|
|
11892
|
+
const rows = stmt(
|
|
11893
|
+
`SELECT DISTINCT file FROM symbols WHERE ${indexedFileMatchSql("file")} ORDER BY length(file), file`
|
|
11894
|
+
).all(...indexedFileMatchArgs(file));
|
|
11895
|
+
return rows.map((row) => row.file);
|
|
11896
|
+
}
|
|
11835
11897
|
function resolveSymbolIds(stmt, symbolName, file) {
|
|
11836
|
-
|
|
11837
|
-
|
|
11838
|
-
|
|
11898
|
+
if (!file) {
|
|
11899
|
+
const rows2 = stmt("SELECT id FROM symbols WHERE name = ? ORDER BY id").all(symbolName);
|
|
11900
|
+
return rows2.map((r) => r.id);
|
|
11901
|
+
}
|
|
11902
|
+
const indexedFiles = resolveIndexedFiles(stmt, file);
|
|
11903
|
+
if (indexedFiles.length === 0) return [];
|
|
11904
|
+
const placeholders = indexedFiles.map(() => "?").join(",");
|
|
11905
|
+
const rows = stmt(
|
|
11906
|
+
`SELECT id FROM symbols WHERE name = ? AND file IN (${placeholders}) ORDER BY id`
|
|
11907
|
+
).all(symbolName, ...indexedFiles);
|
|
11839
11908
|
return rows.map((r) => r.id);
|
|
11840
11909
|
}
|
|
11841
11910
|
function findIncomingCallsByName(stmt, symbolName, file, limit) {
|
|
@@ -12157,7 +12226,7 @@ function getFileGraphWithStatement(stmt, packageFilter) {
|
|
|
12157
12226
|
const allFiles = stmt("SELECT DISTINCT file FROM symbols").all();
|
|
12158
12227
|
const packageOf = readPackageLabeller(stmt);
|
|
12159
12228
|
const langOf = (file) => detectLang(file) ?? "other";
|
|
12160
|
-
const pkgFilePaths = allFiles.filter((f) => packageOf(f.file)
|
|
12229
|
+
const pkgFilePaths = allFiles.filter((f) => matchesIndexedPackageFilter(f.file, packageOf(f.file), packageFilter)).map((f) => f.file);
|
|
12161
12230
|
const localFiles = new Set(pkgFilePaths);
|
|
12162
12231
|
if (localFiles.size === 0) return { nodes: [], edges: [] };
|
|
12163
12232
|
const filePlaceholders = [...localFiles].map(() => "?").join(",");
|
|
@@ -12233,9 +12302,12 @@ function getFileGraphWithStatement(stmt, packageFilter) {
|
|
|
12233
12302
|
return { nodes: [...fileNodes.values()], edges };
|
|
12234
12303
|
}
|
|
12235
12304
|
function getSymbolGraphWithStatement(stmt, fileFilter) {
|
|
12305
|
+
const indexedFiles = resolveIndexedFiles(stmt, fileFilter);
|
|
12306
|
+
if (indexedFiles.length === 0) return { nodes: [], edges: [] };
|
|
12307
|
+
const filePlaceholders = indexedFiles.map(() => "?").join(",");
|
|
12236
12308
|
const syms = stmt(
|
|
12237
|
-
|
|
12238
|
-
).all(
|
|
12309
|
+
`SELECT id, name, kind, lang, file, line, signature, scope FROM symbols WHERE file IN (${filePlaceholders}) ORDER BY line, id`
|
|
12310
|
+
).all(...indexedFiles);
|
|
12239
12311
|
if (syms.length === 0) return { nodes: [], edges: [] };
|
|
12240
12312
|
const symById = new Map(syms.map((symbol) => [symbol.id, symbol]));
|
|
12241
12313
|
const relatedIds = new Set(syms.map((symbol) => symbol.id));
|
|
@@ -12245,16 +12317,16 @@ function getSymbolGraphWithStatement(stmt, fileFilter) {
|
|
|
12245
12317
|
SELECT r.from_id, r.to_id, r.to_name, r.call_type, r.line
|
|
12246
12318
|
FROM refs r
|
|
12247
12319
|
JOIN symbols s ON s.id = r.from_id
|
|
12248
|
-
WHERE s.file
|
|
12320
|
+
WHERE s.file IN (${filePlaceholders})
|
|
12249
12321
|
UNION
|
|
12250
12322
|
SELECT r.from_id, r.to_id, r.to_name, r.call_type, r.line
|
|
12251
12323
|
FROM refs r
|
|
12252
12324
|
JOIN symbols s ON s.id = r.to_id
|
|
12253
|
-
WHERE s.file
|
|
12325
|
+
WHERE s.file IN (${filePlaceholders})
|
|
12254
12326
|
)
|
|
12255
12327
|
WHERE to_id IS NOT NULL
|
|
12256
12328
|
GROUP BY from_id, to_id, call_type`
|
|
12257
|
-
).all(
|
|
12329
|
+
).all(...indexedFiles, ...indexedFiles);
|
|
12258
12330
|
const edgeMap = /* @__PURE__ */ new Map();
|
|
12259
12331
|
for (const r of refRows) {
|
|
12260
12332
|
if (r.to_id == null) continue;
|
|
@@ -12273,43 +12345,15 @@ function getSymbolGraphWithStatement(stmt, fileFilter) {
|
|
|
12273
12345
|
).all(...missingIds);
|
|
12274
12346
|
for (const s of extras) symById.set(s.id, s);
|
|
12275
12347
|
}
|
|
12276
|
-
const nodes = buildSymbolGraphNodes(
|
|
12348
|
+
const nodes = buildSymbolGraphNodes(
|
|
12349
|
+
symById,
|
|
12350
|
+
relatedIds,
|
|
12351
|
+
new Set(syms.map((symbol) => symbol.file)),
|
|
12352
|
+
readPackageLabeller(stmt)
|
|
12353
|
+
);
|
|
12277
12354
|
return { nodes, edges };
|
|
12278
12355
|
}
|
|
12279
12356
|
|
|
12280
|
-
// src/codebase-index/writer-helpers.ts
|
|
12281
|
-
import { resolveWstackPaths as resolveWstackPaths2 } from "@wrongstack/core/utils";
|
|
12282
|
-
function escapeLike(value) {
|
|
12283
|
-
return value.replace(/[\\%_]/g, (char) => `\\${char}`);
|
|
12284
|
-
}
|
|
12285
|
-
function assignRefsToSymbols(refs, symbols) {
|
|
12286
|
-
if (refs.length === 0 || symbols.length === 0) return [];
|
|
12287
|
-
const ordered = [...symbols].sort((a, b) => a.line - b.line || a.col - b.col || a.id - b.id);
|
|
12288
|
-
const seen = /* @__PURE__ */ new Set();
|
|
12289
|
-
const assigned = [];
|
|
12290
|
-
for (const ref of refs) {
|
|
12291
|
-
let owner2;
|
|
12292
|
-
for (const symbol of ordered) {
|
|
12293
|
-
if (symbol.line > ref.line) break;
|
|
12294
|
-
owner2 = symbol;
|
|
12295
|
-
}
|
|
12296
|
-
if (!owner2 && ref.callType === "import") owner2 = ordered[0];
|
|
12297
|
-
if (!owner2 || owner2.id <= 0) continue;
|
|
12298
|
-
const key = `${owner2.id}:${ref.toName}:${ref.callType}:${ref.module ?? ""}`;
|
|
12299
|
-
if (seen.has(key)) continue;
|
|
12300
|
-
seen.add(key);
|
|
12301
|
-
assigned.push({ ...ref, fromId: owner2.id });
|
|
12302
|
-
}
|
|
12303
|
-
return assigned;
|
|
12304
|
-
}
|
|
12305
|
-
function resolveIndexDir(projectRoot, override) {
|
|
12306
|
-
return override ?? resolveWstackPaths2({ projectRoot }).projectCodebaseIndex;
|
|
12307
|
-
}
|
|
12308
|
-
function codebaseIndexDirOverride(ctx) {
|
|
12309
|
-
const v = ctx.meta?.["codebaseIndexDir"];
|
|
12310
|
-
return typeof v === "string" ? v : void 0;
|
|
12311
|
-
}
|
|
12312
|
-
|
|
12313
12357
|
// src/codebase-index/vector-search.ts
|
|
12314
12358
|
var RRF_K = 60;
|
|
12315
12359
|
var VECTOR_DIMENSIONS = 384;
|
|
@@ -13952,8 +13996,8 @@ function isProjectIndexServerHealth(value) {
|
|
|
13952
13996
|
return typeof health.checkedAt === "number" && typeof health.uptimeMs === "number" && typeof memory?.rss === "number" && typeof memory.heapUsed === "number" && typeof memory.heapTotal === "number" && typeof memory.external === "number" && typeof health.clients === "number" && typeof health.activeRequests === "number" && typeof health.activeWrites === "number" && typeof health.queuedWrites === "number" && typeof health.pendingExternalFiles === "number" && typeof health.watchingExternal === "boolean" && typeof activity?.indexing === "boolean" && typeof activity.currentFile === "number" && typeof activity.totalFiles === "number" && typeof activity.generation === "number";
|
|
13953
13997
|
}
|
|
13954
13998
|
function delay(ms) {
|
|
13955
|
-
return new Promise((
|
|
13956
|
-
const timer = setTimeout(
|
|
13999
|
+
return new Promise((resolve23) => {
|
|
14000
|
+
const timer = setTimeout(resolve23, ms);
|
|
13957
14001
|
timer.unref?.();
|
|
13958
14002
|
});
|
|
13959
14003
|
}
|
|
@@ -14159,7 +14203,7 @@ var ProjectServerConnection = class {
|
|
|
14159
14203
|
return Promise.reject(new Error("codebase-index server connection is not available"));
|
|
14160
14204
|
}
|
|
14161
14205
|
const id = this.nextId++;
|
|
14162
|
-
return new Promise((
|
|
14206
|
+
return new Promise((resolve23, reject) => {
|
|
14163
14207
|
const timer = setTimeout(() => {
|
|
14164
14208
|
const entry = this.pending.get(id);
|
|
14165
14209
|
if (!entry) return;
|
|
@@ -14182,7 +14226,7 @@ var ProjectServerConnection = class {
|
|
|
14182
14226
|
entry.reject(cancellationError(signal));
|
|
14183
14227
|
} : void 0;
|
|
14184
14228
|
this.pending.set(id, {
|
|
14185
|
-
resolve:
|
|
14229
|
+
resolve: resolve23,
|
|
14186
14230
|
reject,
|
|
14187
14231
|
timer,
|
|
14188
14232
|
signal,
|
|
@@ -14251,7 +14295,7 @@ var ProjectServerConnection = class {
|
|
|
14251
14295
|
this.binaryBuffer = [];
|
|
14252
14296
|
this.useBinary = false;
|
|
14253
14297
|
this.textDecoder = null;
|
|
14254
|
-
return new Promise((
|
|
14298
|
+
return new Promise((resolve23, reject) => {
|
|
14255
14299
|
const socket = net3.createConnection(this.endpoint);
|
|
14256
14300
|
this.socket = socket;
|
|
14257
14301
|
const timer = setTimeout(() => {
|
|
@@ -14263,7 +14307,7 @@ var ProjectServerConnection = class {
|
|
|
14263
14307
|
clearTimeout(timer);
|
|
14264
14308
|
this.connectResolve = null;
|
|
14265
14309
|
this.connectReject = null;
|
|
14266
|
-
|
|
14310
|
+
resolve23();
|
|
14267
14311
|
};
|
|
14268
14312
|
const finishReject = (error) => {
|
|
14269
14313
|
clearTimeout(timer);
|
|
@@ -15277,9 +15321,9 @@ var ParserWorkerPool = class {
|
|
|
15277
15321
|
for (let i = 0; i < files.length; i++) {
|
|
15278
15322
|
chunks[i % workerCount].push(files[i]);
|
|
15279
15323
|
}
|
|
15280
|
-
return new Promise((
|
|
15324
|
+
return new Promise((resolve23, reject) => {
|
|
15281
15325
|
this.pending.set(batchId, {
|
|
15282
|
-
resolve:
|
|
15326
|
+
resolve: resolve23,
|
|
15283
15327
|
reject,
|
|
15284
15328
|
accumulated: [],
|
|
15285
15329
|
expectedWorkers: workerCount,
|
|
@@ -15310,10 +15354,10 @@ var ParserWorkerPool = class {
|
|
|
15310
15354
|
await Promise.allSettled(
|
|
15311
15355
|
workers.map(
|
|
15312
15356
|
(w) => Promise.race([
|
|
15313
|
-
new Promise((
|
|
15314
|
-
w.once("exit", () =>
|
|
15357
|
+
new Promise((resolve23) => {
|
|
15358
|
+
w.once("exit", () => resolve23());
|
|
15315
15359
|
}),
|
|
15316
|
-
new Promise((
|
|
15360
|
+
new Promise((resolve23) => setTimeout(() => resolve23(), 2e3))
|
|
15317
15361
|
]).then(() => {
|
|
15318
15362
|
if (!w.threadId) return;
|
|
15319
15363
|
return w.terminate().catch(() => {
|
|
@@ -15374,7 +15418,7 @@ function shouldUseParserWorkerPool(candidateFileCount, parseBatchCount) {
|
|
|
15374
15418
|
return !isFrugalPerf() && candidateFileCount >= WORKER_POOL_THRESHOLD && parseBatchCount > 1;
|
|
15375
15419
|
}
|
|
15376
15420
|
function yieldEventLoop() {
|
|
15377
|
-
return new Promise((
|
|
15421
|
+
return new Promise((resolve23) => setImmediate(resolve23));
|
|
15378
15422
|
}
|
|
15379
15423
|
function throwIfAborted(signal) {
|
|
15380
15424
|
if (!signal?.aborted) return;
|
|
@@ -15406,7 +15450,7 @@ function normalizeComparablePath(value) {
|
|
|
15406
15450
|
return process.platform === "win32" ? resolved.toLowerCase() : resolved;
|
|
15407
15451
|
}
|
|
15408
15452
|
function gitOutput(projectRoot, args) {
|
|
15409
|
-
return new Promise((
|
|
15453
|
+
return new Promise((resolve23, reject) => {
|
|
15410
15454
|
execFile(
|
|
15411
15455
|
"git",
|
|
15412
15456
|
["-C", projectRoot, ...args],
|
|
@@ -15417,7 +15461,7 @@ function gitOutput(projectRoot, args) {
|
|
|
15417
15461
|
},
|
|
15418
15462
|
(error, stdout) => {
|
|
15419
15463
|
if (error) reject(error);
|
|
15420
|
-
else
|
|
15464
|
+
else resolve23(Buffer.isBuffer(stdout) ? stdout : Buffer.from(stdout));
|
|
15421
15465
|
}
|
|
15422
15466
|
);
|
|
15423
15467
|
});
|
|
@@ -16193,7 +16237,7 @@ function callIndexOp(op, args, opts) {
|
|
|
16193
16237
|
opts.signal.reason instanceof Error ? opts.signal.reason : new Error("Indexing cancelled")
|
|
16194
16238
|
);
|
|
16195
16239
|
}
|
|
16196
|
-
return new Promise((
|
|
16240
|
+
return new Promise((resolve23, reject) => {
|
|
16197
16241
|
const id = nextRpcId++;
|
|
16198
16242
|
const timer = setTimeout(() => {
|
|
16199
16243
|
pending.delete(id);
|
|
@@ -16215,7 +16259,7 @@ function callIndexOp(op, args, opts) {
|
|
|
16215
16259
|
pending.set(id, {
|
|
16216
16260
|
resolve: (v) => {
|
|
16217
16261
|
cleanup();
|
|
16218
|
-
|
|
16262
|
+
resolve23(v);
|
|
16219
16263
|
},
|
|
16220
16264
|
reject: (e) => {
|
|
16221
16265
|
cleanup();
|
|
@@ -17142,9 +17186,90 @@ var codebaseAstReplaceTool = {
|
|
|
17142
17186
|
}
|
|
17143
17187
|
};
|
|
17144
17188
|
|
|
17145
|
-
// src/codebase-index/codebase-
|
|
17189
|
+
// src/codebase-index/codebase-invariant-check-tool.ts
|
|
17190
|
+
import * as fs22 from "node:fs/promises";
|
|
17146
17191
|
import * as path27 from "node:path";
|
|
17147
17192
|
import { toErrorMessage as toErrorMessage4 } from "@wrongstack/core/utils";
|
|
17193
|
+
init_languages2();
|
|
17194
|
+
var codebaseInvariantCheckTool = {
|
|
17195
|
+
name: "codebase-invariant-check",
|
|
17196
|
+
category: "Inspect",
|
|
17197
|
+
icon: "index",
|
|
17198
|
+
permission: "auto",
|
|
17199
|
+
subjectKey: "file",
|
|
17200
|
+
mutating: false,
|
|
17201
|
+
capabilities: ["fs.read"],
|
|
17202
|
+
description: "Mathematically verify AST backward-compatibility invariants between original code and candidate mutations across TypeScript, Python, Go, Rust, Java, etc. Detects missing exports (INV-001), mandatory parameter additions (INV-002), interface breaking expansions (INV-003), and return type changes (INV-004) with zero hallucinations.",
|
|
17203
|
+
usageHint: "PRE-FLIGHT AST INVARIANT AUDIT:\n\n- Provide `file` and `modifiedCode` (or both `originalCode` and `modifiedCode`).\n- Returns `valid: true` if changes are strictly backward compatible.\n- Returns structured `violations[]` with exact rule IDs, offending symbol names, and fix instructions.",
|
|
17204
|
+
inputSchema: {
|
|
17205
|
+
type: "object",
|
|
17206
|
+
properties: {
|
|
17207
|
+
file: {
|
|
17208
|
+
type: "string",
|
|
17209
|
+
description: "Path to existing source file to compare against candidate modifications."
|
|
17210
|
+
},
|
|
17211
|
+
originalCode: {
|
|
17212
|
+
type: "string",
|
|
17213
|
+
description: "Original source code string (if not reading from an existing file)."
|
|
17214
|
+
},
|
|
17215
|
+
modifiedCode: {
|
|
17216
|
+
type: "string",
|
|
17217
|
+
description: "The candidate modified code string to validate."
|
|
17218
|
+
},
|
|
17219
|
+
lang: {
|
|
17220
|
+
type: "string",
|
|
17221
|
+
description: "Language hint (ts, py, go, rs, etc.). Inferred from file path if omitted."
|
|
17222
|
+
}
|
|
17223
|
+
},
|
|
17224
|
+
required: ["modifiedCode"],
|
|
17225
|
+
additionalProperties: false
|
|
17226
|
+
},
|
|
17227
|
+
async execute(input, ctx) {
|
|
17228
|
+
try {
|
|
17229
|
+
let originalCode = input.originalCode;
|
|
17230
|
+
let lang = input.lang;
|
|
17231
|
+
if (!originalCode && input.file) {
|
|
17232
|
+
const resolved = path27.isAbsolute(input.file) ? input.file : path27.resolve(ctx.projectRoot, input.file);
|
|
17233
|
+
originalCode = await fs22.readFile(resolved, "utf8");
|
|
17234
|
+
if (!lang) {
|
|
17235
|
+
lang = detectLang(resolved) ?? "ts";
|
|
17236
|
+
}
|
|
17237
|
+
}
|
|
17238
|
+
if (originalCode === void 0) {
|
|
17239
|
+
return {
|
|
17240
|
+
valid: false,
|
|
17241
|
+
violations: [],
|
|
17242
|
+
summary: "Neither originalCode nor file was provided for invariant comparison.",
|
|
17243
|
+
error: "Missing originalCode or file path."
|
|
17244
|
+
};
|
|
17245
|
+
}
|
|
17246
|
+
const res = await polyglotInvariantEngine.evaluate({
|
|
17247
|
+
originalCode,
|
|
17248
|
+
modifiedCode: input.modifiedCode,
|
|
17249
|
+
lang,
|
|
17250
|
+
filePath: input.file
|
|
17251
|
+
});
|
|
17252
|
+
const summary = res.valid ? "AST Invariants PASSED. Mutation is 100% backward compatible." : `AST Invariants FAILED with ${res.violations.length} violation(s):
|
|
17253
|
+
` + res.violations.map((v) => ` - [${v.ruleId}] ${v.symbolName}: ${v.message}`).join("\n");
|
|
17254
|
+
return {
|
|
17255
|
+
valid: res.valid,
|
|
17256
|
+
violations: res.violations,
|
|
17257
|
+
summary
|
|
17258
|
+
};
|
|
17259
|
+
} catch (err) {
|
|
17260
|
+
return {
|
|
17261
|
+
valid: false,
|
|
17262
|
+
violations: [],
|
|
17263
|
+
summary: `Error during invariant evaluation: ${toErrorMessage4(err)}`,
|
|
17264
|
+
error: toErrorMessage4(err)
|
|
17265
|
+
};
|
|
17266
|
+
}
|
|
17267
|
+
}
|
|
17268
|
+
};
|
|
17269
|
+
|
|
17270
|
+
// src/codebase-index/codebase-impact-analysis-tool.ts
|
|
17271
|
+
import * as path28 from "node:path";
|
|
17272
|
+
import { toErrorMessage as toErrorMessage5 } from "@wrongstack/core/utils";
|
|
17148
17273
|
var TEST_FILE_REGEX = /(?:test|spec|mock|fixture|bench)[s]?[/\\._]/i;
|
|
17149
17274
|
var codebaseImpactAnalysisTool = {
|
|
17150
17275
|
name: "codebase-impact-analysis",
|
|
@@ -17181,6 +17306,9 @@ var codebaseImpactAnalysisTool = {
|
|
|
17181
17306
|
const limit = 200;
|
|
17182
17307
|
const transitive = input.transitive ?? true;
|
|
17183
17308
|
let rawSites = [];
|
|
17309
|
+
let symbolFound = true;
|
|
17310
|
+
let indexUnavailable = false;
|
|
17311
|
+
let indexError;
|
|
17184
17312
|
try {
|
|
17185
17313
|
const serviced = await incomingCallsService2({
|
|
17186
17314
|
projectRoot,
|
|
@@ -17191,13 +17319,49 @@ var codebaseImpactAnalysisTool = {
|
|
|
17191
17319
|
transitive
|
|
17192
17320
|
});
|
|
17193
17321
|
rawSites = serviced.calls;
|
|
17194
|
-
|
|
17322
|
+
symbolFound = serviced.symbolFound;
|
|
17323
|
+
} catch (err) {
|
|
17324
|
+
symbolFound = false;
|
|
17325
|
+
indexUnavailable = true;
|
|
17326
|
+
indexError = toErrorMessage5(err);
|
|
17327
|
+
}
|
|
17328
|
+
if (indexUnavailable) {
|
|
17329
|
+
const detail = indexError ? ` (${indexError})` : "";
|
|
17330
|
+
const reason = `Index query failed for '${input.symbol}'. Run codebase-index, then retry.${detail}`;
|
|
17331
|
+
return {
|
|
17332
|
+
status: "error",
|
|
17333
|
+
symbol: input.symbol,
|
|
17334
|
+
riskLevel: "low",
|
|
17335
|
+
summary: reason,
|
|
17336
|
+
totalCallSites: 0,
|
|
17337
|
+
affectedProductionFiles: [],
|
|
17338
|
+
affectedTestFiles: [],
|
|
17339
|
+
callSites: [],
|
|
17340
|
+
recommendedActionPlan: [reason],
|
|
17341
|
+
symbolFound: false,
|
|
17342
|
+
error: reason
|
|
17343
|
+
};
|
|
17344
|
+
}
|
|
17345
|
+
if (!symbolFound) {
|
|
17346
|
+
const reason = `Symbol '${input.symbol}' was not found in the index` + (input.file ? ` for file filter '${input.file}'` : "") + ". Use codebase-search to verify the name.";
|
|
17347
|
+
return {
|
|
17348
|
+
status: "ok",
|
|
17349
|
+
symbol: input.symbol,
|
|
17350
|
+
riskLevel: "low",
|
|
17351
|
+
summary: reason,
|
|
17352
|
+
totalCallSites: 0,
|
|
17353
|
+
affectedProductionFiles: [],
|
|
17354
|
+
affectedTestFiles: [],
|
|
17355
|
+
callSites: [],
|
|
17356
|
+
recommendedActionPlan: [reason],
|
|
17357
|
+
symbolFound: false
|
|
17358
|
+
};
|
|
17195
17359
|
}
|
|
17196
17360
|
const prodFilesSet = /* @__PURE__ */ new Set();
|
|
17197
17361
|
const testFilesSet = /* @__PURE__ */ new Set();
|
|
17198
17362
|
const callSites = [];
|
|
17199
17363
|
for (const site of rawSites) {
|
|
17200
|
-
const relPath =
|
|
17364
|
+
const relPath = path28.relative(projectRoot, site.symbol.file).replace(/\\/g, "/");
|
|
17201
17365
|
const isTest = TEST_FILE_REGEX.test(relPath);
|
|
17202
17366
|
if (isTest) {
|
|
17203
17367
|
testFilesSet.add(relPath);
|
|
@@ -17247,7 +17411,8 @@ var codebaseImpactAnalysisTool = {
|
|
|
17247
17411
|
affectedProductionFiles: prodFiles,
|
|
17248
17412
|
affectedTestFiles: testFiles,
|
|
17249
17413
|
callSites,
|
|
17250
|
-
recommendedActionPlan
|
|
17414
|
+
recommendedActionPlan,
|
|
17415
|
+
symbolFound: true
|
|
17251
17416
|
};
|
|
17252
17417
|
} catch (err) {
|
|
17253
17418
|
return {
|
|
@@ -17260,14 +17425,15 @@ var codebaseImpactAnalysisTool = {
|
|
|
17260
17425
|
affectedTestFiles: [],
|
|
17261
17426
|
callSites: [],
|
|
17262
17427
|
recommendedActionPlan: [],
|
|
17263
|
-
|
|
17428
|
+
symbolFound: false,
|
|
17429
|
+
error: toErrorMessage5(err)
|
|
17264
17430
|
};
|
|
17265
17431
|
}
|
|
17266
17432
|
}
|
|
17267
17433
|
};
|
|
17268
17434
|
|
|
17269
17435
|
// src/codebase-index/codebase-incoming-calls-tool.ts
|
|
17270
|
-
import { toErrorMessage as
|
|
17436
|
+
import { toErrorMessage as toErrorMessage6 } from "@wrongstack/core/utils";
|
|
17271
17437
|
var codebaseIncomingCallsTool = {
|
|
17272
17438
|
name: "codebase-incoming-calls",
|
|
17273
17439
|
category: "Project",
|
|
@@ -17340,7 +17506,7 @@ var codebaseIncomingCallsTool = {
|
|
|
17340
17506
|
symbol: input.symbol,
|
|
17341
17507
|
calls: [],
|
|
17342
17508
|
total: 0,
|
|
17343
|
-
indexStatus: `Index query failed: ${
|
|
17509
|
+
indexStatus: `Index query failed: ${toErrorMessage6(err)}. Fall back to grep for this lookup.`
|
|
17344
17510
|
};
|
|
17345
17511
|
}
|
|
17346
17512
|
const { calls, symbolFound, ambiguous, totalMatches } = serviced;
|
|
@@ -17395,7 +17561,7 @@ var codebaseIncomingCallsTool = {
|
|
|
17395
17561
|
import { ToolValidationError } from "@wrongstack/core/types";
|
|
17396
17562
|
|
|
17397
17563
|
// src/codebase-index/codebase-search-tool.ts
|
|
17398
|
-
import { toErrorMessage as
|
|
17564
|
+
import { toErrorMessage as toErrorMessage7 } from "@wrongstack/core/utils";
|
|
17399
17565
|
var INDEXABLE_LANG_IDS = [
|
|
17400
17566
|
"ts",
|
|
17401
17567
|
"tsx",
|
|
@@ -17520,7 +17686,7 @@ var codebaseSearchTool = {
|
|
|
17520
17686
|
results: [],
|
|
17521
17687
|
total: 0,
|
|
17522
17688
|
query: input.query,
|
|
17523
|
-
indexStatus: `Index query failed: ${
|
|
17689
|
+
indexStatus: `Index query failed: ${toErrorMessage7(err)}. Fall back to grep/glob for this lookup.`
|
|
17524
17690
|
};
|
|
17525
17691
|
}
|
|
17526
17692
|
const { results, total } = searched;
|
|
@@ -17628,7 +17794,7 @@ var codebaseIndexTool = {
|
|
|
17628
17794
|
};
|
|
17629
17795
|
|
|
17630
17796
|
// src/codebase-index/codebase-outgoing-calls-tool.ts
|
|
17631
|
-
import { toErrorMessage as
|
|
17797
|
+
import { toErrorMessage as toErrorMessage8 } from "@wrongstack/core/utils";
|
|
17632
17798
|
var codebaseOutgoingCallsTool = {
|
|
17633
17799
|
name: "codebase-outgoing-calls",
|
|
17634
17800
|
category: "Project",
|
|
@@ -17701,7 +17867,7 @@ var codebaseOutgoingCallsTool = {
|
|
|
17701
17867
|
symbol: input.symbol,
|
|
17702
17868
|
calls: [],
|
|
17703
17869
|
total: 0,
|
|
17704
|
-
indexStatus: `Index query failed: ${
|
|
17870
|
+
indexStatus: `Index query failed: ${toErrorMessage8(err)}. Fall back to grep for this lookup.`
|
|
17705
17871
|
};
|
|
17706
17872
|
}
|
|
17707
17873
|
const { calls, symbolFound, unresolvedCount, totalMatches } = serviced;
|
|
@@ -17753,18 +17919,18 @@ var codebaseOutgoingCallsTool = {
|
|
|
17753
17919
|
};
|
|
17754
17920
|
|
|
17755
17921
|
// src/codebase-index/codebase-repo-map-tool.ts
|
|
17756
|
-
import { toErrorMessage as
|
|
17922
|
+
import { toErrorMessage as toErrorMessage9 } from "@wrongstack/core/utils";
|
|
17757
17923
|
|
|
17758
17924
|
// src/codebase-index/repo-map.ts
|
|
17759
17925
|
init_languages2();
|
|
17760
|
-
import * as
|
|
17761
|
-
import * as
|
|
17926
|
+
import * as fs24 from "node:fs/promises";
|
|
17927
|
+
import * as path30 from "node:path";
|
|
17762
17928
|
|
|
17763
17929
|
// src/codebase-index/skeleton-extractor.ts
|
|
17764
17930
|
init_languages2();
|
|
17765
17931
|
init_tree_sitter_parser();
|
|
17766
|
-
import * as
|
|
17767
|
-
import * as
|
|
17932
|
+
import * as fs23 from "node:fs/promises";
|
|
17933
|
+
import * as path29 from "node:path";
|
|
17768
17934
|
var tsModule3 = null;
|
|
17769
17935
|
async function loadTs3() {
|
|
17770
17936
|
if (!tsModule3) {
|
|
@@ -18092,7 +18258,7 @@ async function extractDirectorySkeleton(opts) {
|
|
|
18092
18258
|
if (filePaths.length >= maxFiles) return;
|
|
18093
18259
|
let entries;
|
|
18094
18260
|
try {
|
|
18095
|
-
entries = await
|
|
18261
|
+
entries = await fs23.readdir(dir, { withFileTypes: true });
|
|
18096
18262
|
} catch {
|
|
18097
18263
|
return;
|
|
18098
18264
|
}
|
|
@@ -18101,7 +18267,7 @@ async function extractDirectorySkeleton(opts) {
|
|
|
18101
18267
|
if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.name === "dist" || entry.name === "build") {
|
|
18102
18268
|
continue;
|
|
18103
18269
|
}
|
|
18104
|
-
const fullPath =
|
|
18270
|
+
const fullPath = path29.join(dir, entry.name);
|
|
18105
18271
|
if (entry.isDirectory()) {
|
|
18106
18272
|
await scan(fullPath);
|
|
18107
18273
|
} else if (entry.isFile() && isIndexablePath(fullPath)) {
|
|
@@ -18118,7 +18284,7 @@ async function extractDirectorySkeleton(opts) {
|
|
|
18118
18284
|
const combinedParts = [];
|
|
18119
18285
|
for (const fp of filePaths) {
|
|
18120
18286
|
try {
|
|
18121
|
-
const content = await
|
|
18287
|
+
const content = await fs23.readFile(fp, "utf8");
|
|
18122
18288
|
const res = await extractFileSkeleton({
|
|
18123
18289
|
file: fp,
|
|
18124
18290
|
content,
|
|
@@ -18129,7 +18295,7 @@ async function extractDirectorySkeleton(opts) {
|
|
|
18129
18295
|
totalSkelChars += res.skeleton.length;
|
|
18130
18296
|
totalOrigLines += res.stats.originalLines;
|
|
18131
18297
|
totalSkelLines += res.stats.skeletonLines;
|
|
18132
|
-
const rel =
|
|
18298
|
+
const rel = path29.relative(opts.dirPath, fp).replace(/\\/g, "/");
|
|
18133
18299
|
combinedParts.push(
|
|
18134
18300
|
`// \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 ${rel} (${res.lang}) \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550
|
|
18135
18301
|
${res.skeleton}`
|
|
@@ -18166,13 +18332,13 @@ async function generateRepoMap(opts) {
|
|
|
18166
18332
|
const projectRoot = opts.projectRoot;
|
|
18167
18333
|
const maxTokens = opts.maxTokens ?? 1200;
|
|
18168
18334
|
const charBudget = maxTokens * 4;
|
|
18169
|
-
const focusSet = new Set((opts.focusFiles ?? []).map((f) =>
|
|
18335
|
+
const focusSet = new Set((opts.focusFiles ?? []).map((f) => path30.resolve(projectRoot, f)));
|
|
18170
18336
|
const allFiles = [];
|
|
18171
18337
|
async function scan(dir) {
|
|
18172
18338
|
if (allFiles.length > 500) return;
|
|
18173
18339
|
let entries;
|
|
18174
18340
|
try {
|
|
18175
|
-
entries = await
|
|
18341
|
+
entries = await fs24.readdir(dir, { withFileTypes: true });
|
|
18176
18342
|
} catch {
|
|
18177
18343
|
return;
|
|
18178
18344
|
}
|
|
@@ -18180,7 +18346,7 @@ async function generateRepoMap(opts) {
|
|
|
18180
18346
|
if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.name === "dist" || entry.name === "build" || entry.name === "coverage") {
|
|
18181
18347
|
continue;
|
|
18182
18348
|
}
|
|
18183
|
-
const fullPath =
|
|
18349
|
+
const fullPath = path30.join(dir, entry.name);
|
|
18184
18350
|
if (entry.isDirectory()) {
|
|
18185
18351
|
await scan(fullPath);
|
|
18186
18352
|
} else if (entry.isFile() && isIndexablePath(fullPath)) {
|
|
@@ -18200,7 +18366,7 @@ async function generateRepoMap(opts) {
|
|
|
18200
18366
|
}
|
|
18201
18367
|
const scoredFiles = [];
|
|
18202
18368
|
for (const file of allFiles) {
|
|
18203
|
-
const relPath =
|
|
18369
|
+
const relPath = path30.relative(projectRoot, file).replace(/\\/g, "/");
|
|
18204
18370
|
let score = 10;
|
|
18205
18371
|
if (focusSet.has(file)) {
|
|
18206
18372
|
score += 100;
|
|
@@ -18215,7 +18381,7 @@ async function generateRepoMap(opts) {
|
|
|
18215
18381
|
for (const candidate of scoredFiles) {
|
|
18216
18382
|
if (currentChars >= charBudget) break;
|
|
18217
18383
|
try {
|
|
18218
|
-
const content = await
|
|
18384
|
+
const content = await fs24.readFile(candidate.file, "utf8");
|
|
18219
18385
|
if (content.length === 0) continue;
|
|
18220
18386
|
const skeletonResult = await extractFileSkeleton({
|
|
18221
18387
|
file: candidate.file,
|
|
@@ -18298,16 +18464,16 @@ var codebaseRepoMapTool = {
|
|
|
18298
18464
|
totalFilesScanned: 0,
|
|
18299
18465
|
estimatedTokens: 0,
|
|
18300
18466
|
rankedFiles: [],
|
|
18301
|
-
error:
|
|
18467
|
+
error: toErrorMessage9(err)
|
|
18302
18468
|
};
|
|
18303
18469
|
}
|
|
18304
18470
|
}
|
|
18305
18471
|
};
|
|
18306
18472
|
|
|
18307
18473
|
// src/codebase-index/codebase-skeleton-tool.ts
|
|
18308
|
-
import * as
|
|
18309
|
-
import * as
|
|
18310
|
-
import { toErrorMessage as
|
|
18474
|
+
import * as fs25 from "node:fs/promises";
|
|
18475
|
+
import * as path31 from "node:path";
|
|
18476
|
+
import { toErrorMessage as toErrorMessage10 } from "@wrongstack/core/utils";
|
|
18311
18477
|
var codebaseSkeletonTool = {
|
|
18312
18478
|
name: "codebase-skeleton",
|
|
18313
18479
|
category: "Project",
|
|
@@ -18346,13 +18512,13 @@ var codebaseSkeletonTool = {
|
|
|
18346
18512
|
additionalProperties: false
|
|
18347
18513
|
},
|
|
18348
18514
|
async execute(input, ctx) {
|
|
18349
|
-
const targetPath =
|
|
18515
|
+
const targetPath = path31.isAbsolute(input.path) ? input.path : path31.resolve(ctx.projectRoot ?? process.cwd(), input.path);
|
|
18350
18516
|
let stat21;
|
|
18351
18517
|
try {
|
|
18352
|
-
stat21 = await
|
|
18518
|
+
stat21 = await fs25.stat(targetPath);
|
|
18353
18519
|
} catch (err) {
|
|
18354
18520
|
throw new Error(
|
|
18355
|
-
`codebase-skeleton: file or directory not found at "${input.path}": ${
|
|
18521
|
+
`codebase-skeleton: file or directory not found at "${input.path}": ${toErrorMessage10(err)}`
|
|
18356
18522
|
);
|
|
18357
18523
|
}
|
|
18358
18524
|
const options = {
|
|
@@ -18385,7 +18551,7 @@ var codebaseSkeletonTool = {
|
|
|
18385
18551
|
files: dirResult.files
|
|
18386
18552
|
};
|
|
18387
18553
|
}
|
|
18388
|
-
const content = await
|
|
18554
|
+
const content = await fs25.readFile(targetPath, "utf8");
|
|
18389
18555
|
const fileResult = await extractFileSkeleton({
|
|
18390
18556
|
file: targetPath,
|
|
18391
18557
|
content,
|
|
@@ -18489,28 +18655,28 @@ var codebaseStatsTool = {
|
|
|
18489
18655
|
// src/codebase-index/codebase-targeted-test-tool.ts
|
|
18490
18656
|
init_spawn_stream();
|
|
18491
18657
|
init_util();
|
|
18492
|
-
import * as
|
|
18493
|
-
import * as
|
|
18494
|
-
import { toErrorMessage as
|
|
18658
|
+
import * as fs26 from "node:fs/promises";
|
|
18659
|
+
import * as path32 from "node:path";
|
|
18660
|
+
import { toErrorMessage as toErrorMessage11 } from "@wrongstack/core/utils";
|
|
18495
18661
|
var TEST_FILE_REGEX2 = /(?:test|spec|mock|fixture|bench)[s]?[/\\._]/i;
|
|
18496
18662
|
async function findConventionTestFiles(projectRoot, sourceRelPath) {
|
|
18497
|
-
const parsed =
|
|
18663
|
+
const parsed = path32.parse(sourceRelPath);
|
|
18498
18664
|
const candidates = [
|
|
18499
|
-
|
|
18500
|
-
|
|
18501
|
-
|
|
18502
|
-
|
|
18503
|
-
|
|
18504
|
-
|
|
18505
|
-
|
|
18506
|
-
|
|
18507
|
-
|
|
18665
|
+
path32.join(parsed.dir, `${parsed.name}.test${parsed.ext}`),
|
|
18666
|
+
path32.join(parsed.dir, `${parsed.name}.spec${parsed.ext}`),
|
|
18667
|
+
path32.join(parsed.dir, `${parsed.name}_test${parsed.ext}`),
|
|
18668
|
+
path32.join(parsed.dir, `test_${parsed.name}${parsed.ext}`),
|
|
18669
|
+
path32.join("tests", `${parsed.name}.test${parsed.ext}`),
|
|
18670
|
+
path32.join("tests", `${parsed.name}.spec${parsed.ext}`),
|
|
18671
|
+
path32.join("test", `${parsed.name}.test${parsed.ext}`),
|
|
18672
|
+
path32.join(parsed.dir, "__tests__", `${parsed.name}.test${parsed.ext}`),
|
|
18673
|
+
path32.join(parsed.dir, "__tests__", `${parsed.name}${parsed.ext}`)
|
|
18508
18674
|
];
|
|
18509
18675
|
const found = [];
|
|
18510
18676
|
for (const cand of candidates) {
|
|
18511
|
-
const absPath =
|
|
18677
|
+
const absPath = path32.resolve(projectRoot, cand);
|
|
18512
18678
|
try {
|
|
18513
|
-
const st = await
|
|
18679
|
+
const st = await fs26.stat(absPath);
|
|
18514
18680
|
if (st.isFile()) {
|
|
18515
18681
|
found.push(cand.replace(/\\/g, "/"));
|
|
18516
18682
|
}
|
|
@@ -18567,7 +18733,7 @@ var codebaseTargetedTestTool = {
|
|
|
18567
18733
|
transitive: true
|
|
18568
18734
|
});
|
|
18569
18735
|
for (const site of serviced.calls) {
|
|
18570
|
-
const relPath =
|
|
18736
|
+
const relPath = path32.relative(projectRoot, site.symbol.file).replace(/\\/g, "/");
|
|
18571
18737
|
if (TEST_FILE_REGEX2.test(relPath)) {
|
|
18572
18738
|
suitesSet.add(relPath);
|
|
18573
18739
|
}
|
|
@@ -18644,7 +18810,7 @@ ${streamRes.stderr}`.trim(),
|
|
|
18644
18810
|
failed: 0,
|
|
18645
18811
|
durationMs: 0,
|
|
18646
18812
|
output: "",
|
|
18647
|
-
error:
|
|
18813
|
+
error: toErrorMessage11(err)
|
|
18648
18814
|
};
|
|
18649
18815
|
}
|
|
18650
18816
|
}
|
|
@@ -18652,8 +18818,8 @@ ${streamRes.stderr}`.trim(),
|
|
|
18652
18818
|
|
|
18653
18819
|
// src/codebase-index/dead-code-scan.ts
|
|
18654
18820
|
init_languages2();
|
|
18655
|
-
import * as
|
|
18656
|
-
import * as
|
|
18821
|
+
import * as fs27 from "node:fs";
|
|
18822
|
+
import * as path33 from "node:path";
|
|
18657
18823
|
var deadCodeScanTool = {
|
|
18658
18824
|
name: "dead-code-scan",
|
|
18659
18825
|
category: "Project",
|
|
@@ -18698,25 +18864,25 @@ var deadCodeScanTool = {
|
|
|
18698
18864
|
};
|
|
18699
18865
|
function tryReadJson(filePath) {
|
|
18700
18866
|
try {
|
|
18701
|
-
const raw =
|
|
18867
|
+
const raw = fs27.readFileSync(filePath, "utf8");
|
|
18702
18868
|
return JSON.parse(raw);
|
|
18703
18869
|
} catch {
|
|
18704
18870
|
return null;
|
|
18705
18871
|
}
|
|
18706
18872
|
}
|
|
18707
18873
|
function resolveAgainst(base, relative19) {
|
|
18708
|
-
if (
|
|
18709
|
-
return
|
|
18874
|
+
if (path33.isAbsolute(relative19)) return relative19;
|
|
18875
|
+
return path33.resolve(base, relative19);
|
|
18710
18876
|
}
|
|
18711
18877
|
function discoverEntryPoints(projectRoot, userEntryPoints) {
|
|
18712
18878
|
const entries = /* @__PURE__ */ new Set();
|
|
18713
18879
|
if (userEntryPoints) {
|
|
18714
18880
|
for (const ep of userEntryPoints) {
|
|
18715
18881
|
const resolved = resolveAgainst(projectRoot, ep);
|
|
18716
|
-
if (
|
|
18882
|
+
if (fs27.existsSync(resolved)) entries.add(resolved);
|
|
18717
18883
|
}
|
|
18718
18884
|
}
|
|
18719
|
-
const rootPkg = tryReadJson(
|
|
18885
|
+
const rootPkg = tryReadJson(path33.join(projectRoot, "package.json"));
|
|
18720
18886
|
if (rootPkg) {
|
|
18721
18887
|
addPkgJsonEntryPoints(projectRoot, rootPkg, entries);
|
|
18722
18888
|
}
|
|
@@ -18730,45 +18896,45 @@ function discoverEntryPoints(projectRoot, userEntryPoints) {
|
|
|
18730
18896
|
workspaces = [];
|
|
18731
18897
|
}
|
|
18732
18898
|
for (const wsDir of workspaces) {
|
|
18733
|
-
const pkgJsonPath =
|
|
18899
|
+
const pkgJsonPath = path33.join(wsDir, "package.json");
|
|
18734
18900
|
const pkg = tryReadJson(pkgJsonPath);
|
|
18735
18901
|
if (pkg) {
|
|
18736
18902
|
addPkgJsonEntryPoints(wsDir, pkg, entries);
|
|
18737
|
-
const convention1 =
|
|
18738
|
-
if (
|
|
18739
|
-
const convention2 =
|
|
18740
|
-
if (
|
|
18741
|
-
const convention3 =
|
|
18742
|
-
if (
|
|
18903
|
+
const convention1 = path33.join(wsDir, "src", "index.ts");
|
|
18904
|
+
if (fs27.existsSync(convention1)) entries.add(convention1);
|
|
18905
|
+
const convention2 = path33.join(wsDir, "src", "main.ts");
|
|
18906
|
+
if (fs27.existsSync(convention2)) entries.add(convention2);
|
|
18907
|
+
const convention3 = path33.join(wsDir, "index.ts");
|
|
18908
|
+
if (fs27.existsSync(convention3)) entries.add(convention3);
|
|
18743
18909
|
}
|
|
18744
18910
|
}
|
|
18745
18911
|
if (!rootPkg || !workspaces.length) {
|
|
18746
18912
|
for (const name of ["src/index.ts", "src/main.ts", "index.ts"]) {
|
|
18747
|
-
const convention =
|
|
18748
|
-
if (
|
|
18913
|
+
const convention = path33.join(projectRoot, name);
|
|
18914
|
+
if (fs27.existsSync(convention)) entries.add(convention);
|
|
18749
18915
|
}
|
|
18750
18916
|
}
|
|
18751
18917
|
return [...entries];
|
|
18752
18918
|
}
|
|
18753
18919
|
var BUILD_OUTPUT_DIRS = ["dist", "out", "build", "release"];
|
|
18754
|
-
var BUILD_OUTPUT_DIR_NAMES = BUILD_OUTPUT_DIRS.map((d) => `${
|
|
18920
|
+
var BUILD_OUTPUT_DIR_NAMES = BUILD_OUTPUT_DIRS.map((d) => `${path33.sep}${d}${path33.sep}`);
|
|
18755
18921
|
function trySourceEquivalent(resolved) {
|
|
18756
|
-
resolved = resolved.replace(/[/\\]/g,
|
|
18922
|
+
resolved = resolved.replace(/[/\\]/g, path33.sep);
|
|
18757
18923
|
for (const marker of BUILD_OUTPUT_DIR_NAMES) {
|
|
18758
18924
|
const idx = resolved.indexOf(marker);
|
|
18759
18925
|
if (idx === -1) continue;
|
|
18760
|
-
const base = resolved.replace(marker, `${
|
|
18926
|
+
const base = resolved.replace(marker, `${path33.sep}src${path33.sep}`);
|
|
18761
18927
|
const candidate = base.replace(/\.(js|mjs|cjs)$/, ".ts");
|
|
18762
|
-
if (candidate !== base &&
|
|
18928
|
+
if (candidate !== base && fs27.existsSync(candidate)) {
|
|
18763
18929
|
return candidate;
|
|
18764
18930
|
}
|
|
18765
18931
|
const dtsStripped = base.replace(/\.d\.ts$/, "");
|
|
18766
18932
|
const candidateDts = dtsStripped + ".ts";
|
|
18767
|
-
if (candidateDts !== base && candidateDts !== candidate &&
|
|
18933
|
+
if (candidateDts !== base && candidateDts !== candidate && fs27.existsSync(candidateDts)) {
|
|
18768
18934
|
return candidateDts;
|
|
18769
18935
|
}
|
|
18770
18936
|
const candidateNoExt = base + ".ts";
|
|
18771
|
-
if (candidate !== candidateNoExt && candidateNoExt !== candidateDts &&
|
|
18937
|
+
if (candidate !== candidateNoExt && candidateNoExt !== candidateDts && fs27.existsSync(candidateNoExt)) {
|
|
18772
18938
|
return candidateNoExt;
|
|
18773
18939
|
}
|
|
18774
18940
|
}
|
|
@@ -18776,9 +18942,9 @@ function trySourceEquivalent(resolved) {
|
|
|
18776
18942
|
}
|
|
18777
18943
|
function tryAddEntryPath(pkgDir, rawPath, entries) {
|
|
18778
18944
|
const resolved = resolveAgainst(pkgDir, rawPath);
|
|
18779
|
-
if (
|
|
18945
|
+
if (fs27.existsSync(resolved)) entries.add(resolved);
|
|
18780
18946
|
const tsResolved = resolved.replace(/\.(js|mjs|cjs)$/, ".ts");
|
|
18781
|
-
if (tsResolved !== resolved &&
|
|
18947
|
+
if (tsResolved !== resolved && fs27.existsSync(tsResolved)) {
|
|
18782
18948
|
entries.add(tsResolved);
|
|
18783
18949
|
}
|
|
18784
18950
|
const srcAlt = trySourceEquivalent(resolved);
|
|
@@ -18822,18 +18988,18 @@ function expandGlobPattern(entry, projectRoot) {
|
|
|
18822
18988
|
const dirs = [];
|
|
18823
18989
|
if (entry.includes("*")) {
|
|
18824
18990
|
const base = entry.replace(/\/\*+$/, "");
|
|
18825
|
-
const baseDir =
|
|
18991
|
+
const baseDir = path33.resolve(projectRoot, base);
|
|
18826
18992
|
try {
|
|
18827
|
-
const children =
|
|
18993
|
+
const children = fs27.readdirSync(baseDir, { withFileTypes: true });
|
|
18828
18994
|
for (const child of children) {
|
|
18829
18995
|
if (child.isDirectory()) {
|
|
18830
|
-
dirs.push(
|
|
18996
|
+
dirs.push(path33.join(baseDir, child.name));
|
|
18831
18997
|
}
|
|
18832
18998
|
}
|
|
18833
18999
|
} catch {
|
|
18834
19000
|
}
|
|
18835
19001
|
} else {
|
|
18836
|
-
dirs.push(
|
|
19002
|
+
dirs.push(path33.resolve(projectRoot, entry));
|
|
18837
19003
|
}
|
|
18838
19004
|
return dirs;
|
|
18839
19005
|
}
|
|
@@ -18850,10 +19016,10 @@ function extractWorkspaceGlobs(pkg, projectRoot) {
|
|
|
18850
19016
|
return dirs;
|
|
18851
19017
|
}
|
|
18852
19018
|
function extractPnpmWorkspaceDirs(projectRoot) {
|
|
18853
|
-
const yamlPath =
|
|
18854
|
-
if (!
|
|
19019
|
+
const yamlPath = path33.join(projectRoot, "pnpm-workspace.yaml");
|
|
19020
|
+
if (!fs27.existsSync(yamlPath)) return [];
|
|
18855
19021
|
try {
|
|
18856
|
-
const content =
|
|
19022
|
+
const content = fs27.readFileSync(yamlPath, "utf8");
|
|
18857
19023
|
const dirs = [];
|
|
18858
19024
|
let inPackages = false;
|
|
18859
19025
|
const lines = content.split("\n");
|
|
@@ -18887,8 +19053,8 @@ function extractPnpmWorkspaceDirs(projectRoot) {
|
|
|
18887
19053
|
}
|
|
18888
19054
|
function resolveModulePath(importerPath, moduleSpecifier, indexedFiles) {
|
|
18889
19055
|
if (!moduleSpecifier.startsWith(".")) return [];
|
|
18890
|
-
const dir =
|
|
18891
|
-
const base =
|
|
19056
|
+
const dir = path33.dirname(importerPath);
|
|
19057
|
+
const base = path33.resolve(dir, moduleSpecifier);
|
|
18892
19058
|
const results = [];
|
|
18893
19059
|
const stripped = base.replace(/\.(ts|tsx|js|jsx|mjs|cjs)$/, "");
|
|
18894
19060
|
const skipBase = stripped !== base && /\.(ts|tsx|js|jsx|mjs|cjs)$/.test(base);
|
|
@@ -18900,18 +19066,18 @@ function resolveModulePath(importerPath, moduleSpecifier, indexedFiles) {
|
|
|
18900
19066
|
if (indexedFiles.has(candidate + ".jsx")) results.push(candidate + ".jsx");
|
|
18901
19067
|
if (indexedFiles.has(candidate + ".mjs")) results.push(candidate + ".mjs");
|
|
18902
19068
|
if (indexedFiles.has(candidate + ".cjs")) results.push(candidate + ".cjs");
|
|
18903
|
-
if (indexedFiles.has(
|
|
18904
|
-
results.push(
|
|
18905
|
-
if (indexedFiles.has(
|
|
18906
|
-
results.push(
|
|
18907
|
-
if (indexedFiles.has(
|
|
18908
|
-
results.push(
|
|
18909
|
-
if (indexedFiles.has(
|
|
18910
|
-
results.push(
|
|
18911
|
-
if (indexedFiles.has(
|
|
18912
|
-
results.push(
|
|
18913
|
-
if (indexedFiles.has(
|
|
18914
|
-
results.push(
|
|
19069
|
+
if (indexedFiles.has(path33.join(candidate, "index.ts")))
|
|
19070
|
+
results.push(path33.join(candidate, "index.ts"));
|
|
19071
|
+
if (indexedFiles.has(path33.join(candidate, "index.tsx")))
|
|
19072
|
+
results.push(path33.join(candidate, "index.tsx"));
|
|
19073
|
+
if (indexedFiles.has(path33.join(candidate, "index.js")))
|
|
19074
|
+
results.push(path33.join(candidate, "index.js"));
|
|
19075
|
+
if (indexedFiles.has(path33.join(candidate, "index.jsx")))
|
|
19076
|
+
results.push(path33.join(candidate, "index.jsx"));
|
|
19077
|
+
if (indexedFiles.has(path33.join(candidate, "index.mjs")))
|
|
19078
|
+
results.push(path33.join(candidate, "index.mjs"));
|
|
19079
|
+
if (indexedFiles.has(path33.join(candidate, "index.cjs")))
|
|
19080
|
+
results.push(path33.join(candidate, "index.cjs"));
|
|
18915
19081
|
}
|
|
18916
19082
|
return [...new Set(results)];
|
|
18917
19083
|
}
|
|
@@ -18943,7 +19109,7 @@ function runDeadCodeScan(projectRoot, opts = {}) {
|
|
|
18943
19109
|
symbolById.set(s.id, s);
|
|
18944
19110
|
}
|
|
18945
19111
|
const discoveredFiles = discoverEntryPoints(projectRoot, opts.userEntryPoints);
|
|
18946
|
-
const entryFileSet = new Set(discoveredFiles.map((f) =>
|
|
19112
|
+
const entryFileSet = new Set(discoveredFiles.map((f) => path33.resolve(f)));
|
|
18947
19113
|
const indexedFiles = /* @__PURE__ */ new Set();
|
|
18948
19114
|
for (const s of allSymbols) indexedFiles.add(s.file);
|
|
18949
19115
|
for (const fm of store.getAllFileMetas()) indexedFiles.add(fm.file);
|
|
@@ -18969,7 +19135,7 @@ function runDeadCodeScan(projectRoot, opts = {}) {
|
|
|
18969
19135
|
if (scannedBarrels.has(epFile)) continue;
|
|
18970
19136
|
scannedBarrels.add(epFile);
|
|
18971
19137
|
try {
|
|
18972
|
-
const content =
|
|
19138
|
+
const content = fs27.readFileSync(epFile, "utf8");
|
|
18973
19139
|
const strippedContent = content.replace(/\/\*[\s\S]*?\*\//g, (m) => " ".repeat(m.length)).replace(/\/\/[^\n]*/g, (m) => " ".repeat(m.length));
|
|
18974
19140
|
const reExportRe = /export\s+(?:(?:type\s+)?\{[\s\S]*?\}\s+from|\*\s+as\s+\w+\s+from|\*\s+from)\s+['"]([^'"]+)['"]/g;
|
|
18975
19141
|
for (; ; ) {
|
|
@@ -19059,7 +19225,7 @@ function runDeadCodeScan(projectRoot, opts = {}) {
|
|
|
19059
19225
|
const deadPackages = [];
|
|
19060
19226
|
const pkgEntries = findPackageEntries(projectRoot);
|
|
19061
19227
|
for (const [pkgName, pkgDir] of pkgEntries) {
|
|
19062
|
-
const pkgFiles = allSymbols.filter((s) => s.file.startsWith(pkgDir +
|
|
19228
|
+
const pkgFiles = allSymbols.filter((s) => s.file.startsWith(pkgDir + path33.sep));
|
|
19063
19229
|
if (pkgFiles.length === 0) continue;
|
|
19064
19230
|
const pkgUsed = pkgFiles.filter((s) => alive.has(s.id));
|
|
19065
19231
|
if (pkgUsed.length === 0) {
|
|
@@ -19095,7 +19261,7 @@ function runDeadCodeScan(projectRoot, opts = {}) {
|
|
|
19095
19261
|
}
|
|
19096
19262
|
function findPackageEntries(projectRoot) {
|
|
19097
19263
|
const pkgMap = /* @__PURE__ */ new Map();
|
|
19098
|
-
const rootPkg = tryReadJson(
|
|
19264
|
+
const rootPkg = tryReadJson(path33.join(projectRoot, "package.json"));
|
|
19099
19265
|
if (rootPkg && typeof rootPkg.name === "string") {
|
|
19100
19266
|
pkgMap.set(rootPkg.name, projectRoot);
|
|
19101
19267
|
}
|
|
@@ -19105,7 +19271,7 @@ function findPackageEntries(projectRoot) {
|
|
|
19105
19271
|
wsDirs = extractPnpmWorkspaceDirs(projectRoot);
|
|
19106
19272
|
}
|
|
19107
19273
|
for (const wsDir of wsDirs) {
|
|
19108
|
-
const wsPkg = tryReadJson(
|
|
19274
|
+
const wsPkg = tryReadJson(path33.join(wsDir, "package.json"));
|
|
19109
19275
|
if (wsPkg && typeof wsPkg.name === "string") {
|
|
19110
19276
|
pkgMap.set(wsPkg.name, wsDir);
|
|
19111
19277
|
}
|
|
@@ -19115,7 +19281,7 @@ function findPackageEntries(projectRoot) {
|
|
|
19115
19281
|
}
|
|
19116
19282
|
|
|
19117
19283
|
// src/clarify.ts
|
|
19118
|
-
import { toErrorMessage as
|
|
19284
|
+
import { toErrorMessage as toErrorMessage12 } from "@wrongstack/core/utils";
|
|
19119
19285
|
var clarifyTool = {
|
|
19120
19286
|
name: "clarify",
|
|
19121
19287
|
category: "Meta",
|
|
@@ -19188,15 +19354,15 @@ var clarifyTool = {
|
|
|
19188
19354
|
question: input.question ?? "",
|
|
19189
19355
|
selectedOptions: [],
|
|
19190
19356
|
decisionSummary: "",
|
|
19191
|
-
error:
|
|
19357
|
+
error: toErrorMessage12(err)
|
|
19192
19358
|
};
|
|
19193
19359
|
}
|
|
19194
19360
|
}
|
|
19195
19361
|
};
|
|
19196
19362
|
|
|
19197
19363
|
// src/design.ts
|
|
19198
|
-
import * as
|
|
19199
|
-
import * as
|
|
19364
|
+
import * as fs28 from "node:fs/promises";
|
|
19365
|
+
import * as path34 from "node:path";
|
|
19200
19366
|
import {
|
|
19201
19367
|
applyTokenOverrides,
|
|
19202
19368
|
getDesignKitLoader,
|
|
@@ -19211,17 +19377,17 @@ import {
|
|
|
19211
19377
|
setDesignOverrides
|
|
19212
19378
|
} from "@wrongstack/core/design";
|
|
19213
19379
|
async function resolveReal(p) {
|
|
19214
|
-
const resolved =
|
|
19380
|
+
const resolved = path34.resolve(p);
|
|
19215
19381
|
let probe = resolved;
|
|
19216
19382
|
const missing = [];
|
|
19217
19383
|
for (; ; ) {
|
|
19218
19384
|
try {
|
|
19219
|
-
return
|
|
19385
|
+
return path34.resolve(await fs28.realpath(probe), ...missing);
|
|
19220
19386
|
} catch (err) {
|
|
19221
19387
|
if (err.code === "ENOENT") {
|
|
19222
|
-
const parent =
|
|
19388
|
+
const parent = path34.dirname(probe);
|
|
19223
19389
|
if (parent === probe) return resolved;
|
|
19224
|
-
missing.unshift(
|
|
19390
|
+
missing.unshift(path34.basename(probe));
|
|
19225
19391
|
probe = parent;
|
|
19226
19392
|
continue;
|
|
19227
19393
|
}
|
|
@@ -19422,16 +19588,16 @@ Run \`design {action:"materialize"}\` to write the tuned tokens to your theme fi
|
|
|
19422
19588
|
outPath: input.out
|
|
19423
19589
|
});
|
|
19424
19590
|
const root = await resolveReal(ctx.projectRoot);
|
|
19425
|
-
const absResolved =
|
|
19426
|
-
const absParent = await resolveReal(
|
|
19427
|
-
const abs =
|
|
19428
|
-
const rel =
|
|
19429
|
-
if (rel.startsWith("..") ||
|
|
19591
|
+
const absResolved = path34.isAbsolute(result.path) ? path34.resolve(result.path) : path34.resolve(path34.join(ctx.projectRoot, result.path));
|
|
19592
|
+
const absParent = await resolveReal(path34.dirname(absResolved));
|
|
19593
|
+
const abs = path34.join(absParent, path34.basename(absResolved));
|
|
19594
|
+
const rel = path34.relative(root, abs);
|
|
19595
|
+
if (rel.startsWith("..") || path34.isAbsolute(rel)) {
|
|
19430
19596
|
throw new Error(`design: materialize path "${result.path}" would escape the project root`);
|
|
19431
19597
|
}
|
|
19432
19598
|
let exists = false;
|
|
19433
19599
|
try {
|
|
19434
|
-
await
|
|
19600
|
+
await fs28.access(abs);
|
|
19435
19601
|
exists = true;
|
|
19436
19602
|
} catch {
|
|
19437
19603
|
}
|
|
@@ -19448,8 +19614,8 @@ ${result.content}
|
|
|
19448
19614
|
\`\`\``
|
|
19449
19615
|
};
|
|
19450
19616
|
}
|
|
19451
|
-
await
|
|
19452
|
-
await
|
|
19617
|
+
await fs28.mkdir(path34.dirname(abs), { recursive: true });
|
|
19618
|
+
await fs28.writeFile(abs, result.content);
|
|
19453
19619
|
return {
|
|
19454
19620
|
action,
|
|
19455
19621
|
kit: active.kit,
|
|
@@ -19499,8 +19665,8 @@ Replace off-palette colors with kit tokens (or the materialized CSS vars / token
|
|
|
19499
19665
|
init_util();
|
|
19500
19666
|
import { spawn as spawn7 } from "node:child_process";
|
|
19501
19667
|
import { statSync as statSync3 } from "node:fs";
|
|
19502
|
-
import * as
|
|
19503
|
-
import * as
|
|
19668
|
+
import * as fs29 from "node:fs/promises";
|
|
19669
|
+
import * as path35 from "node:path";
|
|
19504
19670
|
import { buildChildEnv as buildChildEnv3 } from "@wrongstack/core/utils";
|
|
19505
19671
|
import { ToolValidationError as ToolValidationError2 } from "@wrongstack/core/types";
|
|
19506
19672
|
var MAX_FILE_DUMP_BYTES = 5 * 1024 * 1024;
|
|
@@ -19615,18 +19781,18 @@ function findGitDir(cwd) {
|
|
|
19615
19781
|
let dir = cwd;
|
|
19616
19782
|
for (let i = 0; i < 20; i++) {
|
|
19617
19783
|
try {
|
|
19618
|
-
const stat21 = statSync3(
|
|
19784
|
+
const stat21 = statSync3(path35.join(dir, ".git"));
|
|
19619
19785
|
if (stat21.isDirectory()) return dir;
|
|
19620
19786
|
} catch {
|
|
19621
19787
|
}
|
|
19622
|
-
const parent =
|
|
19788
|
+
const parent = path35.dirname(dir);
|
|
19623
19789
|
if (parent === dir) break;
|
|
19624
19790
|
dir = parent;
|
|
19625
19791
|
}
|
|
19626
19792
|
return null;
|
|
19627
19793
|
}
|
|
19628
19794
|
function runGit(args, cwd, signal) {
|
|
19629
|
-
return new Promise((
|
|
19795
|
+
return new Promise((resolve23) => {
|
|
19630
19796
|
let stdout = "";
|
|
19631
19797
|
let stderr = "";
|
|
19632
19798
|
const child = spawn7("git", args, {
|
|
@@ -19642,8 +19808,8 @@ function runGit(args, cwd, signal) {
|
|
|
19642
19808
|
child.stderr?.on("data", (c) => {
|
|
19643
19809
|
stderr += c.toString();
|
|
19644
19810
|
});
|
|
19645
|
-
child.on("close", (code) =>
|
|
19646
|
-
child.on("error", (e) =>
|
|
19811
|
+
child.on("close", (code) => resolve23({ stdout, stderr, exitCode: code ?? 0 }));
|
|
19812
|
+
child.on("error", (e) => resolve23({ stdout: "", stderr: e.message, exitCode: 1 }));
|
|
19647
19813
|
});
|
|
19648
19814
|
}
|
|
19649
19815
|
async function fileDiff(input, ctx, _signal) {
|
|
@@ -19661,7 +19827,7 @@ async function fileDiff(input, ctx, _signal) {
|
|
|
19661
19827
|
let truncated = false;
|
|
19662
19828
|
for (const file of files) {
|
|
19663
19829
|
const absPath = await safeResolveReal(file, ctx);
|
|
19664
|
-
const stat21 = await
|
|
19830
|
+
const stat21 = await fs29.stat(absPath).catch(() => null);
|
|
19665
19831
|
if (!stat21?.isFile()) continue;
|
|
19666
19832
|
if (stat21.size > MAX_FILE_DUMP_BYTES) {
|
|
19667
19833
|
truncated = true;
|
|
@@ -19670,7 +19836,7 @@ async function fileDiff(input, ctx, _signal) {
|
|
|
19670
19836
|
);
|
|
19671
19837
|
continue;
|
|
19672
19838
|
}
|
|
19673
|
-
const content = await
|
|
19839
|
+
const content = await fs29.readFile(absPath, "utf8");
|
|
19674
19840
|
const lines = content.split(/\r?\n/);
|
|
19675
19841
|
results.push(formatWithLineNumbers(file, lines));
|
|
19676
19842
|
}
|
|
@@ -19693,8 +19859,8 @@ ${numbered}`;
|
|
|
19693
19859
|
|
|
19694
19860
|
// src/document.ts
|
|
19695
19861
|
init_util();
|
|
19696
|
-
import * as
|
|
19697
|
-
import * as
|
|
19862
|
+
import * as fs30 from "node:fs/promises";
|
|
19863
|
+
import * as path36 from "node:path";
|
|
19698
19864
|
var documentTool = {
|
|
19699
19865
|
name: "document",
|
|
19700
19866
|
category: "Project",
|
|
@@ -19742,7 +19908,7 @@ var documentTool = {
|
|
|
19742
19908
|
) : input.path ? [await safeResolveReal(input.path, ctx)] : [];
|
|
19743
19909
|
for (const absPath of fileList) {
|
|
19744
19910
|
try {
|
|
19745
|
-
const content = await
|
|
19911
|
+
const content = await fs30.readFile(absPath, "utf8");
|
|
19746
19912
|
filesProcessed++;
|
|
19747
19913
|
const processed = processFile(
|
|
19748
19914
|
content,
|
|
@@ -19780,12 +19946,12 @@ async function resolveFiles(filesInput, cwd, ctx) {
|
|
|
19780
19946
|
if (!entry) continue;
|
|
19781
19947
|
let absPath;
|
|
19782
19948
|
try {
|
|
19783
|
-
absPath = ensureInsideRoot(
|
|
19949
|
+
absPath = ensureInsideRoot(path36.resolve(cwd, entry), ctx);
|
|
19784
19950
|
} catch {
|
|
19785
19951
|
continue;
|
|
19786
19952
|
}
|
|
19787
19953
|
try {
|
|
19788
|
-
const stat21 = await
|
|
19954
|
+
const stat21 = await fs30.stat(absPath);
|
|
19789
19955
|
if (stat21.isFile()) resolved.push(absPath);
|
|
19790
19956
|
} catch {
|
|
19791
19957
|
}
|
|
@@ -19856,7 +20022,7 @@ function processFile(content, absPath, _style, _overwrite, target) {
|
|
|
19856
20022
|
// src/e2e.ts
|
|
19857
20023
|
init_util();
|
|
19858
20024
|
import { open, readdir as readdir9 } from "node:fs/promises";
|
|
19859
|
-
import * as
|
|
20025
|
+
import * as path37 from "node:path";
|
|
19860
20026
|
async function readBoundedText(filePath, maxBytes) {
|
|
19861
20027
|
let handle;
|
|
19862
20028
|
try {
|
|
@@ -19906,8 +20072,8 @@ var MAX_PACKAGE_BYTES = 512 * 1024;
|
|
|
19906
20072
|
var MAX_CONFIG_BYTES = 512 * 1024;
|
|
19907
20073
|
var MAX_SPEC_SAMPLES = 20;
|
|
19908
20074
|
function relativePath(root, target) {
|
|
19909
|
-
const value =
|
|
19910
|
-
return value.split(
|
|
20075
|
+
const value = path37.relative(root, target) || ".";
|
|
20076
|
+
return value.split(path37.sep).join("/");
|
|
19911
20077
|
}
|
|
19912
20078
|
function escapeRegExp(value) {
|
|
19913
20079
|
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
@@ -19979,7 +20145,7 @@ async function scanWorkspace(root, maxDepth, signal) {
|
|
|
19979
20145
|
}
|
|
19980
20146
|
for (const entry of entries) {
|
|
19981
20147
|
signal.throwIfAborted();
|
|
19982
|
-
const absolutePath =
|
|
20148
|
+
const absolutePath = path37.join(current.directory, entry.name);
|
|
19983
20149
|
if (entry.isFile()) {
|
|
19984
20150
|
if (entry.name === "package.json") result.packageFiles.push(absolutePath);
|
|
19985
20151
|
const framework = CONFIG_NAMES.get(entry.name);
|
|
@@ -20040,9 +20206,9 @@ async function detectPackageManager3(projectRoot, scanRoot, declared) {
|
|
|
20040
20206
|
if (names.has("bun.lock") || names.has("bun.lockb")) return "bun";
|
|
20041
20207
|
if (names.has("package-lock.json") || names.has("npm-shrinkwrap.json")) return "npm";
|
|
20042
20208
|
if (directory === scanRoot) break;
|
|
20043
|
-
const parent =
|
|
20044
|
-
const relativeParent =
|
|
20045
|
-
if (parent === directory || relativeParent.startsWith("..") ||
|
|
20209
|
+
const parent = path37.dirname(directory);
|
|
20210
|
+
const relativeParent = path37.relative(scanRoot, parent);
|
|
20211
|
+
if (parent === directory || relativeParent.startsWith("..") || path37.isAbsolute(relativeParent)) {
|
|
20046
20212
|
break;
|
|
20047
20213
|
}
|
|
20048
20214
|
directory = parent;
|
|
@@ -20087,7 +20253,7 @@ function isSpec(framework, filename) {
|
|
|
20087
20253
|
return /\.(?:spec|test)\.(?:[cm]?[jt]sx?)$/i.test(filename);
|
|
20088
20254
|
}
|
|
20089
20255
|
async function collectSpecs(root, framework, testDirectory, signal) {
|
|
20090
|
-
const roots = testDirectory ? [
|
|
20256
|
+
const roots = testDirectory ? [path37.resolve(root, testDirectory)] : framework === "cypress" ? [path37.join(root, "cypress", "e2e"), path37.join(root, "cypress", "integration")] : [path37.join(root, "tests")];
|
|
20091
20257
|
const samples = [];
|
|
20092
20258
|
let count = 0;
|
|
20093
20259
|
let scanned = 0;
|
|
@@ -20106,7 +20272,7 @@ async function collectSpecs(root, framework, testDirectory, signal) {
|
|
|
20106
20272
|
}
|
|
20107
20273
|
for (const entry of entries) {
|
|
20108
20274
|
signal.throwIfAborted();
|
|
20109
|
-
const target =
|
|
20275
|
+
const target = path37.join(directory, entry.name);
|
|
20110
20276
|
if (entry.isDirectory() && !SKIP_DIRECTORIES.has(entry.name)) queue.push(target);
|
|
20111
20277
|
else if (entry.isFile() && isSpec(framework, entry.name)) {
|
|
20112
20278
|
count += 1;
|
|
@@ -20126,7 +20292,7 @@ function nearestPackage(projectRoot, packagesByDirectory, scanRoot) {
|
|
|
20126
20292
|
const found = packagesByDirectory.get(directory);
|
|
20127
20293
|
if (found) return found;
|
|
20128
20294
|
if (directory === scanRoot) return void 0;
|
|
20129
|
-
const parent =
|
|
20295
|
+
const parent = path37.dirname(directory);
|
|
20130
20296
|
if (parent === directory || relativePath(scanRoot, parent).startsWith("..")) return void 0;
|
|
20131
20297
|
directory = parent;
|
|
20132
20298
|
}
|
|
@@ -20137,13 +20303,13 @@ async function discoverE2EProjects(root, options) {
|
|
|
20137
20303
|
const packages = (await Promise.all(scan.packageFiles.map(readPackageInfo))).filter(
|
|
20138
20304
|
(info) => Boolean(info)
|
|
20139
20305
|
);
|
|
20140
|
-
const packagesByDirectory = new Map(packages.map((info) => [
|
|
20306
|
+
const packagesByDirectory = new Map(packages.map((info) => [path37.dirname(info.path), info]));
|
|
20141
20307
|
const candidates = /* @__PURE__ */ new Map();
|
|
20142
20308
|
for (const config of scan.configs) {
|
|
20143
20309
|
if (options.framework && options.framework !== "all" && config.framework !== options.framework) {
|
|
20144
20310
|
continue;
|
|
20145
20311
|
}
|
|
20146
|
-
const projectRoot =
|
|
20312
|
+
const projectRoot = path37.dirname(config.absolutePath);
|
|
20147
20313
|
candidates.set(`${config.framework}:${projectRoot}`, {
|
|
20148
20314
|
framework: config.framework,
|
|
20149
20315
|
root: projectRoot,
|
|
@@ -20151,7 +20317,7 @@ async function discoverE2EProjects(root, options) {
|
|
|
20151
20317
|
});
|
|
20152
20318
|
}
|
|
20153
20319
|
for (const info of packages) {
|
|
20154
|
-
const projectRoot =
|
|
20320
|
+
const projectRoot = path37.dirname(info.path);
|
|
20155
20321
|
for (const framework of frameworkFromPackage(info)) {
|
|
20156
20322
|
if (options.framework && options.framework !== "all" && framework !== options.framework)
|
|
20157
20323
|
continue;
|
|
@@ -20167,10 +20333,10 @@ async function discoverE2EProjects(root, options) {
|
|
|
20167
20333
|
const scripts = matchingScripts(info, candidate.framework);
|
|
20168
20334
|
const manager = await detectPackageManager3(candidate.root, root, info?.packageManager);
|
|
20169
20335
|
const testDirectory = candidate.framework === "playwright" ? staticString(source, "testDir") : void 0;
|
|
20170
|
-
const resolvedTestDirectory = testDirectory ?
|
|
20171
|
-
const relativeTestDirectory = resolvedTestDirectory ?
|
|
20336
|
+
const resolvedTestDirectory = testDirectory ? path37.resolve(candidate.root, testDirectory) : void 0;
|
|
20337
|
+
const relativeTestDirectory = resolvedTestDirectory ? path37.relative(root, resolvedTestDirectory) : void 0;
|
|
20172
20338
|
const unsafeTestDirectory = Boolean(
|
|
20173
|
-
relativeTestDirectory && (relativeTestDirectory.startsWith("..") ||
|
|
20339
|
+
relativeTestDirectory && (relativeTestDirectory.startsWith("..") || path37.isAbsolute(relativeTestDirectory))
|
|
20174
20340
|
);
|
|
20175
20341
|
const specs = options.includeSpecs === false || unsafeTestDirectory ? { count: 0, samples: [], truncated: false } : await collectSpecs(candidate.root, candidate.framework, testDirectory, options.signal);
|
|
20176
20342
|
const warnings = [];
|
|
@@ -20270,7 +20436,7 @@ var e2ePlanTool = {
|
|
|
20270
20436
|
};
|
|
20271
20437
|
|
|
20272
20438
|
// src/edit.ts
|
|
20273
|
-
import * as
|
|
20439
|
+
import * as fs31 from "node:fs/promises";
|
|
20274
20440
|
import {
|
|
20275
20441
|
atomicWrite as atomicWrite3,
|
|
20276
20442
|
detectNewlineStyle,
|
|
@@ -20494,7 +20660,7 @@ function prefixSimilarity(a, b) {
|
|
|
20494
20660
|
}
|
|
20495
20661
|
|
|
20496
20662
|
// src/_syntax-check.ts
|
|
20497
|
-
import * as
|
|
20663
|
+
import * as path38 from "node:path";
|
|
20498
20664
|
var TS_LIKE = /* @__PURE__ */ new Set([".ts", ".tsx", ".mts", ".cts", ".js", ".jsx", ".mjs", ".cjs"]);
|
|
20499
20665
|
var MAX_CHECK_CHARS = 15e5;
|
|
20500
20666
|
var MAX_ERRORS = 5;
|
|
@@ -20518,15 +20684,15 @@ async function checkSyntax(filePath, content, previousContent) {
|
|
|
20518
20684
|
return { errors, preExisting };
|
|
20519
20685
|
}
|
|
20520
20686
|
function isJsoncFile(filePath) {
|
|
20521
|
-
const base =
|
|
20687
|
+
const base = path38.basename(filePath).toLowerCase();
|
|
20522
20688
|
if (base.endsWith(".jsonc")) return true;
|
|
20523
20689
|
if (/^(tsconfig|jsconfig)([.-].*)?\.json$/.test(base)) return true;
|
|
20524
|
-
const dir =
|
|
20690
|
+
const dir = path38.basename(path38.dirname(filePath)).toLowerCase();
|
|
20525
20691
|
return dir === ".vscode";
|
|
20526
20692
|
}
|
|
20527
20693
|
async function parseErrors(filePath, content) {
|
|
20528
20694
|
if (content.length > MAX_CHECK_CHARS) return void 0;
|
|
20529
|
-
const ext =
|
|
20695
|
+
const ext = path38.extname(filePath).toLowerCase();
|
|
20530
20696
|
if (ext === ".json" || ext === ".jsonc") {
|
|
20531
20697
|
try {
|
|
20532
20698
|
JSON.parse(content);
|
|
@@ -20553,7 +20719,7 @@ async function parseErrors(filePath, content) {
|
|
|
20553
20719
|
ts2.ScriptKind.JSX
|
|
20554
20720
|
);
|
|
20555
20721
|
const sourceFile = ts2.createSourceFile(
|
|
20556
|
-
|
|
20722
|
+
path38.basename(filePath),
|
|
20557
20723
|
content,
|
|
20558
20724
|
ts2.ScriptTarget.Latest,
|
|
20559
20725
|
/* setParentNodes */
|
|
@@ -20644,7 +20810,7 @@ var editTool = {
|
|
|
20644
20810
|
});
|
|
20645
20811
|
}
|
|
20646
20812
|
const absPath = await safeResolveReal(input.path, ctx);
|
|
20647
|
-
const stat21 = await
|
|
20813
|
+
const stat21 = await fs31.stat(absPath).catch((err) => {
|
|
20648
20814
|
if (err.code === "ENOENT") {
|
|
20649
20815
|
throw new ToolValidationError3({
|
|
20650
20816
|
message: `edit: file "${input.path}" does not exist. Use \`write\` instead.`,
|
|
@@ -20661,8 +20827,8 @@ var editTool = {
|
|
|
20661
20827
|
});
|
|
20662
20828
|
}
|
|
20663
20829
|
const autoRead = !ctx.hasRead(absPath);
|
|
20664
|
-
const original = await
|
|
20665
|
-
const updated = await
|
|
20830
|
+
const original = await fs31.readFile(absPath, "utf8");
|
|
20831
|
+
const updated = await fs31.stat(absPath);
|
|
20666
20832
|
const mtimeTolerance = process.platform === "win32" ? 2e3 : 1;
|
|
20667
20833
|
const originalHash = sha256hex(original);
|
|
20668
20834
|
const lastReadHash = ctx.lastReadHash?.(absPath);
|
|
@@ -20770,7 +20936,7 @@ var editTool = {
|
|
|
20770
20936
|
enqueueReindex({ projectRoot: ctx.projectRoot, files: [absPath] });
|
|
20771
20937
|
} catch {
|
|
20772
20938
|
}
|
|
20773
|
-
const written = await
|
|
20939
|
+
const written = await fs31.stat(absPath);
|
|
20774
20940
|
ctx.recordRead(absPath, written.mtimeMs, "write", sha256hex(newFile));
|
|
20775
20941
|
ctx.session.recordFileChange({
|
|
20776
20942
|
path: absPath,
|
|
@@ -20820,7 +20986,7 @@ import {
|
|
|
20820
20986
|
emitProcessOutput as emitProcessOutput3,
|
|
20821
20987
|
emitProcessStarted as emitProcessStarted3
|
|
20822
20988
|
} from "@wrongstack/core/observability";
|
|
20823
|
-
import { toErrorMessage as
|
|
20989
|
+
import { toErrorMessage as toErrorMessage13 } from "@wrongstack/core/utils/error";
|
|
20824
20990
|
|
|
20825
20991
|
// src/_danger-detect.ts
|
|
20826
20992
|
var argHas = (args, value) => args.includes(value);
|
|
@@ -21176,7 +21342,7 @@ init_win32_resolve();
|
|
|
21176
21342
|
|
|
21177
21343
|
// src/exec-kill-guard.ts
|
|
21178
21344
|
import * as os8 from "node:os";
|
|
21179
|
-
import * as
|
|
21345
|
+
import * as path39 from "node:path";
|
|
21180
21346
|
var isWin3 = os8.platform() === "win32";
|
|
21181
21347
|
async function checkExecKillCommand(cmd, args) {
|
|
21182
21348
|
if (!cmd) return { blocked: false };
|
|
@@ -21393,7 +21559,7 @@ async function checkKillTarget(target) {
|
|
|
21393
21559
|
reason: `Blocked: kill ${target.signal} '${target.name}' targets a WrongStack process name.`
|
|
21394
21560
|
};
|
|
21395
21561
|
}
|
|
21396
|
-
const currentImage =
|
|
21562
|
+
const currentImage = path39.basename(process.execPath).toLowerCase().replace(/\.exe$/, "");
|
|
21397
21563
|
const targetsNodeRuntime = nameLower === "node" || nameLower.startsWith("node");
|
|
21398
21564
|
if (targetsNodeRuntime && currentImage === "node") {
|
|
21399
21565
|
return {
|
|
@@ -22278,7 +22444,7 @@ var execTool = {
|
|
|
22278
22444
|
}
|
|
22279
22445
|
};
|
|
22280
22446
|
function runCommand(cmd, args, cwd, timeout, signal, sessionId, danger) {
|
|
22281
|
-
return new Promise((
|
|
22447
|
+
return new Promise((resolve23) => {
|
|
22282
22448
|
let stdout = "";
|
|
22283
22449
|
let stderr = "";
|
|
22284
22450
|
let killed = false;
|
|
@@ -22286,7 +22452,7 @@ function runCommand(cmd, args, cwd, timeout, signal, sessionId, danger) {
|
|
|
22286
22452
|
const finish = (result) => {
|
|
22287
22453
|
if (resolvedOnce.value) return;
|
|
22288
22454
|
resolvedOnce.value = true;
|
|
22289
|
-
|
|
22455
|
+
resolve23(result);
|
|
22290
22456
|
};
|
|
22291
22457
|
const startedAt = Date.now();
|
|
22292
22458
|
let stdoutBytes = 0;
|
|
@@ -22338,7 +22504,7 @@ function runCommand(cmd, args, cwd, timeout, signal, sessionId, danger) {
|
|
|
22338
22504
|
command: cmd,
|
|
22339
22505
|
args,
|
|
22340
22506
|
stdout: "",
|
|
22341
|
-
stderr: `spawn failed: ${
|
|
22507
|
+
stderr: `spawn failed: ${toErrorMessage13(err)}`,
|
|
22342
22508
|
exitCode: 1,
|
|
22343
22509
|
truncated: false,
|
|
22344
22510
|
allowed: true,
|
|
@@ -22962,10 +23128,10 @@ function parseFormatterCounts(fixer, output) {
|
|
|
22962
23128
|
};
|
|
22963
23129
|
}
|
|
22964
23130
|
async function detectFixer(cwd) {
|
|
22965
|
-
const
|
|
23131
|
+
const fs43 = await import("node:fs/promises");
|
|
22966
23132
|
const exists = async (file) => {
|
|
22967
23133
|
try {
|
|
22968
|
-
await
|
|
23134
|
+
await fs43.stat(`${cwd}/${file}`);
|
|
22969
23135
|
return true;
|
|
22970
23136
|
} catch {
|
|
22971
23137
|
return false;
|
|
@@ -22988,7 +23154,7 @@ async function detectFixer(cwd) {
|
|
|
22988
23154
|
if (await exists(cfg)) return "prettier";
|
|
22989
23155
|
}
|
|
22990
23156
|
try {
|
|
22991
|
-
const raw = await
|
|
23157
|
+
const raw = await fs43.readFile(`${cwd}/package.json`, "utf8");
|
|
22992
23158
|
const pkg = JSON.parse(raw);
|
|
22993
23159
|
if (pkg["prettier"] !== void 0) return "prettier";
|
|
22994
23160
|
} catch {
|
|
@@ -23000,7 +23166,7 @@ async function detectFixer(cwd) {
|
|
|
23000
23166
|
init_util();
|
|
23001
23167
|
import { spawn as spawn9 } from "node:child_process";
|
|
23002
23168
|
import { statSync as statSync4 } from "node:fs";
|
|
23003
|
-
import { dirname as dirname13, resolve as
|
|
23169
|
+
import { dirname as dirname13, resolve as resolve19, sep as sep6 } from "node:path";
|
|
23004
23170
|
import { assessCommitSafety } from "@wrongstack/core/coordination";
|
|
23005
23171
|
import { buildChildEnv as buildChildEnv4 } from "@wrongstack/core/utils";
|
|
23006
23172
|
var TIMEOUT_MS2 = 3e4;
|
|
@@ -23161,8 +23327,8 @@ function validateWorktreeInput(input, projectRoot) {
|
|
|
23161
23327
|
return reject(`unsafe worktree path: ${input.worktreePath}`);
|
|
23162
23328
|
}
|
|
23163
23329
|
if ((input.worktreeAction === "add" || input.worktreeAction === "remove") && input.worktreePath) {
|
|
23164
|
-
const root =
|
|
23165
|
-
const abs =
|
|
23330
|
+
const root = resolve19(projectRoot);
|
|
23331
|
+
const abs = resolve19(root, input.worktreePath);
|
|
23166
23332
|
if (abs !== root && !abs.startsWith(root + sep6)) {
|
|
23167
23333
|
return reject(`unsafe worktree path (escapes project root): ${input.worktreePath}`);
|
|
23168
23334
|
}
|
|
@@ -23256,7 +23422,7 @@ function buildArgs(input) {
|
|
|
23256
23422
|
}
|
|
23257
23423
|
}
|
|
23258
23424
|
function runGit2(args, cwd, signal) {
|
|
23259
|
-
return new Promise((
|
|
23425
|
+
return new Promise((resolve23) => {
|
|
23260
23426
|
let stdout = "";
|
|
23261
23427
|
let stderr = "";
|
|
23262
23428
|
const child = spawn9("git", args, {
|
|
@@ -23277,7 +23443,7 @@ function runGit2(args, cwd, signal) {
|
|
|
23277
23443
|
}
|
|
23278
23444
|
});
|
|
23279
23445
|
child.on("error", (err) => {
|
|
23280
|
-
|
|
23446
|
+
resolve23({
|
|
23281
23447
|
command: args[0],
|
|
23282
23448
|
stdout: normalizeCommandOutput(stdout),
|
|
23283
23449
|
stderr: err.message,
|
|
@@ -23286,7 +23452,7 @@ function runGit2(args, cwd, signal) {
|
|
|
23286
23452
|
});
|
|
23287
23453
|
});
|
|
23288
23454
|
child.on("close", (code) => {
|
|
23289
|
-
|
|
23455
|
+
resolve23({
|
|
23290
23456
|
command: args[0],
|
|
23291
23457
|
stdout: normalizeCommandOutput(stdout),
|
|
23292
23458
|
stderr: normalizeCommandOutput(stderr),
|
|
@@ -23298,8 +23464,8 @@ function runGit2(args, cwd, signal) {
|
|
|
23298
23464
|
}
|
|
23299
23465
|
|
|
23300
23466
|
// src/glob.ts
|
|
23301
|
-
import * as
|
|
23302
|
-
import * as
|
|
23467
|
+
import * as fs32 from "node:fs/promises";
|
|
23468
|
+
import * as path40 from "node:path";
|
|
23303
23469
|
import { compileGlob as compileGlob2, DEFAULT_WALK_IGNORE_DIRS as DEFAULT_WALK_IGNORE_DIRS2 } from "@wrongstack/core/utils";
|
|
23304
23470
|
import { ToolValidationError as ToolValidationError6 } from "@wrongstack/core/types";
|
|
23305
23471
|
|
|
@@ -23379,7 +23545,7 @@ var globTool = {
|
|
|
23379
23545
|
return;
|
|
23380
23546
|
}
|
|
23381
23547
|
try {
|
|
23382
|
-
const st = await
|
|
23548
|
+
const st = await fs32.stat(full);
|
|
23383
23549
|
if (truncated || results.length >= limit) {
|
|
23384
23550
|
truncated = true;
|
|
23385
23551
|
return;
|
|
@@ -23400,7 +23566,7 @@ var globTool = {
|
|
|
23400
23566
|
}
|
|
23401
23567
|
let entries;
|
|
23402
23568
|
try {
|
|
23403
|
-
entries = await
|
|
23569
|
+
entries = await fs32.readdir(dir, { withFileTypes: true });
|
|
23404
23570
|
} catch {
|
|
23405
23571
|
return;
|
|
23406
23572
|
}
|
|
@@ -23410,7 +23576,7 @@ var globTool = {
|
|
|
23410
23576
|
const name = e.name;
|
|
23411
23577
|
if (DEFAULT_IGNORE2.has(name)) continue;
|
|
23412
23578
|
const rel = relPrefix ? `${relPrefix}/${name}` : name;
|
|
23413
|
-
const full =
|
|
23579
|
+
const full = path40.join(dir, name);
|
|
23414
23580
|
if (e.isDirectory()) {
|
|
23415
23581
|
if (isGitIgnored(rel, true)) continue;
|
|
23416
23582
|
subdirs.push({ full, rel });
|
|
@@ -23425,15 +23591,15 @@ var globTool = {
|
|
|
23425
23591
|
}
|
|
23426
23592
|
} else if (e.isSymbolicLink()) {
|
|
23427
23593
|
try {
|
|
23428
|
-
const st = await
|
|
23594
|
+
const st = await fs32.stat(full);
|
|
23429
23595
|
if (st.isDirectory()) {
|
|
23430
23596
|
if (isGitIgnored(rel, true)) continue;
|
|
23431
|
-
const real = await
|
|
23597
|
+
const real = await fs32.realpath(full);
|
|
23432
23598
|
await assertRealInsideRoot(real, ctx);
|
|
23433
23599
|
subdirs.push({ full, rel });
|
|
23434
23600
|
} else if (st.isFile()) {
|
|
23435
23601
|
if (isGitIgnored(rel, false)) continue;
|
|
23436
|
-
const real = await
|
|
23602
|
+
const real = await fs32.realpath(full);
|
|
23437
23603
|
await assertRealInsideRoot(real, ctx);
|
|
23438
23604
|
re.lastIndex = 0;
|
|
23439
23605
|
const relMatch = re.test(rel);
|
|
@@ -23463,8 +23629,8 @@ var globTool = {
|
|
|
23463
23629
|
|
|
23464
23630
|
// src/grep.ts
|
|
23465
23631
|
import { spawn as spawn10 } from "node:child_process";
|
|
23466
|
-
import * as
|
|
23467
|
-
import * as
|
|
23632
|
+
import * as fs33 from "node:fs/promises";
|
|
23633
|
+
import * as path41 from "node:path";
|
|
23468
23634
|
import { ToolValidationError as ToolValidationError7 } from "@wrongstack/core/types";
|
|
23469
23635
|
import {
|
|
23470
23636
|
buildChildEnv as buildChildEnv5,
|
|
@@ -23699,7 +23865,7 @@ var grepTool = {
|
|
|
23699
23865
|
};
|
|
23700
23866
|
var rgAvailabilityCache;
|
|
23701
23867
|
function detectRg() {
|
|
23702
|
-
rgAvailabilityCache ??= new Promise((
|
|
23868
|
+
rgAvailabilityCache ??= new Promise((resolve23) => {
|
|
23703
23869
|
try {
|
|
23704
23870
|
const p = spawn10("rg", ["--version"], {
|
|
23705
23871
|
env: buildChildEnv5(),
|
|
@@ -23707,10 +23873,10 @@ function detectRg() {
|
|
|
23707
23873
|
signal: AbortSignal.timeout(1e4),
|
|
23708
23874
|
windowsHide: true
|
|
23709
23875
|
});
|
|
23710
|
-
p.on("error", () =>
|
|
23711
|
-
p.on("close", (code) =>
|
|
23876
|
+
p.on("error", () => resolve23(false));
|
|
23877
|
+
p.on("close", (code) => resolve23(code === 0));
|
|
23712
23878
|
} catch {
|
|
23713
|
-
|
|
23879
|
+
resolve23(false);
|
|
23714
23880
|
}
|
|
23715
23881
|
});
|
|
23716
23882
|
return rgAvailabilityCache;
|
|
@@ -23727,8 +23893,8 @@ async function* runRgStream(input, base, mode, limit, signal) {
|
|
|
23727
23893
|
for (const ignored of DEFAULT_IGNORE3) {
|
|
23728
23894
|
args.push("--glob", `!${ignored}/**`, "--glob", `!**/${ignored}/**`);
|
|
23729
23895
|
}
|
|
23730
|
-
const gitignorePath =
|
|
23731
|
-
if (await
|
|
23896
|
+
const gitignorePath = path41.join(base, ".gitignore");
|
|
23897
|
+
if (await fs33.access(gitignorePath).then(
|
|
23732
23898
|
() => true,
|
|
23733
23899
|
() => false
|
|
23734
23900
|
)) {
|
|
@@ -23918,9 +24084,9 @@ async function runNative(input, base, mode, limit, signal) {
|
|
|
23918
24084
|
if (globRe && !globRe.test(name) && !globRe.test(full)) return;
|
|
23919
24085
|
if (globRe) globRe.lastIndex = 0;
|
|
23920
24086
|
try {
|
|
23921
|
-
const stat21 = await
|
|
24087
|
+
const stat21 = await fs33.stat(full);
|
|
23922
24088
|
if (!stat21.isFile() || stat21.size > maxBytes || stopped || signal.aborted) return;
|
|
23923
|
-
const file = await
|
|
24089
|
+
const file = await fs33.open(full, "r");
|
|
23924
24090
|
try {
|
|
23925
24091
|
let bytesReadTotal = 0;
|
|
23926
24092
|
let lineNumber = 0;
|
|
@@ -24005,7 +24171,7 @@ async function runNative(input, base, mode, limit, signal) {
|
|
|
24005
24171
|
if (stopped || signal.aborted) return;
|
|
24006
24172
|
let entries;
|
|
24007
24173
|
try {
|
|
24008
|
-
entries = await
|
|
24174
|
+
entries = await fs33.readdir(dir, { withFileTypes: true });
|
|
24009
24175
|
} catch {
|
|
24010
24176
|
return;
|
|
24011
24177
|
}
|
|
@@ -24016,7 +24182,7 @@ async function runNative(input, base, mode, limit, signal) {
|
|
|
24016
24182
|
if (DEFAULT_IGNORE3.has(e.name)) continue;
|
|
24017
24183
|
if (e.isSymbolicLink()) continue;
|
|
24018
24184
|
const rel = relPrefix ? `${relPrefix}/${e.name}` : e.name;
|
|
24019
|
-
const full =
|
|
24185
|
+
const full = path41.join(dir, e.name);
|
|
24020
24186
|
if (e.isDirectory()) {
|
|
24021
24187
|
if (isGitIgnored(rel, true)) continue;
|
|
24022
24188
|
subdirs.push({ full, rel });
|
|
@@ -24256,7 +24422,7 @@ function resolveManifestPath(cwd, pkgManager) {
|
|
|
24256
24422
|
}
|
|
24257
24423
|
|
|
24258
24424
|
// src/json.ts
|
|
24259
|
-
import * as
|
|
24425
|
+
import * as fs34 from "node:fs/promises";
|
|
24260
24426
|
import { deepMerge as deepMergeCore } from "@wrongstack/core/utils";
|
|
24261
24427
|
init_util();
|
|
24262
24428
|
var MAX_JSON_FILE_BYTES = 16 * 1024 * 1024;
|
|
@@ -24271,11 +24437,11 @@ var JsonFileTooLargeError = class extends Error {
|
|
|
24271
24437
|
};
|
|
24272
24438
|
async function readJsonFileBounded(filePath, ctx) {
|
|
24273
24439
|
const resolved = await safeResolveReal(filePath, ctx);
|
|
24274
|
-
const stat21 = await
|
|
24440
|
+
const stat21 = await fs34.stat(resolved);
|
|
24275
24441
|
if (stat21.size > MAX_JSON_FILE_BYTES) {
|
|
24276
24442
|
throw new JsonFileTooLargeError(filePath, stat21.size);
|
|
24277
24443
|
}
|
|
24278
|
-
return
|
|
24444
|
+
return fs34.readFile(resolved, "utf8");
|
|
24279
24445
|
}
|
|
24280
24446
|
var jsonTool = {
|
|
24281
24447
|
name: "json",
|
|
@@ -24752,60 +24918,60 @@ function jmespathSearch(data, query) {
|
|
|
24752
24918
|
}
|
|
24753
24919
|
function validateJsonSchema(data, schema) {
|
|
24754
24920
|
const errors = [];
|
|
24755
|
-
function check(value, s,
|
|
24921
|
+
function check(value, s, path49) {
|
|
24756
24922
|
if (s["type"]) {
|
|
24757
24923
|
const expectedType = s["type"];
|
|
24758
24924
|
const actualType = Array.isArray(value) ? "array" : value === null ? "null" : typeof value;
|
|
24759
24925
|
if (expectedType === "integer") {
|
|
24760
|
-
if (!Number.isInteger(value)) errors.push(`${
|
|
24926
|
+
if (!Number.isInteger(value)) errors.push(`${path49}: expected integer, got ${actualType}`);
|
|
24761
24927
|
} else if (expectedType !== actualType) {
|
|
24762
|
-
errors.push(`${
|
|
24928
|
+
errors.push(`${path49}: expected ${expectedType}, got ${actualType}`);
|
|
24763
24929
|
}
|
|
24764
24930
|
}
|
|
24765
24931
|
if (typeof value === "string" && s["format"] === "uri" && value) {
|
|
24766
24932
|
try {
|
|
24767
24933
|
new URL(value);
|
|
24768
24934
|
} catch {
|
|
24769
|
-
errors.push(`${
|
|
24935
|
+
errors.push(`${path49}: not a valid URI`);
|
|
24770
24936
|
}
|
|
24771
24937
|
}
|
|
24772
24938
|
if (typeof value === "string" && s["pattern"]) {
|
|
24773
24939
|
const compiled = compileUserRegex(s["pattern"], "");
|
|
24774
24940
|
if (!compiled.ok) {
|
|
24775
|
-
errors.push(`${
|
|
24941
|
+
errors.push(`${path49}: invalid schema pattern \u2014 ${compiled.reason}`);
|
|
24776
24942
|
} else if (!compiled.regex.test(capSubject(value))) {
|
|
24777
|
-
errors.push(`${
|
|
24943
|
+
errors.push(`${path49}: does not match pattern ${s["pattern"]}`);
|
|
24778
24944
|
}
|
|
24779
24945
|
}
|
|
24780
24946
|
if (typeof value === "string" && s["minLength"] !== void 0 && value.length < s["minLength"]) {
|
|
24781
|
-
errors.push(`${
|
|
24947
|
+
errors.push(`${path49}: string too short (min ${s["minLength"]})`);
|
|
24782
24948
|
}
|
|
24783
24949
|
if (typeof value === "string" && s["maxLength"] !== void 0 && value.length > s["maxLength"]) {
|
|
24784
|
-
errors.push(`${
|
|
24950
|
+
errors.push(`${path49}: string too long (max ${s["maxLength"]})`);
|
|
24785
24951
|
}
|
|
24786
24952
|
if (typeof value === "number" && s["minimum"] !== void 0 && value < s["minimum"]) {
|
|
24787
|
-
errors.push(`${
|
|
24953
|
+
errors.push(`${path49}: below minimum ${s["minimum"]}`);
|
|
24788
24954
|
}
|
|
24789
24955
|
if (typeof value === "number" && s["maximum"] !== void 0 && value > s["maximum"]) {
|
|
24790
|
-
errors.push(`${
|
|
24956
|
+
errors.push(`${path49}: above maximum ${s["maximum"]}`);
|
|
24791
24957
|
}
|
|
24792
24958
|
if (Array.isArray(value) && s["items"] && Array.isArray(s["items"])) {
|
|
24793
24959
|
for (let i = 0; i < value.length; i++) {
|
|
24794
|
-
check(value[i], s["items"], `${
|
|
24960
|
+
check(value[i], s["items"], `${path49}[${i}]`);
|
|
24795
24961
|
}
|
|
24796
24962
|
}
|
|
24797
24963
|
if (typeof value === "object" && value !== null && !Array.isArray(value) && s["properties"]) {
|
|
24798
24964
|
const props = s["properties"];
|
|
24799
24965
|
for (const [k, propSchema] of Object.entries(props)) {
|
|
24800
|
-
check(value[k], propSchema, `${
|
|
24966
|
+
check(value[k], propSchema, `${path49}.${k}`);
|
|
24801
24967
|
}
|
|
24802
24968
|
}
|
|
24803
24969
|
}
|
|
24804
24970
|
check(data, schema, "$");
|
|
24805
24971
|
return { valid: errors.length === 0, errors };
|
|
24806
24972
|
}
|
|
24807
|
-
function simpleQuery(data,
|
|
24808
|
-
const parts =
|
|
24973
|
+
function simpleQuery(data, path49) {
|
|
24974
|
+
const parts = path49.replace(/\[(\d+)\]/g, ".$1").split(".").filter(Boolean);
|
|
24809
24975
|
let current = data;
|
|
24810
24976
|
for (const part of parts) {
|
|
24811
24977
|
if (current === null || current === void 0) return void 0;
|
|
@@ -27477,7 +27643,7 @@ async function dockerLogs(service, lines, filterRe, cwd, signal, since) {
|
|
|
27477
27643
|
};
|
|
27478
27644
|
}
|
|
27479
27645
|
args.push("--timestamps", service);
|
|
27480
|
-
return new Promise((
|
|
27646
|
+
return new Promise((resolve23) => {
|
|
27481
27647
|
let stdout = "";
|
|
27482
27648
|
let stderr = "";
|
|
27483
27649
|
const MAX = 2e5;
|
|
@@ -27493,7 +27659,7 @@ async function dockerLogs(service, lines, filterRe, cwd, signal, since) {
|
|
|
27493
27659
|
if (settled) return;
|
|
27494
27660
|
settled = true;
|
|
27495
27661
|
clearTimeout(timer);
|
|
27496
|
-
|
|
27662
|
+
resolve23(result);
|
|
27497
27663
|
};
|
|
27498
27664
|
const child = spawn11("docker", args, {
|
|
27499
27665
|
cwd,
|
|
@@ -27538,7 +27704,7 @@ async function dockerLogs(service, lines, filterRe, cwd, signal, since) {
|
|
|
27538
27704
|
}
|
|
27539
27705
|
var DOCKER_LOGS_TIMEOUT_MS = 3e3;
|
|
27540
27706
|
var MAX_TAIL_LINES = 1e5;
|
|
27541
|
-
async function fileLogs(
|
|
27707
|
+
async function fileLogs(path49, lines, filterRe) {
|
|
27542
27708
|
const { createInterface } = await import("node:readline");
|
|
27543
27709
|
const { createReadStream: createReadStream2 } = await import("node:fs");
|
|
27544
27710
|
const entries = [];
|
|
@@ -27547,7 +27713,7 @@ async function fileLogs(path48, lines, filterRe) {
|
|
|
27547
27713
|
let writeIdx = 0;
|
|
27548
27714
|
let totalLines = 0;
|
|
27549
27715
|
const rl = createInterface({
|
|
27550
|
-
input: createReadStream2(
|
|
27716
|
+
input: createReadStream2(path49),
|
|
27551
27717
|
crlfDelay: Number.POSITIVE_INFINITY
|
|
27552
27718
|
});
|
|
27553
27719
|
for await (const line of rl) {
|
|
@@ -27568,7 +27734,7 @@ async function fileLogs(path48, lines, filterRe) {
|
|
|
27568
27734
|
if (parsed) entries.push(parsed);
|
|
27569
27735
|
}
|
|
27570
27736
|
return {
|
|
27571
|
-
source:
|
|
27737
|
+
source: path49,
|
|
27572
27738
|
entries,
|
|
27573
27739
|
total: entries.length,
|
|
27574
27740
|
truncated: totalLines > effLines,
|
|
@@ -27710,7 +27876,7 @@ var outdatedTool = {
|
|
|
27710
27876
|
}
|
|
27711
27877
|
};
|
|
27712
27878
|
function runOutdated(manager, args, cwd, signal) {
|
|
27713
|
-
return new Promise((
|
|
27879
|
+
return new Promise((resolve23) => {
|
|
27714
27880
|
let stdout = "";
|
|
27715
27881
|
let stderr = "";
|
|
27716
27882
|
const MAX = 1e5;
|
|
@@ -27735,10 +27901,10 @@ function runOutdated(manager, args, cwd, signal) {
|
|
|
27735
27901
|
});
|
|
27736
27902
|
child.on("close", (code) => {
|
|
27737
27903
|
const result = parseOutdatedOutput(stdout, code ?? 0);
|
|
27738
|
-
|
|
27904
|
+
resolve23(result);
|
|
27739
27905
|
});
|
|
27740
27906
|
child.on("error", (e) => {
|
|
27741
|
-
|
|
27907
|
+
resolve23({
|
|
27742
27908
|
exit_code: 1,
|
|
27743
27909
|
packages: [],
|
|
27744
27910
|
total: 0,
|
|
@@ -27798,10 +27964,10 @@ Note: exit code 1 from \`outdated\` means outdated packages were found (expected
|
|
|
27798
27964
|
// src/patch.ts
|
|
27799
27965
|
init_util();
|
|
27800
27966
|
import { spawn as spawn13 } from "node:child_process";
|
|
27801
|
-
import * as
|
|
27967
|
+
import * as fs35 from "node:fs/promises";
|
|
27802
27968
|
import * as os9 from "node:os";
|
|
27803
|
-
import * as
|
|
27804
|
-
import { buildChildEnv as buildChildEnv8, toErrorMessage as
|
|
27969
|
+
import * as path42 from "node:path";
|
|
27970
|
+
import { buildChildEnv as buildChildEnv8, toErrorMessage as toErrorMessage14 } from "@wrongstack/core/utils";
|
|
27805
27971
|
var patchTool = {
|
|
27806
27972
|
name: "patch",
|
|
27807
27973
|
category: "Filesystem",
|
|
@@ -27845,26 +28011,26 @@ var patchTool = {
|
|
|
27845
28011
|
try {
|
|
27846
28012
|
dir = input.directory ? await safeResolveReal(input.directory, ctx) : ctx.cwd;
|
|
27847
28013
|
} catch (err) {
|
|
27848
|
-
return refuse(`patch refused: ${
|
|
28014
|
+
return refuse(`patch refused: ${toErrorMessage14(err)}`);
|
|
27849
28015
|
}
|
|
27850
|
-
const realRoot = await
|
|
28016
|
+
const realRoot = await fs35.realpath(ctx.projectRoot).catch(() => path42.resolve(ctx.projectRoot));
|
|
27851
28017
|
const targets = extractDiffTargets(input.patch);
|
|
27852
28018
|
const resolvedTargets = [];
|
|
27853
28019
|
for (const t of targets) {
|
|
27854
28020
|
const stripped = stripPathComponents(t.raw, strip);
|
|
27855
28021
|
if (!stripped) continue;
|
|
27856
|
-
if (
|
|
28022
|
+
if (path42.isAbsolute(stripped)) {
|
|
27857
28023
|
return refuse(`patch refused: target "${t.raw}" strips to absolute path`);
|
|
27858
28024
|
}
|
|
27859
|
-
const candidate =
|
|
28025
|
+
const candidate = path42.resolve(dir, stripped);
|
|
27860
28026
|
let real;
|
|
27861
28027
|
try {
|
|
27862
28028
|
real = await resolveRealInsideRoot(candidate, ctx);
|
|
27863
28029
|
} catch (err) {
|
|
27864
|
-
return refuse(`patch refused: target "${t.raw}" ${
|
|
28030
|
+
return refuse(`patch refused: target "${t.raw}" ${toErrorMessage14(err)}`);
|
|
27865
28031
|
}
|
|
27866
|
-
const rel =
|
|
27867
|
-
if (rel.startsWith("..") ||
|
|
28032
|
+
const rel = path42.relative(realRoot, real);
|
|
28033
|
+
if (rel.startsWith("..") || path42.isAbsolute(rel)) {
|
|
27868
28034
|
return refuse(`patch refused: target "${t.raw}" resolves outside project root`);
|
|
27869
28035
|
}
|
|
27870
28036
|
resolvedTargets.push({ raw: t.raw, deleted: t.deleted, abs: real });
|
|
@@ -27873,17 +28039,17 @@ var patchTool = {
|
|
|
27873
28039
|
const beforeExisted = /* @__PURE__ */ new Set();
|
|
27874
28040
|
if (!dryRun) {
|
|
27875
28041
|
for (const target of resolvedTargets) {
|
|
27876
|
-
const existed = (await
|
|
28042
|
+
const existed = (await fs35.stat(target.abs).catch(() => null))?.isFile() ?? false;
|
|
27877
28043
|
if (existed) beforeExisted.add(target.abs);
|
|
27878
28044
|
beforeContents.set(target.abs, await readTextForTracking(target.abs));
|
|
27879
28045
|
}
|
|
27880
28046
|
}
|
|
27881
|
-
const tmpDir = await
|
|
28047
|
+
const tmpDir = await fs35.mkdtemp(path42.join(os9.tmpdir(), ".wstack_patch_"));
|
|
27882
28048
|
try {
|
|
27883
|
-
await
|
|
28049
|
+
await fs35.chmod(tmpDir, 448).catch(() => {
|
|
27884
28050
|
});
|
|
27885
|
-
const patchFile =
|
|
27886
|
-
await
|
|
28051
|
+
const patchFile = path42.join(tmpDir, "in.diff");
|
|
28052
|
+
await fs35.writeFile(patchFile, input.patch, { mode: 384 });
|
|
27887
28053
|
const args = [`-p${strip}`, "--merge", ...dryRun ? ["--dry-run"] : [], "-i", patchFile];
|
|
27888
28054
|
const result = await runPatch(args, dir, opts.signal, {
|
|
27889
28055
|
patchFile,
|
|
@@ -27895,7 +28061,7 @@ var patchTool = {
|
|
|
27895
28061
|
for (const target of resolvedTargets) {
|
|
27896
28062
|
const abs = target.abs;
|
|
27897
28063
|
const before = beforeContents.get(abs) ?? null;
|
|
27898
|
-
const stat21 = await
|
|
28064
|
+
const stat21 = await fs35.stat(abs).catch(() => null);
|
|
27899
28065
|
if (!stat21?.isFile()) {
|
|
27900
28066
|
if (beforeExisted.has(abs)) {
|
|
27901
28067
|
touched.push(abs);
|
|
@@ -27928,7 +28094,7 @@ var patchTool = {
|
|
|
27928
28094
|
}
|
|
27929
28095
|
if (result.exitCode !== 0) {
|
|
27930
28096
|
if (!dryRun) {
|
|
27931
|
-
const partial = touched.length > 0 ? ` ${touched.length} file(s) were still modified on disk and have been recorded for rewind: ${touched.map((p) =>
|
|
28097
|
+
const partial = touched.length > 0 ? ` ${touched.length} file(s) were still modified on disk and have been recorded for rewind: ${touched.map((p) => path42.relative(realRoot, p) || p).join(", ")}.` : "";
|
|
27932
28098
|
return {
|
|
27933
28099
|
applied: touched.length,
|
|
27934
28100
|
rejected: 1,
|
|
@@ -27936,7 +28102,7 @@ var patchTool = {
|
|
|
27936
28102
|
// success path (which returns GNU patch's dir-relative names).
|
|
27937
28103
|
// `touched` entries are realpaths from resolveRealInsideRoot, and
|
|
27938
28104
|
// realRoot is also a realpath, so path.relative is like-for-like.
|
|
27939
|
-
files: touched.map((p) =>
|
|
28105
|
+
files: touched.map((p) => path42.relative(realRoot, p) || p),
|
|
27940
28106
|
dry_run: dryRun,
|
|
27941
28107
|
message: `patch failed: ${result.stderr || result.stdout}${partial}`
|
|
27942
28108
|
};
|
|
@@ -27952,7 +28118,7 @@ var patchTool = {
|
|
|
27952
28118
|
}
|
|
27953
28119
|
const patched = result.engine === "git" ? [
|
|
27954
28120
|
...new Set(
|
|
27955
|
-
resolvedTargets.map((target) =>
|
|
28121
|
+
resolvedTargets.map((target) => path42.relative(dir, target.abs) || target.abs)
|
|
27956
28122
|
)
|
|
27957
28123
|
] : extractPatchedFiles(result.stdout);
|
|
27958
28124
|
return {
|
|
@@ -27963,7 +28129,7 @@ var patchTool = {
|
|
|
27963
28129
|
message: result.stdout || "patch applied"
|
|
27964
28130
|
};
|
|
27965
28131
|
} finally {
|
|
27966
|
-
await
|
|
28132
|
+
await fs35.rm(tmpDir, { recursive: true, force: true }).catch(() => {
|
|
27967
28133
|
});
|
|
27968
28134
|
}
|
|
27969
28135
|
}
|
|
@@ -27971,9 +28137,9 @@ var patchTool = {
|
|
|
27971
28137
|
var MAX_TRACKING_BYTES = 5 * 1024 * 1024;
|
|
27972
28138
|
async function readTextForTracking(absPath) {
|
|
27973
28139
|
try {
|
|
27974
|
-
const stat21 = await
|
|
28140
|
+
const stat21 = await fs35.stat(absPath);
|
|
27975
28141
|
if (!stat21.isFile() || stat21.size > MAX_TRACKING_BYTES) return null;
|
|
27976
|
-
const buf = await
|
|
28142
|
+
const buf = await fs35.readFile(absPath);
|
|
27977
28143
|
if (buf.includes(0)) return null;
|
|
27978
28144
|
return buf.toString("utf8");
|
|
27979
28145
|
} catch {
|
|
@@ -28057,7 +28223,7 @@ function runPatch(args, cwd, signal, fallback) {
|
|
|
28057
28223
|
});
|
|
28058
28224
|
}
|
|
28059
28225
|
function runPatchProcess(command, args, cwd, signal) {
|
|
28060
|
-
return new Promise((
|
|
28226
|
+
return new Promise((resolve23) => {
|
|
28061
28227
|
let stdout = "";
|
|
28062
28228
|
let stderr = "";
|
|
28063
28229
|
const env = { ...buildChildEnv8(), LANG: "C", LC_ALL: "C" };
|
|
@@ -28076,11 +28242,11 @@ function runPatchProcess(command, args, cwd, signal) {
|
|
|
28076
28242
|
});
|
|
28077
28243
|
child.on(
|
|
28078
28244
|
"close",
|
|
28079
|
-
(code) =>
|
|
28245
|
+
(code) => resolve23({ exitCode: code ?? 1, stdout, stderr, unavailable: false })
|
|
28080
28246
|
);
|
|
28081
28247
|
child.on(
|
|
28082
28248
|
"error",
|
|
28083
|
-
(e) =>
|
|
28249
|
+
(e) => resolve23({
|
|
28084
28250
|
exitCode: 1,
|
|
28085
28251
|
stdout: "",
|
|
28086
28252
|
stderr: e.message,
|
|
@@ -28871,9 +29037,9 @@ function mkResult(plan, ok, message, todos) {
|
|
|
28871
29037
|
|
|
28872
29038
|
// src/read.ts
|
|
28873
29039
|
init_util();
|
|
28874
|
-
import * as
|
|
29040
|
+
import * as fs36 from "node:fs/promises";
|
|
28875
29041
|
import { FsError, ToolValidationError as ToolValidationError8 } from "@wrongstack/core/types";
|
|
28876
|
-
import { toErrorMessage as
|
|
29042
|
+
import { toErrorMessage as toErrorMessage15 } from "@wrongstack/core/utils";
|
|
28877
29043
|
var ADVANCED_MODE_META_KEY = "tools.read.advancedMode";
|
|
28878
29044
|
var MAX_BYTES2 = 5 * 1024 * 1024;
|
|
28879
29045
|
var readTool = {
|
|
@@ -28931,7 +29097,7 @@ var readTool = {
|
|
|
28931
29097
|
const shouldIncludeSymbols = input.includeSymbols === true || input.includeSymbols !== false && ctx.meta[ADVANCED_MODE_META_KEY] === true;
|
|
28932
29098
|
let stat21;
|
|
28933
29099
|
try {
|
|
28934
|
-
stat21 = await
|
|
29100
|
+
stat21 = await fs36.stat(absPath);
|
|
28935
29101
|
} catch (err) {
|
|
28936
29102
|
const code = err.code;
|
|
28937
29103
|
if (code === "ENOENT") {
|
|
@@ -28943,7 +29109,7 @@ var readTool = {
|
|
|
28943
29109
|
});
|
|
28944
29110
|
}
|
|
28945
29111
|
throw new FsError({
|
|
28946
|
-
message: `read: failed to stat "${input.path}": ${
|
|
29112
|
+
message: `read: failed to stat "${input.path}": ${toErrorMessage15(err)}`,
|
|
28947
29113
|
code: "FS_READ_FAILED",
|
|
28948
29114
|
path: absPath,
|
|
28949
29115
|
context: { errno: code },
|
|
@@ -28983,7 +29149,7 @@ var readTool = {
|
|
|
28983
29149
|
...symResult2?.symbols ? { symbols: symResult2.symbols } : {}
|
|
28984
29150
|
};
|
|
28985
29151
|
}
|
|
28986
|
-
const buf = await
|
|
29152
|
+
const buf = await fs36.readFile(absPath);
|
|
28987
29153
|
if (isBinaryBuffer(buf)) {
|
|
28988
29154
|
throw new FsError({
|
|
28989
29155
|
message: `read: "${input.path}" appears to be binary`,
|
|
@@ -29150,8 +29316,8 @@ ${interesting.join("\n")}` : "symbols/imports: (none detected)"
|
|
|
29150
29316
|
|
|
29151
29317
|
// src/replace.ts
|
|
29152
29318
|
import { spawn as spawn14 } from "node:child_process";
|
|
29153
|
-
import * as
|
|
29154
|
-
import * as
|
|
29319
|
+
import * as fs37 from "node:fs/promises";
|
|
29320
|
+
import * as path43 from "node:path";
|
|
29155
29321
|
import { ToolValidationError as ToolValidationError9 } from "@wrongstack/core/types";
|
|
29156
29322
|
import {
|
|
29157
29323
|
atomicWrite as atomicWrite4,
|
|
@@ -29234,14 +29400,14 @@ var replaceTool = {
|
|
|
29234
29400
|
const dryRun = input.dry_run ?? true;
|
|
29235
29401
|
const filesInput = Array.isArray(input.files) ? input.files.join(",") : input.files;
|
|
29236
29402
|
const fileList = await resolveFiles2(filesInput, ctx, globRe);
|
|
29237
|
-
const realRoot = await
|
|
29403
|
+
const realRoot = await fs37.realpath(ctx.projectRoot).catch(() => ctx.projectRoot);
|
|
29238
29404
|
const results = [];
|
|
29239
29405
|
let totalReplacements = 0;
|
|
29240
29406
|
let diffBytesUsed = 0;
|
|
29241
29407
|
let diffsOmitted = 0;
|
|
29242
29408
|
let diffsTruncated = 0;
|
|
29243
29409
|
for (const absPath of fileList) {
|
|
29244
|
-
const lstat2 = await
|
|
29410
|
+
const lstat2 = await fs37.lstat(absPath).catch((err) => {
|
|
29245
29411
|
if (err.code === "ENOENT") return null;
|
|
29246
29412
|
throw err;
|
|
29247
29413
|
});
|
|
@@ -29249,17 +29415,17 @@ var replaceTool = {
|
|
|
29249
29415
|
if (lstat2.isSymbolicLink()) continue;
|
|
29250
29416
|
let realPath;
|
|
29251
29417
|
try {
|
|
29252
|
-
realPath = await
|
|
29418
|
+
realPath = await fs37.realpath(absPath);
|
|
29253
29419
|
} catch {
|
|
29254
29420
|
continue;
|
|
29255
29421
|
}
|
|
29256
|
-
const rel =
|
|
29257
|
-
if (rel.startsWith("..") ||
|
|
29258
|
-
const stat21 = await
|
|
29422
|
+
const rel = path43.relative(realRoot, realPath);
|
|
29423
|
+
if (rel.startsWith("..") || path43.isAbsolute(rel)) continue;
|
|
29424
|
+
const stat21 = await fs37.stat(realPath).catch(() => null);
|
|
29259
29425
|
if (!stat21?.isFile()) continue;
|
|
29260
29426
|
let content;
|
|
29261
29427
|
try {
|
|
29262
|
-
const buf = await
|
|
29428
|
+
const buf = await fs37.readFile(realPath);
|
|
29263
29429
|
if (isBinaryBuffer(buf)) continue;
|
|
29264
29430
|
content = buf.toString("utf8");
|
|
29265
29431
|
} catch {
|
|
@@ -29282,7 +29448,7 @@ var replaceTool = {
|
|
|
29282
29448
|
if (!dryRun) {
|
|
29283
29449
|
const newContent = toStyle2(newContentLf, style);
|
|
29284
29450
|
await atomicWrite4(realPath, newContent, { mode: stat21.mode & 511 });
|
|
29285
|
-
const written = await
|
|
29451
|
+
const written = await fs37.stat(realPath).catch(() => null);
|
|
29286
29452
|
if (written) {
|
|
29287
29453
|
ctx.recordRead?.(realPath, written.mtimeMs, "write", sha256hex(newContent));
|
|
29288
29454
|
}
|
|
@@ -29382,8 +29548,8 @@ async function resolveFiles2(filesInput, ctx, extraGlob) {
|
|
|
29382
29548
|
const resolved = [];
|
|
29383
29549
|
for (const p of parts) {
|
|
29384
29550
|
const absPath = await safeResolveReal(p, ctx);
|
|
29385
|
-
if (extraGlob && !passesExtraGlob(extraGlob,
|
|
29386
|
-
const stat21 = await
|
|
29551
|
+
if (extraGlob && !passesExtraGlob(extraGlob, path43.basename(absPath), absPath)) continue;
|
|
29552
|
+
const stat21 = await fs37.stat(absPath).catch(() => null);
|
|
29387
29553
|
if (stat21?.isFile()) {
|
|
29388
29554
|
resolved.push(absPath);
|
|
29389
29555
|
}
|
|
@@ -29397,7 +29563,7 @@ async function globFiles(pattern, base, extraGlob) {
|
|
|
29397
29563
|
const { promise } = spawnRgFind(pattern, base);
|
|
29398
29564
|
const files = await promise;
|
|
29399
29565
|
if (extraGlob) {
|
|
29400
|
-
return files.filter((f) => passesExtraGlob(extraGlob,
|
|
29566
|
+
return files.filter((f) => passesExtraGlob(extraGlob, path43.basename(f), f));
|
|
29401
29567
|
}
|
|
29402
29568
|
return files;
|
|
29403
29569
|
} catch {
|
|
@@ -29407,17 +29573,17 @@ async function globFiles(pattern, base, extraGlob) {
|
|
|
29407
29573
|
}
|
|
29408
29574
|
var rgAvailabilityCache2;
|
|
29409
29575
|
function checkRg() {
|
|
29410
|
-
rgAvailabilityCache2 ??= new Promise((
|
|
29576
|
+
rgAvailabilityCache2 ??= new Promise((resolve23) => {
|
|
29411
29577
|
try {
|
|
29412
29578
|
const p = spawn14("rg", ["--version"], {
|
|
29413
29579
|
env: buildChildEnv9(),
|
|
29414
29580
|
stdio: "ignore",
|
|
29415
29581
|
windowsHide: true
|
|
29416
29582
|
});
|
|
29417
|
-
p.on("error", () =>
|
|
29418
|
-
p.on("close", (code) =>
|
|
29583
|
+
p.on("error", () => resolve23(false));
|
|
29584
|
+
p.on("close", (code) => resolve23(code === 0));
|
|
29419
29585
|
} catch {
|
|
29420
|
-
|
|
29586
|
+
resolve23(false);
|
|
29421
29587
|
}
|
|
29422
29588
|
});
|
|
29423
29589
|
return rgAvailabilityCache2;
|
|
@@ -29443,10 +29609,10 @@ function spawnRgFind(pattern, base) {
|
|
|
29443
29609
|
}
|
|
29444
29610
|
});
|
|
29445
29611
|
return {
|
|
29446
|
-
promise: new Promise((
|
|
29612
|
+
promise: new Promise((resolve23, reject) => {
|
|
29447
29613
|
child.on("error", reject);
|
|
29448
29614
|
child.on("close", () => {
|
|
29449
|
-
|
|
29615
|
+
resolve23(buf.split("\n").filter(Boolean));
|
|
29450
29616
|
});
|
|
29451
29617
|
})
|
|
29452
29618
|
};
|
|
@@ -29457,15 +29623,15 @@ async function globNative(pattern, base, extraGlob) {
|
|
|
29457
29623
|
const walk = async (dir) => {
|
|
29458
29624
|
let entries;
|
|
29459
29625
|
try {
|
|
29460
|
-
entries = await
|
|
29626
|
+
entries = await fs37.readdir(dir, { withFileTypes: true });
|
|
29461
29627
|
} catch {
|
|
29462
29628
|
return;
|
|
29463
29629
|
}
|
|
29464
29630
|
for (const e of entries) {
|
|
29465
29631
|
if (DEFAULT_IGNORE4.includes(e.name)) continue;
|
|
29466
|
-
const full =
|
|
29632
|
+
const full = path43.join(dir, e.name);
|
|
29467
29633
|
try {
|
|
29468
|
-
const stat21 = await
|
|
29634
|
+
const stat21 = await fs37.lstat(full);
|
|
29469
29635
|
if (stat21.isSymbolicLink()) continue;
|
|
29470
29636
|
} catch {
|
|
29471
29637
|
continue;
|
|
@@ -29489,8 +29655,8 @@ async function globNative(pattern, base, extraGlob) {
|
|
|
29489
29655
|
|
|
29490
29656
|
// src/scaffold.ts
|
|
29491
29657
|
init_util();
|
|
29492
|
-
import * as
|
|
29493
|
-
import * as
|
|
29658
|
+
import * as fs38 from "node:fs/promises";
|
|
29659
|
+
import * as path44 from "node:path";
|
|
29494
29660
|
import { atomicWrite as atomicWrite5 } from "@wrongstack/core/utils";
|
|
29495
29661
|
var BUILT_IN_TEMPLATES = {
|
|
29496
29662
|
"npm-package": {
|
|
@@ -29641,16 +29807,16 @@ async function handleBuiltIn(name, templateFiles, cwd, ctx, dryRun, vars) {
|
|
|
29641
29807
|
let filesCreated = 0;
|
|
29642
29808
|
for (const [filePath, content] of Object.entries(templateFiles)) {
|
|
29643
29809
|
const resolvedPath = substituteVars(filePath, name, vars);
|
|
29644
|
-
const joinedPath =
|
|
29645
|
-
const root =
|
|
29646
|
-
const target =
|
|
29647
|
-
const rel =
|
|
29648
|
-
if (rel.startsWith("..") ||
|
|
29810
|
+
const joinedPath = path44.join(cwd, resolvedPath);
|
|
29811
|
+
const root = path44.resolve(ctx.projectRoot);
|
|
29812
|
+
const target = path44.resolve(joinedPath);
|
|
29813
|
+
const rel = path44.relative(root, target);
|
|
29814
|
+
if (rel.startsWith("..") || path44.isAbsolute(rel)) {
|
|
29649
29815
|
throw new Error(`scaffold: generated path "${resolvedPath}" would escape project root`);
|
|
29650
29816
|
}
|
|
29651
29817
|
const fullPath = target;
|
|
29652
29818
|
if (!dryRun) {
|
|
29653
|
-
await
|
|
29819
|
+
await fs38.mkdir(path44.dirname(fullPath), { recursive: true });
|
|
29654
29820
|
await atomicWrite5(fullPath, substituteVars(content, name, vars));
|
|
29655
29821
|
}
|
|
29656
29822
|
files.push(resolvedPath);
|
|
@@ -29683,7 +29849,7 @@ function substituteVars(content, name, vars) {
|
|
|
29683
29849
|
// src/search.ts
|
|
29684
29850
|
import { FetchError as FetchError3, ToolValidationError as ToolValidationError10 } from "@wrongstack/core/types";
|
|
29685
29851
|
import { expectDefined as expectDefined9 } from "@wrongstack/core/utils";
|
|
29686
|
-
import { toErrorMessage as
|
|
29852
|
+
import { toErrorMessage as toErrorMessage16 } from "@wrongstack/core/utils";
|
|
29687
29853
|
var DEFAULT_NUM = 10;
|
|
29688
29854
|
var MAX_RESULTS = 50;
|
|
29689
29855
|
var MAX_SNIPPET_CHARS = 300;
|
|
@@ -29893,9 +30059,9 @@ async function duckduckgoSearch(query, signal) {
|
|
|
29893
30059
|
return { results: parseDuckDuckGo(html, MAX_RESULTS) };
|
|
29894
30060
|
} catch (err) {
|
|
29895
30061
|
console.log(
|
|
29896
|
-
JSON.stringify({ level: "debug", event: "search_failed", query, error:
|
|
30062
|
+
JSON.stringify({ level: "debug", event: "search_failed", query, error: toErrorMessage16(err) })
|
|
29897
30063
|
);
|
|
29898
|
-
return { results: [], error: `duckduckgo unreachable: ${
|
|
30064
|
+
return { results: [], error: `duckduckgo unreachable: ${toErrorMessage16(err)}` };
|
|
29899
30065
|
}
|
|
29900
30066
|
}
|
|
29901
30067
|
function takeFrom(iter, max) {
|
|
@@ -29961,7 +30127,7 @@ async function googleSearch(query, signal) {
|
|
|
29961
30127
|
const html = await fetchWithTimeout(url, signal, TIMEOUT_MS3).then((r) => r.text());
|
|
29962
30128
|
return { results: parseGoogleResults(html, MAX_RESULTS) };
|
|
29963
30129
|
} catch (err) {
|
|
29964
|
-
return { results: [], error: `google unreachable: ${
|
|
30130
|
+
return { results: [], error: `google unreachable: ${toErrorMessage16(err)}` };
|
|
29965
30131
|
}
|
|
29966
30132
|
}
|
|
29967
30133
|
function parseGoogleResults(html, num) {
|
|
@@ -29998,7 +30164,7 @@ async function bingSearch(query, signal) {
|
|
|
29998
30164
|
const html = await fetchWithTimeout(url, signal, TIMEOUT_MS3).then((r) => r.text());
|
|
29999
30165
|
return { results: parseBingResults(html, MAX_RESULTS) };
|
|
30000
30166
|
} catch (err) {
|
|
30001
|
-
return { results: [], error: `bing unreachable: ${
|
|
30167
|
+
return { results: [], error: `bing unreachable: ${toErrorMessage16(err)}` };
|
|
30002
30168
|
}
|
|
30003
30169
|
}
|
|
30004
30170
|
function parseBingResults(html, num) {
|
|
@@ -30096,9 +30262,9 @@ function decodeHtmlEntities(text) {
|
|
|
30096
30262
|
}
|
|
30097
30263
|
|
|
30098
30264
|
// src/security-ast-scan-tool.ts
|
|
30099
|
-
import * as
|
|
30100
|
-
import * as
|
|
30101
|
-
import { toErrorMessage as
|
|
30265
|
+
import * as fs39 from "node:fs/promises";
|
|
30266
|
+
import * as path45 from "node:path";
|
|
30267
|
+
import { toErrorMessage as toErrorMessage17 } from "@wrongstack/core/utils";
|
|
30102
30268
|
var SECRET_PATTERNS = [
|
|
30103
30269
|
{ name: "AWS Access Key", regex: /\b(AKIA[0-9A-Z]{16})\b/ },
|
|
30104
30270
|
{ name: "GitHub Token", regex: /\b(gh[pousr]_[A-Za-z0-9_]{36,255})\b/ },
|
|
@@ -30264,9 +30430,9 @@ var securityAstScanTool = {
|
|
|
30264
30430
|
let targetFile = input.file ?? "inline-code.ts";
|
|
30265
30431
|
let content = input.content;
|
|
30266
30432
|
if (!content && input.file) {
|
|
30267
|
-
const absPath =
|
|
30268
|
-
targetFile =
|
|
30269
|
-
content = await
|
|
30433
|
+
const absPath = path45.isAbsolute(input.file) ? input.file : path45.resolve(projectRoot, input.file);
|
|
30434
|
+
targetFile = path45.relative(projectRoot, absPath).replace(/\\/g, "/");
|
|
30435
|
+
content = await fs39.readFile(absPath, "utf8");
|
|
30270
30436
|
}
|
|
30271
30437
|
if (!content) {
|
|
30272
30438
|
return {
|
|
@@ -30307,15 +30473,15 @@ var securityAstScanTool = {
|
|
|
30307
30473
|
warningCount: 0,
|
|
30308
30474
|
findings: [],
|
|
30309
30475
|
summary: "",
|
|
30310
|
-
error:
|
|
30476
|
+
error: toErrorMessage17(err)
|
|
30311
30477
|
};
|
|
30312
30478
|
}
|
|
30313
30479
|
}
|
|
30314
30480
|
};
|
|
30315
30481
|
|
|
30316
30482
|
// src/set-working-dir.ts
|
|
30317
|
-
import * as
|
|
30318
|
-
import { toErrorMessage as
|
|
30483
|
+
import * as fs40 from "node:fs/promises";
|
|
30484
|
+
import { toErrorMessage as toErrorMessage18 } from "@wrongstack/core/utils";
|
|
30319
30485
|
var setWorkingDirTool = {
|
|
30320
30486
|
name: "set_working_dir",
|
|
30321
30487
|
category: "Context",
|
|
@@ -30349,12 +30515,12 @@ var setWorkingDirTool = {
|
|
|
30349
30515
|
} catch (err) {
|
|
30350
30516
|
return {
|
|
30351
30517
|
current: ctx.workingDir,
|
|
30352
|
-
error:
|
|
30518
|
+
error: toErrorMessage18(err)
|
|
30353
30519
|
};
|
|
30354
30520
|
}
|
|
30355
30521
|
let isDirectory = false;
|
|
30356
30522
|
try {
|
|
30357
|
-
isDirectory = (await
|
|
30523
|
+
isDirectory = (await fs40.stat(resolved)).isDirectory();
|
|
30358
30524
|
} catch {
|
|
30359
30525
|
isDirectory = false;
|
|
30360
30526
|
}
|
|
@@ -30889,7 +31055,7 @@ ${formatTaskList2(file.tasks)}` : file.tasks.length > 0 ? formatTaskList2(file.t
|
|
|
30889
31055
|
init_spawn_stream();
|
|
30890
31056
|
init_util();
|
|
30891
31057
|
init_legacy_bridge();
|
|
30892
|
-
import * as
|
|
31058
|
+
import * as path46 from "node:path";
|
|
30893
31059
|
var testTool = {
|
|
30894
31060
|
name: "test",
|
|
30895
31061
|
category: "Code Quality",
|
|
@@ -30996,7 +31162,7 @@ async function detectRunner(cwd) {
|
|
|
30996
31162
|
const candidates = ["vitest.config.ts", "jest.config.js", ".mocharc.json"];
|
|
30997
31163
|
for (const f of candidates) {
|
|
30998
31164
|
try {
|
|
30999
|
-
await stat21(
|
|
31165
|
+
await stat21(path46.join(cwd, f));
|
|
31000
31166
|
if (f.includes("vitest")) return "vitest";
|
|
31001
31167
|
if (f.includes("jest")) return "jest";
|
|
31002
31168
|
if (f.includes("mocha")) return "mocha";
|
|
@@ -31373,8 +31539,8 @@ var toolUseTool = {
|
|
|
31373
31539
|
|
|
31374
31540
|
// src/tree.ts
|
|
31375
31541
|
init_util();
|
|
31376
|
-
import * as
|
|
31377
|
-
import * as
|
|
31542
|
+
import * as fs41 from "node:fs/promises";
|
|
31543
|
+
import * as path47 from "node:path";
|
|
31378
31544
|
import { DEFAULT_WALK_IGNORE_DIRS as DEFAULT_WALK_IGNORE_DIRS4, expectDefined as expectDefined10 } from "@wrongstack/core/utils";
|
|
31379
31545
|
var DEFAULT_IGNORE5 = /* @__PURE__ */ new Set([
|
|
31380
31546
|
...DEFAULT_WALK_IGNORE_DIRS4,
|
|
@@ -31537,7 +31703,7 @@ var treeTool = {
|
|
|
31537
31703
|
async function walkDir(dir, depth, opts) {
|
|
31538
31704
|
opts.signal.throwIfAborted();
|
|
31539
31705
|
if (opts.retention.truncated) return;
|
|
31540
|
-
const entries = await
|
|
31706
|
+
const entries = await fs41.readdir(dir, { withFileTypes: true }).catch(() => []);
|
|
31541
31707
|
const filtered = entries.filter((e) => {
|
|
31542
31708
|
if (!opts.showHidden && e.name.startsWith(".")) return false;
|
|
31543
31709
|
if (opts.exclude.has(e.name)) return false;
|
|
@@ -31579,7 +31745,7 @@ async function walkDir(dir, depth, opts) {
|
|
|
31579
31745
|
opts.retention.outputBytes += lineBytes;
|
|
31580
31746
|
if (entry.isDirectory() && (opts.maxDepth === 0 || depth < opts.maxDepth)) {
|
|
31581
31747
|
const childPrefix = opts.prefix + connector;
|
|
31582
|
-
await walkDir(
|
|
31748
|
+
await walkDir(path47.join(dir, entry.name), depth + 1, {
|
|
31583
31749
|
...opts,
|
|
31584
31750
|
prefix: childPrefix,
|
|
31585
31751
|
isLast
|
|
@@ -31592,7 +31758,7 @@ async function walkDir(dir, depth, opts) {
|
|
|
31592
31758
|
init_spawn_stream();
|
|
31593
31759
|
init_util();
|
|
31594
31760
|
init_legacy_bridge();
|
|
31595
|
-
import * as
|
|
31761
|
+
import * as path48 from "node:path";
|
|
31596
31762
|
var typecheckTool = {
|
|
31597
31763
|
name: "typecheck",
|
|
31598
31764
|
category: "Code Quality",
|
|
@@ -31704,8 +31870,8 @@ async function findTsConfig(cwd) {
|
|
|
31704
31870
|
const candidates = ["tsconfig.json", "tsconfig.base.json"];
|
|
31705
31871
|
for (const f of candidates) {
|
|
31706
31872
|
try {
|
|
31707
|
-
const s = await stat21(
|
|
31708
|
-
if (s.isFile()) return
|
|
31873
|
+
const s = await stat21(path48.join(cwd, f));
|
|
31874
|
+
if (s.isFile()) return path48.join(cwd, f);
|
|
31709
31875
|
} catch {
|
|
31710
31876
|
}
|
|
31711
31877
|
}
|
|
@@ -31713,7 +31879,7 @@ async function findTsConfig(cwd) {
|
|
|
31713
31879
|
}
|
|
31714
31880
|
|
|
31715
31881
|
// src/write.ts
|
|
31716
|
-
import * as
|
|
31882
|
+
import * as fs42 from "node:fs/promises";
|
|
31717
31883
|
import { ToolValidationError as ToolValidationError11 } from "@wrongstack/core/types";
|
|
31718
31884
|
import {
|
|
31719
31885
|
atomicWrite as atomicWrite6,
|
|
@@ -31790,14 +31956,14 @@ async function prepareWrite(input, ctx) {
|
|
|
31790
31956
|
let existed = false;
|
|
31791
31957
|
let prev = "";
|
|
31792
31958
|
try {
|
|
31793
|
-
const stat21 = await
|
|
31959
|
+
const stat21 = await fs42.stat(absPath);
|
|
31794
31960
|
existed = stat21.isFile();
|
|
31795
31961
|
if (existed) {
|
|
31796
31962
|
if (!ctx.hasRead(absPath)) {
|
|
31797
|
-
prev = await
|
|
31963
|
+
prev = await fs42.readFile(absPath, "utf8");
|
|
31798
31964
|
ctx.recordRead(absPath, stat21.mtimeMs, "write", sha256hex(prev));
|
|
31799
31965
|
} else {
|
|
31800
|
-
prev = await
|
|
31966
|
+
prev = await fs42.readFile(absPath, "utf8");
|
|
31801
31967
|
}
|
|
31802
31968
|
}
|
|
31803
31969
|
} catch (err) {
|
|
@@ -31818,7 +31984,7 @@ async function finishWrite(input, ctx, prepared, signal) {
|
|
|
31818
31984
|
const rawDiff = prepared.existed ? unifiedDiff3(prepared.prev, content, { fromFile: input.path, toFile: input.path }) : `+++ ${input.path}
|
|
31819
31985
|
+ (new file, ${content.split("\n").length} lines)`;
|
|
31820
31986
|
const { text: diff, truncated: diffTruncated } = truncateDiffPayload(rawDiff, MAX_DIFF_BYTES3);
|
|
31821
|
-
const stat21 = await
|
|
31987
|
+
const stat21 = await fs42.stat(prepared.absPath);
|
|
31822
31988
|
ctx.recordRead(prepared.absPath, stat21.mtimeMs, "write", sha256hex(content));
|
|
31823
31989
|
ctx.session.recordFileChange({
|
|
31824
31990
|
path: prepared.absPath,
|
|
@@ -31876,6 +32042,7 @@ var builtinTools = [
|
|
|
31876
32042
|
editTool,
|
|
31877
32043
|
clarifyTool,
|
|
31878
32044
|
codebaseAstReplaceTool,
|
|
32045
|
+
codebaseInvariantCheckTool,
|
|
31879
32046
|
codebaseStatsTool,
|
|
31880
32047
|
codebaseSearchTool,
|
|
31881
32048
|
codebaseSkeletonTool,
|