@wrongstack/tools 0.9.7 → 0.9.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/audit.js.map +1 -1
- package/dist/bash.js +0 -3
- package/dist/bash.js.map +1 -1
- package/dist/builtin.js +67 -30
- package/dist/builtin.js.map +1 -1
- package/dist/circuit-breaker.d.ts +0 -2
- package/dist/circuit-breaker.js +0 -3
- package/dist/circuit-breaker.js.map +1 -1
- package/dist/codebase-index/index.d.ts +2 -2
- package/dist/codebase-index/index.js +2 -2
- package/dist/codebase-index/index.js.map +1 -1
- package/dist/{codebase-stats-tool-BLhQmPNc.d.ts → codebase-stats-tool-C8ApERbn.d.ts} +0 -11
- package/dist/diff.js +15 -5
- package/dist/diff.js.map +1 -1
- package/dist/document.js +1 -2
- package/dist/document.js.map +1 -1
- package/dist/edit.js +31 -1
- package/dist/edit.js.map +1 -1
- package/dist/exec.js +0 -3
- package/dist/exec.js.map +1 -1
- package/dist/fetch.d.ts +10 -1
- package/dist/fetch.js +6 -7
- package/dist/fetch.js.map +1 -1
- package/dist/format.js.map +1 -1
- package/dist/glob.js.map +1 -1
- package/dist/grep.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +65 -28
- package/dist/index.js.map +1 -1
- package/dist/install.js.map +1 -1
- package/dist/json.js.map +1 -1
- package/dist/lint.js.map +1 -1
- package/dist/logs.js +4 -0
- package/dist/logs.js.map +1 -1
- package/dist/outdated.js.map +1 -1
- package/dist/pack.js +67 -30
- package/dist/pack.js.map +1 -1
- package/dist/patch.js.map +1 -1
- package/dist/process-registry.js +0 -3
- package/dist/process-registry.js.map +1 -1
- package/dist/read.js +37 -5
- package/dist/read.js.map +1 -1
- package/dist/replace.js +0 -1
- package/dist/replace.js.map +1 -1
- package/dist/scaffold.js.map +1 -1
- package/dist/search.js +177 -5
- package/dist/search.js.map +1 -1
- package/dist/test.js.map +1 -1
- package/dist/tree.js.map +1 -1
- package/dist/typecheck.js.map +1 -1
- package/dist/write.js +31 -1
- package/dist/write.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -34,6 +34,36 @@ function ensureInsideRoot(absPath, ctx) {
|
|
|
34
34
|
function safeResolve(input, ctx) {
|
|
35
35
|
return ensureInsideRoot(resolvePath(input, ctx), ctx);
|
|
36
36
|
}
|
|
37
|
+
async function assertRealInsideRoot(absPath, ctx) {
|
|
38
|
+
const realRoot = await fs4.realpath(ctx.projectRoot).catch(() => path.resolve(ctx.projectRoot));
|
|
39
|
+
let probe = absPath;
|
|
40
|
+
for (; ; ) {
|
|
41
|
+
let real;
|
|
42
|
+
try {
|
|
43
|
+
real = await fs4.realpath(probe);
|
|
44
|
+
} catch (err) {
|
|
45
|
+
if (err.code === "ENOENT") {
|
|
46
|
+
const parent = path.dirname(probe);
|
|
47
|
+
if (parent === probe) return;
|
|
48
|
+
probe = parent;
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
throw err;
|
|
52
|
+
}
|
|
53
|
+
const rel = path.relative(realRoot, real);
|
|
54
|
+
if (rel.startsWith("..") || path.isAbsolute(rel)) {
|
|
55
|
+
throw new Error(
|
|
56
|
+
`Path "${absPath}" resolves through a symlink outside project root "${realRoot}"`
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
async function safeResolveReal(input, ctx) {
|
|
63
|
+
const abs = safeResolve(input, ctx);
|
|
64
|
+
await assertRealInsideRoot(abs, ctx);
|
|
65
|
+
return abs;
|
|
66
|
+
}
|
|
37
67
|
function truncateMiddle(s, max) {
|
|
38
68
|
if (Buffer.byteLength(s, "utf8") <= max) return s;
|
|
39
69
|
const half = Math.floor(max / 2);
|
|
@@ -71,14 +101,16 @@ var readTool = {
|
|
|
71
101
|
},
|
|
72
102
|
async execute(input, ctx) {
|
|
73
103
|
if (!input?.path) throw new Error("read: path is required");
|
|
74
|
-
const absPath =
|
|
104
|
+
const absPath = await safeResolveReal(input.path, ctx);
|
|
75
105
|
let stat11;
|
|
76
106
|
try {
|
|
77
107
|
stat11 = await fs4.stat(absPath);
|
|
78
108
|
} catch (err) {
|
|
79
109
|
const code = err.code;
|
|
80
110
|
if (code === "ENOENT") throw new Error(`read: file not found "${input.path}"`);
|
|
81
|
-
throw new Error(
|
|
111
|
+
throw new Error(
|
|
112
|
+
`read: failed to stat "${input.path}": ${err instanceof Error ? err.message : String(err)}`
|
|
113
|
+
);
|
|
82
114
|
}
|
|
83
115
|
if (!stat11.isFile()) throw new Error(`read: "${input.path}" is not a regular file`);
|
|
84
116
|
if (stat11.size > MAX_BYTES) {
|
|
@@ -129,7 +161,7 @@ var writeTool = {
|
|
|
129
161
|
async execute(input, ctx) {
|
|
130
162
|
if (!input?.path) throw new Error("write: path is required");
|
|
131
163
|
if (input.content === void 0) throw new Error("write: content is required");
|
|
132
|
-
const absPath =
|
|
164
|
+
const absPath = await safeResolveReal(input.path, ctx);
|
|
133
165
|
let existed = false;
|
|
134
166
|
let prev = "";
|
|
135
167
|
try {
|
|
@@ -190,7 +222,7 @@ var editTool = {
|
|
|
190
222
|
if (input.old_string === void 0) throw new Error("edit: old_string is required");
|
|
191
223
|
if (input.new_string === void 0) throw new Error("edit: new_string is required");
|
|
192
224
|
if (input.old_string === "") throw new Error("edit: old_string cannot be empty");
|
|
193
|
-
const absPath =
|
|
225
|
+
const absPath = await safeResolveReal(input.path, ctx);
|
|
194
226
|
const stat11 = await fs4.stat(absPath).catch((err) => {
|
|
195
227
|
if (err.code === "ENOENT") {
|
|
196
228
|
throw new Error(`edit: file "${input.path}" does not exist. Use \`write\` instead.`);
|
|
@@ -454,7 +486,6 @@ async function resolveFiles(filesInput, ctx, extraGlob) {
|
|
|
454
486
|
return resolved;
|
|
455
487
|
}
|
|
456
488
|
async function globFiles(pattern, base, extraGlob) {
|
|
457
|
-
const { spawn: spawn11 } = await import('node:child_process');
|
|
458
489
|
const rgAvailable = await checkRg();
|
|
459
490
|
if (rgAvailable) {
|
|
460
491
|
try {
|
|
@@ -886,8 +917,6 @@ var CircuitBreaker = class {
|
|
|
886
917
|
lastSlowAt = null;
|
|
887
918
|
/** Timestamp when the breaker was opened (for cooldown calculation). */
|
|
888
919
|
openedAt = null;
|
|
889
|
-
/** Timestamp when the last call ran (for half-open gate). */
|
|
890
|
-
lastCallAt = null;
|
|
891
920
|
constructor(config = {}) {
|
|
892
921
|
this.maxConsecutiveFailures = config.maxConsecutiveFailures ?? DEFAULT_MAX_CONSECUTIVE_FAILURES;
|
|
893
922
|
this.slowCallThresholdMs = config.slowCallThresholdMs ?? DEFAULT_SLOW_CALL_THRESHOLD_MS;
|
|
@@ -945,7 +974,6 @@ var CircuitBreaker = class {
|
|
|
945
974
|
*/
|
|
946
975
|
afterCall(durationMs, failed) {
|
|
947
976
|
const now = Date.now();
|
|
948
|
-
this.lastCallAt = now;
|
|
949
977
|
if (this.state === "half-open") {
|
|
950
978
|
if (failed) {
|
|
951
979
|
this._trip();
|
|
@@ -1760,11 +1788,10 @@ function getPinnedDispatcher() {
|
|
|
1760
1788
|
}
|
|
1761
1789
|
return pinnedAgent;
|
|
1762
1790
|
}
|
|
1763
|
-
async function
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
};
|
|
1791
|
+
async function guardedFetch(url, maxRedirects, signal, headers = {
|
|
1792
|
+
"user-agent": "WrongStack/1.0 (+https://wrongstack.com)",
|
|
1793
|
+
accept: "text/html,application/json;q=0.9,text/plain;q=0.8,*/*;q=0.1"
|
|
1794
|
+
}) {
|
|
1768
1795
|
let redirectCount = 0;
|
|
1769
1796
|
let currentUrl = url;
|
|
1770
1797
|
for (; ; ) {
|
|
@@ -1842,7 +1869,7 @@ var fetchTool = {
|
|
|
1842
1869
|
const timer = setTimeout(() => ctrl.abort(new Error("fetch timeout")), TIMEOUT_MS2);
|
|
1843
1870
|
const combined = combineSignals(opts.signal, ctrl.signal);
|
|
1844
1871
|
try {
|
|
1845
|
-
const res = await
|
|
1872
|
+
const res = await guardedFetch(input.url, 5, combined);
|
|
1846
1873
|
const ct = res.headers.get("content-type") ?? "application/octet-stream";
|
|
1847
1874
|
if (/^image\/|^audio\/|^video\/|application\/octet-stream/.test(ct)) {
|
|
1848
1875
|
throw new Error(`fetch: refusing to read binary content-type "${ct}"`);
|
|
@@ -2234,11 +2261,8 @@ async function fetchWithTimeout(url, signal, timeoutMs) {
|
|
|
2234
2261
|
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
2235
2262
|
const fetchSignal = anySignal(signal, controller.signal);
|
|
2236
2263
|
try {
|
|
2237
|
-
const res = await
|
|
2238
|
-
|
|
2239
|
-
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
|
|
2240
|
-
},
|
|
2241
|
-
signal: fetchSignal
|
|
2264
|
+
const res = await guardedFetch(url, 5, fetchSignal, {
|
|
2265
|
+
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
|
|
2242
2266
|
});
|
|
2243
2267
|
clearTimeout(timer);
|
|
2244
2268
|
return res;
|
|
@@ -2957,6 +2981,12 @@ var diffTool = {
|
|
|
2957
2981
|
}
|
|
2958
2982
|
};
|
|
2959
2983
|
async function gitDiff(input, ctx, signal) {
|
|
2984
|
+
if (input.a?.startsWith("-")) {
|
|
2985
|
+
throw new Error(`diff: unsafe ref "${input.a}" \u2014 refs may not begin with '-' (flag injection)`);
|
|
2986
|
+
}
|
|
2987
|
+
if (input.b?.startsWith("-")) {
|
|
2988
|
+
throw new Error(`diff: unsafe ref "${input.b}" \u2014 refs may not begin with '-' (flag injection)`);
|
|
2989
|
+
}
|
|
2960
2990
|
const gitDir = findGitDir2(ctx.cwd);
|
|
2961
2991
|
if (!gitDir) {
|
|
2962
2992
|
return { diff: "", files: [], truncated: false, mode: "unified" };
|
|
@@ -2995,7 +3025,12 @@ function runGit2(args, cwd, signal) {
|
|
|
2995
3025
|
return new Promise((resolve7) => {
|
|
2996
3026
|
let stdout = "";
|
|
2997
3027
|
let stderr = "";
|
|
2998
|
-
const child = spawn("git", args, {
|
|
3028
|
+
const child = spawn("git", args, {
|
|
3029
|
+
cwd,
|
|
3030
|
+
signal,
|
|
3031
|
+
env: buildChildEnv(),
|
|
3032
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
3033
|
+
});
|
|
2999
3034
|
child.stdout?.on("data", (c) => {
|
|
3000
3035
|
stdout += c.toString();
|
|
3001
3036
|
});
|
|
@@ -3006,8 +3041,7 @@ function runGit2(args, cwd, signal) {
|
|
|
3006
3041
|
child.on("error", (e) => resolve7({ stdout: "", stderr: e.message, exitCode: 1 }));
|
|
3007
3042
|
});
|
|
3008
3043
|
}
|
|
3009
|
-
async function fileDiff(input, ctx,
|
|
3010
|
-
input.path ? safeResolve(input.path, ctx) : ctx.cwd;
|
|
3044
|
+
async function fileDiff(input, ctx, _signal) {
|
|
3011
3045
|
input.context ?? 3;
|
|
3012
3046
|
const files = input.files ? (Array.isArray(input.files) ? input.files : input.files.split(",")).map((f) => f.trim()).filter(Boolean) : [];
|
|
3013
3047
|
if (files.length === 0) {
|
|
@@ -3036,8 +3070,8 @@ ${formatUnified(lines)}`);
|
|
|
3036
3070
|
mode: input.mode ?? "unified"
|
|
3037
3071
|
};
|
|
3038
3072
|
}
|
|
3039
|
-
function formatUnified(lines,
|
|
3040
|
-
return lines.map((line,
|
|
3073
|
+
function formatUnified(lines, _context) {
|
|
3074
|
+
return lines.map((line, _i) => ` ${line}`).join("\n");
|
|
3041
3075
|
}
|
|
3042
3076
|
var DEFAULT_IGNORE4 = [
|
|
3043
3077
|
"node_modules",
|
|
@@ -4143,6 +4177,10 @@ async function dockerLogs(service, lines, filterRe, cwd, signal, since) {
|
|
|
4143
4177
|
child.stderr?.on("data", (c) => {
|
|
4144
4178
|
if (stderr.length < MAX) stderr += c.toString();
|
|
4145
4179
|
});
|
|
4180
|
+
child.stdout?.on("error", () => {
|
|
4181
|
+
});
|
|
4182
|
+
child.stderr?.on("error", () => {
|
|
4183
|
+
});
|
|
4146
4184
|
child.on("close", () => {
|
|
4147
4185
|
const output = stdout + stderr;
|
|
4148
4186
|
const entries = parseLogLines(output, filterRe);
|
|
@@ -4319,9 +4357,8 @@ async function resolveFiles2(filesInput, cwd) {
|
|
|
4319
4357
|
}
|
|
4320
4358
|
return resolved;
|
|
4321
4359
|
}
|
|
4322
|
-
function processFile(content, absPath,
|
|
4360
|
+
function processFile(content, absPath, _style, _overwrite, target) {
|
|
4323
4361
|
const results = [];
|
|
4324
|
-
content.split("\n");
|
|
4325
4362
|
const functionRegex = /(?:async\s+)?function\s+(\w+)\s*\(([^)]*)\)/g;
|
|
4326
4363
|
const arrowRegex = /(?:const|let|var)\s+(\w+)\s*=\s*(?:async\s+)?\(([^)]*)\)\s*=>/g;
|
|
4327
4364
|
const classRegex = /class\s+(\w+)/g;
|
|
@@ -6236,7 +6273,7 @@ function regexParse(opts) {
|
|
|
6236
6273
|
}
|
|
6237
6274
|
return lo + 1;
|
|
6238
6275
|
}
|
|
6239
|
-
function extractDeclaration(lineIdx,
|
|
6276
|
+
function extractDeclaration(lineIdx, _match) {
|
|
6240
6277
|
const line = lines[lineIdx] ?? "";
|
|
6241
6278
|
return line.trim().slice(0, 500);
|
|
6242
6279
|
}
|
|
@@ -6701,7 +6738,7 @@ async function parseFile(file, content, lang) {
|
|
|
6701
6738
|
return { file, lang, symbols: [], mtimeMs: Date.now() };
|
|
6702
6739
|
}
|
|
6703
6740
|
}
|
|
6704
|
-
async function runIndexer(
|
|
6741
|
+
async function runIndexer(_ctx, opts) {
|
|
6705
6742
|
const { projectRoot, force = false, langs, ignore = [] } = opts;
|
|
6706
6743
|
const store = new IndexStore(projectRoot);
|
|
6707
6744
|
const startMs = Date.now();
|