@wrongstack/tools 0.291.0 → 0.291.2
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 +10 -1
- package/dist/bash-kill-guard.d.ts.map +1 -1
- package/dist/bash.js +140 -14
- package/dist/bash.js.map +2 -2
- package/dist/builtin.js +464 -90
- package/dist/builtin.js.map +4 -4
- package/dist/exec-kill-guard.d.ts +29 -0
- package/dist/exec-kill-guard.d.ts.map +1 -0
- package/dist/exec.d.ts.map +1 -1
- package/dist/exec.js +670 -10
- package/dist/exec.js.map +4 -4
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +490 -113
- package/dist/index.js.map +4 -4
- package/dist/pack.js +464 -90
- package/dist/pack.js.map +4 -4
- package/package.json +3 -3
package/dist/builtin.js
CHANGED
|
@@ -639,8 +639,8 @@ var init_process_registry = __esm({
|
|
|
639
639
|
if (p.killed) return true;
|
|
640
640
|
if (p.protected) return false;
|
|
641
641
|
const { force = false, graceMs = DEFAULT_GRACE_MS } = opts;
|
|
642
|
-
const
|
|
643
|
-
if (
|
|
642
|
+
const isWin5 = os.platform() === "win32";
|
|
643
|
+
if (isWin5) {
|
|
644
644
|
const liveRealChild = p.child.exitCode === null && typeof p.child.pid === "number";
|
|
645
645
|
const directFallback = () => {
|
|
646
646
|
if (p.child.exitCode === null) {
|
|
@@ -2605,8 +2605,8 @@ async function scanDirectory(directory, depth, profiles, limits, state, extraIgn
|
|
|
2605
2605
|
collectFileEvidence(directory, fullPath, entry.name, profiles, state);
|
|
2606
2606
|
}
|
|
2607
2607
|
}
|
|
2608
|
-
function collectFileEvidence(directory, fullPath,
|
|
2609
|
-
const lower =
|
|
2608
|
+
function collectFileEvidence(directory, fullPath, basename10, profiles, state) {
|
|
2609
|
+
const lower = basename10.toLowerCase();
|
|
2610
2610
|
const extension = path4.extname(lower);
|
|
2611
2611
|
for (const profile of profiles) {
|
|
2612
2612
|
const detector = profile.detectors.find(
|
|
@@ -2617,7 +2617,7 @@ function collectFileEvidence(directory, fullPath, basename9, profiles, state) {
|
|
|
2617
2617
|
candidate.evidence.push({
|
|
2618
2618
|
kind: detector.kind,
|
|
2619
2619
|
path: fullPath,
|
|
2620
|
-
value:
|
|
2620
|
+
value: basename10,
|
|
2621
2621
|
weight: detector.weight
|
|
2622
2622
|
});
|
|
2623
2623
|
if (detector.kind === "manifest" || detector.kind === "config") {
|
|
@@ -3934,15 +3934,15 @@ async function changedPaths(before, after, beforeSizes, afterSizes) {
|
|
|
3934
3934
|
const beforeSet = new Set(before);
|
|
3935
3935
|
const afterSet = new Set(after);
|
|
3936
3936
|
const changed = /* @__PURE__ */ new Set();
|
|
3937
|
-
for (const
|
|
3938
|
-
if (!beforeSet.has(
|
|
3937
|
+
for (const path33 of after) {
|
|
3938
|
+
if (!beforeSet.has(path33)) changed.add(path33);
|
|
3939
3939
|
}
|
|
3940
|
-
for (const
|
|
3941
|
-
if (!afterSet.has(
|
|
3940
|
+
for (const path33 of before) {
|
|
3941
|
+
if (!afterSet.has(path33)) changed.add(path33);
|
|
3942
3942
|
}
|
|
3943
3943
|
if (beforeSizes && afterSizes) {
|
|
3944
|
-
for (const
|
|
3945
|
-
if (beforeSizes.get(
|
|
3944
|
+
for (const path33 of after) {
|
|
3945
|
+
if (beforeSizes.get(path33) !== afterSizes.get(path33)) changed.add(path33);
|
|
3946
3946
|
}
|
|
3947
3947
|
}
|
|
3948
3948
|
return [...changed].sort();
|
|
@@ -5374,17 +5374,18 @@ function getPersistentProcessRegistry() {
|
|
|
5374
5374
|
|
|
5375
5375
|
// src/bash-kill-guard.ts
|
|
5376
5376
|
var isWin2 = os3.platform() === "win32";
|
|
5377
|
+
var SCRIPT_KILL_RE = /^(?:\.\\|\.\/)?(?:kill|terminate|stop)\S*\.(?:ps1|bat|cmd|sh)(?:\s|$)/i;
|
|
5378
|
+
var SCRIPT_KILL_RE_POSIX = /^(?:\.\/)?(?:kill|terminate|stop)\S*\.sh(?:\s|$)/i;
|
|
5379
|
+
var SCRIPT_KILL_FALLBACK_RE = /^\S*(?:kill|terminate|stop)\S*\.(?:ps1|bat|cmd|sh)\b/i;
|
|
5377
5380
|
function extractKillCommand(command) {
|
|
5378
5381
|
const normalized = command.replace(/\s+/g, " ").trim();
|
|
5379
|
-
const shellCMatch = normalized.match(
|
|
5380
|
-
|
|
5381
|
-
|
|
5382
|
-
if (shellCMatch?.[1]) {
|
|
5383
|
-
const inner = shellCMatch[1].trim();
|
|
5382
|
+
const shellCMatch = normalized.match(/^.+?\s+-c\s+(['"])([\s\S]+)\1$/);
|
|
5383
|
+
if (shellCMatch?.[2]) {
|
|
5384
|
+
const inner = shellCMatch[2].trim();
|
|
5384
5385
|
return isKillRelatedCommand(inner) ? inner : null;
|
|
5385
5386
|
}
|
|
5386
5387
|
const shellCUnquoted = normalized.match(
|
|
5387
|
-
|
|
5388
|
+
/^.+?\s+-c\s+(kill(?:\s+-s\s+[a-zA-Z0-9]+|\s+-[a-zA-Z0-9]+)?\s+\d+)$/
|
|
5388
5389
|
);
|
|
5389
5390
|
if (shellCUnquoted?.[1]) {
|
|
5390
5391
|
return shellCUnquoted[1];
|
|
@@ -5396,22 +5397,47 @@ function isKillRelatedCommand(cmd) {
|
|
|
5396
5397
|
if (isWin2) {
|
|
5397
5398
|
if (/^taskkill\s/i.test(normalized)) return true;
|
|
5398
5399
|
if (/^tskill\s/i.test(normalized)) return true;
|
|
5400
|
+
if (/^(stop-process|kill|stop)\s/i.test(normalized)) return true;
|
|
5401
|
+
if (/^wmic\s+process\s/i.test(normalized) && /\bdelete\b/i.test(normalized)) return true;
|
|
5402
|
+
if (SCRIPT_KILL_RE.test(normalized)) return true;
|
|
5399
5403
|
return false;
|
|
5400
5404
|
}
|
|
5401
5405
|
if (/^kill(\s|$)/.test(normalized)) return true;
|
|
5402
5406
|
if (/^(pkill|killall|pgrep|skill)\s/.test(normalized)) return true;
|
|
5403
5407
|
if (/^\/proc\/\d+\/(?:kill|fd)/.test(normalized)) return true;
|
|
5408
|
+
if (SCRIPT_KILL_RE_POSIX.test(normalized)) return true;
|
|
5404
5409
|
return false;
|
|
5405
5410
|
}
|
|
5406
5411
|
function parseKillCommand(command) {
|
|
5407
5412
|
const normalized = command.replace(/\s+/g, " ").trim();
|
|
5408
5413
|
if (isWin2) {
|
|
5409
|
-
const
|
|
5410
|
-
|
|
5411
|
-
|
|
5414
|
+
const hasTaskkillForce = /(?:^|\s)\/F(?=\s|$)/i.test(normalized);
|
|
5415
|
+
const isSimpleTaskkill = /^taskkill\s+/i.test(normalized) && !/[|&<>]/.test(normalized);
|
|
5416
|
+
const taskkillPidMatch = isSimpleTaskkill ? normalized.match(/(?:^|\s)\/PID\s+(\d+)(?=\s|$)/i) : null;
|
|
5417
|
+
if (taskkillPidMatch?.[1]) {
|
|
5418
|
+
return {
|
|
5419
|
+
pid: parseInt(taskkillPidMatch[1], 10),
|
|
5420
|
+
signal: hasTaskkillForce ? "FORCE" : "TERM",
|
|
5421
|
+
isGroupKill: false,
|
|
5422
|
+
isAllKill: false,
|
|
5423
|
+
originalCommand: command
|
|
5424
|
+
};
|
|
5425
|
+
}
|
|
5426
|
+
const taskkillImMatch = isSimpleTaskkill ? normalized.match(/(?:^|\s)\/IM\s+([^\s/]+)(?=\s|$)/i) : null;
|
|
5427
|
+
if (taskkillImMatch?.[1]) {
|
|
5428
|
+
return {
|
|
5429
|
+
name: taskkillImMatch[1],
|
|
5430
|
+
signal: hasTaskkillForce ? "FORCE" : "TERM",
|
|
5431
|
+
isGroupKill: false,
|
|
5432
|
+
isAllKill: false,
|
|
5433
|
+
originalCommand: command
|
|
5434
|
+
};
|
|
5435
|
+
}
|
|
5436
|
+
const taskkillFiMatch = isSimpleTaskkill ? normalized.match(/(?:^|\s)\/FI\s+"IMAGENAME\s+eq\s+([^"]+)"(?=\s|$)/i) : null;
|
|
5437
|
+
if (taskkillFiMatch?.[1]) {
|
|
5412
5438
|
return {
|
|
5413
|
-
|
|
5414
|
-
signal:
|
|
5439
|
+
name: taskkillFiMatch[1],
|
|
5440
|
+
signal: hasTaskkillForce ? "FORCE" : "TERM",
|
|
5415
5441
|
isGroupKill: false,
|
|
5416
5442
|
isAllKill: false,
|
|
5417
5443
|
originalCommand: command
|
|
@@ -5419,18 +5445,109 @@ function parseKillCommand(command) {
|
|
|
5419
5445
|
}
|
|
5420
5446
|
const tskillMatch = normalized.match(/^tskill\s+(\d+)/i);
|
|
5421
5447
|
if (tskillMatch?.[1]) {
|
|
5422
|
-
const pidStr = tskillMatch[1];
|
|
5423
5448
|
return {
|
|
5424
|
-
pid: parseInt(
|
|
5449
|
+
pid: parseInt(tskillMatch[1], 10),
|
|
5425
5450
|
signal: "TERM",
|
|
5426
5451
|
isGroupKill: false,
|
|
5427
5452
|
isAllKill: false,
|
|
5428
5453
|
originalCommand: command
|
|
5429
5454
|
};
|
|
5430
5455
|
}
|
|
5456
|
+
const isStopProcIdCommand = /^(?:stop-process|kill)(?:\s+-(?:id|pid)\s+\d+|\s+-[a-zA-Z]+)+$/i.test(normalized);
|
|
5457
|
+
const stopProcIdMatch = normalized.match(/(?:^|\s)-(?:id|pid)\s+(\d+)(?=\s|$)/i);
|
|
5458
|
+
if (isStopProcIdCommand && stopProcIdMatch?.[1]) {
|
|
5459
|
+
return {
|
|
5460
|
+
pid: parseInt(stopProcIdMatch[1], 10),
|
|
5461
|
+
signal: "FORCE",
|
|
5462
|
+
isGroupKill: false,
|
|
5463
|
+
isAllKill: false,
|
|
5464
|
+
originalCommand: command
|
|
5465
|
+
};
|
|
5466
|
+
}
|
|
5467
|
+
const killSignalOptionMatch = normalized.match(/^kill\s+-s\s+([a-zA-Z0-9]+)\s+(\d+)$/i);
|
|
5468
|
+
if (killSignalOptionMatch?.[1] && killSignalOptionMatch[2]) {
|
|
5469
|
+
return {
|
|
5470
|
+
pid: parseInt(killSignalOptionMatch[2], 10),
|
|
5471
|
+
signal: killSignalOptionMatch[1].toUpperCase(),
|
|
5472
|
+
isGroupKill: false,
|
|
5473
|
+
isAllKill: false,
|
|
5474
|
+
originalCommand: command
|
|
5475
|
+
};
|
|
5476
|
+
}
|
|
5477
|
+
const killPosixMatch = normalized.match(/^kill\s+(?:(-[a-zA-Z0-9]+)\s+)?(\d+)$/);
|
|
5478
|
+
if (killPosixMatch?.[2]) {
|
|
5479
|
+
const sig = killPosixMatch[1] ? killPosixMatch[1].slice(1).toUpperCase() : "TERM";
|
|
5480
|
+
return {
|
|
5481
|
+
pid: parseInt(killPosixMatch[2], 10),
|
|
5482
|
+
signal: sig,
|
|
5483
|
+
isGroupKill: false,
|
|
5484
|
+
isAllKill: false,
|
|
5485
|
+
originalCommand: command
|
|
5486
|
+
};
|
|
5487
|
+
}
|
|
5488
|
+
const stopProcNameMatch = normalized.match(
|
|
5489
|
+
/^(?:stop-process|kill)\s+-(?:name|n)\s+(?:['"]([a-zA-Z0-9_.-]+)['"]|([a-zA-Z0-9_.-]+))(?:\s|$)/i
|
|
5490
|
+
);
|
|
5491
|
+
const stopProcName = stopProcNameMatch?.[1] ?? stopProcNameMatch?.[2];
|
|
5492
|
+
if (stopProcName) {
|
|
5493
|
+
return {
|
|
5494
|
+
name: stopProcName,
|
|
5495
|
+
signal: "FORCE",
|
|
5496
|
+
isGroupKill: false,
|
|
5497
|
+
isAllKill: false,
|
|
5498
|
+
originalCommand: command
|
|
5499
|
+
};
|
|
5500
|
+
}
|
|
5501
|
+
const stopProcStandalone = normalized.match(
|
|
5502
|
+
/^(?:stop-process|kill)\s+['"]?([a-zA-Z][a-zA-Z0-9_.-]+)['"]?$/i
|
|
5503
|
+
);
|
|
5504
|
+
if (stopProcStandalone?.[1]) {
|
|
5505
|
+
return {
|
|
5506
|
+
name: stopProcStandalone[1],
|
|
5507
|
+
signal: "FORCE",
|
|
5508
|
+
isGroupKill: false,
|
|
5509
|
+
isAllKill: false,
|
|
5510
|
+
originalCommand: command
|
|
5511
|
+
};
|
|
5512
|
+
}
|
|
5513
|
+
const wmicMatch = normalized.match(
|
|
5514
|
+
/^wmic\s+process\s+where\s+['"]?(?:name\s*=\s*['"]?)([a-zA-Z0-9_.-]+)/i
|
|
5515
|
+
);
|
|
5516
|
+
if (wmicMatch?.[1]) {
|
|
5517
|
+
return {
|
|
5518
|
+
name: wmicMatch[1],
|
|
5519
|
+
signal: "FORCE",
|
|
5520
|
+
isGroupKill: false,
|
|
5521
|
+
isAllKill: false,
|
|
5522
|
+
originalCommand: command
|
|
5523
|
+
};
|
|
5524
|
+
}
|
|
5525
|
+
const killScriptMatch = normalized.match(SCRIPT_KILL_RE);
|
|
5526
|
+
if (killScriptMatch) {
|
|
5527
|
+
return {
|
|
5528
|
+
name: "kill-script",
|
|
5529
|
+
// sentinel — isKillProtected always blocks "kill-script"
|
|
5530
|
+
signal: "FORCE",
|
|
5531
|
+
isGroupKill: false,
|
|
5532
|
+
isAllKill: false,
|
|
5533
|
+
originalCommand: command
|
|
5534
|
+
};
|
|
5535
|
+
}
|
|
5431
5536
|
return null;
|
|
5432
5537
|
}
|
|
5433
|
-
const
|
|
5538
|
+
const signalOptionMatch = normalized.match(/^kill\s+-s\s+([a-zA-Z0-9]+)\s+(\d+|-?\d+)$/i);
|
|
5539
|
+
if (signalOptionMatch?.[1] && signalOptionMatch[2]) {
|
|
5540
|
+
const pidOrGroup = signalOptionMatch[2];
|
|
5541
|
+
const isGroupKill = pidOrGroup.startsWith("-");
|
|
5542
|
+
return {
|
|
5543
|
+
pid: parseInt(isGroupKill ? pidOrGroup.slice(1) : pidOrGroup, 10),
|
|
5544
|
+
signal: signalOptionMatch[1].toUpperCase(),
|
|
5545
|
+
isGroupKill,
|
|
5546
|
+
isAllKill: false,
|
|
5547
|
+
originalCommand: command
|
|
5548
|
+
};
|
|
5549
|
+
}
|
|
5550
|
+
const simpleMatch = normalized.match(/^kill\s+(?:(-[a-zA-Z0-9]+)\s+)?(\d+|-?\d+)$/);
|
|
5434
5551
|
if (simpleMatch) {
|
|
5435
5552
|
const signal = simpleMatch[1] ?? "-TERM";
|
|
5436
5553
|
const pidOrGroup = simpleMatch[2];
|
|
@@ -5490,6 +5607,9 @@ async function getProtectedEntries() {
|
|
|
5490
5607
|
}
|
|
5491
5608
|
async function isKillProtected(kill) {
|
|
5492
5609
|
const registry = getPersistentProcessRegistry();
|
|
5610
|
+
if (kill.name === "kill-script") {
|
|
5611
|
+
return true;
|
|
5612
|
+
}
|
|
5493
5613
|
if (kill.name) {
|
|
5494
5614
|
const entries = await getProtectedEntries();
|
|
5495
5615
|
const killNameLower = kill.name.toLowerCase();
|
|
@@ -5529,6 +5649,12 @@ async function checkAndBlockKillCommand(command) {
|
|
|
5529
5649
|
reason: `Blocked: complex kill pipeline detected \u2014 "${killCmd.slice(0, 50)}..."`
|
|
5530
5650
|
};
|
|
5531
5651
|
}
|
|
5652
|
+
if (SCRIPT_KILL_FALLBACK_RE.test(killCmd)) {
|
|
5653
|
+
return {
|
|
5654
|
+
blocked: true,
|
|
5655
|
+
reason: `Blocked: script-based kill detected \u2014 "${killCmd.slice(0, 80)}" may target protected WrongStack processes (cannot inspect script body).`
|
|
5656
|
+
};
|
|
5657
|
+
}
|
|
5532
5658
|
return { blocked: false };
|
|
5533
5659
|
}
|
|
5534
5660
|
if (await isKillProtected(parsed)) {
|
|
@@ -5552,8 +5678,8 @@ async function checkAndBlockKillCommand(command) {
|
|
|
5552
5678
|
|
|
5553
5679
|
// src/_shell-pick.ts
|
|
5554
5680
|
var POSIX_DEFAULT = "cmd";
|
|
5555
|
-
function pickShell(
|
|
5556
|
-
if (
|
|
5681
|
+
function pickShell(platform5, command, env) {
|
|
5682
|
+
if (platform5 !== "win32") return POSIX_DEFAULT;
|
|
5557
5683
|
const override = env.get("WRONGSTACK_SHELL")?.trim().toLowerCase();
|
|
5558
5684
|
if (override === "cmd" || override === "cmd.exe") return "cmd";
|
|
5559
5685
|
if (override === "powershell" || override === "powershell.exe") return "powershell";
|
|
@@ -5757,10 +5883,10 @@ var bashTool = {
|
|
|
5757
5883
|
}));
|
|
5758
5884
|
}
|
|
5759
5885
|
const timeoutMs = Math.max(1, Math.min(input.timeout_ms ?? DEFAULT_TIMEOUT_MS2, 6e5));
|
|
5760
|
-
const
|
|
5886
|
+
const isWin5 = os4.platform() === "win32";
|
|
5761
5887
|
let plan;
|
|
5762
5888
|
let winShellKind;
|
|
5763
|
-
if (
|
|
5889
|
+
if (isWin5) {
|
|
5764
5890
|
const shell2 = pickShell("win32", input.command, {
|
|
5765
5891
|
get: (k) => process.env[k]
|
|
5766
5892
|
});
|
|
@@ -5789,7 +5915,7 @@ var bashTool = {
|
|
|
5789
5915
|
const shell = plan.bin;
|
|
5790
5916
|
const args = plan.useStdin ? [...plan.argv] : [...plan.argv, input.command];
|
|
5791
5917
|
const env = buildChildEnv2(ctx.session?.id);
|
|
5792
|
-
const detached = !
|
|
5918
|
+
const detached = !isWin5;
|
|
5793
5919
|
const startedAt = Date.now();
|
|
5794
5920
|
if (input.background) {
|
|
5795
5921
|
let buf2 = "";
|
|
@@ -5807,7 +5933,7 @@ var bashTool = {
|
|
|
5807
5933
|
// apply: the child gets a hidden console that grandchildren inherit.
|
|
5808
5934
|
// Windows children survive parent exit either way. POSIX keeps
|
|
5809
5935
|
// detached for the process-group kill semantics.
|
|
5810
|
-
detached: !
|
|
5936
|
+
detached: !isWin5,
|
|
5811
5937
|
windowsHide: true
|
|
5812
5938
|
});
|
|
5813
5939
|
if (plan.useStdin) {
|
|
@@ -5918,7 +6044,7 @@ var bashTool = {
|
|
|
5918
6044
|
stdio: [plan.useStdin ? "pipe" : "ignore", "pipe", "pipe"],
|
|
5919
6045
|
detached,
|
|
5920
6046
|
windowsHide: true,
|
|
5921
|
-
...
|
|
6047
|
+
...isWin5 ? {} : { signal: opts.signal }
|
|
5922
6048
|
});
|
|
5923
6049
|
if (plan.useStdin) {
|
|
5924
6050
|
try {
|
|
@@ -5971,7 +6097,7 @@ var bashTool = {
|
|
|
5971
6097
|
const timers = [];
|
|
5972
6098
|
const spool = createOutputSpool({ tool: "bash", thresholdBytes: MAX_OUTPUT });
|
|
5973
6099
|
function killWithTimeout(child2, timeoutMs2) {
|
|
5974
|
-
if (
|
|
6100
|
+
if (isWin5) {
|
|
5975
6101
|
if (typeof child2.pid === "number" && child2.exitCode === null) {
|
|
5976
6102
|
const attempted = registry.kill(child2.pid, { force: true, graceMs: timeoutMs2 });
|
|
5977
6103
|
if (!attempted) {
|
|
@@ -6012,7 +6138,7 @@ var bashTool = {
|
|
|
6012
6138
|
timers.push(timer);
|
|
6013
6139
|
timer.unref?.();
|
|
6014
6140
|
const onAbort = () => killWithTimeout(child, 2e3);
|
|
6015
|
-
if (
|
|
6141
|
+
if (isWin5) {
|
|
6016
6142
|
if (opts.signal.aborted) onAbort();
|
|
6017
6143
|
else opts.signal.addEventListener("abort", onAbort, { once: true });
|
|
6018
6144
|
}
|
|
@@ -6126,7 +6252,7 @@ ${hint}` : ""),
|
|
|
6126
6252
|
} finally {
|
|
6127
6253
|
for (const t of timers) clearTimeout(t);
|
|
6128
6254
|
spool.finalize();
|
|
6129
|
-
if (
|
|
6255
|
+
if (isWin5) opts.signal.removeEventListener("abort", onAbort);
|
|
6130
6256
|
child.stdout?.off("data", onStdoutData);
|
|
6131
6257
|
child.stderr?.off("data", onStderrData);
|
|
6132
6258
|
child.stdout?.destroy();
|
|
@@ -9998,9 +10124,9 @@ function parseSymbols5(opts) {
|
|
|
9998
10124
|
function regexParse2(opts) {
|
|
9999
10125
|
const { file, content, lang } = opts;
|
|
10000
10126
|
const symbols = [];
|
|
10001
|
-
const
|
|
10002
|
-
const isPackageJson =
|
|
10003
|
-
const isTsconfig =
|
|
10127
|
+
const basename10 = path17.basename(file).toLowerCase();
|
|
10128
|
+
const isPackageJson = basename10 === "package.json";
|
|
10129
|
+
const isTsconfig = basename10 === "tsconfig.json" || basename10 === "tsconfig.build.json";
|
|
10004
10130
|
const isJsonSchema = content.includes("$schema") || content.includes("$id") || content.includes("$ref");
|
|
10005
10131
|
const isOpenApi = content.includes("openapi") || content.includes("swagger");
|
|
10006
10132
|
const lines = content.split("\n");
|
|
@@ -13154,8 +13280,243 @@ function levelRank(level) {
|
|
|
13154
13280
|
}
|
|
13155
13281
|
}
|
|
13156
13282
|
|
|
13283
|
+
// src/exec-kill-guard.ts
|
|
13284
|
+
import * as os7 from "node:os";
|
|
13285
|
+
import * as path24 from "node:path";
|
|
13286
|
+
var isWin3 = os7.platform() === "win32";
|
|
13287
|
+
async function checkExecKillCommand(cmd, args) {
|
|
13288
|
+
if (!cmd) return { blocked: false };
|
|
13289
|
+
const cmdLower = cmd.toLowerCase().trim();
|
|
13290
|
+
const fullCommand = [cmdLower, ...args].join(" ").replace(/\s+/g, " ").trim();
|
|
13291
|
+
if (isWin3) {
|
|
13292
|
+
if (cmdLower === "taskkill" || cmdLower === "taskkill.exe") {
|
|
13293
|
+
const hasForce = args.some((a) => a.toUpperCase() === "/F" || a.toUpperCase() === "-F");
|
|
13294
|
+
const signal = hasForce ? "FORCE" : "TERM";
|
|
13295
|
+
for (let i = 0; i < args.length; i++) {
|
|
13296
|
+
const a = args[i];
|
|
13297
|
+
if (a.toUpperCase() === "/IM" || a.toUpperCase() === "-IM") {
|
|
13298
|
+
const nameArg = args[i + 1];
|
|
13299
|
+
if (nameArg) {
|
|
13300
|
+
const result = await checkKillTarget({ name: nameArg, signal, cmd: fullCommand });
|
|
13301
|
+
if (result.blocked) return result;
|
|
13302
|
+
}
|
|
13303
|
+
}
|
|
13304
|
+
}
|
|
13305
|
+
for (let i = 0; i < args.length; i++) {
|
|
13306
|
+
const a = args[i];
|
|
13307
|
+
if (a.toUpperCase() === "/PID" || a.toUpperCase() === "-PID") {
|
|
13308
|
+
const pidArg = args[i + 1];
|
|
13309
|
+
if (pidArg && /^\d+$/.test(pidArg)) {
|
|
13310
|
+
const result = await checkKillTarget({
|
|
13311
|
+
pid: parseInt(pidArg, 10),
|
|
13312
|
+
signal,
|
|
13313
|
+
cmd: fullCommand
|
|
13314
|
+
});
|
|
13315
|
+
if (result.blocked) return result;
|
|
13316
|
+
}
|
|
13317
|
+
}
|
|
13318
|
+
}
|
|
13319
|
+
for (let i = 0; i < args.length; i++) {
|
|
13320
|
+
const a = args[i];
|
|
13321
|
+
if (a.toUpperCase() === "/FI" || a.toUpperCase() === "-FI") {
|
|
13322
|
+
const filterArg = args[i + 1];
|
|
13323
|
+
if (filterArg) {
|
|
13324
|
+
const nameMatch = filterArg.match(/IMAGENAME\s+eq\s+"?([^"\s]+)/i);
|
|
13325
|
+
if (nameMatch?.[1]) {
|
|
13326
|
+
const result = await checkKillTarget({ name: nameMatch[1], signal, cmd: fullCommand });
|
|
13327
|
+
if (result.blocked) return result;
|
|
13328
|
+
}
|
|
13329
|
+
}
|
|
13330
|
+
}
|
|
13331
|
+
}
|
|
13332
|
+
return { blocked: false };
|
|
13333
|
+
}
|
|
13334
|
+
if (cmdLower === "powershell" || cmdLower === "powershell.exe" || cmdLower === "pwsh" || cmdLower === "pwsh.exe" || cmdLower === "cmd" || cmdLower === "cmd.exe") {
|
|
13335
|
+
const shellFlagIndex = args.findIndex((arg) => {
|
|
13336
|
+
const lower = arg.toLowerCase();
|
|
13337
|
+
return lower === "-c" || lower === "-command" || lower === "/c";
|
|
13338
|
+
});
|
|
13339
|
+
if (shellFlagIndex >= 0) {
|
|
13340
|
+
const innerTokens = tokenizeShellCommand(args.slice(shellFlagIndex + 1).join(" "));
|
|
13341
|
+
const innerCommand = innerTokens[0];
|
|
13342
|
+
if (innerCommand) {
|
|
13343
|
+
const result = await checkExecKillCommand(innerCommand, innerTokens.slice(1));
|
|
13344
|
+
if (result.blocked) return result;
|
|
13345
|
+
}
|
|
13346
|
+
}
|
|
13347
|
+
}
|
|
13348
|
+
if (cmdLower === "stop-process" || cmdLower === "kill") {
|
|
13349
|
+
for (let i = 0; i < args.length; i++) {
|
|
13350
|
+
const a = args[i];
|
|
13351
|
+
if (a === "-Name" || a === "-n") {
|
|
13352
|
+
const nameArg = args[i + 1]?.replace(/^['"]|['"]$/g, "");
|
|
13353
|
+
if (nameArg) {
|
|
13354
|
+
const result = await checkKillTarget({
|
|
13355
|
+
name: nameArg,
|
|
13356
|
+
signal: "FORCE",
|
|
13357
|
+
cmd: fullCommand
|
|
13358
|
+
});
|
|
13359
|
+
if (result.blocked) return result;
|
|
13360
|
+
}
|
|
13361
|
+
}
|
|
13362
|
+
if (a === "-Id" || a === "-PID" || a === "-pid") {
|
|
13363
|
+
const pidArg = args[i + 1];
|
|
13364
|
+
if (pidArg && /^\d+$/.test(pidArg)) {
|
|
13365
|
+
const result = await checkKillTarget({
|
|
13366
|
+
pid: parseInt(pidArg, 10),
|
|
13367
|
+
signal: "FORCE",
|
|
13368
|
+
cmd: fullCommand
|
|
13369
|
+
});
|
|
13370
|
+
if (result.blocked) return result;
|
|
13371
|
+
}
|
|
13372
|
+
}
|
|
13373
|
+
}
|
|
13374
|
+
const firstNonFlag = args.find((a) => !a.startsWith("-"));
|
|
13375
|
+
if (firstNonFlag) {
|
|
13376
|
+
const name = firstNonFlag.replace(/^['"]|['"]$/g, "");
|
|
13377
|
+
const result = await checkKillTarget({ name, signal: "TERM", cmd: fullCommand });
|
|
13378
|
+
if (result.blocked) return result;
|
|
13379
|
+
}
|
|
13380
|
+
}
|
|
13381
|
+
if (cmdLower === "wmic" || cmdLower === "wmic.exe") {
|
|
13382
|
+
const joined = args.join(" ").toLowerCase();
|
|
13383
|
+
if (/\bprocess\b/.test(joined) && /\bdelete\b/.test(joined)) {
|
|
13384
|
+
const nameMatch = joined.match(/name\s*=\s*['"]?([^'"]+)/);
|
|
13385
|
+
if (nameMatch?.[1]) {
|
|
13386
|
+
const result = await checkKillTarget({
|
|
13387
|
+
name: nameMatch[1].trim(),
|
|
13388
|
+
signal: "FORCE",
|
|
13389
|
+
cmd: fullCommand
|
|
13390
|
+
});
|
|
13391
|
+
if (result.blocked) return result;
|
|
13392
|
+
}
|
|
13393
|
+
return {
|
|
13394
|
+
blocked: true,
|
|
13395
|
+
reason: "Blocked: wmic process delete targets all matched processes \u2014 would include protected WrongStack processes."
|
|
13396
|
+
};
|
|
13397
|
+
}
|
|
13398
|
+
}
|
|
13399
|
+
if (cmdLower === "node" || cmdLower === "node.exe") {
|
|
13400
|
+
if (args.includes("-e") || args.includes("--eval")) {
|
|
13401
|
+
const evalIdx = args.indexOf("-e") !== -1 ? args.indexOf("-e") : args.indexOf("--eval");
|
|
13402
|
+
const evalCode = args[evalIdx + 1] ?? "";
|
|
13403
|
+
if (/\bprocess\.kill\s*\(/.test(evalCode)) {
|
|
13404
|
+
const pidMatch = evalCode.match(/process\.kill\s*\(\s*(\d+)/);
|
|
13405
|
+
if (pidMatch?.[1]) {
|
|
13406
|
+
const pid = parseInt(pidMatch[1], 10);
|
|
13407
|
+
const result = await checkKillTarget({ pid, signal: "SIGTERM", cmd: fullCommand });
|
|
13408
|
+
if (result.blocked) return result;
|
|
13409
|
+
}
|
|
13410
|
+
return {
|
|
13411
|
+
blocked: true,
|
|
13412
|
+
reason: "Blocked: node -e with process.kill() \u2014 would target protected WrongStack process(es)."
|
|
13413
|
+
};
|
|
13414
|
+
}
|
|
13415
|
+
}
|
|
13416
|
+
}
|
|
13417
|
+
} else {
|
|
13418
|
+
if (cmdLower === "kill") {
|
|
13419
|
+
for (const a of args) {
|
|
13420
|
+
const num = a.replace(/^-/, "");
|
|
13421
|
+
if (/^\d+$/.test(num)) {
|
|
13422
|
+
const pid = parseInt(num, 10);
|
|
13423
|
+
const result = await checkKillTarget({ pid, signal: "SIGTERM", cmd: fullCommand });
|
|
13424
|
+
if (result.blocked) return result;
|
|
13425
|
+
}
|
|
13426
|
+
}
|
|
13427
|
+
}
|
|
13428
|
+
if (cmdLower === "pkill" || cmdLower === "killall") {
|
|
13429
|
+
const firstNonFlag = args.find((a) => !a.startsWith("-"));
|
|
13430
|
+
if (firstNonFlag) {
|
|
13431
|
+
const result = await checkKillTarget({
|
|
13432
|
+
name: firstNonFlag,
|
|
13433
|
+
signal: "SIGTERM",
|
|
13434
|
+
cmd: fullCommand
|
|
13435
|
+
});
|
|
13436
|
+
if (result.blocked) return result;
|
|
13437
|
+
}
|
|
13438
|
+
}
|
|
13439
|
+
}
|
|
13440
|
+
return { blocked: false };
|
|
13441
|
+
}
|
|
13442
|
+
function tokenizeShellCommand(command) {
|
|
13443
|
+
const tokens = [];
|
|
13444
|
+
let current = "";
|
|
13445
|
+
let quote = null;
|
|
13446
|
+
for (const char of command.trim()) {
|
|
13447
|
+
if (quote) {
|
|
13448
|
+
if (char === quote) quote = null;
|
|
13449
|
+
else current += char;
|
|
13450
|
+
continue;
|
|
13451
|
+
}
|
|
13452
|
+
if (char === '"' || char === "'") {
|
|
13453
|
+
quote = char;
|
|
13454
|
+
} else if (/\s/.test(char)) {
|
|
13455
|
+
if (current) {
|
|
13456
|
+
tokens.push(current);
|
|
13457
|
+
current = "";
|
|
13458
|
+
}
|
|
13459
|
+
} else {
|
|
13460
|
+
current += char;
|
|
13461
|
+
}
|
|
13462
|
+
}
|
|
13463
|
+
if (current) tokens.push(current);
|
|
13464
|
+
return tokens;
|
|
13465
|
+
}
|
|
13466
|
+
async function checkKillTarget(target) {
|
|
13467
|
+
const registry = getPersistentProcessRegistry();
|
|
13468
|
+
if (target.pid !== void 0) {
|
|
13469
|
+
const blocked = await registry.shouldBlockKill(target.pid);
|
|
13470
|
+
if (blocked) {
|
|
13471
|
+
return {
|
|
13472
|
+
blocked: true,
|
|
13473
|
+
reason: `Blocked: kill ${target.signal} PID ${target.pid} targets a protected WrongStack process (${target.cmd.slice(0, 80)}).`
|
|
13474
|
+
};
|
|
13475
|
+
}
|
|
13476
|
+
if (target.pid === process.pid) {
|
|
13477
|
+
return {
|
|
13478
|
+
blocked: true,
|
|
13479
|
+
reason: "Blocked: cannot kill the current WrongStack process."
|
|
13480
|
+
};
|
|
13481
|
+
}
|
|
13482
|
+
if (target.pid === process.ppid) {
|
|
13483
|
+
return {
|
|
13484
|
+
blocked: true,
|
|
13485
|
+
reason: "Blocked: cannot kill the parent terminal hosting WrongStack."
|
|
13486
|
+
};
|
|
13487
|
+
}
|
|
13488
|
+
return { blocked: false };
|
|
13489
|
+
}
|
|
13490
|
+
if (target.name) {
|
|
13491
|
+
const nameLower = target.name.toLowerCase().replace(/\.exe$/, "");
|
|
13492
|
+
if (nameLower.includes("wrongstack")) {
|
|
13493
|
+
return {
|
|
13494
|
+
blocked: true,
|
|
13495
|
+
reason: `Blocked: kill ${target.signal} '${target.name}' targets a WrongStack process name.`
|
|
13496
|
+
};
|
|
13497
|
+
}
|
|
13498
|
+
const currentImage = path24.basename(process.execPath).toLowerCase().replace(/\.exe$/, "");
|
|
13499
|
+
const targetsNodeRuntime = nameLower === "node" || nameLower.startsWith("node");
|
|
13500
|
+
if (targetsNodeRuntime && currentImage === "node") {
|
|
13501
|
+
return {
|
|
13502
|
+
blocked: true,
|
|
13503
|
+
reason: `Blocked: kill ${target.signal} '${target.name}' would kill the active WrongStack node.exe runtime.`
|
|
13504
|
+
};
|
|
13505
|
+
}
|
|
13506
|
+
const protectedPids = await registry.getAllProtectedPids();
|
|
13507
|
+
if (protectedPids.length > 0 && targetsNodeRuntime) {
|
|
13508
|
+
return {
|
|
13509
|
+
blocked: true,
|
|
13510
|
+
reason: `Blocked: kill ${target.signal} '${target.name}' would kill all node.exe processes including active WrongStack instance(s).`
|
|
13511
|
+
};
|
|
13512
|
+
}
|
|
13513
|
+
return { blocked: false };
|
|
13514
|
+
}
|
|
13515
|
+
return { blocked: false };
|
|
13516
|
+
}
|
|
13517
|
+
|
|
13157
13518
|
// src/exec.ts
|
|
13158
|
-
var
|
|
13519
|
+
var isWin4 = process.platform === "win32";
|
|
13159
13520
|
var DEFAULT_ALLOWED_COMMANDS = /* @__PURE__ */ new Set([
|
|
13160
13521
|
// JS / TS toolchain
|
|
13161
13522
|
"node",
|
|
@@ -13931,6 +14292,19 @@ var execTool = {
|
|
|
13931
14292
|
const args = (input.args ?? []).slice(0, MAX_ARGS);
|
|
13932
14293
|
const timeout = Math.max(1, Math.min(input.timeout ?? DEFAULT_TIMEOUT_MS3, DEFAULT_TIMEOUT_MS3));
|
|
13933
14294
|
const danger = detectDanger(cmd, args, dangerBypass);
|
|
14295
|
+
const killCheck = await checkExecKillCommand(cmd, args);
|
|
14296
|
+
if (killCheck.blocked) {
|
|
14297
|
+
return {
|
|
14298
|
+
command: cmd,
|
|
14299
|
+
args,
|
|
14300
|
+
stdout: "",
|
|
14301
|
+
stderr: killCheck.reason ?? "Kill command blocked: targets a protected WrongStack process.",
|
|
14302
|
+
exitCode: 1,
|
|
14303
|
+
truncated: false,
|
|
14304
|
+
allowed: false,
|
|
14305
|
+
danger
|
|
14306
|
+
};
|
|
14307
|
+
}
|
|
13934
14308
|
const argError = validateArgs(cmd, args);
|
|
13935
14309
|
if (argError) {
|
|
13936
14310
|
return {
|
|
@@ -13981,7 +14355,7 @@ function runCommand(cmd, args, cwd, timeout, signal, sessionId, danger) {
|
|
|
13981
14355
|
let timedOut = false;
|
|
13982
14356
|
const spool = createOutputSpool({ tool: `exec-${cmd}`, thresholdBytes: MAX_OUTPUT2 });
|
|
13983
14357
|
const resolved = resolveWin32Command(cmd);
|
|
13984
|
-
const needsShell =
|
|
14358
|
+
const needsShell = isWin4 && (resolved.endsWith(".cmd") || resolved.endsWith(".bat"));
|
|
13985
14359
|
const shim = needsShell ? buildWin32CmdShimInvocation(resolved, args) : null;
|
|
13986
14360
|
const spawnCmd = shim?.command ?? resolved;
|
|
13987
14361
|
const spawnArgs = shim?.args ?? args;
|
|
@@ -14006,7 +14380,7 @@ function runCommand(cmd, args, cwd, timeout, signal, sessionId, danger) {
|
|
|
14006
14380
|
env: buildChildEnv2(sessionId),
|
|
14007
14381
|
stdio: ["ignore", "pipe", "pipe"],
|
|
14008
14382
|
windowsHide: true,
|
|
14009
|
-
...
|
|
14383
|
+
...isWin4 ? {} : { signal },
|
|
14010
14384
|
...shim ? { windowsVerbatimArguments: shim.windowsVerbatimArguments } : {}
|
|
14011
14385
|
});
|
|
14012
14386
|
} catch (err) {
|
|
@@ -14045,7 +14419,7 @@ function runCommand(cmd, args, cwd, timeout, signal, sessionId, danger) {
|
|
|
14045
14419
|
const isAbort = err && err.code === "ABORT_ERR";
|
|
14046
14420
|
const stderrText = isAbort ? `Aborted: ${err.message}` : err.message;
|
|
14047
14421
|
clearTimeout(timer);
|
|
14048
|
-
if (
|
|
14422
|
+
if (isWin4) signal.removeEventListener("abort", onAbort);
|
|
14049
14423
|
if (typeof pid === "number") registry.unregister(pid);
|
|
14050
14424
|
registry.afterCall(Date.now() - startedAt, true);
|
|
14051
14425
|
spool.finalize();
|
|
@@ -14078,7 +14452,7 @@ function runCommand(cmd, args, cwd, timeout, signal, sessionId, danger) {
|
|
|
14078
14452
|
if (typeof pid === "number") registry.kill(pid, { force: true });
|
|
14079
14453
|
else child.kill("SIGTERM");
|
|
14080
14454
|
};
|
|
14081
|
-
if (
|
|
14455
|
+
if (isWin4) {
|
|
14082
14456
|
if (signal.aborted) onAbort();
|
|
14083
14457
|
else signal.addEventListener("abort", onAbort, { once: true });
|
|
14084
14458
|
}
|
|
@@ -14098,7 +14472,7 @@ function runCommand(cmd, args, cwd, timeout, signal, sessionId, danger) {
|
|
|
14098
14472
|
});
|
|
14099
14473
|
child.on("close", (code) => {
|
|
14100
14474
|
clearTimeout(timer);
|
|
14101
|
-
if (
|
|
14475
|
+
if (isWin4) signal.removeEventListener("abort", onAbort);
|
|
14102
14476
|
if (typeof pid === "number") registry.unregister(pid);
|
|
14103
14477
|
const durationMs = Date.now() - startedAt;
|
|
14104
14478
|
const exitCode = killed ? 124 : code ?? 1;
|
|
@@ -14909,7 +15283,7 @@ function runGit2(args, cwd, signal) {
|
|
|
14909
15283
|
|
|
14910
15284
|
// src/glob.ts
|
|
14911
15285
|
import * as fs20 from "node:fs/promises";
|
|
14912
|
-
import * as
|
|
15286
|
+
import * as path25 from "node:path";
|
|
14913
15287
|
import { compileGlob as compileGlob3 } from "@wrongstack/core";
|
|
14914
15288
|
|
|
14915
15289
|
// src/_concurrency.ts
|
|
@@ -15013,7 +15387,7 @@ var globTool = {
|
|
|
15013
15387
|
if (DEFAULT_IGNORE2.includes(name)) continue;
|
|
15014
15388
|
if (ignored.includes(name)) continue;
|
|
15015
15389
|
const rel = relPrefix ? `${relPrefix}/${name}` : name;
|
|
15016
|
-
const full =
|
|
15390
|
+
const full = path25.join(dir, name);
|
|
15017
15391
|
if (e.isDirectory()) {
|
|
15018
15392
|
subdirs.push({ full, rel });
|
|
15019
15393
|
} else if (e.isFile()) {
|
|
@@ -15057,7 +15431,7 @@ var globTool = {
|
|
|
15057
15431
|
};
|
|
15058
15432
|
async function readGitignore(dir) {
|
|
15059
15433
|
try {
|
|
15060
|
-
const raw = await fs20.readFile(
|
|
15434
|
+
const raw = await fs20.readFile(path25.join(dir, ".gitignore"), "utf8");
|
|
15061
15435
|
return raw.split("\n").map((l) => l.trim()).filter((l) => l && !l.startsWith("#"));
|
|
15062
15436
|
} catch {
|
|
15063
15437
|
return [];
|
|
@@ -15068,7 +15442,7 @@ async function readGitignore(dir) {
|
|
|
15068
15442
|
import { expectDefined as expectDefined7 } from "@wrongstack/core";
|
|
15069
15443
|
import { spawn as spawn10 } from "node:child_process";
|
|
15070
15444
|
import * as fs21 from "node:fs/promises";
|
|
15071
|
-
import * as
|
|
15445
|
+
import * as path26 from "node:path";
|
|
15072
15446
|
import { buildChildEnv as buildChildEnv5, compileGlob as compileGlob4, ToolValidationError as ToolValidationError4 } from "@wrongstack/core";
|
|
15073
15447
|
|
|
15074
15448
|
// src/_regex.ts
|
|
@@ -15461,7 +15835,7 @@ async function runNative(input, base, mode, limit, signal) {
|
|
|
15461
15835
|
if (stopped) return;
|
|
15462
15836
|
if (DEFAULT_IGNORE3.includes(e.name)) continue;
|
|
15463
15837
|
if (e.isSymbolicLink()) continue;
|
|
15464
|
-
const full =
|
|
15838
|
+
const full = path26.join(dir, e.name);
|
|
15465
15839
|
if (e.isDirectory()) {
|
|
15466
15840
|
subdirs.push(full);
|
|
15467
15841
|
} else if (e.isFile()) {
|
|
@@ -16049,56 +16423,56 @@ function jmespathSearch(data, query) {
|
|
|
16049
16423
|
}
|
|
16050
16424
|
function validateJsonSchema(data, schema) {
|
|
16051
16425
|
const errors = [];
|
|
16052
|
-
function check(value, s,
|
|
16426
|
+
function check(value, s, path33) {
|
|
16053
16427
|
if (s["type"]) {
|
|
16054
16428
|
const expectedType = s["type"];
|
|
16055
16429
|
const actualType = Array.isArray(value) ? "array" : value === null ? "null" : typeof value;
|
|
16056
16430
|
if (expectedType === "integer") {
|
|
16057
|
-
if (!Number.isInteger(value)) errors.push(`${
|
|
16431
|
+
if (!Number.isInteger(value)) errors.push(`${path33}: expected integer, got ${actualType}`);
|
|
16058
16432
|
} else if (expectedType !== actualType) {
|
|
16059
|
-
errors.push(`${
|
|
16433
|
+
errors.push(`${path33}: expected ${expectedType}, got ${actualType}`);
|
|
16060
16434
|
}
|
|
16061
16435
|
}
|
|
16062
16436
|
if (typeof value === "string" && s["format"] === "uri" && value) {
|
|
16063
16437
|
try {
|
|
16064
16438
|
new URL(value);
|
|
16065
16439
|
} catch {
|
|
16066
|
-
errors.push(`${
|
|
16440
|
+
errors.push(`${path33}: not a valid URI`);
|
|
16067
16441
|
}
|
|
16068
16442
|
}
|
|
16069
16443
|
if (typeof value === "string" && s["pattern"]) {
|
|
16070
16444
|
const re = new RegExp(s["pattern"]);
|
|
16071
|
-
if (!re.test(value)) errors.push(`${
|
|
16445
|
+
if (!re.test(value)) errors.push(`${path33}: does not match pattern ${s["pattern"]}`);
|
|
16072
16446
|
}
|
|
16073
16447
|
if (typeof value === "string" && s["minLength"] !== void 0 && value.length < s["minLength"]) {
|
|
16074
|
-
errors.push(`${
|
|
16448
|
+
errors.push(`${path33}: string too short (min ${s["minLength"]})`);
|
|
16075
16449
|
}
|
|
16076
16450
|
if (typeof value === "string" && s["maxLength"] !== void 0 && value.length > s["maxLength"]) {
|
|
16077
|
-
errors.push(`${
|
|
16451
|
+
errors.push(`${path33}: string too long (max ${s["maxLength"]})`);
|
|
16078
16452
|
}
|
|
16079
16453
|
if (typeof value === "number" && s["minimum"] !== void 0 && value < s["minimum"]) {
|
|
16080
|
-
errors.push(`${
|
|
16454
|
+
errors.push(`${path33}: below minimum ${s["minimum"]}`);
|
|
16081
16455
|
}
|
|
16082
16456
|
if (typeof value === "number" && s["maximum"] !== void 0 && value > s["maximum"]) {
|
|
16083
|
-
errors.push(`${
|
|
16457
|
+
errors.push(`${path33}: above maximum ${s["maximum"]}`);
|
|
16084
16458
|
}
|
|
16085
16459
|
if (Array.isArray(value) && s["items"] && Array.isArray(s["items"])) {
|
|
16086
16460
|
for (let i = 0; i < value.length; i++) {
|
|
16087
|
-
check(value[i], s["items"], `${
|
|
16461
|
+
check(value[i], s["items"], `${path33}[${i}]`);
|
|
16088
16462
|
}
|
|
16089
16463
|
}
|
|
16090
16464
|
if (typeof value === "object" && value !== null && !Array.isArray(value) && s["properties"]) {
|
|
16091
16465
|
const props = s["properties"];
|
|
16092
16466
|
for (const [k, propSchema] of Object.entries(props)) {
|
|
16093
|
-
check(value[k], propSchema, `${
|
|
16467
|
+
check(value[k], propSchema, `${path33}.${k}`);
|
|
16094
16468
|
}
|
|
16095
16469
|
}
|
|
16096
16470
|
}
|
|
16097
16471
|
check(data, schema, "$");
|
|
16098
16472
|
return { valid: errors.length === 0, errors };
|
|
16099
16473
|
}
|
|
16100
|
-
function simpleQuery(data,
|
|
16101
|
-
const parts =
|
|
16474
|
+
function simpleQuery(data, path33) {
|
|
16475
|
+
const parts = path33.replace(/\[(\d+)\]/g, ".$1").split(".").filter(Boolean);
|
|
16102
16476
|
let current = data;
|
|
16103
16477
|
for (const part of parts) {
|
|
16104
16478
|
if (current === null || current === void 0) return void 0;
|
|
@@ -17705,7 +18079,7 @@ async function dockerLogs(service, lines, filterRe, cwd, signal, since) {
|
|
|
17705
18079
|
}
|
|
17706
18080
|
var DOCKER_LOGS_TIMEOUT_MS = 3e3;
|
|
17707
18081
|
var MAX_TAIL_LINES = 1e5;
|
|
17708
|
-
async function fileLogs(
|
|
18082
|
+
async function fileLogs(path33, lines, filterRe, stream) {
|
|
17709
18083
|
const { createInterface } = await import("node:readline");
|
|
17710
18084
|
const { createReadStream: createReadStream2 } = await import("node:fs");
|
|
17711
18085
|
const entries = [];
|
|
@@ -17714,7 +18088,7 @@ async function fileLogs(path32, lines, filterRe, stream) {
|
|
|
17714
18088
|
let writeIdx = 0;
|
|
17715
18089
|
let totalLines = 0;
|
|
17716
18090
|
const rl = createInterface({
|
|
17717
|
-
input: createReadStream2(
|
|
18091
|
+
input: createReadStream2(path33),
|
|
17718
18092
|
crlfDelay: Number.POSITIVE_INFINITY
|
|
17719
18093
|
});
|
|
17720
18094
|
for await (const line of rl) {
|
|
@@ -17735,7 +18109,7 @@ async function fileLogs(path32, lines, filterRe, stream) {
|
|
|
17735
18109
|
if (parsed) entries.push(parsed);
|
|
17736
18110
|
}
|
|
17737
18111
|
return {
|
|
17738
|
-
source:
|
|
18112
|
+
source: path33,
|
|
17739
18113
|
entries,
|
|
17740
18114
|
total: entries.length,
|
|
17741
18115
|
truncated: totalLines > effLines,
|
|
@@ -17966,8 +18340,8 @@ function parseOutdatedOutput(json2, exitCode) {
|
|
|
17966
18340
|
init_util();
|
|
17967
18341
|
import { spawn as spawn13 } from "node:child_process";
|
|
17968
18342
|
import * as fs23 from "node:fs/promises";
|
|
17969
|
-
import * as
|
|
17970
|
-
import * as
|
|
18343
|
+
import * as os8 from "node:os";
|
|
18344
|
+
import * as path27 from "node:path";
|
|
17971
18345
|
import { buildChildEnv as buildChildEnv8 } from "@wrongstack/core";
|
|
17972
18346
|
var patchTool = {
|
|
17973
18347
|
name: "patch",
|
|
@@ -18003,9 +18377,9 @@ var patchTool = {
|
|
|
18003
18377
|
for (const t of targets) {
|
|
18004
18378
|
const stripped = stripPathComponents(t, strip);
|
|
18005
18379
|
if (!stripped) continue;
|
|
18006
|
-
const candidate =
|
|
18007
|
-
const rel =
|
|
18008
|
-
if (rel.startsWith("..") ||
|
|
18380
|
+
const candidate = path27.resolve(dir, stripped);
|
|
18381
|
+
const rel = path27.relative(ctx.projectRoot, candidate);
|
|
18382
|
+
if (rel.startsWith("..") || path27.isAbsolute(rel)) {
|
|
18009
18383
|
return {
|
|
18010
18384
|
applied: 0,
|
|
18011
18385
|
rejected: 1,
|
|
@@ -18022,11 +18396,11 @@ var patchTool = {
|
|
|
18022
18396
|
beforeContents.set(target, await readTextForTracking(target));
|
|
18023
18397
|
}
|
|
18024
18398
|
}
|
|
18025
|
-
const tmpDir = await fs23.mkdtemp(
|
|
18399
|
+
const tmpDir = await fs23.mkdtemp(path27.join(os8.tmpdir(), ".wstack_patch_"));
|
|
18026
18400
|
try {
|
|
18027
18401
|
await fs23.chmod(tmpDir, 448).catch(() => {
|
|
18028
18402
|
});
|
|
18029
|
-
const patchFile =
|
|
18403
|
+
const patchFile = path27.join(tmpDir, "in.diff");
|
|
18030
18404
|
await fs23.writeFile(patchFile, input.patch, { mode: 384 });
|
|
18031
18405
|
const args = [`-p${strip}`, "--merge", ...dryRun ? ["--dry-run"] : [], "-i", patchFile];
|
|
18032
18406
|
const result = await runPatch(args, dir, opts.signal);
|
|
@@ -18612,7 +18986,7 @@ ${interesting.join("\n")}` : "symbols/imports: (none detected)"
|
|
|
18612
18986
|
import { expectDefined as expectDefined8 } from "@wrongstack/core";
|
|
18613
18987
|
import { spawn as spawn14 } from "node:child_process";
|
|
18614
18988
|
import * as fs25 from "node:fs/promises";
|
|
18615
|
-
import * as
|
|
18989
|
+
import * as path28 from "node:path";
|
|
18616
18990
|
import {
|
|
18617
18991
|
atomicWrite as atomicWrite3,
|
|
18618
18992
|
buildChildEnv as buildChildEnv9,
|
|
@@ -18701,8 +19075,8 @@ var replaceTool = {
|
|
|
18701
19075
|
} catch {
|
|
18702
19076
|
continue;
|
|
18703
19077
|
}
|
|
18704
|
-
const rel =
|
|
18705
|
-
if (rel.startsWith("..") ||
|
|
19078
|
+
const rel = path28.relative(realRoot, realPath);
|
|
19079
|
+
if (rel.startsWith("..") || path28.isAbsolute(rel)) continue;
|
|
18706
19080
|
const stat17 = await fs25.stat(realPath).catch(() => null);
|
|
18707
19081
|
if (!stat17?.isFile()) continue;
|
|
18708
19082
|
let content;
|
|
@@ -18831,7 +19205,7 @@ async function globNative(pattern, base, extraGlob) {
|
|
|
18831
19205
|
}
|
|
18832
19206
|
for (const e of entries) {
|
|
18833
19207
|
if (DEFAULT_IGNORE4.includes(e.name)) continue;
|
|
18834
|
-
const full =
|
|
19208
|
+
const full = path28.join(dir, e.name);
|
|
18835
19209
|
try {
|
|
18836
19210
|
const stat17 = await fs25.lstat(full);
|
|
18837
19211
|
if (stat17.isSymbolicLink()) continue;
|
|
@@ -18858,7 +19232,7 @@ async function globNative(pattern, base, extraGlob) {
|
|
|
18858
19232
|
// src/scaffold.ts
|
|
18859
19233
|
init_util();
|
|
18860
19234
|
import * as fs26 from "node:fs/promises";
|
|
18861
|
-
import * as
|
|
19235
|
+
import * as path29 from "node:path";
|
|
18862
19236
|
import { atomicWrite as atomicWrite4 } from "@wrongstack/core";
|
|
18863
19237
|
var BUILT_IN_TEMPLATES = {
|
|
18864
19238
|
"npm-package": {
|
|
@@ -19008,16 +19382,16 @@ async function handleBuiltIn(name, templateFiles, cwd, ctx, dryRun, vars) {
|
|
|
19008
19382
|
let filesCreated = 0;
|
|
19009
19383
|
for (const [filePath, content] of Object.entries(templateFiles)) {
|
|
19010
19384
|
const resolvedPath = substituteVars(filePath, name, vars);
|
|
19011
|
-
const joinedPath =
|
|
19012
|
-
const root =
|
|
19013
|
-
const target =
|
|
19014
|
-
const rel =
|
|
19015
|
-
if (rel.startsWith("..") ||
|
|
19385
|
+
const joinedPath = path29.join(cwd, resolvedPath);
|
|
19386
|
+
const root = path29.resolve(ctx.projectRoot);
|
|
19387
|
+
const target = path29.resolve(joinedPath);
|
|
19388
|
+
const rel = path29.relative(root, target);
|
|
19389
|
+
if (rel.startsWith("..") || path29.isAbsolute(rel)) {
|
|
19016
19390
|
throw new Error(`scaffold: generated path "${resolvedPath}" would escape project root`);
|
|
19017
19391
|
}
|
|
19018
19392
|
const fullPath = target;
|
|
19019
19393
|
if (!dryRun) {
|
|
19020
|
-
await fs26.mkdir(
|
|
19394
|
+
await fs26.mkdir(path29.dirname(fullPath), { recursive: true });
|
|
19021
19395
|
await atomicWrite4(fullPath, substituteVars(content, name, vars));
|
|
19022
19396
|
}
|
|
19023
19397
|
files.push(resolvedPath);
|
|
@@ -19874,7 +20248,7 @@ ${formatTaskList2(file.tasks)}` : file.tasks.length > 0 ? formatTaskList2(file.t
|
|
|
19874
20248
|
init_spawn_stream();
|
|
19875
20249
|
init_util();
|
|
19876
20250
|
init_legacy_bridge();
|
|
19877
|
-
import * as
|
|
20251
|
+
import * as path30 from "node:path";
|
|
19878
20252
|
var testTool = {
|
|
19879
20253
|
name: "test",
|
|
19880
20254
|
category: "Code Quality",
|
|
@@ -19981,7 +20355,7 @@ async function detectRunner(cwd) {
|
|
|
19981
20355
|
const candidates = ["vitest.config.ts", "jest.config.js", ".mocharc.json"];
|
|
19982
20356
|
for (const f of candidates) {
|
|
19983
20357
|
try {
|
|
19984
|
-
await stat17(
|
|
20358
|
+
await stat17(path30.join(cwd, f));
|
|
19985
20359
|
if (f.includes("vitest")) return "vitest";
|
|
19986
20360
|
if (f.includes("jest")) return "jest";
|
|
19987
20361
|
if (f.includes("mocha")) return "mocha";
|
|
@@ -20452,7 +20826,7 @@ var toolUseTool = {
|
|
|
20452
20826
|
init_util();
|
|
20453
20827
|
import { expectDefined as expectDefined10 } from "@wrongstack/core";
|
|
20454
20828
|
import * as fs28 from "node:fs/promises";
|
|
20455
|
-
import * as
|
|
20829
|
+
import * as path31 from "node:path";
|
|
20456
20830
|
var DEFAULT_IGNORE5 = [
|
|
20457
20831
|
"node_modules",
|
|
20458
20832
|
".git",
|
|
@@ -20623,7 +20997,7 @@ async function walkDir(dir, depth, opts) {
|
|
|
20623
20997
|
opts.lines.push(opts.prefix + branch + displayName);
|
|
20624
20998
|
if (entry.isDirectory() && (opts.maxDepth === 0 || depth < opts.maxDepth)) {
|
|
20625
20999
|
const childPrefix = opts.prefix + connector;
|
|
20626
|
-
await walkDir(
|
|
21000
|
+
await walkDir(path31.join(dir, entry.name), depth + 1, {
|
|
20627
21001
|
...opts,
|
|
20628
21002
|
prefix: childPrefix,
|
|
20629
21003
|
isLast
|
|
@@ -20636,7 +21010,7 @@ async function walkDir(dir, depth, opts) {
|
|
|
20636
21010
|
init_spawn_stream();
|
|
20637
21011
|
init_util();
|
|
20638
21012
|
init_legacy_bridge();
|
|
20639
|
-
import * as
|
|
21013
|
+
import * as path32 from "node:path";
|
|
20640
21014
|
var typecheckTool = {
|
|
20641
21015
|
name: "typecheck",
|
|
20642
21016
|
category: "Code Quality",
|
|
@@ -20739,8 +21113,8 @@ async function findTsConfig(cwd) {
|
|
|
20739
21113
|
const candidates = ["tsconfig.json", "tsconfig.base.json"];
|
|
20740
21114
|
for (const f of candidates) {
|
|
20741
21115
|
try {
|
|
20742
|
-
const s = await stat17(
|
|
20743
|
-
if (s.isFile()) return
|
|
21116
|
+
const s = await stat17(path32.join(cwd, f));
|
|
21117
|
+
if (s.isFile()) return path32.join(cwd, f);
|
|
20744
21118
|
} catch {
|
|
20745
21119
|
}
|
|
20746
21120
|
}
|