@wrongstack/tools 0.308.0 → 0.308.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bash-kill-guard.d.ts +1 -0
- package/dist/bash.js +15 -1
- package/dist/builtin.js +612 -143
- package/dist/exec.js +34 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +644 -171
- package/dist/pack.js +611 -143
- package/dist/pwsh.d.ts +22 -0
- package/dist/tool-tier.js +612 -143
- package/package.json +5 -4
package/dist/tool-tier.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((resolve24) => {
|
|
1035
|
+
waiter = resolve24;
|
|
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 fs44 = await import("node:fs/promises");
|
|
1139
1139
|
try {
|
|
1140
|
-
const raw = await
|
|
1140
|
+
const raw = await fs44.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 fs44.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 path50 of after) {
|
|
4141
|
+
if (!beforeSet.has(path50)) changed.add(path50);
|
|
4142
4142
|
}
|
|
4143
|
-
for (const
|
|
4144
|
-
if (!afterSet.has(
|
|
4143
|
+
for (const path50 of before) {
|
|
4144
|
+
if (!afterSet.has(path50)) changed.add(path50);
|
|
4145
4145
|
}
|
|
4146
4146
|
if (beforeSizes && afterSizes) {
|
|
4147
|
-
for (const
|
|
4148
|
-
if (beforeSizes.get(
|
|
4147
|
+
for (const path50 of after) {
|
|
4148
|
+
if (beforeSizes.get(path50) !== afterSizes.get(path50)) changed.add(path50);
|
|
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
|
+
(resolve24, 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
|
+
resolve24({ 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((resolve24) => {
|
|
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
|
+
resolve24(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((resolve24, 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
|
+
resolve24({ code, stdout });
|
|
6400
6400
|
});
|
|
6401
6401
|
});
|
|
6402
6402
|
}
|
|
@@ -8604,6 +8604,18 @@ function parseKillCommand(command) {
|
|
|
8604
8604
|
originalCommand: command
|
|
8605
8605
|
};
|
|
8606
8606
|
}
|
|
8607
|
+
const wmicPidMatch = normalized.match(
|
|
8608
|
+
/^wmic\s+process\s+where\s+['"]?processid\s*=\s*['"]?(\d+)/i
|
|
8609
|
+
);
|
|
8610
|
+
if (wmicPidMatch?.[1]) {
|
|
8611
|
+
return {
|
|
8612
|
+
pid: parseInt(wmicPidMatch[1], 10),
|
|
8613
|
+
signal: "FORCE",
|
|
8614
|
+
isGroupKill: false,
|
|
8615
|
+
isAllKill: false,
|
|
8616
|
+
originalCommand: command
|
|
8617
|
+
};
|
|
8618
|
+
}
|
|
8607
8619
|
const killScriptMatch = normalized.match(SCRIPT_KILL_RE);
|
|
8608
8620
|
if (killScriptMatch) {
|
|
8609
8621
|
return {
|
|
@@ -8723,7 +8735,9 @@ async function isKillProtected(kill) {
|
|
|
8723
8735
|
return protectedPids.length > 0;
|
|
8724
8736
|
}
|
|
8725
8737
|
if (kill.pid !== void 0) {
|
|
8726
|
-
|
|
8738
|
+
if (await registry.shouldBlockKill(kill.pid)) return true;
|
|
8739
|
+
if (kill.pid === process.pid || kill.pid === process.ppid) return true;
|
|
8740
|
+
return false;
|
|
8727
8741
|
}
|
|
8728
8742
|
return false;
|
|
8729
8743
|
}
|
|
@@ -8770,8 +8784,8 @@ async function checkAndBlockKillCommand(command) {
|
|
|
8770
8784
|
|
|
8771
8785
|
// src/_shell-pick.ts
|
|
8772
8786
|
var POSIX_DEFAULT = "cmd";
|
|
8773
|
-
function pickShell(
|
|
8774
|
-
if (
|
|
8787
|
+
function pickShell(platform6, command, env) {
|
|
8788
|
+
if (platform6 !== "win32") return POSIX_DEFAULT;
|
|
8775
8789
|
const override = env.get("WRONGSTACK_SHELL")?.trim().toLowerCase();
|
|
8776
8790
|
if (override === "cmd" || override === "cmd.exe") return "cmd";
|
|
8777
8791
|
if (override === "powershell" || override === "powershell.exe") return "powershell";
|
|
@@ -9230,10 +9244,10 @@ var bashTool = {
|
|
|
9230
9244
|
queue.push(c);
|
|
9231
9245
|
}
|
|
9232
9246
|
};
|
|
9233
|
-
const next = () => new Promise((
|
|
9247
|
+
const next = () => new Promise((resolve24) => {
|
|
9234
9248
|
const c = queue.shift();
|
|
9235
|
-
if (c)
|
|
9236
|
-
else resolveNext =
|
|
9249
|
+
if (c) resolve24(c);
|
|
9250
|
+
else resolveNext = resolve24;
|
|
9237
9251
|
});
|
|
9238
9252
|
let lastFlush = Date.now();
|
|
9239
9253
|
const flush = () => {
|
|
@@ -9696,11 +9710,11 @@ var BrowserArtifactStore = class {
|
|
|
9696
9710
|
};
|
|
9697
9711
|
async function hashFile(target) {
|
|
9698
9712
|
const hash = createHash3("sha256");
|
|
9699
|
-
await new Promise((
|
|
9713
|
+
await new Promise((resolve24, reject) => {
|
|
9700
9714
|
const stream = createReadStream(target);
|
|
9701
9715
|
stream.on("data", (chunk) => hash.update(chunk));
|
|
9702
9716
|
stream.once("error", reject);
|
|
9703
|
-
stream.once("end",
|
|
9717
|
+
stream.once("end", resolve24);
|
|
9704
9718
|
});
|
|
9705
9719
|
return hash.digest("hex");
|
|
9706
9720
|
}
|
|
@@ -9850,7 +9864,7 @@ var BrowserNetworkGuardProxy = class {
|
|
|
9850
9864
|
async start() {
|
|
9851
9865
|
if (this.url) return this.url;
|
|
9852
9866
|
if (this.startPromise) return this.startPromise;
|
|
9853
|
-
this.startPromise = new Promise((
|
|
9867
|
+
this.startPromise = new Promise((resolve24, reject) => {
|
|
9854
9868
|
const onError = (error) => {
|
|
9855
9869
|
this.server.off("listening", onListening);
|
|
9856
9870
|
reject(error);
|
|
@@ -9863,7 +9877,7 @@ var BrowserNetworkGuardProxy = class {
|
|
|
9863
9877
|
return;
|
|
9864
9878
|
}
|
|
9865
9879
|
this.url = `http://127.0.0.1:${address.port}`;
|
|
9866
|
-
|
|
9880
|
+
resolve24(this.url);
|
|
9867
9881
|
};
|
|
9868
9882
|
this.server.once("error", onError);
|
|
9869
9883
|
this.server.once("listening", onListening);
|
|
@@ -9878,7 +9892,7 @@ var BrowserNetworkGuardProxy = class {
|
|
|
9878
9892
|
for (const socket of this.sockets) socket.destroy();
|
|
9879
9893
|
this.sockets.clear();
|
|
9880
9894
|
if (!this.server.listening) return;
|
|
9881
|
-
await new Promise((
|
|
9895
|
+
await new Promise((resolve24) => this.server.close(() => resolve24()));
|
|
9882
9896
|
}
|
|
9883
9897
|
async forwardHttp(request2, response) {
|
|
9884
9898
|
try {
|
|
@@ -10451,7 +10465,7 @@ function pushBounded(target, value, limit) {
|
|
|
10451
10465
|
}
|
|
10452
10466
|
async function abortable(signal, operation, onAbort) {
|
|
10453
10467
|
signal.throwIfAborted();
|
|
10454
|
-
return new Promise((
|
|
10468
|
+
return new Promise((resolve24, reject) => {
|
|
10455
10469
|
let settled = false;
|
|
10456
10470
|
let aborting = false;
|
|
10457
10471
|
const finish = (fn) => {
|
|
@@ -10469,7 +10483,7 @@ async function abortable(signal, operation, onAbort) {
|
|
|
10469
10483
|
signal.addEventListener("abort", abort, { once: true });
|
|
10470
10484
|
operation().then(
|
|
10471
10485
|
(value) => {
|
|
10472
|
-
if (!aborting) finish(() =>
|
|
10486
|
+
if (!aborting) finish(() => resolve24(value));
|
|
10473
10487
|
},
|
|
10474
10488
|
(err) => {
|
|
10475
10489
|
if (!aborting) finish(() => reject(err));
|
|
@@ -13996,8 +14010,8 @@ function isProjectIndexServerHealth(value) {
|
|
|
13996
14010
|
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";
|
|
13997
14011
|
}
|
|
13998
14012
|
function delay(ms) {
|
|
13999
|
-
return new Promise((
|
|
14000
|
-
const timer = setTimeout(
|
|
14013
|
+
return new Promise((resolve24) => {
|
|
14014
|
+
const timer = setTimeout(resolve24, ms);
|
|
14001
14015
|
timer.unref?.();
|
|
14002
14016
|
});
|
|
14003
14017
|
}
|
|
@@ -14203,7 +14217,7 @@ var ProjectServerConnection = class {
|
|
|
14203
14217
|
return Promise.reject(new Error("codebase-index server connection is not available"));
|
|
14204
14218
|
}
|
|
14205
14219
|
const id = this.nextId++;
|
|
14206
|
-
return new Promise((
|
|
14220
|
+
return new Promise((resolve24, reject) => {
|
|
14207
14221
|
const timer = setTimeout(() => {
|
|
14208
14222
|
const entry = this.pending.get(id);
|
|
14209
14223
|
if (!entry) return;
|
|
@@ -14226,7 +14240,7 @@ var ProjectServerConnection = class {
|
|
|
14226
14240
|
entry.reject(cancellationError(signal));
|
|
14227
14241
|
} : void 0;
|
|
14228
14242
|
this.pending.set(id, {
|
|
14229
|
-
resolve:
|
|
14243
|
+
resolve: resolve24,
|
|
14230
14244
|
reject,
|
|
14231
14245
|
timer,
|
|
14232
14246
|
signal,
|
|
@@ -14295,7 +14309,7 @@ var ProjectServerConnection = class {
|
|
|
14295
14309
|
this.binaryBuffer = [];
|
|
14296
14310
|
this.useBinary = false;
|
|
14297
14311
|
this.textDecoder = null;
|
|
14298
|
-
return new Promise((
|
|
14312
|
+
return new Promise((resolve24, reject) => {
|
|
14299
14313
|
const socket = net3.createConnection(this.endpoint);
|
|
14300
14314
|
this.socket = socket;
|
|
14301
14315
|
const timer = setTimeout(() => {
|
|
@@ -14307,7 +14321,7 @@ var ProjectServerConnection = class {
|
|
|
14307
14321
|
clearTimeout(timer);
|
|
14308
14322
|
this.connectResolve = null;
|
|
14309
14323
|
this.connectReject = null;
|
|
14310
|
-
|
|
14324
|
+
resolve24();
|
|
14311
14325
|
};
|
|
14312
14326
|
const finishReject = (error) => {
|
|
14313
14327
|
clearTimeout(timer);
|
|
@@ -15321,9 +15335,9 @@ var ParserWorkerPool = class {
|
|
|
15321
15335
|
for (let i = 0; i < files.length; i++) {
|
|
15322
15336
|
chunks[i % workerCount].push(files[i]);
|
|
15323
15337
|
}
|
|
15324
|
-
return new Promise((
|
|
15338
|
+
return new Promise((resolve24, reject) => {
|
|
15325
15339
|
this.pending.set(batchId, {
|
|
15326
|
-
resolve:
|
|
15340
|
+
resolve: resolve24,
|
|
15327
15341
|
reject,
|
|
15328
15342
|
accumulated: [],
|
|
15329
15343
|
expectedWorkers: workerCount,
|
|
@@ -15354,10 +15368,10 @@ var ParserWorkerPool = class {
|
|
|
15354
15368
|
await Promise.allSettled(
|
|
15355
15369
|
workers.map(
|
|
15356
15370
|
(w) => Promise.race([
|
|
15357
|
-
new Promise((
|
|
15358
|
-
w.once("exit", () =>
|
|
15371
|
+
new Promise((resolve24) => {
|
|
15372
|
+
w.once("exit", () => resolve24());
|
|
15359
15373
|
}),
|
|
15360
|
-
new Promise((
|
|
15374
|
+
new Promise((resolve24) => setTimeout(() => resolve24(), 2e3))
|
|
15361
15375
|
]).then(() => {
|
|
15362
15376
|
if (!w.threadId) return;
|
|
15363
15377
|
return w.terminate().catch(() => {
|
|
@@ -15418,7 +15432,7 @@ function shouldUseParserWorkerPool(candidateFileCount, parseBatchCount) {
|
|
|
15418
15432
|
return !isFrugalPerf() && candidateFileCount >= WORKER_POOL_THRESHOLD && parseBatchCount > 1;
|
|
15419
15433
|
}
|
|
15420
15434
|
function yieldEventLoop() {
|
|
15421
|
-
return new Promise((
|
|
15435
|
+
return new Promise((resolve24) => setImmediate(resolve24));
|
|
15422
15436
|
}
|
|
15423
15437
|
function throwIfAborted(signal) {
|
|
15424
15438
|
if (!signal?.aborted) return;
|
|
@@ -15450,7 +15464,7 @@ function normalizeComparablePath(value) {
|
|
|
15450
15464
|
return process.platform === "win32" ? resolved.toLowerCase() : resolved;
|
|
15451
15465
|
}
|
|
15452
15466
|
function gitOutput(projectRoot, args) {
|
|
15453
|
-
return new Promise((
|
|
15467
|
+
return new Promise((resolve24, reject) => {
|
|
15454
15468
|
execFile(
|
|
15455
15469
|
"git",
|
|
15456
15470
|
["-C", projectRoot, ...args],
|
|
@@ -15461,7 +15475,7 @@ function gitOutput(projectRoot, args) {
|
|
|
15461
15475
|
},
|
|
15462
15476
|
(error, stdout) => {
|
|
15463
15477
|
if (error) reject(error);
|
|
15464
|
-
else
|
|
15478
|
+
else resolve24(Buffer.isBuffer(stdout) ? stdout : Buffer.from(stdout));
|
|
15465
15479
|
}
|
|
15466
15480
|
);
|
|
15467
15481
|
});
|
|
@@ -16237,7 +16251,7 @@ function callIndexOp(op, args, opts) {
|
|
|
16237
16251
|
opts.signal.reason instanceof Error ? opts.signal.reason : new Error("Indexing cancelled")
|
|
16238
16252
|
);
|
|
16239
16253
|
}
|
|
16240
|
-
return new Promise((
|
|
16254
|
+
return new Promise((resolve24, reject) => {
|
|
16241
16255
|
const id = nextRpcId++;
|
|
16242
16256
|
const timer = setTimeout(() => {
|
|
16243
16257
|
pending.delete(id);
|
|
@@ -16259,7 +16273,7 @@ function callIndexOp(op, args, opts) {
|
|
|
16259
16273
|
pending.set(id, {
|
|
16260
16274
|
resolve: (v) => {
|
|
16261
16275
|
cleanup();
|
|
16262
|
-
|
|
16276
|
+
resolve24(v);
|
|
16263
16277
|
},
|
|
16264
16278
|
reject: (e) => {
|
|
16265
16279
|
cleanup();
|
|
@@ -19792,7 +19806,7 @@ function findGitDir(cwd) {
|
|
|
19792
19806
|
return null;
|
|
19793
19807
|
}
|
|
19794
19808
|
function runGit(args, cwd, signal) {
|
|
19795
|
-
return new Promise((
|
|
19809
|
+
return new Promise((resolve24) => {
|
|
19796
19810
|
let stdout = "";
|
|
19797
19811
|
let stderr = "";
|
|
19798
19812
|
const child = spawn7("git", args, {
|
|
@@ -19808,8 +19822,8 @@ function runGit(args, cwd, signal) {
|
|
|
19808
19822
|
child.stderr?.on("data", (c) => {
|
|
19809
19823
|
stderr += c.toString();
|
|
19810
19824
|
});
|
|
19811
|
-
child.on("close", (code) =>
|
|
19812
|
-
child.on("error", (e) =>
|
|
19825
|
+
child.on("close", (code) => resolve24({ stdout, stderr, exitCode: code ?? 0 }));
|
|
19826
|
+
child.on("error", (e) => resolve24({ stdout: "", stderr: e.message, exitCode: 1 }));
|
|
19813
19827
|
});
|
|
19814
19828
|
}
|
|
19815
19829
|
async function fileDiff(input, ctx, _signal) {
|
|
@@ -21024,6 +21038,40 @@ var RULES = [
|
|
|
21024
21038
|
},
|
|
21025
21039
|
reason: "Remove-Item with -Recurse -Force"
|
|
21026
21040
|
},
|
|
21041
|
+
// ----- Windows PowerShell Disk & Volume destruction -----
|
|
21042
|
+
{
|
|
21043
|
+
id: "powershell-disk-volume-destroy",
|
|
21044
|
+
level: "destructive",
|
|
21045
|
+
test: (cmd, args) => {
|
|
21046
|
+
if (cmd !== "powershell" && cmd !== "pwsh") return false;
|
|
21047
|
+
return args.some(
|
|
21048
|
+
(a) => /^(?:Format-Volume|Clear-Disk|Initialize-Disk|Remove-Partition|Clear-Volume)(?:\s|$)/i.test(a)
|
|
21049
|
+
);
|
|
21050
|
+
},
|
|
21051
|
+
reason: "PowerShell disk/volume partition destruction"
|
|
21052
|
+
},
|
|
21053
|
+
// ----- Windows PowerShell System Restart / Shutdown -----
|
|
21054
|
+
{
|
|
21055
|
+
id: "powershell-stop-restart-computer",
|
|
21056
|
+
level: "destructive",
|
|
21057
|
+
test: (cmd, args) => {
|
|
21058
|
+
if (cmd !== "powershell" && cmd !== "pwsh") return false;
|
|
21059
|
+
return args.some((a) => /^(?:Stop-Computer|Restart-Computer)(?:\s|$)/i.test(a));
|
|
21060
|
+
},
|
|
21061
|
+
reason: "PowerShell system shutdown or restart"
|
|
21062
|
+
},
|
|
21063
|
+
// ----- Windows PowerShell ExecutionPolicy / Payload evasion -----
|
|
21064
|
+
{
|
|
21065
|
+
id: "powershell-execution-policy-bypass",
|
|
21066
|
+
level: "caution",
|
|
21067
|
+
test: (cmd, args) => {
|
|
21068
|
+
if (cmd !== "powershell" && cmd !== "pwsh") return false;
|
|
21069
|
+
return args.some(
|
|
21070
|
+
(a) => /Set-ExecutionPolicy\s+(?:Bypass|Unrestricted)|-(?:EncodedCommand|enc)\b/i.test(a)
|
|
21071
|
+
);
|
|
21072
|
+
},
|
|
21073
|
+
reason: "PowerShell execution policy bypass or encoded command"
|
|
21074
|
+
},
|
|
21027
21075
|
// ----- find -exec / -ok / -execdir -----
|
|
21028
21076
|
{
|
|
21029
21077
|
id: "find-exec",
|
|
@@ -22444,7 +22492,7 @@ var execTool = {
|
|
|
22444
22492
|
}
|
|
22445
22493
|
};
|
|
22446
22494
|
function runCommand(cmd, args, cwd, timeout, signal, sessionId, danger) {
|
|
22447
|
-
return new Promise((
|
|
22495
|
+
return new Promise((resolve24) => {
|
|
22448
22496
|
let stdout = "";
|
|
22449
22497
|
let stderr = "";
|
|
22450
22498
|
let killed = false;
|
|
@@ -22452,7 +22500,7 @@ function runCommand(cmd, args, cwd, timeout, signal, sessionId, danger) {
|
|
|
22452
22500
|
const finish = (result) => {
|
|
22453
22501
|
if (resolvedOnce.value) return;
|
|
22454
22502
|
resolvedOnce.value = true;
|
|
22455
|
-
|
|
22503
|
+
resolve24(result);
|
|
22456
22504
|
};
|
|
22457
22505
|
const startedAt = Date.now();
|
|
22458
22506
|
let stdoutBytes = 0;
|
|
@@ -23128,10 +23176,10 @@ function parseFormatterCounts(fixer, output) {
|
|
|
23128
23176
|
};
|
|
23129
23177
|
}
|
|
23130
23178
|
async function detectFixer(cwd) {
|
|
23131
|
-
const
|
|
23179
|
+
const fs44 = await import("node:fs/promises");
|
|
23132
23180
|
const exists = async (file) => {
|
|
23133
23181
|
try {
|
|
23134
|
-
await
|
|
23182
|
+
await fs44.stat(`${cwd}/${file}`);
|
|
23135
23183
|
return true;
|
|
23136
23184
|
} catch {
|
|
23137
23185
|
return false;
|
|
@@ -23154,7 +23202,7 @@ async function detectFixer(cwd) {
|
|
|
23154
23202
|
if (await exists(cfg)) return "prettier";
|
|
23155
23203
|
}
|
|
23156
23204
|
try {
|
|
23157
|
-
const raw = await
|
|
23205
|
+
const raw = await fs44.readFile(`${cwd}/package.json`, "utf8");
|
|
23158
23206
|
const pkg = JSON.parse(raw);
|
|
23159
23207
|
if (pkg["prettier"] !== void 0) return "prettier";
|
|
23160
23208
|
} catch {
|
|
@@ -23422,7 +23470,7 @@ function buildArgs(input) {
|
|
|
23422
23470
|
}
|
|
23423
23471
|
}
|
|
23424
23472
|
function runGit2(args, cwd, signal) {
|
|
23425
|
-
return new Promise((
|
|
23473
|
+
return new Promise((resolve24) => {
|
|
23426
23474
|
let stdout = "";
|
|
23427
23475
|
let stderr = "";
|
|
23428
23476
|
const child = spawn9("git", args, {
|
|
@@ -23443,7 +23491,7 @@ function runGit2(args, cwd, signal) {
|
|
|
23443
23491
|
}
|
|
23444
23492
|
});
|
|
23445
23493
|
child.on("error", (err) => {
|
|
23446
|
-
|
|
23494
|
+
resolve24({
|
|
23447
23495
|
command: args[0],
|
|
23448
23496
|
stdout: normalizeCommandOutput(stdout),
|
|
23449
23497
|
stderr: err.message,
|
|
@@ -23452,7 +23500,7 @@ function runGit2(args, cwd, signal) {
|
|
|
23452
23500
|
});
|
|
23453
23501
|
});
|
|
23454
23502
|
child.on("close", (code) => {
|
|
23455
|
-
|
|
23503
|
+
resolve24({
|
|
23456
23504
|
command: args[0],
|
|
23457
23505
|
stdout: normalizeCommandOutput(stdout),
|
|
23458
23506
|
stderr: normalizeCommandOutput(stderr),
|
|
@@ -23865,7 +23913,7 @@ var grepTool = {
|
|
|
23865
23913
|
};
|
|
23866
23914
|
var rgAvailabilityCache;
|
|
23867
23915
|
function detectRg() {
|
|
23868
|
-
rgAvailabilityCache ??= new Promise((
|
|
23916
|
+
rgAvailabilityCache ??= new Promise((resolve24) => {
|
|
23869
23917
|
try {
|
|
23870
23918
|
const p = spawn10("rg", ["--version"], {
|
|
23871
23919
|
env: buildChildEnv5(),
|
|
@@ -23873,10 +23921,10 @@ function detectRg() {
|
|
|
23873
23921
|
signal: AbortSignal.timeout(1e4),
|
|
23874
23922
|
windowsHide: true
|
|
23875
23923
|
});
|
|
23876
|
-
p.on("error", () =>
|
|
23877
|
-
p.on("close", (code) =>
|
|
23924
|
+
p.on("error", () => resolve24(false));
|
|
23925
|
+
p.on("close", (code) => resolve24(code === 0));
|
|
23878
23926
|
} catch {
|
|
23879
|
-
|
|
23927
|
+
resolve24(false);
|
|
23880
23928
|
}
|
|
23881
23929
|
});
|
|
23882
23930
|
return rgAvailabilityCache;
|
|
@@ -24918,60 +24966,60 @@ function jmespathSearch(data, query) {
|
|
|
24918
24966
|
}
|
|
24919
24967
|
function validateJsonSchema(data, schema) {
|
|
24920
24968
|
const errors = [];
|
|
24921
|
-
function check(value, s,
|
|
24969
|
+
function check(value, s, path50) {
|
|
24922
24970
|
if (s["type"]) {
|
|
24923
24971
|
const expectedType = s["type"];
|
|
24924
24972
|
const actualType = Array.isArray(value) ? "array" : value === null ? "null" : typeof value;
|
|
24925
24973
|
if (expectedType === "integer") {
|
|
24926
|
-
if (!Number.isInteger(value)) errors.push(`${
|
|
24974
|
+
if (!Number.isInteger(value)) errors.push(`${path50}: expected integer, got ${actualType}`);
|
|
24927
24975
|
} else if (expectedType !== actualType) {
|
|
24928
|
-
errors.push(`${
|
|
24976
|
+
errors.push(`${path50}: expected ${expectedType}, got ${actualType}`);
|
|
24929
24977
|
}
|
|
24930
24978
|
}
|
|
24931
24979
|
if (typeof value === "string" && s["format"] === "uri" && value) {
|
|
24932
24980
|
try {
|
|
24933
24981
|
new URL(value);
|
|
24934
24982
|
} catch {
|
|
24935
|
-
errors.push(`${
|
|
24983
|
+
errors.push(`${path50}: not a valid URI`);
|
|
24936
24984
|
}
|
|
24937
24985
|
}
|
|
24938
24986
|
if (typeof value === "string" && s["pattern"]) {
|
|
24939
24987
|
const compiled = compileUserRegex(s["pattern"], "");
|
|
24940
24988
|
if (!compiled.ok) {
|
|
24941
|
-
errors.push(`${
|
|
24989
|
+
errors.push(`${path50}: invalid schema pattern \u2014 ${compiled.reason}`);
|
|
24942
24990
|
} else if (!compiled.regex.test(capSubject(value))) {
|
|
24943
|
-
errors.push(`${
|
|
24991
|
+
errors.push(`${path50}: does not match pattern ${s["pattern"]}`);
|
|
24944
24992
|
}
|
|
24945
24993
|
}
|
|
24946
24994
|
if (typeof value === "string" && s["minLength"] !== void 0 && value.length < s["minLength"]) {
|
|
24947
|
-
errors.push(`${
|
|
24995
|
+
errors.push(`${path50}: string too short (min ${s["minLength"]})`);
|
|
24948
24996
|
}
|
|
24949
24997
|
if (typeof value === "string" && s["maxLength"] !== void 0 && value.length > s["maxLength"]) {
|
|
24950
|
-
errors.push(`${
|
|
24998
|
+
errors.push(`${path50}: string too long (max ${s["maxLength"]})`);
|
|
24951
24999
|
}
|
|
24952
25000
|
if (typeof value === "number" && s["minimum"] !== void 0 && value < s["minimum"]) {
|
|
24953
|
-
errors.push(`${
|
|
25001
|
+
errors.push(`${path50}: below minimum ${s["minimum"]}`);
|
|
24954
25002
|
}
|
|
24955
25003
|
if (typeof value === "number" && s["maximum"] !== void 0 && value > s["maximum"]) {
|
|
24956
|
-
errors.push(`${
|
|
25004
|
+
errors.push(`${path50}: above maximum ${s["maximum"]}`);
|
|
24957
25005
|
}
|
|
24958
25006
|
if (Array.isArray(value) && s["items"] && Array.isArray(s["items"])) {
|
|
24959
25007
|
for (let i = 0; i < value.length; i++) {
|
|
24960
|
-
check(value[i], s["items"], `${
|
|
25008
|
+
check(value[i], s["items"], `${path50}[${i}]`);
|
|
24961
25009
|
}
|
|
24962
25010
|
}
|
|
24963
25011
|
if (typeof value === "object" && value !== null && !Array.isArray(value) && s["properties"]) {
|
|
24964
25012
|
const props = s["properties"];
|
|
24965
25013
|
for (const [k, propSchema] of Object.entries(props)) {
|
|
24966
|
-
check(value[k], propSchema, `${
|
|
25014
|
+
check(value[k], propSchema, `${path50}.${k}`);
|
|
24967
25015
|
}
|
|
24968
25016
|
}
|
|
24969
25017
|
}
|
|
24970
25018
|
check(data, schema, "$");
|
|
24971
25019
|
return { valid: errors.length === 0, errors };
|
|
24972
25020
|
}
|
|
24973
|
-
function simpleQuery(data,
|
|
24974
|
-
const parts =
|
|
25021
|
+
function simpleQuery(data, path50) {
|
|
25022
|
+
const parts = path50.replace(/\[(\d+)\]/g, ".$1").split(".").filter(Boolean);
|
|
24975
25023
|
let current = data;
|
|
24976
25024
|
for (const part of parts) {
|
|
24977
25025
|
if (current === null || current === void 0) return void 0;
|
|
@@ -27643,7 +27691,7 @@ async function dockerLogs(service, lines, filterRe, cwd, signal, since) {
|
|
|
27643
27691
|
};
|
|
27644
27692
|
}
|
|
27645
27693
|
args.push("--timestamps", service);
|
|
27646
|
-
return new Promise((
|
|
27694
|
+
return new Promise((resolve24) => {
|
|
27647
27695
|
let stdout = "";
|
|
27648
27696
|
let stderr = "";
|
|
27649
27697
|
const MAX = 2e5;
|
|
@@ -27659,7 +27707,7 @@ async function dockerLogs(service, lines, filterRe, cwd, signal, since) {
|
|
|
27659
27707
|
if (settled) return;
|
|
27660
27708
|
settled = true;
|
|
27661
27709
|
clearTimeout(timer);
|
|
27662
|
-
|
|
27710
|
+
resolve24(result);
|
|
27663
27711
|
};
|
|
27664
27712
|
const child = spawn11("docker", args, {
|
|
27665
27713
|
cwd,
|
|
@@ -27704,7 +27752,7 @@ async function dockerLogs(service, lines, filterRe, cwd, signal, since) {
|
|
|
27704
27752
|
}
|
|
27705
27753
|
var DOCKER_LOGS_TIMEOUT_MS = 3e3;
|
|
27706
27754
|
var MAX_TAIL_LINES = 1e5;
|
|
27707
|
-
async function fileLogs(
|
|
27755
|
+
async function fileLogs(path50, lines, filterRe) {
|
|
27708
27756
|
const { createInterface } = await import("node:readline");
|
|
27709
27757
|
const { createReadStream: createReadStream2 } = await import("node:fs");
|
|
27710
27758
|
const entries = [];
|
|
@@ -27713,7 +27761,7 @@ async function fileLogs(path49, lines, filterRe) {
|
|
|
27713
27761
|
let writeIdx = 0;
|
|
27714
27762
|
let totalLines = 0;
|
|
27715
27763
|
const rl = createInterface({
|
|
27716
|
-
input: createReadStream2(
|
|
27764
|
+
input: createReadStream2(path50),
|
|
27717
27765
|
crlfDelay: Number.POSITIVE_INFINITY
|
|
27718
27766
|
});
|
|
27719
27767
|
for await (const line of rl) {
|
|
@@ -27734,7 +27782,7 @@ async function fileLogs(path49, lines, filterRe) {
|
|
|
27734
27782
|
if (parsed) entries.push(parsed);
|
|
27735
27783
|
}
|
|
27736
27784
|
return {
|
|
27737
|
-
source:
|
|
27785
|
+
source: path50,
|
|
27738
27786
|
entries,
|
|
27739
27787
|
total: entries.length,
|
|
27740
27788
|
truncated: totalLines > effLines,
|
|
@@ -27876,7 +27924,7 @@ var outdatedTool = {
|
|
|
27876
27924
|
}
|
|
27877
27925
|
};
|
|
27878
27926
|
function runOutdated(manager, args, cwd, signal) {
|
|
27879
|
-
return new Promise((
|
|
27927
|
+
return new Promise((resolve24) => {
|
|
27880
27928
|
let stdout = "";
|
|
27881
27929
|
let stderr = "";
|
|
27882
27930
|
const MAX = 1e5;
|
|
@@ -27901,10 +27949,10 @@ function runOutdated(manager, args, cwd, signal) {
|
|
|
27901
27949
|
});
|
|
27902
27950
|
child.on("close", (code) => {
|
|
27903
27951
|
const result = parseOutdatedOutput(stdout, code ?? 0);
|
|
27904
|
-
|
|
27952
|
+
resolve24(result);
|
|
27905
27953
|
});
|
|
27906
27954
|
child.on("error", (e) => {
|
|
27907
|
-
|
|
27955
|
+
resolve24({
|
|
27908
27956
|
exit_code: 1,
|
|
27909
27957
|
packages: [],
|
|
27910
27958
|
total: 0,
|
|
@@ -28223,7 +28271,7 @@ function runPatch(args, cwd, signal, fallback) {
|
|
|
28223
28271
|
});
|
|
28224
28272
|
}
|
|
28225
28273
|
function runPatchProcess(command, args, cwd, signal) {
|
|
28226
|
-
return new Promise((
|
|
28274
|
+
return new Promise((resolve24) => {
|
|
28227
28275
|
let stdout = "";
|
|
28228
28276
|
let stderr = "";
|
|
28229
28277
|
const env = { ...buildChildEnv8(), LANG: "C", LC_ALL: "C" };
|
|
@@ -28242,11 +28290,11 @@ function runPatchProcess(command, args, cwd, signal) {
|
|
|
28242
28290
|
});
|
|
28243
28291
|
child.on(
|
|
28244
28292
|
"close",
|
|
28245
|
-
(code) =>
|
|
28293
|
+
(code) => resolve24({ exitCode: code ?? 1, stdout, stderr, unavailable: false })
|
|
28246
28294
|
);
|
|
28247
28295
|
child.on(
|
|
28248
28296
|
"error",
|
|
28249
|
-
(e) =>
|
|
28297
|
+
(e) => resolve24({
|
|
28250
28298
|
exitCode: 1,
|
|
28251
28299
|
stdout: "",
|
|
28252
28300
|
stderr: e.message,
|
|
@@ -29035,9 +29083,428 @@ function mkResult(plan, ok, message, todos) {
|
|
|
29035
29083
|
return result;
|
|
29036
29084
|
}
|
|
29037
29085
|
|
|
29086
|
+
// src/pwsh.ts
|
|
29087
|
+
import { spawn as spawn14 } from "node:child_process";
|
|
29088
|
+
import * as fs36 from "node:fs";
|
|
29089
|
+
import * as os10 from "node:os";
|
|
29090
|
+
import * as path43 from "node:path";
|
|
29091
|
+
import { StringDecoder as StringDecoder3 } from "node:string_decoder";
|
|
29092
|
+
import {
|
|
29093
|
+
emitProcessCompleted as emitProcessCompleted4,
|
|
29094
|
+
emitProcessOutput as emitProcessOutput4,
|
|
29095
|
+
emitProcessStarted as emitProcessStarted4
|
|
29096
|
+
} from "@wrongstack/core/observability";
|
|
29097
|
+
init_output_spool();
|
|
29098
|
+
init_util();
|
|
29099
|
+
init_process_registry();
|
|
29100
|
+
init_win32_resolve();
|
|
29101
|
+
var MAX_OUTPUT4 = 32768;
|
|
29102
|
+
var DEFAULT_TIMEOUT_MS4 = 3e5;
|
|
29103
|
+
var STREAM_FLUSH_INTERVAL_MS2 = 200;
|
|
29104
|
+
var STREAM_FLUSH_BYTES2 = 4 * 1024;
|
|
29105
|
+
var MAX_QUEUE_CHUNKS2 = 500;
|
|
29106
|
+
var PWSH_TOOL_DESCRIPTION = "Execute a PowerShell command (`pwsh -Command`) in a fresh process on Windows and return its stdout/stderr. Stateless per call: pass `workdir` instead of using `cd`.";
|
|
29107
|
+
var PWSH_TOOL_USAGE_HINT = "Best practices & sandbox protocol for pwsh:\n- **Stateless**: No cwd, variables, or functions persist between calls. Use `workdir` to set the directory.\n- **Paths & Environs**: Use native Windows paths (`C:\\...`) and read env vars via `$env:NAME` (and `$env:DSH_*`).\n- **Exit Codes**: Non-zero exits are reported as `[exit code: N]`. On Windows, a force-killed command settles as exit code 1 (interruption).\n- **Background**: Set `run_in_background: true` for long-running processes (returns job id; manage via job_output/job_kill).\n- **Sandboxing**: Under read-only sandbox, pwsh runs in `ConstrainedLanguage` mode (prefer cmdlets, basic types; .NET reflection and COM fail). Workspace-write runs in `FullLanguage`.\n- **Escalation**: If denied by policy (`[sandbox: file access denied]`), retry once with `sandbox_permissions` plus a one-sentence `justification`.";
|
|
29108
|
+
function wrapPwshCommand(command) {
|
|
29109
|
+
const bootstrap = "[Console]::OutputEncoding = [System.Text.Encoding]::UTF8;$ProgressPreference = 'SilentlyContinue';$ConfirmPreference = 'None';$WhatIfPreference = $false";
|
|
29110
|
+
return `${bootstrap}
|
|
29111
|
+
$ErrorActionPreference = 'Stop'
|
|
29112
|
+
${command}
|
|
29113
|
+
if ($LASTEXITCODE -is [int]) { exit $LASTEXITCODE }`;
|
|
29114
|
+
}
|
|
29115
|
+
var pwshTool = {
|
|
29116
|
+
name: "pwsh",
|
|
29117
|
+
category: "Shell",
|
|
29118
|
+
description: PWSH_TOOL_DESCRIPTION,
|
|
29119
|
+
usageHint: PWSH_TOOL_USAGE_HINT,
|
|
29120
|
+
selection: {
|
|
29121
|
+
doNotUseWhen: "the command is an allowlisted single binary (node, git, pnpm, tsc) needing no shell expansion or pipelines.",
|
|
29122
|
+
useInstead: ["exec"]
|
|
29123
|
+
},
|
|
29124
|
+
permission: "confirm",
|
|
29125
|
+
mutating: true,
|
|
29126
|
+
riskTier: "destructive",
|
|
29127
|
+
icon: "terminal",
|
|
29128
|
+
subjectKey: "command",
|
|
29129
|
+
capabilities: ["shell.arbitrary"],
|
|
29130
|
+
timeoutMs: 61e4,
|
|
29131
|
+
maxOutputBytes: MAX_OUTPUT4,
|
|
29132
|
+
estimatedDurationMs: 3e4,
|
|
29133
|
+
inputSchema: {
|
|
29134
|
+
type: "object",
|
|
29135
|
+
properties: {
|
|
29136
|
+
command: {
|
|
29137
|
+
type: "string",
|
|
29138
|
+
description: "The exact PowerShell command or script block to run."
|
|
29139
|
+
},
|
|
29140
|
+
workdir: {
|
|
29141
|
+
type: "string",
|
|
29142
|
+
description: "Absolute or project-relative path to the working directory for this command. Defaults to session working directory."
|
|
29143
|
+
},
|
|
29144
|
+
timeout_ms: {
|
|
29145
|
+
type: "integer",
|
|
29146
|
+
description: "Optional timeout for this specific command in milliseconds (default 300000, max 600000)."
|
|
29147
|
+
},
|
|
29148
|
+
run_in_background: {
|
|
29149
|
+
type: "boolean",
|
|
29150
|
+
description: "If true, launch the process in the background and return the job ID / PID immediately."
|
|
29151
|
+
},
|
|
29152
|
+
background: {
|
|
29153
|
+
type: "boolean",
|
|
29154
|
+
description: "Alias for run_in_background."
|
|
29155
|
+
},
|
|
29156
|
+
sandbox_permissions: {
|
|
29157
|
+
type: "string",
|
|
29158
|
+
description: "Escalation mode if retrying a sandbox-denied command (e.g., workspace-write)."
|
|
29159
|
+
},
|
|
29160
|
+
justification: {
|
|
29161
|
+
type: "string",
|
|
29162
|
+
description: "One-sentence justification when retrying a denied command with sandbox_permissions."
|
|
29163
|
+
}
|
|
29164
|
+
},
|
|
29165
|
+
required: ["command"]
|
|
29166
|
+
},
|
|
29167
|
+
async execute(input, ctx, opts) {
|
|
29168
|
+
let final;
|
|
29169
|
+
const executeStream = pwshTool.executeStream;
|
|
29170
|
+
if (!executeStream) throw new Error("pwshTool: stream execution unavailable");
|
|
29171
|
+
for await (const ev of executeStream(input, ctx, opts)) {
|
|
29172
|
+
if (ev.type === "final") final = ev.output;
|
|
29173
|
+
}
|
|
29174
|
+
if (!final) throw new Error("pwsh: stream ended without final event");
|
|
29175
|
+
return final;
|
|
29176
|
+
},
|
|
29177
|
+
async *executeStream(input, ctx, opts) {
|
|
29178
|
+
if (!input?.command) throw new Error("pwsh: command is required");
|
|
29179
|
+
const isBackground = !!(input.run_in_background || input.background);
|
|
29180
|
+
const registry = getProcessRegistry();
|
|
29181
|
+
if (!registry.beforeCall(isBackground)) {
|
|
29182
|
+
yield {
|
|
29183
|
+
type: "final",
|
|
29184
|
+
output: {
|
|
29185
|
+
output: "",
|
|
29186
|
+
exit_code: 1,
|
|
29187
|
+
timed_out: false,
|
|
29188
|
+
pid: null,
|
|
29189
|
+
error: "pwsh: circuit breaker open \u2014 too many consecutive failures or slow calls. Use /kill to inspect or /kill reset to recover."
|
|
29190
|
+
}
|
|
29191
|
+
};
|
|
29192
|
+
return;
|
|
29193
|
+
}
|
|
29194
|
+
const killCheck = await checkAndBlockKillCommand(input.command);
|
|
29195
|
+
if (killCheck.blocked) {
|
|
29196
|
+
yield {
|
|
29197
|
+
type: "final",
|
|
29198
|
+
output: {
|
|
29199
|
+
output: "",
|
|
29200
|
+
exit_code: 1,
|
|
29201
|
+
timed_out: false,
|
|
29202
|
+
pid: null,
|
|
29203
|
+
error: `pwsh: ${killCheck.reason}`
|
|
29204
|
+
}
|
|
29205
|
+
};
|
|
29206
|
+
return;
|
|
29207
|
+
}
|
|
29208
|
+
const isWin5 = os10.platform() === "win32";
|
|
29209
|
+
const bin = isWin5 ? resolvePowerShell("pwsh.exe") : "pwsh";
|
|
29210
|
+
const args = shellArgs("pwsh");
|
|
29211
|
+
const stdinBody = wrapPwshCommand(input.command);
|
|
29212
|
+
const env = buildChildEnv2(ctx.session?.id);
|
|
29213
|
+
let targetCwd = ctx.workingDir ?? ctx.projectRoot;
|
|
29214
|
+
if (input.workdir) {
|
|
29215
|
+
const resolved = path43.isAbsolute(input.workdir) ? input.workdir : path43.resolve(ctx.projectRoot, input.workdir);
|
|
29216
|
+
if (fs36.existsSync(resolved)) {
|
|
29217
|
+
targetCwd = resolved;
|
|
29218
|
+
}
|
|
29219
|
+
}
|
|
29220
|
+
const startedAt = Date.now();
|
|
29221
|
+
const detached = !isWin5;
|
|
29222
|
+
if (isBackground) {
|
|
29223
|
+
const child2 = spawn14(bin, args, {
|
|
29224
|
+
cwd: targetCwd,
|
|
29225
|
+
env,
|
|
29226
|
+
detached,
|
|
29227
|
+
stdio: ["pipe", "ignore", "ignore"],
|
|
29228
|
+
windowsHide: true
|
|
29229
|
+
});
|
|
29230
|
+
if (child2.stdin) {
|
|
29231
|
+
child2.stdin.write(stdinBody);
|
|
29232
|
+
child2.stdin.end();
|
|
29233
|
+
}
|
|
29234
|
+
const pid2 = child2.pid;
|
|
29235
|
+
if (typeof pid2 === "number") {
|
|
29236
|
+
registry.register({
|
|
29237
|
+
pid: pid2,
|
|
29238
|
+
name: "pwsh",
|
|
29239
|
+
command: redactCommand(input.command),
|
|
29240
|
+
startedAt: Date.now(),
|
|
29241
|
+
sessionId: ctx.session?.id,
|
|
29242
|
+
child: child2,
|
|
29243
|
+
processGroupLeader: detached && child2.pid === pid2,
|
|
29244
|
+
background: true
|
|
29245
|
+
});
|
|
29246
|
+
child2.on("close", () => registry.unregister(pid2));
|
|
29247
|
+
child2.on("error", () => {
|
|
29248
|
+
registry.unregister(pid2);
|
|
29249
|
+
registry.afterCall(Date.now() - startedAt, true, isBackground);
|
|
29250
|
+
});
|
|
29251
|
+
child2.unref();
|
|
29252
|
+
const jobId = `job_${pid2}`;
|
|
29253
|
+
ctx.recordSideEffect?.({
|
|
29254
|
+
toolUseId: `pwsh-bg-${Date.now()}`,
|
|
29255
|
+
toolName: "pwsh",
|
|
29256
|
+
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
29257
|
+
input: { command: redactCommand(input.command), background: true },
|
|
29258
|
+
outcome: `started background job ${jobId} (PID: ${pid2})`,
|
|
29259
|
+
risk: "shell"
|
|
29260
|
+
});
|
|
29261
|
+
yield {
|
|
29262
|
+
type: "final",
|
|
29263
|
+
output: {
|
|
29264
|
+
output: `Background job started: ${jobId} (PID: ${pid2})
|
|
29265
|
+
Working directory: ${targetCwd}`,
|
|
29266
|
+
exit_code: null,
|
|
29267
|
+
timed_out: false,
|
|
29268
|
+
pid: pid2,
|
|
29269
|
+
job_id: jobId
|
|
29270
|
+
}
|
|
29271
|
+
};
|
|
29272
|
+
return;
|
|
29273
|
+
}
|
|
29274
|
+
yield {
|
|
29275
|
+
type: "final",
|
|
29276
|
+
output: {
|
|
29277
|
+
output: "",
|
|
29278
|
+
exit_code: 1,
|
|
29279
|
+
timed_out: false,
|
|
29280
|
+
pid: null,
|
|
29281
|
+
error: "pwsh: failed to obtain PID for background process"
|
|
29282
|
+
}
|
|
29283
|
+
};
|
|
29284
|
+
return;
|
|
29285
|
+
}
|
|
29286
|
+
const spool = createOutputSpool({ tool: "pwsh", thresholdBytes: MAX_OUTPUT4 });
|
|
29287
|
+
const child = spawn14(bin, args, {
|
|
29288
|
+
cwd: targetCwd,
|
|
29289
|
+
env,
|
|
29290
|
+
detached,
|
|
29291
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
29292
|
+
windowsHide: true
|
|
29293
|
+
});
|
|
29294
|
+
const pid = child.pid;
|
|
29295
|
+
let stdoutBytes = 0;
|
|
29296
|
+
let stderrBytes = 0;
|
|
29297
|
+
let telemetryCompleted = false;
|
|
29298
|
+
emitProcessStarted4({
|
|
29299
|
+
...pid !== void 0 ? { pid } : {},
|
|
29300
|
+
parentPid: process.pid,
|
|
29301
|
+
command: redactCommand(`${bin} ${args.join(" ")}`),
|
|
29302
|
+
args: redactCommand(args.join(" ")).split(" ").filter(Boolean),
|
|
29303
|
+
cwd: targetCwd,
|
|
29304
|
+
background: false,
|
|
29305
|
+
startedAt: new Date(startedAt).toISOString()
|
|
29306
|
+
});
|
|
29307
|
+
const completeForeground = (exitCode, sig) => {
|
|
29308
|
+
if (telemetryCompleted) return;
|
|
29309
|
+
telemetryCompleted = true;
|
|
29310
|
+
emitProcessCompleted4({
|
|
29311
|
+
...pid !== void 0 ? { pid } : {},
|
|
29312
|
+
exitCode,
|
|
29313
|
+
...sig ? { signal: sig } : {},
|
|
29314
|
+
durationMs: Date.now() - startedAt,
|
|
29315
|
+
stdoutBytes,
|
|
29316
|
+
stderrBytes,
|
|
29317
|
+
timedOut,
|
|
29318
|
+
endedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
29319
|
+
});
|
|
29320
|
+
};
|
|
29321
|
+
if (typeof pid === "number") {
|
|
29322
|
+
registry.register({
|
|
29323
|
+
pid,
|
|
29324
|
+
name: "pwsh",
|
|
29325
|
+
command: redactCommand(input.command),
|
|
29326
|
+
startedAt: Date.now(),
|
|
29327
|
+
sessionId: ctx.session?.id,
|
|
29328
|
+
child,
|
|
29329
|
+
processGroupLeader: detached && child.pid === pid
|
|
29330
|
+
});
|
|
29331
|
+
}
|
|
29332
|
+
if (child.stdin) {
|
|
29333
|
+
child.stdin.write(stdinBody);
|
|
29334
|
+
child.stdin.end();
|
|
29335
|
+
}
|
|
29336
|
+
const timeoutMs = Math.min(
|
|
29337
|
+
Math.max(1e3, input.timeout_ms ?? DEFAULT_TIMEOUT_MS4),
|
|
29338
|
+
6e5
|
|
29339
|
+
);
|
|
29340
|
+
let timedOut = false;
|
|
29341
|
+
const timers = [];
|
|
29342
|
+
const killWithTimeout = (timeout) => {
|
|
29343
|
+
if (isWin5) {
|
|
29344
|
+
if (typeof child.pid === "number" && child.exitCode === null) {
|
|
29345
|
+
const attempted = registry.kill(child.pid, { force: true, graceMs: timeout });
|
|
29346
|
+
if (!attempted) {
|
|
29347
|
+
try {
|
|
29348
|
+
child.kill();
|
|
29349
|
+
} catch {
|
|
29350
|
+
}
|
|
29351
|
+
}
|
|
29352
|
+
}
|
|
29353
|
+
return;
|
|
29354
|
+
}
|
|
29355
|
+
if (typeof child.pid === "number") {
|
|
29356
|
+
registry.kill(child.pid, { graceMs: timeout });
|
|
29357
|
+
} else {
|
|
29358
|
+
try {
|
|
29359
|
+
child.kill("SIGTERM");
|
|
29360
|
+
} catch {
|
|
29361
|
+
}
|
|
29362
|
+
}
|
|
29363
|
+
};
|
|
29364
|
+
const timer = setTimeout(() => {
|
|
29365
|
+
timedOut = true;
|
|
29366
|
+
killWithTimeout(2e3);
|
|
29367
|
+
}, timeoutMs);
|
|
29368
|
+
timers.push(timer);
|
|
29369
|
+
const onAbort = () => killWithTimeout(2e3);
|
|
29370
|
+
if (opts.signal.aborted) onAbort();
|
|
29371
|
+
else opts.signal.addEventListener("abort", onAbort, { once: true });
|
|
29372
|
+
const queue = [];
|
|
29373
|
+
let resolveNext = null;
|
|
29374
|
+
const push = (c) => {
|
|
29375
|
+
if (resolveNext) {
|
|
29376
|
+
const r = resolveNext;
|
|
29377
|
+
resolveNext = null;
|
|
29378
|
+
r(c);
|
|
29379
|
+
} else {
|
|
29380
|
+
queue.push(c);
|
|
29381
|
+
}
|
|
29382
|
+
};
|
|
29383
|
+
const next = () => new Promise((resolve24) => {
|
|
29384
|
+
const c = queue.shift();
|
|
29385
|
+
if (c) resolve24(c);
|
|
29386
|
+
else resolveNext = resolve24;
|
|
29387
|
+
});
|
|
29388
|
+
let buf = "";
|
|
29389
|
+
let pending2 = "";
|
|
29390
|
+
let lastFlush = Date.now();
|
|
29391
|
+
const flush = () => {
|
|
29392
|
+
if (pending2.length === 0) return null;
|
|
29393
|
+
const text = pending2;
|
|
29394
|
+
pending2 = "";
|
|
29395
|
+
lastFlush = Date.now();
|
|
29396
|
+
return text;
|
|
29397
|
+
};
|
|
29398
|
+
let paused = false;
|
|
29399
|
+
const pauseIfFlooded = () => {
|
|
29400
|
+
if (!paused && queue.length >= MAX_QUEUE_CHUNKS2) {
|
|
29401
|
+
paused = true;
|
|
29402
|
+
child.stdout?.pause();
|
|
29403
|
+
child.stderr?.pause();
|
|
29404
|
+
}
|
|
29405
|
+
};
|
|
29406
|
+
const resumeIfDrained = () => {
|
|
29407
|
+
if (paused && queue.length < MAX_QUEUE_CHUNKS2) {
|
|
29408
|
+
paused = false;
|
|
29409
|
+
child.stdout?.resume();
|
|
29410
|
+
child.stderr?.resume();
|
|
29411
|
+
}
|
|
29412
|
+
};
|
|
29413
|
+
const stdoutDecoder = new StringDecoder3("utf8");
|
|
29414
|
+
const stderrDecoder = new StringDecoder3("utf8");
|
|
29415
|
+
const onData = (chunk, stream) => {
|
|
29416
|
+
const text = (stream === "stdout" ? stdoutDecoder : stderrDecoder).write(chunk);
|
|
29417
|
+
if (stream === "stdout") stdoutBytes += chunk.byteLength;
|
|
29418
|
+
else stderrBytes += chunk.byteLength;
|
|
29419
|
+
emitProcessOutput4({ pid: pid ?? 0, stream, chunk });
|
|
29420
|
+
if (buf.length < MAX_OUTPUT4) {
|
|
29421
|
+
buf += text.slice(0, MAX_OUTPUT4 - buf.length);
|
|
29422
|
+
}
|
|
29423
|
+
spool.write(text);
|
|
29424
|
+
pending2 += text;
|
|
29425
|
+
push({ kind: "data", text });
|
|
29426
|
+
pauseIfFlooded();
|
|
29427
|
+
};
|
|
29428
|
+
child.stdout?.on("data", (chunk) => onData(chunk, "stdout"));
|
|
29429
|
+
child.stderr?.on("data", (chunk) => onData(chunk, "stderr"));
|
|
29430
|
+
child.on("error", (err) => {
|
|
29431
|
+
for (const t of timers) clearTimeout(t);
|
|
29432
|
+
registry.afterCall(Date.now() - startedAt, true);
|
|
29433
|
+
completeForeground(1);
|
|
29434
|
+
push({ kind: "error", err });
|
|
29435
|
+
});
|
|
29436
|
+
child.on("close", (code, signal) => {
|
|
29437
|
+
for (const t of timers) clearTimeout(t);
|
|
29438
|
+
if (typeof pid === "number") registry.unregister(pid);
|
|
29439
|
+
registry.afterCall(Date.now() - startedAt, code !== 0 && code !== null);
|
|
29440
|
+
completeForeground(timedOut ? 124 : code ?? (signal ? 1 : 0), signal ?? void 0);
|
|
29441
|
+
const tail = stdoutDecoder.end() + stderrDecoder.end();
|
|
29442
|
+
if (tail) {
|
|
29443
|
+
if (buf.length < MAX_OUTPUT4) buf += tail.slice(0, MAX_OUTPUT4 - buf.length);
|
|
29444
|
+
spool.write(tail);
|
|
29445
|
+
pending2 += tail;
|
|
29446
|
+
}
|
|
29447
|
+
push({ kind: "end", code });
|
|
29448
|
+
});
|
|
29449
|
+
try {
|
|
29450
|
+
while (true) {
|
|
29451
|
+
const c = await next();
|
|
29452
|
+
resumeIfDrained();
|
|
29453
|
+
if (c.kind === "error") throw c.err;
|
|
29454
|
+
if (c.kind === "end") {
|
|
29455
|
+
const remainder = flush();
|
|
29456
|
+
if (remainder !== null) {
|
|
29457
|
+
yield { type: "partial_output", text: remainder };
|
|
29458
|
+
}
|
|
29459
|
+
const spooled = spool.finalize();
|
|
29460
|
+
let formattedOutput = normalizeCommandOutput(buf);
|
|
29461
|
+
if (c.code !== null && c.code !== 0 && !timedOut) {
|
|
29462
|
+
if (!formattedOutput.includes(`[exit code: ${c.code}]`)) {
|
|
29463
|
+
formattedOutput = formattedOutput ? `${formattedOutput}
|
|
29464
|
+
[exit code: ${c.code}]` : `[exit code: ${c.code}]`;
|
|
29465
|
+
}
|
|
29466
|
+
}
|
|
29467
|
+
const hint = !timedOut && typeof c.code === "number" && c.code !== 0 ? diagnoseBashism(input.command, "pwsh") : void 0;
|
|
29468
|
+
const danger = detectDanger("pwsh", [input.command]);
|
|
29469
|
+
const cautionText = danger.level === "caution" && danger.reasons.length > 0 ? `
|
|
29470
|
+
[caution: ${danger.reasons.join("; ")}]` : "";
|
|
29471
|
+
const finalResultText = formattedOutput + (spooled ? spoolNote(spooled) : "") + (hint ? `
|
|
29472
|
+
|
|
29473
|
+
${hint}` : "") + cautionText;
|
|
29474
|
+
ctx.recordSideEffect?.({
|
|
29475
|
+
toolUseId: `pwsh-${Date.now()}`,
|
|
29476
|
+
toolName: "pwsh",
|
|
29477
|
+
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
29478
|
+
input: { command: redactCommand(input.command) },
|
|
29479
|
+
outcome: timedOut ? `timed out (exit ${c.code})` : `exit ${c.code}`,
|
|
29480
|
+
risk: "shell"
|
|
29481
|
+
});
|
|
29482
|
+
yield {
|
|
29483
|
+
type: "final",
|
|
29484
|
+
output: {
|
|
29485
|
+
output: finalResultText,
|
|
29486
|
+
exit_code: timedOut ? 1 : c.code,
|
|
29487
|
+
timed_out: timedOut,
|
|
29488
|
+
pid
|
|
29489
|
+
}
|
|
29490
|
+
};
|
|
29491
|
+
return;
|
|
29492
|
+
}
|
|
29493
|
+
const now = Date.now();
|
|
29494
|
+
if (pending2.length >= STREAM_FLUSH_BYTES2 || now - lastFlush >= STREAM_FLUSH_INTERVAL_MS2) {
|
|
29495
|
+
const text = flush();
|
|
29496
|
+
if (text) yield { type: "partial_output", text };
|
|
29497
|
+
}
|
|
29498
|
+
}
|
|
29499
|
+
} finally {
|
|
29500
|
+
for (const t of timers) clearTimeout(t);
|
|
29501
|
+
}
|
|
29502
|
+
}
|
|
29503
|
+
};
|
|
29504
|
+
|
|
29038
29505
|
// src/read.ts
|
|
29039
29506
|
init_util();
|
|
29040
|
-
import * as
|
|
29507
|
+
import * as fs37 from "node:fs/promises";
|
|
29041
29508
|
import { FsError, ToolValidationError as ToolValidationError8 } from "@wrongstack/core/types";
|
|
29042
29509
|
import { toErrorMessage as toErrorMessage15 } from "@wrongstack/core/utils";
|
|
29043
29510
|
var ADVANCED_MODE_META_KEY = "tools.read.advancedMode";
|
|
@@ -29097,7 +29564,7 @@ var readTool = {
|
|
|
29097
29564
|
const shouldIncludeSymbols = input.includeSymbols === true || input.includeSymbols !== false && ctx.meta[ADVANCED_MODE_META_KEY] === true;
|
|
29098
29565
|
let stat21;
|
|
29099
29566
|
try {
|
|
29100
|
-
stat21 = await
|
|
29567
|
+
stat21 = await fs37.stat(absPath);
|
|
29101
29568
|
} catch (err) {
|
|
29102
29569
|
const code = err.code;
|
|
29103
29570
|
if (code === "ENOENT") {
|
|
@@ -29149,7 +29616,7 @@ var readTool = {
|
|
|
29149
29616
|
...symResult2?.symbols ? { symbols: symResult2.symbols } : {}
|
|
29150
29617
|
};
|
|
29151
29618
|
}
|
|
29152
|
-
const buf = await
|
|
29619
|
+
const buf = await fs37.readFile(absPath);
|
|
29153
29620
|
if (isBinaryBuffer(buf)) {
|
|
29154
29621
|
throw new FsError({
|
|
29155
29622
|
message: `read: "${input.path}" appears to be binary`,
|
|
@@ -29315,9 +29782,9 @@ ${interesting.join("\n")}` : "symbols/imports: (none detected)"
|
|
|
29315
29782
|
}
|
|
29316
29783
|
|
|
29317
29784
|
// src/replace.ts
|
|
29318
|
-
import { spawn as
|
|
29319
|
-
import * as
|
|
29320
|
-
import * as
|
|
29785
|
+
import { spawn as spawn15 } from "node:child_process";
|
|
29786
|
+
import * as fs38 from "node:fs/promises";
|
|
29787
|
+
import * as path44 from "node:path";
|
|
29321
29788
|
import { ToolValidationError as ToolValidationError9 } from "@wrongstack/core/types";
|
|
29322
29789
|
import {
|
|
29323
29790
|
atomicWrite as atomicWrite4,
|
|
@@ -29400,14 +29867,14 @@ var replaceTool = {
|
|
|
29400
29867
|
const dryRun = input.dry_run ?? true;
|
|
29401
29868
|
const filesInput = Array.isArray(input.files) ? input.files.join(",") : input.files;
|
|
29402
29869
|
const fileList = await resolveFiles2(filesInput, ctx, globRe);
|
|
29403
|
-
const realRoot = await
|
|
29870
|
+
const realRoot = await fs38.realpath(ctx.projectRoot).catch(() => ctx.projectRoot);
|
|
29404
29871
|
const results = [];
|
|
29405
29872
|
let totalReplacements = 0;
|
|
29406
29873
|
let diffBytesUsed = 0;
|
|
29407
29874
|
let diffsOmitted = 0;
|
|
29408
29875
|
let diffsTruncated = 0;
|
|
29409
29876
|
for (const absPath of fileList) {
|
|
29410
|
-
const lstat2 = await
|
|
29877
|
+
const lstat2 = await fs38.lstat(absPath).catch((err) => {
|
|
29411
29878
|
if (err.code === "ENOENT") return null;
|
|
29412
29879
|
throw err;
|
|
29413
29880
|
});
|
|
@@ -29415,17 +29882,17 @@ var replaceTool = {
|
|
|
29415
29882
|
if (lstat2.isSymbolicLink()) continue;
|
|
29416
29883
|
let realPath;
|
|
29417
29884
|
try {
|
|
29418
|
-
realPath = await
|
|
29885
|
+
realPath = await fs38.realpath(absPath);
|
|
29419
29886
|
} catch {
|
|
29420
29887
|
continue;
|
|
29421
29888
|
}
|
|
29422
|
-
const rel =
|
|
29423
|
-
if (rel.startsWith("..") ||
|
|
29424
|
-
const stat21 = await
|
|
29889
|
+
const rel = path44.relative(realRoot, realPath);
|
|
29890
|
+
if (rel.startsWith("..") || path44.isAbsolute(rel)) continue;
|
|
29891
|
+
const stat21 = await fs38.stat(realPath).catch(() => null);
|
|
29425
29892
|
if (!stat21?.isFile()) continue;
|
|
29426
29893
|
let content;
|
|
29427
29894
|
try {
|
|
29428
|
-
const buf = await
|
|
29895
|
+
const buf = await fs38.readFile(realPath);
|
|
29429
29896
|
if (isBinaryBuffer(buf)) continue;
|
|
29430
29897
|
content = buf.toString("utf8");
|
|
29431
29898
|
} catch {
|
|
@@ -29448,7 +29915,7 @@ var replaceTool = {
|
|
|
29448
29915
|
if (!dryRun) {
|
|
29449
29916
|
const newContent = toStyle2(newContentLf, style);
|
|
29450
29917
|
await atomicWrite4(realPath, newContent, { mode: stat21.mode & 511 });
|
|
29451
|
-
const written = await
|
|
29918
|
+
const written = await fs38.stat(realPath).catch(() => null);
|
|
29452
29919
|
if (written) {
|
|
29453
29920
|
ctx.recordRead?.(realPath, written.mtimeMs, "write", sha256hex(newContent));
|
|
29454
29921
|
}
|
|
@@ -29548,8 +30015,8 @@ async function resolveFiles2(filesInput, ctx, extraGlob) {
|
|
|
29548
30015
|
const resolved = [];
|
|
29549
30016
|
for (const p of parts) {
|
|
29550
30017
|
const absPath = await safeResolveReal(p, ctx);
|
|
29551
|
-
if (extraGlob && !passesExtraGlob(extraGlob,
|
|
29552
|
-
const stat21 = await
|
|
30018
|
+
if (extraGlob && !passesExtraGlob(extraGlob, path44.basename(absPath), absPath)) continue;
|
|
30019
|
+
const stat21 = await fs38.stat(absPath).catch(() => null);
|
|
29553
30020
|
if (stat21?.isFile()) {
|
|
29554
30021
|
resolved.push(absPath);
|
|
29555
30022
|
}
|
|
@@ -29563,7 +30030,7 @@ async function globFiles(pattern, base, extraGlob) {
|
|
|
29563
30030
|
const { promise } = spawnRgFind(pattern, base);
|
|
29564
30031
|
const files = await promise;
|
|
29565
30032
|
if (extraGlob) {
|
|
29566
|
-
return files.filter((f) => passesExtraGlob(extraGlob,
|
|
30033
|
+
return files.filter((f) => passesExtraGlob(extraGlob, path44.basename(f), f));
|
|
29567
30034
|
}
|
|
29568
30035
|
return files;
|
|
29569
30036
|
} catch {
|
|
@@ -29573,24 +30040,24 @@ async function globFiles(pattern, base, extraGlob) {
|
|
|
29573
30040
|
}
|
|
29574
30041
|
var rgAvailabilityCache2;
|
|
29575
30042
|
function checkRg() {
|
|
29576
|
-
rgAvailabilityCache2 ??= new Promise((
|
|
30043
|
+
rgAvailabilityCache2 ??= new Promise((resolve24) => {
|
|
29577
30044
|
try {
|
|
29578
|
-
const p =
|
|
30045
|
+
const p = spawn15("rg", ["--version"], {
|
|
29579
30046
|
env: buildChildEnv9(),
|
|
29580
30047
|
stdio: "ignore",
|
|
29581
30048
|
windowsHide: true
|
|
29582
30049
|
});
|
|
29583
|
-
p.on("error", () =>
|
|
29584
|
-
p.on("close", (code) =>
|
|
30050
|
+
p.on("error", () => resolve24(false));
|
|
30051
|
+
p.on("close", (code) => resolve24(code === 0));
|
|
29585
30052
|
} catch {
|
|
29586
|
-
|
|
30053
|
+
resolve24(false);
|
|
29587
30054
|
}
|
|
29588
30055
|
});
|
|
29589
30056
|
return rgAvailabilityCache2;
|
|
29590
30057
|
}
|
|
29591
30058
|
function spawnRgFind(pattern, base) {
|
|
29592
30059
|
const args = ["--files", "--glob", pattern, base];
|
|
29593
|
-
const child =
|
|
30060
|
+
const child = spawn15("rg", args, {
|
|
29594
30061
|
signal: AbortSignal.timeout(3e4),
|
|
29595
30062
|
env: buildChildEnv9(),
|
|
29596
30063
|
stdio: ["ignore", "pipe", "pipe"],
|
|
@@ -29609,10 +30076,10 @@ function spawnRgFind(pattern, base) {
|
|
|
29609
30076
|
}
|
|
29610
30077
|
});
|
|
29611
30078
|
return {
|
|
29612
|
-
promise: new Promise((
|
|
30079
|
+
promise: new Promise((resolve24, reject) => {
|
|
29613
30080
|
child.on("error", reject);
|
|
29614
30081
|
child.on("close", () => {
|
|
29615
|
-
|
|
30082
|
+
resolve24(buf.split("\n").filter(Boolean));
|
|
29616
30083
|
});
|
|
29617
30084
|
})
|
|
29618
30085
|
};
|
|
@@ -29623,15 +30090,15 @@ async function globNative(pattern, base, extraGlob) {
|
|
|
29623
30090
|
const walk = async (dir) => {
|
|
29624
30091
|
let entries;
|
|
29625
30092
|
try {
|
|
29626
|
-
entries = await
|
|
30093
|
+
entries = await fs38.readdir(dir, { withFileTypes: true });
|
|
29627
30094
|
} catch {
|
|
29628
30095
|
return;
|
|
29629
30096
|
}
|
|
29630
30097
|
for (const e of entries) {
|
|
29631
30098
|
if (DEFAULT_IGNORE4.includes(e.name)) continue;
|
|
29632
|
-
const full =
|
|
30099
|
+
const full = path44.join(dir, e.name);
|
|
29633
30100
|
try {
|
|
29634
|
-
const stat21 = await
|
|
30101
|
+
const stat21 = await fs38.lstat(full);
|
|
29635
30102
|
if (stat21.isSymbolicLink()) continue;
|
|
29636
30103
|
} catch {
|
|
29637
30104
|
continue;
|
|
@@ -29655,8 +30122,8 @@ async function globNative(pattern, base, extraGlob) {
|
|
|
29655
30122
|
|
|
29656
30123
|
// src/scaffold.ts
|
|
29657
30124
|
init_util();
|
|
29658
|
-
import * as
|
|
29659
|
-
import * as
|
|
30125
|
+
import * as fs39 from "node:fs/promises";
|
|
30126
|
+
import * as path45 from "node:path";
|
|
29660
30127
|
import { atomicWrite as atomicWrite5 } from "@wrongstack/core/utils";
|
|
29661
30128
|
var BUILT_IN_TEMPLATES = {
|
|
29662
30129
|
"npm-package": {
|
|
@@ -29807,16 +30274,16 @@ async function handleBuiltIn(name, templateFiles, cwd, ctx, dryRun, vars) {
|
|
|
29807
30274
|
let filesCreated = 0;
|
|
29808
30275
|
for (const [filePath, content] of Object.entries(templateFiles)) {
|
|
29809
30276
|
const resolvedPath = substituteVars(filePath, name, vars);
|
|
29810
|
-
const joinedPath =
|
|
29811
|
-
const root =
|
|
29812
|
-
const target =
|
|
29813
|
-
const rel =
|
|
29814
|
-
if (rel.startsWith("..") ||
|
|
30277
|
+
const joinedPath = path45.join(cwd, resolvedPath);
|
|
30278
|
+
const root = path45.resolve(ctx.projectRoot);
|
|
30279
|
+
const target = path45.resolve(joinedPath);
|
|
30280
|
+
const rel = path45.relative(root, target);
|
|
30281
|
+
if (rel.startsWith("..") || path45.isAbsolute(rel)) {
|
|
29815
30282
|
throw new Error(`scaffold: generated path "${resolvedPath}" would escape project root`);
|
|
29816
30283
|
}
|
|
29817
30284
|
const fullPath = target;
|
|
29818
30285
|
if (!dryRun) {
|
|
29819
|
-
await
|
|
30286
|
+
await fs39.mkdir(path45.dirname(fullPath), { recursive: true });
|
|
29820
30287
|
await atomicWrite5(fullPath, substituteVars(content, name, vars));
|
|
29821
30288
|
}
|
|
29822
30289
|
files.push(resolvedPath);
|
|
@@ -30262,8 +30729,8 @@ function decodeHtmlEntities(text) {
|
|
|
30262
30729
|
}
|
|
30263
30730
|
|
|
30264
30731
|
// src/security-ast-scan-tool.ts
|
|
30265
|
-
import * as
|
|
30266
|
-
import * as
|
|
30732
|
+
import * as fs40 from "node:fs/promises";
|
|
30733
|
+
import * as path46 from "node:path";
|
|
30267
30734
|
import { toErrorMessage as toErrorMessage17 } from "@wrongstack/core/utils";
|
|
30268
30735
|
var SECRET_PATTERNS = [
|
|
30269
30736
|
{ name: "AWS Access Key", regex: /\b(AKIA[0-9A-Z]{16})\b/ },
|
|
@@ -30430,9 +30897,9 @@ var securityAstScanTool = {
|
|
|
30430
30897
|
let targetFile = input.file ?? "inline-code.ts";
|
|
30431
30898
|
let content = input.content;
|
|
30432
30899
|
if (!content && input.file) {
|
|
30433
|
-
const absPath =
|
|
30434
|
-
targetFile =
|
|
30435
|
-
content = await
|
|
30900
|
+
const absPath = path46.isAbsolute(input.file) ? input.file : path46.resolve(projectRoot, input.file);
|
|
30901
|
+
targetFile = path46.relative(projectRoot, absPath).replace(/\\/g, "/");
|
|
30902
|
+
content = await fs40.readFile(absPath, "utf8");
|
|
30436
30903
|
}
|
|
30437
30904
|
if (!content) {
|
|
30438
30905
|
return {
|
|
@@ -30480,7 +30947,7 @@ var securityAstScanTool = {
|
|
|
30480
30947
|
};
|
|
30481
30948
|
|
|
30482
30949
|
// src/set-working-dir.ts
|
|
30483
|
-
import * as
|
|
30950
|
+
import * as fs41 from "node:fs/promises";
|
|
30484
30951
|
import { toErrorMessage as toErrorMessage18 } from "@wrongstack/core/utils";
|
|
30485
30952
|
var setWorkingDirTool = {
|
|
30486
30953
|
name: "set_working_dir",
|
|
@@ -30520,7 +30987,7 @@ var setWorkingDirTool = {
|
|
|
30520
30987
|
}
|
|
30521
30988
|
let isDirectory = false;
|
|
30522
30989
|
try {
|
|
30523
|
-
isDirectory = (await
|
|
30990
|
+
isDirectory = (await fs41.stat(resolved)).isDirectory();
|
|
30524
30991
|
} catch {
|
|
30525
30992
|
isDirectory = false;
|
|
30526
30993
|
}
|
|
@@ -31055,7 +31522,7 @@ ${formatTaskList2(file.tasks)}` : file.tasks.length > 0 ? formatTaskList2(file.t
|
|
|
31055
31522
|
init_spawn_stream();
|
|
31056
31523
|
init_util();
|
|
31057
31524
|
init_legacy_bridge();
|
|
31058
|
-
import * as
|
|
31525
|
+
import * as path47 from "node:path";
|
|
31059
31526
|
var testTool = {
|
|
31060
31527
|
name: "test",
|
|
31061
31528
|
category: "Code Quality",
|
|
@@ -31162,7 +31629,7 @@ async function detectRunner(cwd) {
|
|
|
31162
31629
|
const candidates = ["vitest.config.ts", "jest.config.js", ".mocharc.json"];
|
|
31163
31630
|
for (const f of candidates) {
|
|
31164
31631
|
try {
|
|
31165
|
-
await stat21(
|
|
31632
|
+
await stat21(path47.join(cwd, f));
|
|
31166
31633
|
if (f.includes("vitest")) return "vitest";
|
|
31167
31634
|
if (f.includes("jest")) return "jest";
|
|
31168
31635
|
if (f.includes("mocha")) return "mocha";
|
|
@@ -31539,8 +32006,8 @@ var toolUseTool = {
|
|
|
31539
32006
|
|
|
31540
32007
|
// src/tree.ts
|
|
31541
32008
|
init_util();
|
|
31542
|
-
import * as
|
|
31543
|
-
import * as
|
|
32009
|
+
import * as fs42 from "node:fs/promises";
|
|
32010
|
+
import * as path48 from "node:path";
|
|
31544
32011
|
import { DEFAULT_WALK_IGNORE_DIRS as DEFAULT_WALK_IGNORE_DIRS4, expectDefined as expectDefined10 } from "@wrongstack/core/utils";
|
|
31545
32012
|
var DEFAULT_IGNORE5 = /* @__PURE__ */ new Set([
|
|
31546
32013
|
...DEFAULT_WALK_IGNORE_DIRS4,
|
|
@@ -31703,7 +32170,7 @@ var treeTool = {
|
|
|
31703
32170
|
async function walkDir(dir, depth, opts) {
|
|
31704
32171
|
opts.signal.throwIfAborted();
|
|
31705
32172
|
if (opts.retention.truncated) return;
|
|
31706
|
-
const entries = await
|
|
32173
|
+
const entries = await fs42.readdir(dir, { withFileTypes: true }).catch(() => []);
|
|
31707
32174
|
const filtered = entries.filter((e) => {
|
|
31708
32175
|
if (!opts.showHidden && e.name.startsWith(".")) return false;
|
|
31709
32176
|
if (opts.exclude.has(e.name)) return false;
|
|
@@ -31745,7 +32212,7 @@ async function walkDir(dir, depth, opts) {
|
|
|
31745
32212
|
opts.retention.outputBytes += lineBytes;
|
|
31746
32213
|
if (entry.isDirectory() && (opts.maxDepth === 0 || depth < opts.maxDepth)) {
|
|
31747
32214
|
const childPrefix = opts.prefix + connector;
|
|
31748
|
-
await walkDir(
|
|
32215
|
+
await walkDir(path48.join(dir, entry.name), depth + 1, {
|
|
31749
32216
|
...opts,
|
|
31750
32217
|
prefix: childPrefix,
|
|
31751
32218
|
isLast
|
|
@@ -31758,7 +32225,7 @@ async function walkDir(dir, depth, opts) {
|
|
|
31758
32225
|
init_spawn_stream();
|
|
31759
32226
|
init_util();
|
|
31760
32227
|
init_legacy_bridge();
|
|
31761
|
-
import * as
|
|
32228
|
+
import * as path49 from "node:path";
|
|
31762
32229
|
var typecheckTool = {
|
|
31763
32230
|
name: "typecheck",
|
|
31764
32231
|
category: "Code Quality",
|
|
@@ -31870,8 +32337,8 @@ async function findTsConfig(cwd) {
|
|
|
31870
32337
|
const candidates = ["tsconfig.json", "tsconfig.base.json"];
|
|
31871
32338
|
for (const f of candidates) {
|
|
31872
32339
|
try {
|
|
31873
|
-
const s = await stat21(
|
|
31874
|
-
if (s.isFile()) return
|
|
32340
|
+
const s = await stat21(path49.join(cwd, f));
|
|
32341
|
+
if (s.isFile()) return path49.join(cwd, f);
|
|
31875
32342
|
} catch {
|
|
31876
32343
|
}
|
|
31877
32344
|
}
|
|
@@ -31879,7 +32346,7 @@ async function findTsConfig(cwd) {
|
|
|
31879
32346
|
}
|
|
31880
32347
|
|
|
31881
32348
|
// src/write.ts
|
|
31882
|
-
import * as
|
|
32349
|
+
import * as fs43 from "node:fs/promises";
|
|
31883
32350
|
import { ToolValidationError as ToolValidationError11 } from "@wrongstack/core/types";
|
|
31884
32351
|
import {
|
|
31885
32352
|
atomicWrite as atomicWrite6,
|
|
@@ -31956,14 +32423,14 @@ async function prepareWrite(input, ctx) {
|
|
|
31956
32423
|
let existed = false;
|
|
31957
32424
|
let prev = "";
|
|
31958
32425
|
try {
|
|
31959
|
-
const stat21 = await
|
|
32426
|
+
const stat21 = await fs43.stat(absPath);
|
|
31960
32427
|
existed = stat21.isFile();
|
|
31961
32428
|
if (existed) {
|
|
31962
32429
|
if (!ctx.hasRead(absPath)) {
|
|
31963
|
-
prev = await
|
|
32430
|
+
prev = await fs43.readFile(absPath, "utf8");
|
|
31964
32431
|
ctx.recordRead(absPath, stat21.mtimeMs, "write", sha256hex(prev));
|
|
31965
32432
|
} else {
|
|
31966
|
-
prev = await
|
|
32433
|
+
prev = await fs43.readFile(absPath, "utf8");
|
|
31967
32434
|
}
|
|
31968
32435
|
}
|
|
31969
32436
|
} catch (err) {
|
|
@@ -31984,7 +32451,7 @@ async function finishWrite(input, ctx, prepared, signal) {
|
|
|
31984
32451
|
const rawDiff = prepared.existed ? unifiedDiff3(prepared.prev, content, { fromFile: input.path, toFile: input.path }) : `+++ ${input.path}
|
|
31985
32452
|
+ (new file, ${content.split("\n").length} lines)`;
|
|
31986
32453
|
const { text: diff, truncated: diffTruncated } = truncateDiffPayload(rawDiff, MAX_DIFF_BYTES3);
|
|
31987
|
-
const stat21 = await
|
|
32454
|
+
const stat21 = await fs43.stat(prepared.absPath);
|
|
31988
32455
|
ctx.recordRead(prepared.absPath, stat21.mtimeMs, "write", sha256hex(content));
|
|
31989
32456
|
ctx.session.recordFileChange({
|
|
31990
32457
|
path: prepared.absPath,
|
|
@@ -32062,6 +32529,7 @@ var TIER1_TOOLS = [
|
|
|
32062
32529
|
var TIER2_TOOLS = [
|
|
32063
32530
|
replaceTool,
|
|
32064
32531
|
execTool,
|
|
32532
|
+
pwshTool,
|
|
32065
32533
|
fetchTool,
|
|
32066
32534
|
gitTool,
|
|
32067
32535
|
treeTool,
|
|
@@ -32105,6 +32573,7 @@ var builtinTools = [
|
|
|
32105
32573
|
grepTool,
|
|
32106
32574
|
bashTool,
|
|
32107
32575
|
execTool,
|
|
32576
|
+
pwshTool,
|
|
32108
32577
|
fetchTool,
|
|
32109
32578
|
searchTool,
|
|
32110
32579
|
todoTool,
|