@wrongstack/tools 0.8.2 → 0.8.5
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 +100 -23
- package/dist/builtin.js.map +1 -1
- package/dist/codebase-index/index.js +14 -6
- package/dist/codebase-index/index.js.map +1 -1
- package/dist/exec.js +14 -2
- package/dist/exec.js.map +1 -1
- package/dist/fetch.js +48 -3
- package/dist/fetch.js.map +1 -1
- package/dist/index.js +100 -23
- package/dist/index.js.map +1 -1
- package/dist/logs.js +22 -11
- package/dist/logs.js.map +1 -1
- package/dist/pack.js +100 -23
- package/dist/pack.js.map +1 -1
- package/dist/replace.js +2 -1
- package/dist/replace.js.map +1 -1
- package/package.json +3 -2
package/dist/builtin.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { spawn,
|
|
1
|
+
import { spawn, execFileSync, spawnSync } from 'node:child_process';
|
|
2
2
|
import { buildChildEnv, stripAnsi, detectNewlineStyle, normalizeToLf, toStyle, atomicWrite, unifiedDiff, compileGlob, loadPlan, emptyPlan, clearPlan, savePlan, getPlanTemplate, addPlanItem, deriveTodosFromPlanItem, removePlanItem, setPlanItemStatus, formatPlan } from '@wrongstack/core';
|
|
3
3
|
import * as path from 'node:path';
|
|
4
4
|
import { dirname } from 'node:path';
|
|
@@ -11,6 +11,7 @@ import { statSync, mkdirSync, writeFileSync } from 'node:fs';
|
|
|
11
11
|
import * as ts from 'typescript';
|
|
12
12
|
import * as dns from 'node:dns/promises';
|
|
13
13
|
import * as net from 'node:net';
|
|
14
|
+
import { Agent } from 'undici';
|
|
14
15
|
|
|
15
16
|
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
16
17
|
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
@@ -1716,7 +1717,7 @@ function syncGoParse(filePath, content, lang) {
|
|
|
1716
1717
|
mkdirSync(tmpDir, { recursive: true });
|
|
1717
1718
|
const scriptPath = path.join(tmpDir, "parse.go");
|
|
1718
1719
|
writeFileSync(scriptPath, GO_PARSE_SCRIPT, "utf8");
|
|
1719
|
-
const stdout =
|
|
1720
|
+
const stdout = execFileSync("go", ["run", scriptPath], {
|
|
1720
1721
|
input: content,
|
|
1721
1722
|
timeout: 15e3,
|
|
1722
1723
|
encoding: "utf8",
|
|
@@ -1962,7 +1963,7 @@ function syncPyParse(filePath, lang) {
|
|
|
1962
1963
|
mkdirSync(tmpDir, { recursive: true });
|
|
1963
1964
|
const scriptPath = path.join(tmpDir, "parse.py");
|
|
1964
1965
|
writeFileSync(scriptPath, PY_PARSE_SCRIPT, "utf8");
|
|
1965
|
-
const stdout =
|
|
1966
|
+
const stdout = execFileSync("python", [scriptPath, filePath], {
|
|
1966
1967
|
timeout: 15e3,
|
|
1967
1968
|
encoding: "utf8",
|
|
1968
1969
|
windowsHide: true
|
|
@@ -2000,11 +2001,19 @@ function parseSymbols4(opts) {
|
|
|
2000
2001
|
}
|
|
2001
2002
|
function checkNativeParser() {
|
|
2002
2003
|
try {
|
|
2003
|
-
|
|
2004
|
+
execFileSync("rustc", ["--version"], { stdio: "pipe" });
|
|
2004
2005
|
const toolsDir = path.join(process.cwd(), "tools");
|
|
2005
2006
|
try {
|
|
2006
|
-
|
|
2007
|
-
"cargo
|
|
2007
|
+
execFileSync(
|
|
2008
|
+
"cargo",
|
|
2009
|
+
[
|
|
2010
|
+
"metadata",
|
|
2011
|
+
"--no-deps",
|
|
2012
|
+
"--format-version",
|
|
2013
|
+
"1",
|
|
2014
|
+
"--manifest-path",
|
|
2015
|
+
path.join(toolsDir, "Cargo.toml")
|
|
2016
|
+
],
|
|
2008
2017
|
{ stdio: "pipe" }
|
|
2009
2018
|
);
|
|
2010
2019
|
return true;
|
|
@@ -3324,8 +3333,20 @@ var BLOCKED_ARG_PATTERNS = {
|
|
|
3324
3333
|
// python -c/--command executes arbitrary code; python -m runs modules
|
|
3325
3334
|
python: [/-c$/, /^--command$/, /^-m$/, /^--module$/],
|
|
3326
3335
|
// git --exec=<cmd> runs arbitrary commands via upload-pack/receive-pack;
|
|
3327
|
-
// -C <dir> changes working directory, bypassing cwd sandbox
|
|
3328
|
-
|
|
3336
|
+
// -C <dir> changes working directory, bypassing cwd sandbox;
|
|
3337
|
+
// -c/--config <k>=<v> injects config that runs commands
|
|
3338
|
+
// (e.g. core.sshCommand, core.pager, http.proxy, alias.x=!cmd).
|
|
3339
|
+
git: [
|
|
3340
|
+
/^--exec=/,
|
|
3341
|
+
/^--upload-pack=/,
|
|
3342
|
+
/^--receive-pack=/,
|
|
3343
|
+
/^-C$/,
|
|
3344
|
+
/^-c$/,
|
|
3345
|
+
/^--config$/,
|
|
3346
|
+
/^-c=/,
|
|
3347
|
+
/^--config=/,
|
|
3348
|
+
/^--config-env=/
|
|
3349
|
+
],
|
|
3329
3350
|
// node -r/--require preloads arbitrary modules; --eval executes code
|
|
3330
3351
|
node: [/^-r$/, /^--require$/, /^-e$/, /^--eval$/, /^--prof-process$/],
|
|
3331
3352
|
// go run could execute arbitrary .go files; -ldflags could inject build-time code
|
|
@@ -3511,6 +3532,48 @@ function runCommand(cmd, args, cwd, timeout, signal, sessionId) {
|
|
|
3511
3532
|
var MAX_BYTES = 131072;
|
|
3512
3533
|
var TIMEOUT_MS2 = 2e4;
|
|
3513
3534
|
var ALLOW_PRIVATE = process.env["WRONGSTACK_FETCH_ALLOW_PRIVATE"] === "1";
|
|
3535
|
+
function guardedLookup(hostname, options, callback) {
|
|
3536
|
+
dns.lookup(hostname, { all: true }).then((records) => {
|
|
3537
|
+
const family = options?.family;
|
|
3538
|
+
const byFamily = family === 4 || family === 6 ? records.filter((r) => r.family === family) : records;
|
|
3539
|
+
const list = byFamily.length > 0 ? byFamily : records;
|
|
3540
|
+
if (!ALLOW_PRIVATE) {
|
|
3541
|
+
for (const r of list) {
|
|
3542
|
+
const bad = r.family === 4 ? isPrivateIPv4(r.address) : isPrivateIPv6(r.address);
|
|
3543
|
+
if (bad) {
|
|
3544
|
+
callback(
|
|
3545
|
+
Object.assign(new Error(`fetch: resolved to private address ${r.address}`), {
|
|
3546
|
+
code: "EAI_FAIL"
|
|
3547
|
+
})
|
|
3548
|
+
);
|
|
3549
|
+
return;
|
|
3550
|
+
}
|
|
3551
|
+
}
|
|
3552
|
+
}
|
|
3553
|
+
if (options?.all) {
|
|
3554
|
+
callback(
|
|
3555
|
+
null,
|
|
3556
|
+
list.map((r) => ({ address: r.address, family: r.family }))
|
|
3557
|
+
);
|
|
3558
|
+
return;
|
|
3559
|
+
}
|
|
3560
|
+
const first = list[0];
|
|
3561
|
+
if (!first) {
|
|
3562
|
+
callback(
|
|
3563
|
+
Object.assign(new Error(`fetch: no address for ${hostname}`), { code: "ENOTFOUND" })
|
|
3564
|
+
);
|
|
3565
|
+
return;
|
|
3566
|
+
}
|
|
3567
|
+
callback(null, first.address, first.family);
|
|
3568
|
+
}).catch((err) => callback(err));
|
|
3569
|
+
}
|
|
3570
|
+
var pinnedAgent;
|
|
3571
|
+
function getPinnedDispatcher() {
|
|
3572
|
+
if (!pinnedAgent) {
|
|
3573
|
+
pinnedAgent = new Agent({ connect: { lookup: guardedLookup } });
|
|
3574
|
+
}
|
|
3575
|
+
return pinnedAgent;
|
|
3576
|
+
}
|
|
3514
3577
|
async function fetchWithRedirectLimit(url, maxRedirects, signal) {
|
|
3515
3578
|
const headers = {
|
|
3516
3579
|
"user-agent": "WrongStack/1.0 (+https://wrongstack.com)",
|
|
@@ -3527,11 +3590,13 @@ async function fetchWithRedirectLimit(url, maxRedirects, signal) {
|
|
|
3527
3590
|
throw new Error("fetch: redirect to http:// blocked (HTTPS required by default)");
|
|
3528
3591
|
}
|
|
3529
3592
|
await assertNotPrivate(parsed.hostname);
|
|
3530
|
-
const
|
|
3593
|
+
const init = {
|
|
3531
3594
|
redirect: "manual",
|
|
3532
3595
|
signal,
|
|
3533
|
-
headers
|
|
3534
|
-
|
|
3596
|
+
headers,
|
|
3597
|
+
dispatcher: getPinnedDispatcher()
|
|
3598
|
+
};
|
|
3599
|
+
const res = await fetch(currentUrl, init);
|
|
3535
3600
|
if (res.status < 300 || res.status > 399) {
|
|
3536
3601
|
return res;
|
|
3537
3602
|
}
|
|
@@ -4906,17 +4971,35 @@ async function dockerLogs(service, lines, filterRe, cwd, signal, since) {
|
|
|
4906
4971
|
let stdout = "";
|
|
4907
4972
|
let stderr = "";
|
|
4908
4973
|
const MAX = 2e5;
|
|
4974
|
+
let settled = false;
|
|
4975
|
+
const empty = () => ({
|
|
4976
|
+
source: `docker:${service}`,
|
|
4977
|
+
entries: [],
|
|
4978
|
+
total: 0,
|
|
4979
|
+
truncated: false,
|
|
4980
|
+
stream_mode: false
|
|
4981
|
+
});
|
|
4982
|
+
const finish = (result) => {
|
|
4983
|
+
if (settled) return;
|
|
4984
|
+
settled = true;
|
|
4985
|
+
clearTimeout(timer);
|
|
4986
|
+
resolve6(result);
|
|
4987
|
+
};
|
|
4909
4988
|
const child = spawn("docker", args, { cwd, signal, env: buildChildEnv(), stdio: ["ignore", "pipe", "pipe"] });
|
|
4989
|
+
const timer = setTimeout(() => {
|
|
4990
|
+
child.kill("SIGTERM");
|
|
4991
|
+
finish(empty());
|
|
4992
|
+
}, DOCKER_LOGS_TIMEOUT_MS);
|
|
4910
4993
|
child.stdout?.on("data", (c) => {
|
|
4911
4994
|
if (stdout.length < MAX) stdout += c.toString();
|
|
4912
4995
|
});
|
|
4913
4996
|
child.stderr?.on("data", (c) => {
|
|
4914
4997
|
if (stderr.length < MAX) stderr += c.toString();
|
|
4915
4998
|
});
|
|
4916
|
-
child.on("close", (
|
|
4999
|
+
child.on("close", () => {
|
|
4917
5000
|
const output = stdout + stderr;
|
|
4918
5001
|
const entries = parseLogLines(output, filterRe);
|
|
4919
|
-
|
|
5002
|
+
finish({
|
|
4920
5003
|
source: `docker:${service}`,
|
|
4921
5004
|
entries,
|
|
4922
5005
|
total: entries.length,
|
|
@@ -4924,17 +5007,10 @@ async function dockerLogs(service, lines, filterRe, cwd, signal, since) {
|
|
|
4924
5007
|
stream_mode: false
|
|
4925
5008
|
});
|
|
4926
5009
|
});
|
|
4927
|
-
child.on("error", (
|
|
4928
|
-
resolve6({
|
|
4929
|
-
source: `docker:${service}`,
|
|
4930
|
-
entries: [],
|
|
4931
|
-
total: 0,
|
|
4932
|
-
truncated: false,
|
|
4933
|
-
stream_mode: false
|
|
4934
|
-
});
|
|
4935
|
-
});
|
|
5010
|
+
child.on("error", () => finish(empty()));
|
|
4936
5011
|
});
|
|
4937
5012
|
}
|
|
5013
|
+
var DOCKER_LOGS_TIMEOUT_MS = 3e3;
|
|
4938
5014
|
var MAX_TAIL_LINES = 1e5;
|
|
4939
5015
|
async function fileLogs(path18, lines, filterRe, stream) {
|
|
4940
5016
|
const { createInterface } = await import('node:readline');
|
|
@@ -5465,6 +5541,7 @@ var replaceTool = {
|
|
|
5465
5541
|
const dryRun = input.dry_run ?? false;
|
|
5466
5542
|
const filesInput = Array.isArray(input.files) ? input.files.join(",") : input.files;
|
|
5467
5543
|
const fileList = await resolveFiles2(filesInput, ctx, globRe);
|
|
5544
|
+
const realRoot = await fs11.realpath(ctx.projectRoot).catch(() => ctx.projectRoot);
|
|
5468
5545
|
const results = [];
|
|
5469
5546
|
let totalReplacements = 0;
|
|
5470
5547
|
for (const absPath of fileList) {
|
|
@@ -5480,7 +5557,7 @@ var replaceTool = {
|
|
|
5480
5557
|
} catch {
|
|
5481
5558
|
continue;
|
|
5482
5559
|
}
|
|
5483
|
-
const rel = path.relative(
|
|
5560
|
+
const rel = path.relative(realRoot, realPath);
|
|
5484
5561
|
if (rel.startsWith("..") || path.isAbsolute(rel)) continue;
|
|
5485
5562
|
const stat11 = await fs11.stat(realPath).catch(() => null);
|
|
5486
5563
|
if (!stat11 || !stat11.isFile()) continue;
|