@wrongstack/tools 0.289.0 → 0.291.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/auto-proceed-loop-guard.d.ts +128 -0
- package/dist/auto-proceed-loop-guard.d.ts.map +1 -0
- package/dist/auto-proceed-loop-guard.js +46 -0
- package/dist/auto-proceed-loop-guard.js.map +7 -0
- 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 +662 -203
- package/dist/builtin.js.map +4 -4
- package/dist/codebase-index/background-indexer.d.ts +1 -1
- package/dist/codebase-index/background-indexer.d.ts.map +1 -1
- package/dist/codebase-index/index.js +181 -104
- package/dist/codebase-index/index.js.map +3 -3
- package/dist/codebase-index/indexer.d.ts.map +1 -1
- package/dist/codebase-index/refs-extractor.d.ts +2 -17
- package/dist/codebase-index/refs-extractor.d.ts.map +1 -1
- package/dist/codebase-index/ts-parser.d.ts.map +1 -1
- package/dist/codebase-index/worker.js +164 -96
- package/dist/codebase-index/worker.js.map +3 -3
- package/dist/codebase-index/writer.d.ts +33 -0
- package/dist/codebase-index/writer.d.ts.map +1 -1
- 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 +765 -237
- package/dist/index.js.map +4 -4
- package/dist/kanban.d.ts +10 -0
- package/dist/kanban.d.ts.map +1 -1
- package/dist/kanban.js +34 -17
- package/dist/kanban.js.map +2 -2
- package/dist/pack.js +662 -203
- package/dist/pack.js.map +4 -4
- package/dist/plan.js.map +2 -2
- package/dist/read.d.ts.map +1 -1
- package/dist/read.js.map +2 -2
- package/dist/session-kanban.d.ts.map +1 -1
- package/dist/session-kanban.js +60 -3
- package/dist/session-kanban.js.map +2 -2
- package/dist/task.js.map +2 -2
- package/dist/todo.js.map +2 -2
- package/package.json +9 -5
package/dist/pack.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();
|
|
@@ -7774,6 +7900,53 @@ function codebaseIndexDirOverride(ctx) {
|
|
|
7774
7900
|
const v = ctx.meta?.["codebaseIndexDir"];
|
|
7775
7901
|
return typeof v === "string" ? v : void 0;
|
|
7776
7902
|
}
|
|
7903
|
+
var StorePool = class {
|
|
7904
|
+
stores = /* @__PURE__ */ new Map();
|
|
7905
|
+
key(projectRoot, indexDir) {
|
|
7906
|
+
return `${projectRoot}\0${indexDir ?? ""}`;
|
|
7907
|
+
}
|
|
7908
|
+
/** Borrow a store. Creates it on first access for this key. */
|
|
7909
|
+
acquire(projectRoot, opts) {
|
|
7910
|
+
const k = this.key(projectRoot, opts?.indexDir);
|
|
7911
|
+
let store = this.stores.get(k);
|
|
7912
|
+
if (!store) {
|
|
7913
|
+
store = new IndexStore(projectRoot, { indexDir: opts?.indexDir });
|
|
7914
|
+
this.stores.set(k, store);
|
|
7915
|
+
}
|
|
7916
|
+
return store;
|
|
7917
|
+
}
|
|
7918
|
+
/** Return the store to the pool. The connection stays warm for subsequent
|
|
7919
|
+
* operations on the same (projectRoot, indexDir). */
|
|
7920
|
+
release(_store) {
|
|
7921
|
+
}
|
|
7922
|
+
/** Close every pooled connection and drain the pool. Call on shutdown. */
|
|
7923
|
+
closeAll() {
|
|
7924
|
+
for (const store of this.stores.values()) {
|
|
7925
|
+
try {
|
|
7926
|
+
store.close();
|
|
7927
|
+
} catch {
|
|
7928
|
+
}
|
|
7929
|
+
}
|
|
7930
|
+
this.stores.clear();
|
|
7931
|
+
}
|
|
7932
|
+
/** Remove one store from the pool. Used by tests that need isolation. */
|
|
7933
|
+
evict(projectRoot, indexDir) {
|
|
7934
|
+
const k = this.key(projectRoot, indexDir);
|
|
7935
|
+
const store = this.stores.get(k);
|
|
7936
|
+
if (store) {
|
|
7937
|
+
try {
|
|
7938
|
+
store.close();
|
|
7939
|
+
} catch {
|
|
7940
|
+
}
|
|
7941
|
+
this.stores.delete(k);
|
|
7942
|
+
}
|
|
7943
|
+
}
|
|
7944
|
+
/** True when the pool holds a connection for the given key. */
|
|
7945
|
+
has(projectRoot, indexDir) {
|
|
7946
|
+
return this.stores.has(this.key(projectRoot, indexDir));
|
|
7947
|
+
}
|
|
7948
|
+
};
|
|
7949
|
+
var indexStorePool = new StorePool();
|
|
7777
7950
|
var warningSilenced = false;
|
|
7778
7951
|
function silenceSqliteExperimentalWarning() {
|
|
7779
7952
|
if (warningSilenced) return;
|
|
@@ -7991,7 +8164,7 @@ var IndexStore = class _IndexStore {
|
|
|
7991
8164
|
return this.runWithRetry(() => {
|
|
7992
8165
|
this.db.exec("BEGIN IMMEDIATE");
|
|
7993
8166
|
try {
|
|
7994
|
-
const maxRows = this.
|
|
8167
|
+
const maxRows = this.stmt("SELECT MAX(id) AS m FROM symbols").all();
|
|
7995
8168
|
let nextId = (maxRows[0]?.m ?? 0) + 1;
|
|
7996
8169
|
const stmt = this.db.prepare(
|
|
7997
8170
|
`INSERT INTO symbols(id, lang, kind, name, file, line, col, signature, doc_comment, scope, text, file_fk)
|
|
@@ -8263,7 +8436,7 @@ var IndexStore = class _IndexStore {
|
|
|
8263
8436
|
return { results, total: candidates.length };
|
|
8264
8437
|
}
|
|
8265
8438
|
getAllIndexable() {
|
|
8266
|
-
return this.
|
|
8439
|
+
return this.stmt("SELECT id, text FROM symbols").all().map(({ id, text }) => ({ id, text }));
|
|
8267
8440
|
}
|
|
8268
8441
|
/**
|
|
8269
8442
|
* Largest symbol id currently in the table (0 when empty). New ids must be
|
|
@@ -8273,7 +8446,7 @@ var IndexStore = class _IndexStore {
|
|
|
8273
8446
|
* `symbols.id`). Ids may have gaps — that is fine.
|
|
8274
8447
|
*/
|
|
8275
8448
|
getMaxSymbolId() {
|
|
8276
|
-
const rows = this.
|
|
8449
|
+
const rows = this.stmt("SELECT MAX(id) AS m FROM symbols").all();
|
|
8277
8450
|
return rows[0]?.m ?? 0;
|
|
8278
8451
|
}
|
|
8279
8452
|
// ─── Stats ───────────────────────────────────────────────────────────────────
|
|
@@ -8281,14 +8454,14 @@ var IndexStore = class _IndexStore {
|
|
|
8281
8454
|
const sizeBytes = this.sizeBytes();
|
|
8282
8455
|
const lastRows = this.db.prepare("SELECT value FROM metadata WHERE key = 'last_indexed'").all();
|
|
8283
8456
|
const lastIndexed = lastRows.length ? Number(lastRows[0]?.value) : null;
|
|
8284
|
-
const totalRows = this.
|
|
8457
|
+
const totalRows = this.stmt("SELECT COUNT(*) FROM symbols").all();
|
|
8285
8458
|
const totalSymbols = totalRows[0] ? Number(totalRows[0]["COUNT(*)"]) : 0;
|
|
8286
|
-
const fileRows = this.
|
|
8459
|
+
const fileRows = this.stmt("SELECT COUNT(*) FROM files").all();
|
|
8287
8460
|
const totalFiles = fileRows[0] ? Number(fileRows[0]["COUNT(*)"]) : 0;
|
|
8288
|
-
const langRows = this.
|
|
8461
|
+
const langRows = this.stmt("SELECT lang, COUNT(*) FROM symbols GROUP BY lang").all();
|
|
8289
8462
|
const byLang = {};
|
|
8290
8463
|
for (const row of langRows) byLang[row.lang] = Number(row["COUNT(*)"]);
|
|
8291
|
-
const kindRows = this.
|
|
8464
|
+
const kindRows = this.stmt("SELECT kind, COUNT(*) FROM symbols GROUP BY kind").all();
|
|
8292
8465
|
const byKind = {};
|
|
8293
8466
|
for (const row of kindRows) byKind[row.kind] = Number(row["COUNT(*)"]);
|
|
8294
8467
|
return {
|
|
@@ -8320,11 +8493,14 @@ var IndexStore = class _IndexStore {
|
|
|
8320
8493
|
this.runWithRetry(() => {
|
|
8321
8494
|
this.db.exec("BEGIN IMMEDIATE");
|
|
8322
8495
|
try {
|
|
8323
|
-
this.db.exec("
|
|
8324
|
-
this.db.exec("
|
|
8325
|
-
this.db.exec("
|
|
8326
|
-
|
|
8496
|
+
this.db.exec("DROP TABLE IF EXISTS refs");
|
|
8497
|
+
this.db.exec("DROP TABLE IF EXISTS symbols");
|
|
8498
|
+
this.db.exec("DROP TABLE IF EXISTS files");
|
|
8499
|
+
this.db.exec("DROP TABLE IF EXISTS metadata");
|
|
8500
|
+
if (this.ftsAvailable) this.db.exec("DROP TABLE IF EXISTS symbols_fts");
|
|
8327
8501
|
this.db.exec("COMMIT");
|
|
8502
|
+
this.stmtCache.clear();
|
|
8503
|
+
this.initSchema();
|
|
8328
8504
|
} catch (err) {
|
|
8329
8505
|
this.db.exec("ROLLBACK");
|
|
8330
8506
|
throw err;
|
|
@@ -8409,7 +8585,7 @@ var IndexStore = class _IndexStore {
|
|
|
8409
8585
|
).run(...options.deleteForFiles);
|
|
8410
8586
|
this.db.prepare(`DELETE FROM symbols WHERE file IN (${placeholders})`).run(...options.deleteForFiles);
|
|
8411
8587
|
}
|
|
8412
|
-
const maxRows = this.
|
|
8588
|
+
const maxRows = this.stmt("SELECT MAX(id) AS m FROM symbols").all();
|
|
8413
8589
|
let nextId = (maxRows[0]?.m ?? 0) + 1;
|
|
8414
8590
|
const symStmt = this.db.prepare(
|
|
8415
8591
|
`INSERT INTO symbols(id, lang, kind, name, file, line, col, signature, doc_comment, scope, text, file_fk)
|
|
@@ -8593,7 +8769,7 @@ var IndexStore = class _IndexStore {
|
|
|
8593
8769
|
* symbol resolved in package B). Node metadata includes symbol/file counts.
|
|
8594
8770
|
*/
|
|
8595
8771
|
getPackageGraph() {
|
|
8596
|
-
const symbols = this.db.prepare("SELECT file, id
|
|
8772
|
+
const symbols = this.db.prepare("SELECT file, id FROM symbols ORDER BY id").all();
|
|
8597
8773
|
const pkgNodes = /* @__PURE__ */ new Map();
|
|
8598
8774
|
const fileToPkg = /* @__PURE__ */ new Map();
|
|
8599
8775
|
const symbolToPkg = /* @__PURE__ */ new Map();
|
|
@@ -8684,15 +8860,18 @@ var IndexStore = class _IndexStore {
|
|
|
8684
8860
|
* derived from cross-file symbol references within the package.
|
|
8685
8861
|
*/
|
|
8686
8862
|
getFileGraph(packageFilter) {
|
|
8687
|
-
const
|
|
8688
|
-
const
|
|
8689
|
-
|
|
8690
|
-
);
|
|
8691
|
-
|
|
8863
|
+
const allFiles = this.db.prepare("SELECT DISTINCT file FROM symbols").all();
|
|
8864
|
+
const pkgFilePaths = allFiles.filter((f) => (_IndexStore.derivePackage(f.file) ?? "(root)") === packageFilter).map((f) => f.file);
|
|
8865
|
+
const localFiles = new Set(pkgFilePaths);
|
|
8866
|
+
if (localFiles.size === 0) return { nodes: [], edges: [] };
|
|
8867
|
+
const filePlaceholders = [...localFiles].map(() => "?").join(",");
|
|
8868
|
+
const pkgSyms = this.db.prepare(
|
|
8869
|
+
`SELECT file, id, name, kind, lang, line FROM symbols WHERE file IN (${filePlaceholders}) ORDER BY id`
|
|
8870
|
+
).all(...pkgFilePaths);
|
|
8692
8871
|
const fileNodes = /* @__PURE__ */ new Map();
|
|
8693
8872
|
const symToFile = /* @__PURE__ */ new Map();
|
|
8694
8873
|
const fileStats = /* @__PURE__ */ new Map();
|
|
8695
|
-
for (const s of
|
|
8874
|
+
for (const s of pkgSyms) {
|
|
8696
8875
|
symToFile.set(s.id, s.file);
|
|
8697
8876
|
const current = fileStats.get(s.file);
|
|
8698
8877
|
fileStats.set(s.file, {
|
|
@@ -8700,8 +8879,6 @@ var IndexStore = class _IndexStore {
|
|
|
8700
8879
|
lang: current?.lang ?? s.lang
|
|
8701
8880
|
});
|
|
8702
8881
|
}
|
|
8703
|
-
const localFiles = new Set(pkgSyms.map((s) => s.file));
|
|
8704
|
-
const indexedFiles = new Set(allSymbols.map((s) => s.file));
|
|
8705
8882
|
const ensureFileNode = (file) => {
|
|
8706
8883
|
if (fileNodes.has(file)) return;
|
|
8707
8884
|
const stats = fileStats.get(file);
|
|
@@ -8719,11 +8896,32 @@ var IndexStore = class _IndexStore {
|
|
|
8719
8896
|
for (const file of localFiles) {
|
|
8720
8897
|
ensureFileNode(file);
|
|
8721
8898
|
}
|
|
8899
|
+
const indexedFiles = new Set(allFiles.map((f) => f.file));
|
|
8722
8900
|
const refRows = this.db.prepare(
|
|
8723
8901
|
`SELECT r.from_id, r.to_id, r.call_type
|
|
8724
8902
|
FROM refs r
|
|
8725
|
-
WHERE r.
|
|
8726
|
-
|
|
8903
|
+
WHERE (r.from_id IN (SELECT id FROM symbols WHERE file IN (${filePlaceholders}))
|
|
8904
|
+
OR r.to_id IN (SELECT id FROM symbols WHERE file IN (${filePlaceholders})))
|
|
8905
|
+
AND r.to_id IS NOT NULL`
|
|
8906
|
+
).all(...pkgFilePaths, ...pkgFilePaths);
|
|
8907
|
+
const knownSymIds = new Set(pkgSyms.map((s) => s.id));
|
|
8908
|
+
const crossRefIds = /* @__PURE__ */ new Set();
|
|
8909
|
+
for (const r of refRows) {
|
|
8910
|
+
if (!knownSymIds.has(r.from_id)) crossRefIds.add(r.from_id);
|
|
8911
|
+
if (!knownSymIds.has(r.to_id)) crossRefIds.add(r.to_id);
|
|
8912
|
+
}
|
|
8913
|
+
if (crossRefIds.size > 0) {
|
|
8914
|
+
const crossPlaceholders = [...crossRefIds].map(() => "?").join(",");
|
|
8915
|
+
const extras = this.db.prepare(
|
|
8916
|
+
`SELECT id, file FROM symbols WHERE id IN (${crossPlaceholders})`
|
|
8917
|
+
).all(...crossRefIds);
|
|
8918
|
+
for (const x of extras) {
|
|
8919
|
+
symToFile.set(x.id, x.file);
|
|
8920
|
+
if (!fileStats.has(x.file)) {
|
|
8921
|
+
fileStats.set(x.file, { count: 0, lang: "ts" });
|
|
8922
|
+
}
|
|
8923
|
+
}
|
|
8924
|
+
}
|
|
8727
8925
|
const edgeMap = /* @__PURE__ */ new Map();
|
|
8728
8926
|
for (const r of refRows) {
|
|
8729
8927
|
if (r.call_type === "import") continue;
|
|
@@ -8745,8 +8943,9 @@ var IndexStore = class _IndexStore {
|
|
|
8745
8943
|
const importRows = this.db.prepare(
|
|
8746
8944
|
`SELECT r.from_id, r.to_name
|
|
8747
8945
|
FROM refs r
|
|
8748
|
-
WHERE r.call_type = 'import'
|
|
8749
|
-
|
|
8946
|
+
WHERE r.call_type = 'import'
|
|
8947
|
+
AND r.from_id IN (SELECT id FROM symbols WHERE file IN (${filePlaceholders}))`
|
|
8948
|
+
).all(...pkgFilePaths);
|
|
8750
8949
|
for (const r of importRows) {
|
|
8751
8950
|
const fromFile = symToFile.get(r.from_id);
|
|
8752
8951
|
if (!fromFile || !localFiles.has(fromFile)) continue;
|
|
@@ -8788,12 +8987,11 @@ var IndexStore = class _IndexStore {
|
|
|
8788
8987
|
* derived from intra-file and cross-file symbol references (who calls whom).
|
|
8789
8988
|
*/
|
|
8790
8989
|
getSymbolGraph(fileFilter) {
|
|
8791
|
-
const
|
|
8792
|
-
"SELECT id, name, kind, lang, file, line, signature, scope FROM symbols ORDER BY
|
|
8793
|
-
).all();
|
|
8794
|
-
const syms = allSymbols.filter((symbol) => symbol.file === fileFilter);
|
|
8990
|
+
const syms = this.db.prepare(
|
|
8991
|
+
"SELECT id, name, kind, lang, file, line, signature, scope FROM symbols WHERE file = ? ORDER BY line, id"
|
|
8992
|
+
).all(fileFilter);
|
|
8795
8993
|
if (syms.length === 0) return { nodes: [], edges: [] };
|
|
8796
|
-
const symById = new Map(
|
|
8994
|
+
const symById = new Map(syms.map((symbol) => [symbol.id, symbol]));
|
|
8797
8995
|
const relatedIds = new Set(syms.map((symbol) => symbol.id));
|
|
8798
8996
|
const toGraphNode = (s) => ({
|
|
8799
8997
|
id: `sym:${s.id}`,
|
|
@@ -8849,6 +9047,15 @@ var IndexStore = class _IndexStore {
|
|
|
8849
9047
|
refType: bestType
|
|
8850
9048
|
});
|
|
8851
9049
|
}
|
|
9050
|
+
const loadedIds = new Set(syms.map((s) => s.id));
|
|
9051
|
+
const missingIds = [...relatedIds].filter((id) => !loadedIds.has(id));
|
|
9052
|
+
if (missingIds.length > 0) {
|
|
9053
|
+
const placeholders = missingIds.map(() => "?").join(",");
|
|
9054
|
+
const extras = this.db.prepare(
|
|
9055
|
+
`SELECT id, name, kind, lang, file, line, signature, scope FROM symbols WHERE id IN (${placeholders})`
|
|
9056
|
+
).all(...missingIds);
|
|
9057
|
+
for (const s of extras) symById.set(s.id, s);
|
|
9058
|
+
}
|
|
8852
9059
|
const nodes = [...relatedIds].map((id) => symById.get(id)).filter((symbol) => symbol !== void 0).sort((a, b) => {
|
|
8853
9060
|
const aExternal = a.file === fileFilter ? 0 : 1;
|
|
8854
9061
|
const bExternal = b.file === fileFilter ? 0 : 1;
|
|
@@ -8874,6 +9081,7 @@ import { Worker } from "node:worker_threads";
|
|
|
8874
9081
|
import { expectDefined as expectDefined6 } from "@wrongstack/core";
|
|
8875
9082
|
import * as fs14 from "node:fs/promises";
|
|
8876
9083
|
import * as path19 from "node:path";
|
|
9084
|
+
import { availableParallelism } from "node:os";
|
|
8877
9085
|
import { compileGlob as compileGlob2 } from "@wrongstack/core";
|
|
8878
9086
|
|
|
8879
9087
|
// src/codebase-index/ts-parser.ts
|
|
@@ -8930,8 +9138,7 @@ function extToLang(ext) {
|
|
|
8930
9138
|
return null;
|
|
8931
9139
|
}
|
|
8932
9140
|
}
|
|
8933
|
-
function getSignature(node, sourceFile) {
|
|
8934
|
-
const printer = ts.createPrinter({});
|
|
9141
|
+
function getSignature(printer, node, sourceFile) {
|
|
8935
9142
|
const raw = printer.printNode(ts.EmitHint.Unspecified, node, sourceFile);
|
|
8936
9143
|
return raw.replace(/\s+/g, " ").slice(0, 500);
|
|
8937
9144
|
}
|
|
@@ -8950,28 +9157,14 @@ function getJsDoc(node, sourceFile) {
|
|
|
8950
9157
|
}
|
|
8951
9158
|
return "";
|
|
8952
9159
|
}
|
|
8953
|
-
function
|
|
8954
|
-
|
|
8955
|
-
|
|
8956
|
-
|
|
8957
|
-
|
|
8958
|
-
|
|
8959
|
-
return false;
|
|
8960
|
-
}
|
|
8961
|
-
function buildScope(node) {
|
|
8962
|
-
const parts = [];
|
|
8963
|
-
let current = node.parent;
|
|
8964
|
-
while (current) {
|
|
8965
|
-
if (ts.isClassDeclaration(current) || ts.isInterfaceDeclaration(current) || ts.isEnumDeclaration(current) || ts.isTypeAliasDeclaration(current)) {
|
|
8966
|
-
parts.unshift(current.name?.text ?? "Anon");
|
|
8967
|
-
} else if (ts.isMethodDeclaration(current) || ts.isGetAccessor(current) || ts.isSetAccessor(current) || ts.isPropertyDeclaration(current) || ts.isFunctionDeclaration(current)) {
|
|
8968
|
-
if (current.name && ts.isIdentifier(current.name)) {
|
|
8969
|
-
parts.unshift(current.name.text);
|
|
8970
|
-
}
|
|
9160
|
+
function pushScopeName(node, parts) {
|
|
9161
|
+
if (ts.isClassDeclaration(node) || ts.isInterfaceDeclaration(node) || ts.isEnumDeclaration(node) || ts.isTypeAliasDeclaration(node)) {
|
|
9162
|
+
parts.push(node.name?.text ?? "Anon");
|
|
9163
|
+
} else if (ts.isMethodDeclaration(node) || ts.isGetAccessor(node) || ts.isSetAccessor(node) || ts.isPropertyDeclaration(node) || ts.isFunctionDeclaration(node)) {
|
|
9164
|
+
if (node.name && ts.isIdentifier(node.name)) {
|
|
9165
|
+
parts.push(node.name.text);
|
|
8971
9166
|
}
|
|
8972
|
-
current = current.parent;
|
|
8973
9167
|
}
|
|
8974
|
-
return parts.join(".");
|
|
8975
9168
|
}
|
|
8976
9169
|
function parseSymbols(opts) {
|
|
8977
9170
|
const { file, content, lang } = opts;
|
|
@@ -8982,45 +9175,39 @@ function parseSymbols(opts) {
|
|
|
8982
9175
|
return { file, lang, symbols: [], mtimeMs: Date.now() };
|
|
8983
9176
|
}
|
|
8984
9177
|
const symbols = [];
|
|
8985
|
-
|
|
9178
|
+
const refs = [];
|
|
9179
|
+
const printer = ts.createPrinter({});
|
|
9180
|
+
function visit(node, funcDepth, scopeParts) {
|
|
8986
9181
|
const kind = kindOf(node);
|
|
8987
9182
|
if (kind) {
|
|
8988
|
-
if ((kind === "const" || kind === "let" || kind === "var" || kind === "parameter") &&
|
|
8989
|
-
|
|
8990
|
-
|
|
9183
|
+
if ((kind === "const" || kind === "let" || kind === "var" || kind === "parameter") && funcDepth > 0) {
|
|
9184
|
+
} else {
|
|
9185
|
+
const nameNode = node.name;
|
|
9186
|
+
if (!nameNode || !ts.isIdentifier(nameNode)) {
|
|
9187
|
+
return;
|
|
9188
|
+
}
|
|
9189
|
+
const name = nameNode.text;
|
|
9190
|
+
const pos2 = nameNode.getStart(sourceFile);
|
|
9191
|
+
const { line: line2, character } = sourceFile.getLineAndCharacterOfPosition(pos2);
|
|
9192
|
+
const scope = scopeParts.join(".");
|
|
9193
|
+
const signature = getSignature(printer, node, sourceFile);
|
|
9194
|
+
const docComment = getJsDoc(node, sourceFile);
|
|
9195
|
+
const text = [name, signature, docComment].filter(Boolean).join(" | ");
|
|
9196
|
+
symbols.push({
|
|
9197
|
+
id: 0,
|
|
9198
|
+
lang,
|
|
9199
|
+
kind,
|
|
9200
|
+
name,
|
|
9201
|
+
file,
|
|
9202
|
+
line: line2 + 1,
|
|
9203
|
+
col: character,
|
|
9204
|
+
signature,
|
|
9205
|
+
docComment,
|
|
9206
|
+
scope,
|
|
9207
|
+
text
|
|
9208
|
+
});
|
|
8991
9209
|
}
|
|
8992
|
-
const nameNode = node.name;
|
|
8993
|
-
if (!nameNode || !ts.isIdentifier(nameNode)) return;
|
|
8994
|
-
const name = nameNode.text;
|
|
8995
|
-
const pos = nameNode.getStart(sourceFile);
|
|
8996
|
-
const { line, character } = sourceFile.getLineAndCharacterOfPosition(pos);
|
|
8997
|
-
const scope = buildScope(node);
|
|
8998
|
-
const signature = getSignature(node, sourceFile);
|
|
8999
|
-
const docComment = getJsDoc(node, sourceFile);
|
|
9000
|
-
const text = [name, signature, docComment].filter(Boolean).join(" | ");
|
|
9001
|
-
symbols.push({
|
|
9002
|
-
id: 0,
|
|
9003
|
-
lang,
|
|
9004
|
-
kind,
|
|
9005
|
-
name,
|
|
9006
|
-
file,
|
|
9007
|
-
line: line + 1,
|
|
9008
|
-
col: character,
|
|
9009
|
-
signature,
|
|
9010
|
-
docComment,
|
|
9011
|
-
scope,
|
|
9012
|
-
text
|
|
9013
|
-
});
|
|
9014
9210
|
}
|
|
9015
|
-
ts.forEachChild(node, visit);
|
|
9016
|
-
}
|
|
9017
|
-
visit(sourceFile);
|
|
9018
|
-
const refs = extractRefs(sourceFile);
|
|
9019
|
-
return { file, lang, symbols, refs, mtimeMs: Date.now() };
|
|
9020
|
-
}
|
|
9021
|
-
function extractRefs(sourceFile) {
|
|
9022
|
-
const refs = [];
|
|
9023
|
-
function visit(node) {
|
|
9024
9211
|
const pos = node.getStart(sourceFile);
|
|
9025
9212
|
const { line } = sourceFile.getLineAndCharacterOfPosition(pos);
|
|
9026
9213
|
const lineNum = line + 1;
|
|
@@ -9045,10 +9232,14 @@ function extractRefs(sourceFile) {
|
|
|
9045
9232
|
const moduleName = getModuleName(node);
|
|
9046
9233
|
if (moduleName) refs.push({ fromId: 0, toName: moduleName, callType: "import", line: lineNum });
|
|
9047
9234
|
}
|
|
9048
|
-
|
|
9235
|
+
const scopeIdx = scopeParts.length;
|
|
9236
|
+
pushScopeName(node, scopeParts);
|
|
9237
|
+
const childFuncDepth = ts.isFunctionLike(node) ? funcDepth + 1 : funcDepth;
|
|
9238
|
+
ts.forEachChild(node, (child) => visit(child, childFuncDepth, scopeParts));
|
|
9239
|
+
scopeParts.length = scopeIdx;
|
|
9049
9240
|
}
|
|
9050
|
-
visit(sourceFile);
|
|
9051
|
-
return deduplicateRefs(refs);
|
|
9241
|
+
visit(sourceFile, 0, []);
|
|
9242
|
+
return { file, lang, symbols, refs: deduplicateRefs(refs), mtimeMs: Date.now() };
|
|
9052
9243
|
}
|
|
9053
9244
|
function getTypeName(name) {
|
|
9054
9245
|
if (ts.isIdentifier(name)) return name.text;
|
|
@@ -9933,9 +10124,9 @@ function parseSymbols5(opts) {
|
|
|
9933
10124
|
function regexParse2(opts) {
|
|
9934
10125
|
const { file, content, lang } = opts;
|
|
9935
10126
|
const symbols = [];
|
|
9936
|
-
const
|
|
9937
|
-
const isPackageJson =
|
|
9938
|
-
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";
|
|
9939
10130
|
const isJsonSchema = content.includes("$schema") || content.includes("$id") || content.includes("$ref");
|
|
9940
10131
|
const isOpenApi = content.includes("openapi") || content.includes("swagger");
|
|
9941
10132
|
const lines = content.split("\n");
|
|
@@ -10330,7 +10521,7 @@ async function loadGitignoreMatcher(projectRoot) {
|
|
|
10330
10521
|
|
|
10331
10522
|
// src/codebase-index/indexer.ts
|
|
10332
10523
|
var YIELD_EVERY_N = 50;
|
|
10333
|
-
var PARALLEL_BATCH =
|
|
10524
|
+
var PARALLEL_BATCH = Math.min(availableParallelism() * 4, 40);
|
|
10334
10525
|
function yieldEventLoop() {
|
|
10335
10526
|
return new Promise((resolve14) => setImmediate(resolve14));
|
|
10336
10527
|
}
|
|
@@ -10508,11 +10699,14 @@ async function runIndexerWithStore(store, opts) {
|
|
|
10508
10699
|
if (!force) {
|
|
10509
10700
|
for (const meta of store.getAllFileMetas()) existingMeta.set(meta.file, meta);
|
|
10510
10701
|
}
|
|
10702
|
+
let filesSinceLastYield = 0;
|
|
10511
10703
|
for (let batchStart = 0; batchStart < files.length; batchStart += PARALLEL_BATCH) {
|
|
10512
10704
|
const batchEnd = Math.min(batchStart + PARALLEL_BATCH, files.length);
|
|
10513
10705
|
const batchFiles = files.slice(batchStart, batchEnd);
|
|
10514
10706
|
opts.onProgress?.(batchEnd, files.length);
|
|
10515
|
-
|
|
10707
|
+
filesSinceLastYield += batchFiles.length;
|
|
10708
|
+
if (filesSinceLastYield >= YIELD_EVERY_N) {
|
|
10709
|
+
filesSinceLastYield = 0;
|
|
10516
10710
|
await yieldEventLoop();
|
|
10517
10711
|
throwIfAborted(signal);
|
|
10518
10712
|
}
|
|
@@ -10723,7 +10917,7 @@ async function indexService(args, hooks = {}) {
|
|
|
10723
10917
|
});
|
|
10724
10918
|
}
|
|
10725
10919
|
function searchService(args) {
|
|
10726
|
-
const store =
|
|
10920
|
+
const store = indexStorePool.acquire(args.projectRoot, { indexDir: args.indexDir });
|
|
10727
10921
|
try {
|
|
10728
10922
|
return store.searchRanked(
|
|
10729
10923
|
args.query,
|
|
@@ -10736,15 +10930,15 @@ function searchService(args) {
|
|
|
10736
10930
|
args.limit
|
|
10737
10931
|
);
|
|
10738
10932
|
} finally {
|
|
10739
|
-
|
|
10933
|
+
indexStorePool.release(store);
|
|
10740
10934
|
}
|
|
10741
10935
|
}
|
|
10742
10936
|
function statsService(args) {
|
|
10743
|
-
const store =
|
|
10937
|
+
const store = indexStorePool.acquire(args.projectRoot, { indexDir: args.indexDir });
|
|
10744
10938
|
try {
|
|
10745
10939
|
return store.getStats();
|
|
10746
10940
|
} finally {
|
|
10747
|
-
|
|
10941
|
+
indexStorePool.release(store);
|
|
10748
10942
|
}
|
|
10749
10943
|
}
|
|
10750
10944
|
|
|
@@ -13086,8 +13280,243 @@ function levelRank(level) {
|
|
|
13086
13280
|
}
|
|
13087
13281
|
}
|
|
13088
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
|
+
|
|
13089
13518
|
// src/exec.ts
|
|
13090
|
-
var
|
|
13519
|
+
var isWin4 = process.platform === "win32";
|
|
13091
13520
|
var DEFAULT_ALLOWED_COMMANDS = /* @__PURE__ */ new Set([
|
|
13092
13521
|
// JS / TS toolchain
|
|
13093
13522
|
"node",
|
|
@@ -13863,6 +14292,19 @@ var execTool = {
|
|
|
13863
14292
|
const args = (input.args ?? []).slice(0, MAX_ARGS);
|
|
13864
14293
|
const timeout = Math.max(1, Math.min(input.timeout ?? DEFAULT_TIMEOUT_MS3, DEFAULT_TIMEOUT_MS3));
|
|
13865
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
|
+
}
|
|
13866
14308
|
const argError = validateArgs(cmd, args);
|
|
13867
14309
|
if (argError) {
|
|
13868
14310
|
return {
|
|
@@ -13913,7 +14355,7 @@ function runCommand(cmd, args, cwd, timeout, signal, sessionId, danger) {
|
|
|
13913
14355
|
let timedOut = false;
|
|
13914
14356
|
const spool = createOutputSpool({ tool: `exec-${cmd}`, thresholdBytes: MAX_OUTPUT2 });
|
|
13915
14357
|
const resolved = resolveWin32Command(cmd);
|
|
13916
|
-
const needsShell =
|
|
14358
|
+
const needsShell = isWin4 && (resolved.endsWith(".cmd") || resolved.endsWith(".bat"));
|
|
13917
14359
|
const shim = needsShell ? buildWin32CmdShimInvocation(resolved, args) : null;
|
|
13918
14360
|
const spawnCmd = shim?.command ?? resolved;
|
|
13919
14361
|
const spawnArgs = shim?.args ?? args;
|
|
@@ -13938,7 +14380,7 @@ function runCommand(cmd, args, cwd, timeout, signal, sessionId, danger) {
|
|
|
13938
14380
|
env: buildChildEnv2(sessionId),
|
|
13939
14381
|
stdio: ["ignore", "pipe", "pipe"],
|
|
13940
14382
|
windowsHide: true,
|
|
13941
|
-
...
|
|
14383
|
+
...isWin4 ? {} : { signal },
|
|
13942
14384
|
...shim ? { windowsVerbatimArguments: shim.windowsVerbatimArguments } : {}
|
|
13943
14385
|
});
|
|
13944
14386
|
} catch (err) {
|
|
@@ -13977,7 +14419,7 @@ function runCommand(cmd, args, cwd, timeout, signal, sessionId, danger) {
|
|
|
13977
14419
|
const isAbort = err && err.code === "ABORT_ERR";
|
|
13978
14420
|
const stderrText = isAbort ? `Aborted: ${err.message}` : err.message;
|
|
13979
14421
|
clearTimeout(timer);
|
|
13980
|
-
if (
|
|
14422
|
+
if (isWin4) signal.removeEventListener("abort", onAbort);
|
|
13981
14423
|
if (typeof pid === "number") registry.unregister(pid);
|
|
13982
14424
|
registry.afterCall(Date.now() - startedAt, true);
|
|
13983
14425
|
spool.finalize();
|
|
@@ -14010,7 +14452,7 @@ function runCommand(cmd, args, cwd, timeout, signal, sessionId, danger) {
|
|
|
14010
14452
|
if (typeof pid === "number") registry.kill(pid, { force: true });
|
|
14011
14453
|
else child.kill("SIGTERM");
|
|
14012
14454
|
};
|
|
14013
|
-
if (
|
|
14455
|
+
if (isWin4) {
|
|
14014
14456
|
if (signal.aborted) onAbort();
|
|
14015
14457
|
else signal.addEventListener("abort", onAbort, { once: true });
|
|
14016
14458
|
}
|
|
@@ -14030,7 +14472,7 @@ function runCommand(cmd, args, cwd, timeout, signal, sessionId, danger) {
|
|
|
14030
14472
|
});
|
|
14031
14473
|
child.on("close", (code) => {
|
|
14032
14474
|
clearTimeout(timer);
|
|
14033
|
-
if (
|
|
14475
|
+
if (isWin4) signal.removeEventListener("abort", onAbort);
|
|
14034
14476
|
if (typeof pid === "number") registry.unregister(pid);
|
|
14035
14477
|
const durationMs = Date.now() - startedAt;
|
|
14036
14478
|
const exitCode = killed ? 124 : code ?? 1;
|
|
@@ -14841,7 +15283,7 @@ function runGit2(args, cwd, signal) {
|
|
|
14841
15283
|
|
|
14842
15284
|
// src/glob.ts
|
|
14843
15285
|
import * as fs20 from "node:fs/promises";
|
|
14844
|
-
import * as
|
|
15286
|
+
import * as path25 from "node:path";
|
|
14845
15287
|
import { compileGlob as compileGlob3 } from "@wrongstack/core";
|
|
14846
15288
|
|
|
14847
15289
|
// src/_concurrency.ts
|
|
@@ -14945,7 +15387,7 @@ var globTool = {
|
|
|
14945
15387
|
if (DEFAULT_IGNORE2.includes(name)) continue;
|
|
14946
15388
|
if (ignored.includes(name)) continue;
|
|
14947
15389
|
const rel = relPrefix ? `${relPrefix}/${name}` : name;
|
|
14948
|
-
const full =
|
|
15390
|
+
const full = path25.join(dir, name);
|
|
14949
15391
|
if (e.isDirectory()) {
|
|
14950
15392
|
subdirs.push({ full, rel });
|
|
14951
15393
|
} else if (e.isFile()) {
|
|
@@ -14989,7 +15431,7 @@ var globTool = {
|
|
|
14989
15431
|
};
|
|
14990
15432
|
async function readGitignore(dir) {
|
|
14991
15433
|
try {
|
|
14992
|
-
const raw = await fs20.readFile(
|
|
15434
|
+
const raw = await fs20.readFile(path25.join(dir, ".gitignore"), "utf8");
|
|
14993
15435
|
return raw.split("\n").map((l) => l.trim()).filter((l) => l && !l.startsWith("#"));
|
|
14994
15436
|
} catch {
|
|
14995
15437
|
return [];
|
|
@@ -15000,7 +15442,7 @@ async function readGitignore(dir) {
|
|
|
15000
15442
|
import { expectDefined as expectDefined7 } from "@wrongstack/core";
|
|
15001
15443
|
import { spawn as spawn10 } from "node:child_process";
|
|
15002
15444
|
import * as fs21 from "node:fs/promises";
|
|
15003
|
-
import * as
|
|
15445
|
+
import * as path26 from "node:path";
|
|
15004
15446
|
import { buildChildEnv as buildChildEnv5, compileGlob as compileGlob4, ToolValidationError as ToolValidationError4 } from "@wrongstack/core";
|
|
15005
15447
|
|
|
15006
15448
|
// src/_regex.ts
|
|
@@ -15393,7 +15835,7 @@ async function runNative(input, base, mode, limit, signal) {
|
|
|
15393
15835
|
if (stopped) return;
|
|
15394
15836
|
if (DEFAULT_IGNORE3.includes(e.name)) continue;
|
|
15395
15837
|
if (e.isSymbolicLink()) continue;
|
|
15396
|
-
const full =
|
|
15838
|
+
const full = path26.join(dir, e.name);
|
|
15397
15839
|
if (e.isDirectory()) {
|
|
15398
15840
|
subdirs.push(full);
|
|
15399
15841
|
} else if (e.isFile()) {
|
|
@@ -15981,56 +16423,56 @@ function jmespathSearch(data, query) {
|
|
|
15981
16423
|
}
|
|
15982
16424
|
function validateJsonSchema(data, schema) {
|
|
15983
16425
|
const errors = [];
|
|
15984
|
-
function check(value, s,
|
|
16426
|
+
function check(value, s, path33) {
|
|
15985
16427
|
if (s["type"]) {
|
|
15986
16428
|
const expectedType = s["type"];
|
|
15987
16429
|
const actualType = Array.isArray(value) ? "array" : value === null ? "null" : typeof value;
|
|
15988
16430
|
if (expectedType === "integer") {
|
|
15989
|
-
if (!Number.isInteger(value)) errors.push(`${
|
|
16431
|
+
if (!Number.isInteger(value)) errors.push(`${path33}: expected integer, got ${actualType}`);
|
|
15990
16432
|
} else if (expectedType !== actualType) {
|
|
15991
|
-
errors.push(`${
|
|
16433
|
+
errors.push(`${path33}: expected ${expectedType}, got ${actualType}`);
|
|
15992
16434
|
}
|
|
15993
16435
|
}
|
|
15994
16436
|
if (typeof value === "string" && s["format"] === "uri" && value) {
|
|
15995
16437
|
try {
|
|
15996
16438
|
new URL(value);
|
|
15997
16439
|
} catch {
|
|
15998
|
-
errors.push(`${
|
|
16440
|
+
errors.push(`${path33}: not a valid URI`);
|
|
15999
16441
|
}
|
|
16000
16442
|
}
|
|
16001
16443
|
if (typeof value === "string" && s["pattern"]) {
|
|
16002
16444
|
const re = new RegExp(s["pattern"]);
|
|
16003
|
-
if (!re.test(value)) errors.push(`${
|
|
16445
|
+
if (!re.test(value)) errors.push(`${path33}: does not match pattern ${s["pattern"]}`);
|
|
16004
16446
|
}
|
|
16005
16447
|
if (typeof value === "string" && s["minLength"] !== void 0 && value.length < s["minLength"]) {
|
|
16006
|
-
errors.push(`${
|
|
16448
|
+
errors.push(`${path33}: string too short (min ${s["minLength"]})`);
|
|
16007
16449
|
}
|
|
16008
16450
|
if (typeof value === "string" && s["maxLength"] !== void 0 && value.length > s["maxLength"]) {
|
|
16009
|
-
errors.push(`${
|
|
16451
|
+
errors.push(`${path33}: string too long (max ${s["maxLength"]})`);
|
|
16010
16452
|
}
|
|
16011
16453
|
if (typeof value === "number" && s["minimum"] !== void 0 && value < s["minimum"]) {
|
|
16012
|
-
errors.push(`${
|
|
16454
|
+
errors.push(`${path33}: below minimum ${s["minimum"]}`);
|
|
16013
16455
|
}
|
|
16014
16456
|
if (typeof value === "number" && s["maximum"] !== void 0 && value > s["maximum"]) {
|
|
16015
|
-
errors.push(`${
|
|
16457
|
+
errors.push(`${path33}: above maximum ${s["maximum"]}`);
|
|
16016
16458
|
}
|
|
16017
16459
|
if (Array.isArray(value) && s["items"] && Array.isArray(s["items"])) {
|
|
16018
16460
|
for (let i = 0; i < value.length; i++) {
|
|
16019
|
-
check(value[i], s["items"], `${
|
|
16461
|
+
check(value[i], s["items"], `${path33}[${i}]`);
|
|
16020
16462
|
}
|
|
16021
16463
|
}
|
|
16022
16464
|
if (typeof value === "object" && value !== null && !Array.isArray(value) && s["properties"]) {
|
|
16023
16465
|
const props = s["properties"];
|
|
16024
16466
|
for (const [k, propSchema] of Object.entries(props)) {
|
|
16025
|
-
check(value[k], propSchema, `${
|
|
16467
|
+
check(value[k], propSchema, `${path33}.${k}`);
|
|
16026
16468
|
}
|
|
16027
16469
|
}
|
|
16028
16470
|
}
|
|
16029
16471
|
check(data, schema, "$");
|
|
16030
16472
|
return { valid: errors.length === 0, errors };
|
|
16031
16473
|
}
|
|
16032
|
-
function simpleQuery(data,
|
|
16033
|
-
const parts =
|
|
16474
|
+
function simpleQuery(data, path33) {
|
|
16475
|
+
const parts = path33.replace(/\[(\d+)\]/g, ".$1").split(".").filter(Boolean);
|
|
16034
16476
|
let current = data;
|
|
16035
16477
|
for (const part of parts) {
|
|
16036
16478
|
if (current === null || current === void 0) return void 0;
|
|
@@ -16098,7 +16540,7 @@ import {
|
|
|
16098
16540
|
duplicateBoard,
|
|
16099
16541
|
exportBoardAsMarkdown,
|
|
16100
16542
|
exportBoardToTaskGraph,
|
|
16101
|
-
|
|
16543
|
+
createBoardFromText,
|
|
16102
16544
|
getBoard as getBoard2,
|
|
16103
16545
|
getKanbanOrchestrationSnapshot,
|
|
16104
16546
|
getKanbanQueueHealth,
|
|
@@ -16622,7 +17064,7 @@ var kanbanTool = {
|
|
|
16622
17064
|
}
|
|
16623
17065
|
case "generate_board": {
|
|
16624
17066
|
if (!input.description) return fail("generate_board requires description.");
|
|
16625
|
-
const boardInput =
|
|
17067
|
+
const boardInput = createBoardFromText({
|
|
16626
17068
|
description: input.description,
|
|
16627
17069
|
...input.title !== void 0 ? { title: input.title } : {},
|
|
16628
17070
|
...input.context !== void 0 ? { context: input.context } : {},
|
|
@@ -17007,20 +17449,31 @@ var kanbanTool = {
|
|
|
17007
17449
|
if (!input.boardId || !input.taskId)
|
|
17008
17450
|
return fail("mark_assignment requires boardId and taskId.");
|
|
17009
17451
|
const assignmentStatus = input.assignmentStatus ?? (input.status === "completed" ? "completed" : input.error ? "failed" : void 0);
|
|
17010
|
-
const board = await updateTaskAssignment(
|
|
17011
|
-
|
|
17012
|
-
|
|
17013
|
-
|
|
17014
|
-
|
|
17015
|
-
|
|
17016
|
-
|
|
17017
|
-
|
|
17018
|
-
|
|
17019
|
-
|
|
17020
|
-
|
|
17021
|
-
|
|
17022
|
-
|
|
17023
|
-
|
|
17452
|
+
const board = await updateTaskAssignment(
|
|
17453
|
+
projectRoot,
|
|
17454
|
+
input.boardId,
|
|
17455
|
+
input.taskId,
|
|
17456
|
+
{
|
|
17457
|
+
...assignmentStatus !== void 0 ? { status: assignmentStatus } : {},
|
|
17458
|
+
...input.subagentId !== void 0 ? { subagentId: input.subagentId } : {},
|
|
17459
|
+
...input.runTaskId !== void 0 ? { runTaskId: input.runTaskId } : {},
|
|
17460
|
+
...input.lastResult !== void 0 ? { lastResult: input.lastResult } : {},
|
|
17461
|
+
...input.error !== void 0 ? { error: input.error } : {},
|
|
17462
|
+
...input.agentId !== void 0 ? { agentId: input.agentId } : {},
|
|
17463
|
+
...input.leaseId !== void 0 ? { leaseId: input.leaseId } : {},
|
|
17464
|
+
...input.claimedAt !== void 0 ? { claimedAt: input.claimedAt } : {},
|
|
17465
|
+
...input.heartbeatAt !== void 0 ? { heartbeatAt: input.heartbeatAt } : {},
|
|
17466
|
+
...input.leaseExpiresAt !== void 0 ? { leaseExpiresAt: input.leaseExpiresAt } : {},
|
|
17467
|
+
...input.attempt !== void 0 ? { attempt: input.attempt } : {},
|
|
17468
|
+
...input.maxAttempts !== void 0 ? { maxAttempts: input.maxAttempts } : {}
|
|
17469
|
+
},
|
|
17470
|
+
// Ownership fence: when expectedLeaseId is supplied, the write is
|
|
17471
|
+
// applied only if the current assignment still holds this lease.
|
|
17472
|
+
// This prevents a recovered+reassigned stale worker's terminal
|
|
17473
|
+
// mark_assignment from overwriting the successor's state. The check
|
|
17474
|
+
// is atomic inside updateTaskAssignment's mutateBoard lock.
|
|
17475
|
+
input.expectedLeaseId !== void 0 ? { expectedLeaseId: input.expectedLeaseId } : {}
|
|
17476
|
+
);
|
|
17024
17477
|
return board ? okBoard(board, "Assignment updated.") : fail("Task not found.");
|
|
17025
17478
|
}
|
|
17026
17479
|
case "heartbeat_assignment": {
|
|
@@ -17029,7 +17482,13 @@ var kanbanTool = {
|
|
|
17029
17482
|
}
|
|
17030
17483
|
const board = await heartbeatTaskAssignment(projectRoot, input.boardId, input.taskId, {
|
|
17031
17484
|
...input.heartbeatAt !== void 0 ? { heartbeatAt: input.heartbeatAt } : {},
|
|
17032
|
-
...input.leaseExpiresAt !== void 0 ? { leaseExpiresAt: input.leaseExpiresAt } : {}
|
|
17485
|
+
...input.leaseExpiresAt !== void 0 ? { leaseExpiresAt: input.leaseExpiresAt } : {},
|
|
17486
|
+
// Ownership fence: when expectedLeaseId is supplied, the renewal
|
|
17487
|
+
// is applied only if the current assignment still holds this lease.
|
|
17488
|
+
// This prevents a recovered+reassigned stale worker's heartbeat
|
|
17489
|
+
// from renewing the successor's lease. The check is atomic inside
|
|
17490
|
+
// heartbeatTaskAssignment's mutateBoard lock.
|
|
17491
|
+
...input.expectedLeaseId !== void 0 ? { expectedLeaseId: input.expectedLeaseId } : {}
|
|
17033
17492
|
});
|
|
17034
17493
|
return board ? okBoard(board, "Assignment heartbeat updated.") : fail("Task assignment not found.");
|
|
17035
17494
|
}
|
|
@@ -17620,7 +18079,7 @@ async function dockerLogs(service, lines, filterRe, cwd, signal, since) {
|
|
|
17620
18079
|
}
|
|
17621
18080
|
var DOCKER_LOGS_TIMEOUT_MS = 3e3;
|
|
17622
18081
|
var MAX_TAIL_LINES = 1e5;
|
|
17623
|
-
async function fileLogs(
|
|
18082
|
+
async function fileLogs(path33, lines, filterRe, stream) {
|
|
17624
18083
|
const { createInterface } = await import("node:readline");
|
|
17625
18084
|
const { createReadStream: createReadStream2 } = await import("node:fs");
|
|
17626
18085
|
const entries = [];
|
|
@@ -17629,7 +18088,7 @@ async function fileLogs(path32, lines, filterRe, stream) {
|
|
|
17629
18088
|
let writeIdx = 0;
|
|
17630
18089
|
let totalLines = 0;
|
|
17631
18090
|
const rl = createInterface({
|
|
17632
|
-
input: createReadStream2(
|
|
18091
|
+
input: createReadStream2(path33),
|
|
17633
18092
|
crlfDelay: Number.POSITIVE_INFINITY
|
|
17634
18093
|
});
|
|
17635
18094
|
for await (const line of rl) {
|
|
@@ -17650,7 +18109,7 @@ async function fileLogs(path32, lines, filterRe, stream) {
|
|
|
17650
18109
|
if (parsed) entries.push(parsed);
|
|
17651
18110
|
}
|
|
17652
18111
|
return {
|
|
17653
|
-
source:
|
|
18112
|
+
source: path33,
|
|
17654
18113
|
entries,
|
|
17655
18114
|
total: entries.length,
|
|
17656
18115
|
truncated: totalLines > effLines,
|
|
@@ -17881,8 +18340,8 @@ function parseOutdatedOutput(json2, exitCode) {
|
|
|
17881
18340
|
init_util();
|
|
17882
18341
|
import { spawn as spawn13 } from "node:child_process";
|
|
17883
18342
|
import * as fs23 from "node:fs/promises";
|
|
17884
|
-
import * as
|
|
17885
|
-
import * as
|
|
18343
|
+
import * as os8 from "node:os";
|
|
18344
|
+
import * as path27 from "node:path";
|
|
17886
18345
|
import { buildChildEnv as buildChildEnv8 } from "@wrongstack/core";
|
|
17887
18346
|
var patchTool = {
|
|
17888
18347
|
name: "patch",
|
|
@@ -17918,9 +18377,9 @@ var patchTool = {
|
|
|
17918
18377
|
for (const t of targets) {
|
|
17919
18378
|
const stripped = stripPathComponents(t, strip);
|
|
17920
18379
|
if (!stripped) continue;
|
|
17921
|
-
const candidate =
|
|
17922
|
-
const rel =
|
|
17923
|
-
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)) {
|
|
17924
18383
|
return {
|
|
17925
18384
|
applied: 0,
|
|
17926
18385
|
rejected: 1,
|
|
@@ -17937,11 +18396,11 @@ var patchTool = {
|
|
|
17937
18396
|
beforeContents.set(target, await readTextForTracking(target));
|
|
17938
18397
|
}
|
|
17939
18398
|
}
|
|
17940
|
-
const tmpDir = await fs23.mkdtemp(
|
|
18399
|
+
const tmpDir = await fs23.mkdtemp(path27.join(os8.tmpdir(), ".wstack_patch_"));
|
|
17941
18400
|
try {
|
|
17942
18401
|
await fs23.chmod(tmpDir, 448).catch(() => {
|
|
17943
18402
|
});
|
|
17944
|
-
const patchFile =
|
|
18403
|
+
const patchFile = path27.join(tmpDir, "in.diff");
|
|
17945
18404
|
await fs23.writeFile(patchFile, input.patch, { mode: 384 });
|
|
17946
18405
|
const args = [`-p${strip}`, "--merge", ...dryRun ? ["--dry-run"] : [], "-i", patchFile];
|
|
17947
18406
|
const result = await runPatch(args, dir, opts.signal);
|
|
@@ -18527,7 +18986,7 @@ ${interesting.join("\n")}` : "symbols/imports: (none detected)"
|
|
|
18527
18986
|
import { expectDefined as expectDefined8 } from "@wrongstack/core";
|
|
18528
18987
|
import { spawn as spawn14 } from "node:child_process";
|
|
18529
18988
|
import * as fs25 from "node:fs/promises";
|
|
18530
|
-
import * as
|
|
18989
|
+
import * as path28 from "node:path";
|
|
18531
18990
|
import {
|
|
18532
18991
|
atomicWrite as atomicWrite3,
|
|
18533
18992
|
buildChildEnv as buildChildEnv9,
|
|
@@ -18616,8 +19075,8 @@ var replaceTool = {
|
|
|
18616
19075
|
} catch {
|
|
18617
19076
|
continue;
|
|
18618
19077
|
}
|
|
18619
|
-
const rel =
|
|
18620
|
-
if (rel.startsWith("..") ||
|
|
19078
|
+
const rel = path28.relative(realRoot, realPath);
|
|
19079
|
+
if (rel.startsWith("..") || path28.isAbsolute(rel)) continue;
|
|
18621
19080
|
const stat17 = await fs25.stat(realPath).catch(() => null);
|
|
18622
19081
|
if (!stat17?.isFile()) continue;
|
|
18623
19082
|
let content;
|
|
@@ -18746,7 +19205,7 @@ async function globNative(pattern, base, extraGlob) {
|
|
|
18746
19205
|
}
|
|
18747
19206
|
for (const e of entries) {
|
|
18748
19207
|
if (DEFAULT_IGNORE4.includes(e.name)) continue;
|
|
18749
|
-
const full =
|
|
19208
|
+
const full = path28.join(dir, e.name);
|
|
18750
19209
|
try {
|
|
18751
19210
|
const stat17 = await fs25.lstat(full);
|
|
18752
19211
|
if (stat17.isSymbolicLink()) continue;
|
|
@@ -18773,7 +19232,7 @@ async function globNative(pattern, base, extraGlob) {
|
|
|
18773
19232
|
// src/scaffold.ts
|
|
18774
19233
|
init_util();
|
|
18775
19234
|
import * as fs26 from "node:fs/promises";
|
|
18776
|
-
import * as
|
|
19235
|
+
import * as path29 from "node:path";
|
|
18777
19236
|
import { atomicWrite as atomicWrite4 } from "@wrongstack/core";
|
|
18778
19237
|
var BUILT_IN_TEMPLATES = {
|
|
18779
19238
|
"npm-package": {
|
|
@@ -18923,16 +19382,16 @@ async function handleBuiltIn(name, templateFiles, cwd, ctx, dryRun, vars) {
|
|
|
18923
19382
|
let filesCreated = 0;
|
|
18924
19383
|
for (const [filePath, content] of Object.entries(templateFiles)) {
|
|
18925
19384
|
const resolvedPath = substituteVars(filePath, name, vars);
|
|
18926
|
-
const joinedPath =
|
|
18927
|
-
const root =
|
|
18928
|
-
const target =
|
|
18929
|
-
const rel =
|
|
18930
|
-
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)) {
|
|
18931
19390
|
throw new Error(`scaffold: generated path "${resolvedPath}" would escape project root`);
|
|
18932
19391
|
}
|
|
18933
19392
|
const fullPath = target;
|
|
18934
19393
|
if (!dryRun) {
|
|
18935
|
-
await fs26.mkdir(
|
|
19394
|
+
await fs26.mkdir(path29.dirname(fullPath), { recursive: true });
|
|
18936
19395
|
await atomicWrite4(fullPath, substituteVars(content, name, vars));
|
|
18937
19396
|
}
|
|
18938
19397
|
files.push(resolvedPath);
|
|
@@ -19789,7 +20248,7 @@ ${formatTaskList2(file.tasks)}` : file.tasks.length > 0 ? formatTaskList2(file.t
|
|
|
19789
20248
|
init_spawn_stream();
|
|
19790
20249
|
init_util();
|
|
19791
20250
|
init_legacy_bridge();
|
|
19792
|
-
import * as
|
|
20251
|
+
import * as path30 from "node:path";
|
|
19793
20252
|
var testTool = {
|
|
19794
20253
|
name: "test",
|
|
19795
20254
|
category: "Code Quality",
|
|
@@ -19896,7 +20355,7 @@ async function detectRunner(cwd) {
|
|
|
19896
20355
|
const candidates = ["vitest.config.ts", "jest.config.js", ".mocharc.json"];
|
|
19897
20356
|
for (const f of candidates) {
|
|
19898
20357
|
try {
|
|
19899
|
-
await stat17(
|
|
20358
|
+
await stat17(path30.join(cwd, f));
|
|
19900
20359
|
if (f.includes("vitest")) return "vitest";
|
|
19901
20360
|
if (f.includes("jest")) return "jest";
|
|
19902
20361
|
if (f.includes("mocha")) return "mocha";
|
|
@@ -20367,7 +20826,7 @@ var toolUseTool = {
|
|
|
20367
20826
|
init_util();
|
|
20368
20827
|
import { expectDefined as expectDefined10 } from "@wrongstack/core";
|
|
20369
20828
|
import * as fs28 from "node:fs/promises";
|
|
20370
|
-
import * as
|
|
20829
|
+
import * as path31 from "node:path";
|
|
20371
20830
|
var DEFAULT_IGNORE5 = [
|
|
20372
20831
|
"node_modules",
|
|
20373
20832
|
".git",
|
|
@@ -20538,7 +20997,7 @@ async function walkDir(dir, depth, opts) {
|
|
|
20538
20997
|
opts.lines.push(opts.prefix + branch + displayName);
|
|
20539
20998
|
if (entry.isDirectory() && (opts.maxDepth === 0 || depth < opts.maxDepth)) {
|
|
20540
20999
|
const childPrefix = opts.prefix + connector;
|
|
20541
|
-
await walkDir(
|
|
21000
|
+
await walkDir(path31.join(dir, entry.name), depth + 1, {
|
|
20542
21001
|
...opts,
|
|
20543
21002
|
prefix: childPrefix,
|
|
20544
21003
|
isLast
|
|
@@ -20551,7 +21010,7 @@ async function walkDir(dir, depth, opts) {
|
|
|
20551
21010
|
init_spawn_stream();
|
|
20552
21011
|
init_util();
|
|
20553
21012
|
init_legacy_bridge();
|
|
20554
|
-
import * as
|
|
21013
|
+
import * as path32 from "node:path";
|
|
20555
21014
|
var typecheckTool = {
|
|
20556
21015
|
name: "typecheck",
|
|
20557
21016
|
category: "Code Quality",
|
|
@@ -20654,8 +21113,8 @@ async function findTsConfig(cwd) {
|
|
|
20654
21113
|
const candidates = ["tsconfig.json", "tsconfig.base.json"];
|
|
20655
21114
|
for (const f of candidates) {
|
|
20656
21115
|
try {
|
|
20657
|
-
const s = await stat17(
|
|
20658
|
-
if (s.isFile()) return
|
|
21116
|
+
const s = await stat17(path32.join(cwd, f));
|
|
21117
|
+
if (s.isFile()) return path32.join(cwd, f);
|
|
20659
21118
|
} catch {
|
|
20660
21119
|
}
|
|
20661
21120
|
}
|