@wrongstack/tools 0.272.2 → 0.273.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/audit.js.map +1 -1
- package/dist/bash.js +225 -24
- package/dist/bash.js.map +1 -1
- package/dist/builtin.js +344 -110
- package/dist/builtin.js.map +1 -1
- package/dist/codebase-index/index.js +9 -5
- package/dist/codebase-index/index.js.map +1 -1
- package/dist/codebase-index/worker.js +9 -5
- package/dist/codebase-index/worker.js.map +1 -1
- package/dist/exec.d.ts +20 -1
- package/dist/exec.js +132 -71
- package/dist/exec.js.map +1 -1
- package/dist/format.js.map +1 -1
- package/dist/index.d.ts +111 -2
- package/dist/index.js +415 -140
- package/dist/index.js.map +1 -1
- package/dist/install.js.map +1 -1
- package/dist/lint.js.map +1 -1
- package/dist/outdated.js.map +1 -1
- package/dist/pack.js +344 -110
- package/dist/pack.js.map +1 -1
- package/dist/replace.js +2 -2
- package/dist/replace.js.map +1 -1
- package/dist/test.js.map +1 -1
- package/dist/typecheck.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -7,11 +7,12 @@ import { spawn, execFileSync } from 'node:child_process';
|
|
|
7
7
|
import * as os2 from 'node:os';
|
|
8
8
|
import * as fs8 from 'node:fs';
|
|
9
9
|
import { statSync, mkdirSync, createWriteStream } from 'node:fs';
|
|
10
|
+
import { toErrorMessage as toErrorMessage$1 } from '@wrongstack/core/utils/error';
|
|
10
11
|
import * as dns from 'node:dns/promises';
|
|
11
12
|
import * as net from 'node:net';
|
|
12
13
|
import { Agent } from 'undici';
|
|
13
14
|
import TurndownService from 'turndown';
|
|
14
|
-
import { toErrorMessage as toErrorMessage$
|
|
15
|
+
import { toErrorMessage as toErrorMessage$2 } from '@wrongstack/core/utils';
|
|
15
16
|
import { randomUUID } from 'node:crypto';
|
|
16
17
|
import { createRequire } from 'node:module';
|
|
17
18
|
import { fileURLToPath } from 'node:url';
|
|
@@ -626,7 +627,7 @@ var replaceTool = {
|
|
|
626
627
|
if (err.code === "ENOENT") return null;
|
|
627
628
|
throw err;
|
|
628
629
|
});
|
|
629
|
-
if (!lstat2
|
|
630
|
+
if (!lstat2?.isFile()) continue;
|
|
630
631
|
if (lstat2.isSymbolicLink()) continue;
|
|
631
632
|
let realPath;
|
|
632
633
|
try {
|
|
@@ -637,7 +638,7 @@ var replaceTool = {
|
|
|
637
638
|
const rel = path.relative(realRoot, realPath);
|
|
638
639
|
if (rel.startsWith("..") || path.isAbsolute(rel)) continue;
|
|
639
640
|
const stat11 = await fs7.stat(realPath).catch(() => null);
|
|
640
|
-
if (!stat11
|
|
641
|
+
if (!stat11?.isFile()) continue;
|
|
641
642
|
let content;
|
|
642
643
|
try {
|
|
643
644
|
const buf = await fs7.readFile(realPath);
|
|
@@ -1798,6 +1799,21 @@ function _resetProcessRegistry() {
|
|
|
1798
1799
|
_registry = void 0;
|
|
1799
1800
|
}
|
|
1800
1801
|
var REGISTRY_FILE = ".wrongstack/process-registry.json";
|
|
1802
|
+
function toErrorMessage2(err) {
|
|
1803
|
+
return err instanceof Error ? err.message : String(err);
|
|
1804
|
+
}
|
|
1805
|
+
function emitStructuredLog(level, event, message, error) {
|
|
1806
|
+
const payload = {
|
|
1807
|
+
level,
|
|
1808
|
+
event,
|
|
1809
|
+
message,
|
|
1810
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
1811
|
+
};
|
|
1812
|
+
if (error !== void 0) {
|
|
1813
|
+
payload.error = toErrorMessage2(error);
|
|
1814
|
+
}
|
|
1815
|
+
console.log(JSON.stringify(payload));
|
|
1816
|
+
}
|
|
1801
1817
|
var HEARTBEAT_INTERVAL_MS = 5e3;
|
|
1802
1818
|
var STALE_THRESHOLD_MS = 3e4;
|
|
1803
1819
|
var LOCKFILE = ".wrongstack/.process-registry.lock";
|
|
@@ -1807,6 +1823,9 @@ function generateInstanceId() {
|
|
|
1807
1823
|
const random = Math.random().toString(36).slice(2, 8);
|
|
1808
1824
|
return `${hostname4}:${pid}:${random}`;
|
|
1809
1825
|
}
|
|
1826
|
+
function isNodeError(err) {
|
|
1827
|
+
return typeof err === "object" && err !== null && "code" in err;
|
|
1828
|
+
}
|
|
1810
1829
|
async function acquireLock(lockfilePath, timeoutMs = 5e3) {
|
|
1811
1830
|
const start = Date.now();
|
|
1812
1831
|
const pidStr = String(process.pid);
|
|
@@ -1821,7 +1840,7 @@ async function acquireLock(lockfilePath, timeoutMs = 5e3) {
|
|
|
1821
1840
|
}
|
|
1822
1841
|
};
|
|
1823
1842
|
} catch (err) {
|
|
1824
|
-
if (err.code === "EEXIST") {
|
|
1843
|
+
if (isNodeError(err) && err.code === "EEXIST") {
|
|
1825
1844
|
try {
|
|
1826
1845
|
const content = await fs7.readFile(lockfilePath, "utf-8");
|
|
1827
1846
|
const parts = content.split(":");
|
|
@@ -1858,7 +1877,7 @@ async function readRegistryFile(filePath) {
|
|
|
1858
1877
|
}
|
|
1859
1878
|
return parsed;
|
|
1860
1879
|
} catch (err) {
|
|
1861
|
-
if (err.code === "ENOENT") {
|
|
1880
|
+
if (isNodeError(err) && err.code === "ENOENT") {
|
|
1862
1881
|
return {
|
|
1863
1882
|
version: 1,
|
|
1864
1883
|
instances: /* @__PURE__ */ new Map(),
|
|
@@ -1894,7 +1913,7 @@ var PersistentProcessRegistry = class {
|
|
|
1894
1913
|
this.lockPath = path.join(homeDir, LOCKFILE);
|
|
1895
1914
|
this.baseRegistry = baseRegistry ?? getProcessRegistry();
|
|
1896
1915
|
this.ensureDirectory().catch((err) => {
|
|
1897
|
-
|
|
1916
|
+
emitStructuredLog("warn", "process_registry.dir_create_failed", "PersistentProcessRegistry: failed to create .wrongstack directory", err);
|
|
1898
1917
|
});
|
|
1899
1918
|
}
|
|
1900
1919
|
async ensureDirectory() {
|
|
@@ -1902,7 +1921,7 @@ var PersistentProcessRegistry = class {
|
|
|
1902
1921
|
try {
|
|
1903
1922
|
await fs7.mkdir(dir, { recursive: true });
|
|
1904
1923
|
} catch (err) {
|
|
1905
|
-
if (err.code !== "EEXIST") throw err;
|
|
1924
|
+
if (!isNodeError(err) || err.code !== "EEXIST") throw err;
|
|
1906
1925
|
}
|
|
1907
1926
|
}
|
|
1908
1927
|
/**
|
|
@@ -1982,6 +2001,7 @@ var PersistentProcessRegistry = class {
|
|
|
1982
2001
|
try {
|
|
1983
2002
|
const data = await readRegistryFile(this.registryPath);
|
|
1984
2003
|
data.instances.set(String(entry.pid), entry);
|
|
2004
|
+
const child = null;
|
|
1985
2005
|
this.baseRegistry.register({
|
|
1986
2006
|
pid: entry.pid,
|
|
1987
2007
|
name: entry.name,
|
|
@@ -1989,8 +2009,7 @@ var PersistentProcessRegistry = class {
|
|
|
1989
2009
|
startedAt: entry.startedAt,
|
|
1990
2010
|
sessionId: entry.sessionId,
|
|
1991
2011
|
protected: entry.protected,
|
|
1992
|
-
child
|
|
1993
|
-
// Main process has no child handle
|
|
2012
|
+
child
|
|
1994
2013
|
});
|
|
1995
2014
|
await writeRegistryFile(this.registryPath, data);
|
|
1996
2015
|
} finally {
|
|
@@ -2038,7 +2057,7 @@ var PersistentProcessRegistry = class {
|
|
|
2038
2057
|
data.lastCleanup = now2;
|
|
2039
2058
|
await writeRegistryFile(this.registryPath, data);
|
|
2040
2059
|
} catch (err) {
|
|
2041
|
-
|
|
2060
|
+
emitStructuredLog("warn", "process_registry.sync_failed", "PersistentProcessRegistry: sync failed", err);
|
|
2042
2061
|
} finally {
|
|
2043
2062
|
await release();
|
|
2044
2063
|
}
|
|
@@ -2059,7 +2078,11 @@ var PersistentProcessRegistry = class {
|
|
|
2059
2078
|
if (process.platform !== "win32") {
|
|
2060
2079
|
process.kill(entry.pid, 0);
|
|
2061
2080
|
} else {
|
|
2062
|
-
|
|
2081
|
+
emitStructuredLog(
|
|
2082
|
+
"debug",
|
|
2083
|
+
"process_registry.stale_pid_check",
|
|
2084
|
+
`PersistentProcessRegistry: checking stale pid ${entry.pid} (${age}ms old)`
|
|
2085
|
+
);
|
|
2063
2086
|
}
|
|
2064
2087
|
} catch {
|
|
2065
2088
|
stalePids.push(_pidStr);
|
|
@@ -2073,7 +2096,7 @@ var PersistentProcessRegistry = class {
|
|
|
2073
2096
|
await writeRegistryFile(this.registryPath, data);
|
|
2074
2097
|
}
|
|
2075
2098
|
} catch (err) {
|
|
2076
|
-
|
|
2099
|
+
emitStructuredLog("warn", "process_registry.cleanup_failed", "PersistentProcessRegistry: cleanup failed", err);
|
|
2077
2100
|
} finally {
|
|
2078
2101
|
await release();
|
|
2079
2102
|
}
|
|
@@ -2302,7 +2325,7 @@ async function isKillProtected(kill) {
|
|
|
2302
2325
|
const entries = await getProtectedEntries();
|
|
2303
2326
|
const killNameLower = kill.name.toLowerCase();
|
|
2304
2327
|
for (const entry of entries) {
|
|
2305
|
-
if (entry.name
|
|
2328
|
+
if (entry.name?.toLowerCase().includes(killNameLower)) {
|
|
2306
2329
|
return true;
|
|
2307
2330
|
}
|
|
2308
2331
|
}
|
|
@@ -2357,6 +2380,155 @@ async function checkAndBlockKillCommand(command) {
|
|
|
2357
2380
|
}
|
|
2358
2381
|
return { blocked: false };
|
|
2359
2382
|
}
|
|
2383
|
+
function pickShell(platform4, command, env) {
|
|
2384
|
+
const override = env.get("WRONGSTACK_SHELL")?.trim().toLowerCase();
|
|
2385
|
+
if (override === "cmd" || override === "cmd.exe") return "cmd";
|
|
2386
|
+
if (override === "powershell" || override === "powershell.exe") return "powershell";
|
|
2387
|
+
if (override === "pwsh" || override === "pwsh.exe") return "pwsh";
|
|
2388
|
+
if (looksLikePowerShell(command)) return "pwsh";
|
|
2389
|
+
return "cmd";
|
|
2390
|
+
}
|
|
2391
|
+
function looksLikePowerShell(command) {
|
|
2392
|
+
if (!command) return false;
|
|
2393
|
+
const trimmed = command.trimStart();
|
|
2394
|
+
if (/\.ps1\b/i.test(trimmed)) return true;
|
|
2395
|
+
if (/^\s*#requires\s/i.test(trimmed)) return true;
|
|
2396
|
+
if (/^\s*param\s*\(/i.test(trimmed)) return true;
|
|
2397
|
+
if (/\$[\w:{]/i.test(trimmed)) return true;
|
|
2398
|
+
if (/\$\(/.test(trimmed)) return true;
|
|
2399
|
+
if (/@\s*['"]/.test(trimmed)) return true;
|
|
2400
|
+
if (/&\s+\$/.test(trimmed)) return true;
|
|
2401
|
+
if (/(^|\s)@\s*\(/.test(trimmed)) return true;
|
|
2402
|
+
if (/(^|\s)@\{/.test(trimmed)) return true;
|
|
2403
|
+
if (/(?:^|[\s\[\(\{,;])(?:-eq|-ne|-lt|-gt|-le|-ge|-like|-notlike|-match|-notmatch|-contains|-notcontains|-in|-notin|-and|-or|-not|-band|-bor|-bxor|-replace|-isplit|-csplit|-osplit|-join|-is|-as|-f)(?:$|[\s\]\)\},;])/i.test(trimmed)) {
|
|
2404
|
+
return true;
|
|
2405
|
+
}
|
|
2406
|
+
if (PS_VERB_RE.test(trimmed)) return true;
|
|
2407
|
+
if (/(?:^|[\s;&|])(gci|gi|gp|gcm|gps|sl|rm|cat|cp|mv)\b/i.test(trimmed)) {
|
|
2408
|
+
return true;
|
|
2409
|
+
}
|
|
2410
|
+
if (looksLikePowerShellExtended(command)) return true;
|
|
2411
|
+
return false;
|
|
2412
|
+
}
|
|
2413
|
+
function looksLikePowerShellExtended(command) {
|
|
2414
|
+
if (!command) return false;
|
|
2415
|
+
const trimmed = command.trimStart();
|
|
2416
|
+
if (/(?:^|\s)[-/](?:WhatIf|Confirm|ErrorAction)(?::[^\s]+|\s|=|$)/i.test(trimmed)) {
|
|
2417
|
+
return true;
|
|
2418
|
+
}
|
|
2419
|
+
if (/(?:^|[\s;&|])(Where-Object|ForEach-Object|Select-Object|Sort-Object|Group-Object|Measure-Object|Compare-Object|Tee-Object)(?:\s|$)/i.test(trimmed)) {
|
|
2420
|
+
return true;
|
|
2421
|
+
}
|
|
2422
|
+
if (/\bWrite-(?:Host|Output|Error|Warning|Verbose|Debug|Information)(?:\s|$)/i.test(trimmed)) {
|
|
2423
|
+
return true;
|
|
2424
|
+
}
|
|
2425
|
+
if (/HK(?:LM|CU|CR|U|CC|DD|PD):\\/i.test(trimmed)) return true;
|
|
2426
|
+
if (/\[(?:string|int|bool|xml|double|float|decimal|char|byte|long|System\.)/i.test(trimmed)) {
|
|
2427
|
+
return true;
|
|
2428
|
+
}
|
|
2429
|
+
if (/^\s*<#|#>\s*$/m.test(trimmed)) return true;
|
|
2430
|
+
if (/(?:^|\s)[-/\/](?:AsPlainText|PipelineVariable|pv|FilterHashtable|OutVariable|ov)(?:\s|=|$)/i.test(trimmed)) {
|
|
2431
|
+
return true;
|
|
2432
|
+
}
|
|
2433
|
+
return false;
|
|
2434
|
+
}
|
|
2435
|
+
function wrapPowerShellScript(command) {
|
|
2436
|
+
const bootstrap = "[Console]::OutputEncoding = [System.Text.Encoding]::UTF8;$ConfirmPreference='None';$WhatIfPreference=$false";
|
|
2437
|
+
return "\uFEFF" + bootstrap + "\ntry {\n" + command + "\n} finally { exit $LASTEXITCODE }";
|
|
2438
|
+
}
|
|
2439
|
+
var PS_VERB_RE = new RegExp(
|
|
2440
|
+
// Boundaries: start-of-string, whitespace, `;`, `&`, `|`, `(`, `{`, `,`.
|
|
2441
|
+
"(?:^|[\\s;&|\\(\\{,])(?:Get|Set|New|Remove|Add|Clear|Copy|Move|Rename|Test|Update|Write|Read|Push|Pop|Invoke|Start|Stop|Wait|Out|Format|Group|Measure|Compare|Resolve|ConvertTo|ConvertFrom|Convert|Import|Export|Select|Where|ForEach|Sort|Tee|Split|Join|Limit|Skip|Step|Trace|Debug|Register|Unregister|Enable|Disable|Restart|Suspend|Resume|Save|Open|Close|Lock|Unlock|Mount|Dismount|Enter|Exit|Use|Show|Hide|Find|Search|Watch|Initialize|Optimize|Compress|Expand|Merge|Checkpoint|Undo|Redo|Approve|Deny|Block|Grant|Revoke|Assert|Confirm|Receive|Send|Connect|Disconnect|Reset|Backup|Restore|Publish|Unpublish|Install|Uninstall|Build|Rebuild|Deploy|Submit|Process|Complete|Approve|Revoke|Pay|Refund|Decline|Receive|Send)-[A-Za-z][A-Za-z0-9]+(?:[\\-\\+][A-Za-z][A-Za-z0-9]+)*(?:$|[\\s\\-\\;\\&\\|\\(\\)\\{\\},])",
|
|
2442
|
+
"i"
|
|
2443
|
+
);
|
|
2444
|
+
function shellArgs(shell) {
|
|
2445
|
+
if (shell === "powershell" || shell === "pwsh") {
|
|
2446
|
+
return ["-NoLogo", "-NoProfile", "-NonInteractive", "-Command", "-"];
|
|
2447
|
+
}
|
|
2448
|
+
return ["/c"];
|
|
2449
|
+
}
|
|
2450
|
+
function diagnoseBashism(command, shell) {
|
|
2451
|
+
if (!command) return void 0;
|
|
2452
|
+
const isCmd = shell === "cmd";
|
|
2453
|
+
const hints = [];
|
|
2454
|
+
const add = (h) => {
|
|
2455
|
+
if (!hints.includes(h)) hints.push(h);
|
|
2456
|
+
};
|
|
2457
|
+
if (/\/dev\/null/.test(command)) {
|
|
2458
|
+
add(
|
|
2459
|
+
isCmd ? "use `nul` instead of `/dev/null` (e.g. `2>nul`)" : "use `$null` instead of `/dev/null` (e.g. `2>$null`)"
|
|
2460
|
+
);
|
|
2461
|
+
}
|
|
2462
|
+
if (/(^|[;&|]\s*)export\s+[A-Za-z_]\w*=/.test(command)) {
|
|
2463
|
+
add(
|
|
2464
|
+
isCmd ? "set env vars with `set NAME=value`, not `export`" : "set env vars with `$env:NAME = 'value'`, not `export`"
|
|
2465
|
+
);
|
|
2466
|
+
}
|
|
2467
|
+
if (/<<-?\s*['"]?[A-Za-z_]\w*/.test(command)) {
|
|
2468
|
+
add(
|
|
2469
|
+
isCmd ? "cmd has no heredocs \u2014 write the content to a file or use multiple `echo` lines" : "PowerShell has no heredocs \u2014 use a single-quoted here-string `@'\u2026'@` (closing `'@` at column 0)"
|
|
2470
|
+
);
|
|
2471
|
+
}
|
|
2472
|
+
if (shell === "powershell" && /(&&|\|\|)/.test(command)) {
|
|
2473
|
+
add("Windows PowerShell 5.1 has no `&&`/`||` \u2014 separate commands with `;` (check `$LASTEXITCODE`)");
|
|
2474
|
+
}
|
|
2475
|
+
if (/\brm\s+-[A-Za-z]*[rf]/.test(command)) {
|
|
2476
|
+
add(
|
|
2477
|
+
isCmd ? "`rm` is not a cmd builtin \u2014 use `del` (files) or `rmdir /s /q` (dirs)" : "use `Remove-Item -Recurse -Force` \u2014 the `rm -rf` bash flags don't exist in PowerShell"
|
|
2478
|
+
);
|
|
2479
|
+
}
|
|
2480
|
+
if (/\bwhich\s+\S/.test(command)) {
|
|
2481
|
+
add(isCmd ? "use `where <cmd>` instead of `which`" : "use `Get-Command <cmd>` instead of `which`");
|
|
2482
|
+
}
|
|
2483
|
+
if (hints.length === 0) return void 0;
|
|
2484
|
+
const label = isCmd ? "cmd.exe" : shell === "pwsh" ? "PowerShell 7" : "Windows PowerShell";
|
|
2485
|
+
return `[wrongstack] This command failed and contains bash/POSIX syntax that ${label} does not accept \u2014 ${hints.join("; ")}. Rewrite it in ${isCmd ? "cmd" : "PowerShell"} syntax and retry.`;
|
|
2486
|
+
}
|
|
2487
|
+
function resolveWin32Command(cmd) {
|
|
2488
|
+
if (process.platform !== "win32") return cmd;
|
|
2489
|
+
if (cmd.includes("/") || cmd.includes("\\") || path.extname(cmd.replace(/\//g, "\\"))) {
|
|
2490
|
+
return cmd;
|
|
2491
|
+
}
|
|
2492
|
+
const pathext = (process.env["PATHEXT"] ?? ".COM;.EXE;.BAT;.CMD;.VBS;.JS;.WS;.MSC").toLowerCase().split(";");
|
|
2493
|
+
const pathDirs = (process.env["PATH"] ?? "").split(path.delimiter);
|
|
2494
|
+
for (const dir of pathDirs) {
|
|
2495
|
+
const base = path.join(dir, cmd);
|
|
2496
|
+
for (const ext of pathext) {
|
|
2497
|
+
const full = `${base}${ext}`;
|
|
2498
|
+
try {
|
|
2499
|
+
fs8.accessSync(full, fs8.constants.X_OK);
|
|
2500
|
+
return full;
|
|
2501
|
+
} catch {
|
|
2502
|
+
}
|
|
2503
|
+
}
|
|
2504
|
+
}
|
|
2505
|
+
return cmd;
|
|
2506
|
+
}
|
|
2507
|
+
function resolvePowerShell(cmd) {
|
|
2508
|
+
if (process.platform !== "win32") return cmd;
|
|
2509
|
+
const lower = cmd.toLowerCase();
|
|
2510
|
+
if (lower !== "pwsh" && lower !== "powershell" && lower !== "pwsh.exe" && lower !== "powershell.exe") {
|
|
2511
|
+
return resolveWin32Command(cmd);
|
|
2512
|
+
}
|
|
2513
|
+
const primary = lower.startsWith("pwsh") ? "pwsh.exe" : "powershell.exe";
|
|
2514
|
+
const fallback = lower.startsWith("pwsh") ? "powershell.exe" : "pwsh.exe";
|
|
2515
|
+
const resolved = resolveWin32Command(primary);
|
|
2516
|
+
if (resolved !== primary) {
|
|
2517
|
+
const fb = resolveWin32Command(fallback);
|
|
2518
|
+
return fb === fallback ? cmd : fb;
|
|
2519
|
+
}
|
|
2520
|
+
return resolved;
|
|
2521
|
+
}
|
|
2522
|
+
var WIN32_SHELL_META = /[&|<>\r\n\0]/;
|
|
2523
|
+
function assertSafeWin32ShellArgs(args) {
|
|
2524
|
+
for (const a of args) {
|
|
2525
|
+
if (typeof a === "string" && WIN32_SHELL_META.test(a)) {
|
|
2526
|
+
throw new Error(
|
|
2527
|
+
"win32 shell spawn: argument contains a shell metacharacter (one of & | < > or a newline) that could enable command injection through the .cmd/.bat wrapper \u2014 refusing to run. Offending argument: " + JSON.stringify(a)
|
|
2528
|
+
);
|
|
2529
|
+
}
|
|
2530
|
+
}
|
|
2531
|
+
}
|
|
2360
2532
|
|
|
2361
2533
|
// src/bash.ts
|
|
2362
2534
|
var MAX_OUTPUT = 32768;
|
|
@@ -2453,18 +2625,36 @@ var bashTool = {
|
|
|
2453
2625
|
}
|
|
2454
2626
|
const timeoutMs = Math.max(1, Math.min(input.timeout_ms ?? DEFAULT_TIMEOUT_MS, 6e5));
|
|
2455
2627
|
const isWin3 = os2.platform() === "win32";
|
|
2456
|
-
|
|
2457
|
-
|
|
2458
|
-
|
|
2459
|
-
|
|
2460
|
-
|
|
2461
|
-
|
|
2462
|
-
|
|
2463
|
-
|
|
2464
|
-
|
|
2465
|
-
|
|
2466
|
-
|
|
2467
|
-
|
|
2628
|
+
let plan;
|
|
2629
|
+
let winShellKind;
|
|
2630
|
+
if (isWin3) {
|
|
2631
|
+
const shell2 = pickShell("win32", input.command, {
|
|
2632
|
+
get: (k) => process.env[k]
|
|
2633
|
+
});
|
|
2634
|
+
winShellKind = shell2;
|
|
2635
|
+
const bin = shell2 === "powershell" ? resolvePowerShell("powershell.exe") : shell2 === "pwsh" ? resolvePowerShell("pwsh.exe") : process.env["COMSPEC"] ?? "cmd.exe";
|
|
2636
|
+
plan = {
|
|
2637
|
+
bin,
|
|
2638
|
+
argv: shellArgs(shell2),
|
|
2639
|
+
useStdin: shell2 === "powershell" || shell2 === "pwsh",
|
|
2640
|
+
stdinBody: shell2 === "powershell" || shell2 === "pwsh" ? wrapPowerShellScript(input.command) : void 0
|
|
2641
|
+
};
|
|
2642
|
+
} else {
|
|
2643
|
+
const explicit = process.env["WRONGSTACK_SHELL"];
|
|
2644
|
+
let bin;
|
|
2645
|
+
if (explicit) bin = explicit;
|
|
2646
|
+
else {
|
|
2647
|
+
const fromEnv = process.env["SHELL"];
|
|
2648
|
+
if (fromEnv) {
|
|
2649
|
+
const name = fromEnv.split("/").pop() ?? "";
|
|
2650
|
+
if (["bash", "zsh", "sh", "dash", "fish"].includes(name)) bin = fromEnv;
|
|
2651
|
+
else bin = "/bin/bash";
|
|
2652
|
+
} else bin = "/bin/bash";
|
|
2653
|
+
}
|
|
2654
|
+
plan = { bin, argv: ["-c"], useStdin: false, stdinBody: void 0 };
|
|
2655
|
+
}
|
|
2656
|
+
const shell = plan.bin;
|
|
2657
|
+
const args = plan.useStdin ? [...plan.argv] : [...plan.argv, input.command];
|
|
2468
2658
|
const env = buildChildEnv(ctx.session?.id);
|
|
2469
2659
|
const detached = !isWin3;
|
|
2470
2660
|
const startedAt = Date.now();
|
|
@@ -2474,7 +2664,9 @@ var bashTool = {
|
|
|
2474
2664
|
const child2 = spawn(shell, args, {
|
|
2475
2665
|
cwd: ctx.projectRoot,
|
|
2476
2666
|
env,
|
|
2477
|
-
|
|
2667
|
+
// PowerShell takes the script on stdin (no argv quoting); cmd.exe
|
|
2668
|
+
// and POSIX shells ignore stdin when given the command inline.
|
|
2669
|
+
stdio: [plan.useStdin ? "pipe" : "ignore", "pipe", "pipe"],
|
|
2478
2670
|
// win32: CreateProcess IGNORES CREATE_NO_WINDOW (windowsHide) when
|
|
2479
2671
|
// DETACHED_PROCESS (detached: true) is set, so the console-less
|
|
2480
2672
|
// cmd.exe's grandchildren (node, dev servers) each allocate a fresh
|
|
@@ -2485,6 +2677,13 @@ var bashTool = {
|
|
|
2485
2677
|
detached: !isWin3,
|
|
2486
2678
|
windowsHide: true
|
|
2487
2679
|
});
|
|
2680
|
+
if (plan.useStdin) {
|
|
2681
|
+
try {
|
|
2682
|
+
child2.stdin?.write(plan.stdinBody ?? input.command);
|
|
2683
|
+
child2.stdin?.end();
|
|
2684
|
+
} catch {
|
|
2685
|
+
}
|
|
2686
|
+
}
|
|
2488
2687
|
const pid2 = child2.pid;
|
|
2489
2688
|
if (typeof pid2 === "number") {
|
|
2490
2689
|
registry.register({
|
|
@@ -2539,11 +2738,20 @@ var bashTool = {
|
|
|
2539
2738
|
const child = spawn(shell, args, {
|
|
2540
2739
|
cwd: ctx.projectRoot,
|
|
2541
2740
|
env,
|
|
2542
|
-
|
|
2741
|
+
// PowerShell takes the script on stdin (no argv quoting); cmd.exe
|
|
2742
|
+
// and POSIX shells ignore stdin when given the command inline.
|
|
2743
|
+
stdio: [plan.useStdin ? "pipe" : "ignore", "pipe", "pipe"],
|
|
2543
2744
|
detached,
|
|
2544
2745
|
windowsHide: true,
|
|
2545
2746
|
...isWin3 ? {} : { signal: opts.signal }
|
|
2546
2747
|
});
|
|
2748
|
+
if (plan.useStdin) {
|
|
2749
|
+
try {
|
|
2750
|
+
child.stdin?.write(plan.stdinBody ?? input.command);
|
|
2751
|
+
child.stdin?.end();
|
|
2752
|
+
} catch {
|
|
2753
|
+
}
|
|
2754
|
+
}
|
|
2547
2755
|
const pid = child.pid;
|
|
2548
2756
|
if (typeof pid === "number") {
|
|
2549
2757
|
registry.register({
|
|
@@ -2694,10 +2902,13 @@ var bashTool = {
|
|
|
2694
2902
|
yield { type: "partial_output", text: remainder };
|
|
2695
2903
|
}
|
|
2696
2904
|
const spooled = spool.finalize();
|
|
2905
|
+
const hint = !timedOut && typeof c.code === "number" && c.code !== 0 && winShellKind ? diagnoseBashism(input.command, winShellKind) : void 0;
|
|
2697
2906
|
yield {
|
|
2698
2907
|
type: "final",
|
|
2699
2908
|
output: {
|
|
2700
|
-
output: normalizeCommandOutput(buf) + (spooled ? spoolNote(spooled) : "")
|
|
2909
|
+
output: normalizeCommandOutput(buf) + (spooled ? spoolNote(spooled) : "") + (hint ? `
|
|
2910
|
+
|
|
2911
|
+
${hint}` : ""),
|
|
2701
2912
|
exit_code: c.code,
|
|
2702
2913
|
timed_out: timedOut
|
|
2703
2914
|
}
|
|
@@ -2725,82 +2936,115 @@ var bashTool = {
|
|
|
2725
2936
|
}
|
|
2726
2937
|
}
|
|
2727
2938
|
};
|
|
2728
|
-
function resolveWin32Command(cmd) {
|
|
2729
|
-
if (process.platform !== "win32") return cmd;
|
|
2730
|
-
if (cmd.includes("/") || cmd.includes("\\") || path.extname(cmd.replace(/\//g, "\\"))) {
|
|
2731
|
-
return cmd;
|
|
2732
|
-
}
|
|
2733
|
-
const pathext = (process.env["PATHEXT"] ?? ".COM;.EXE;.BAT;.CMD;.VBS;.JS;.WS;.MSC").toLowerCase().split(";");
|
|
2734
|
-
const pathDirs = (process.env["PATH"] ?? "").split(path.delimiter);
|
|
2735
|
-
for (const dir of pathDirs) {
|
|
2736
|
-
const base = path.join(dir, cmd);
|
|
2737
|
-
for (const ext of pathext) {
|
|
2738
|
-
const full = `${base}${ext}`;
|
|
2739
|
-
try {
|
|
2740
|
-
fs8.accessSync(full, fs8.constants.X_OK);
|
|
2741
|
-
return full;
|
|
2742
|
-
} catch {
|
|
2743
|
-
}
|
|
2744
|
-
}
|
|
2745
|
-
}
|
|
2746
|
-
return cmd;
|
|
2747
|
-
}
|
|
2748
|
-
var WIN32_SHELL_META = /[&|<>\r\n\0]/;
|
|
2749
|
-
function assertSafeWin32ShellArgs(args) {
|
|
2750
|
-
for (const a of args) {
|
|
2751
|
-
if (typeof a === "string" && WIN32_SHELL_META.test(a)) {
|
|
2752
|
-
throw new Error(
|
|
2753
|
-
"win32 shell spawn: argument contains a shell metacharacter (one of & | < > or a newline) that could enable command injection through the .cmd/.bat wrapper \u2014 refusing to run. Offending argument: " + JSON.stringify(a)
|
|
2754
|
-
);
|
|
2755
|
-
}
|
|
2756
|
-
}
|
|
2757
|
-
}
|
|
2758
2939
|
|
|
2759
|
-
// src/
|
|
2940
|
+
// src/_session-shell.ts
|
|
2941
|
+
function normalizeShell(value) {
|
|
2942
|
+
const v = value?.trim().toLowerCase();
|
|
2943
|
+
if (v === "cmd" || v === "cmd.exe") return "cmd";
|
|
2944
|
+
if (v === "powershell" || v === "powershell.exe") return "powershell";
|
|
2945
|
+
if (v === "pwsh" || v === "pwsh.exe") return "pwsh";
|
|
2946
|
+
return void 0;
|
|
2947
|
+
}
|
|
2948
|
+
function resolveSessionShell(platform4, env, deps = {}) {
|
|
2949
|
+
if (platform4 !== "win32") return void 0;
|
|
2950
|
+
const override = normalizeShell(env.get("WRONGSTACK_SHELL"));
|
|
2951
|
+
if (override) return override;
|
|
2952
|
+
const hasBinary = deps.hasBinary ?? ((bin) => resolveWin32Command(bin) !== bin);
|
|
2953
|
+
if (hasBinary("pwsh.exe")) return "pwsh";
|
|
2954
|
+
if (hasBinary("powershell.exe")) return "powershell";
|
|
2955
|
+
return "cmd";
|
|
2956
|
+
}
|
|
2957
|
+
function ensureSessionShell(opts = {}) {
|
|
2958
|
+
const env = opts.env ?? process.env;
|
|
2959
|
+
const platform4 = opts.platform ?? process.platform;
|
|
2960
|
+
if (platform4 !== "win32") return void 0;
|
|
2961
|
+
const existing = normalizeShell(env["WRONGSTACK_SHELL"]);
|
|
2962
|
+
if (existing) return existing;
|
|
2963
|
+
const chosen = resolveSessionShell(platform4, { get: (k) => env[k] }, { hasBinary: opts.hasBinary }) ?? "cmd";
|
|
2964
|
+
env["WRONGSTACK_SHELL"] = chosen;
|
|
2965
|
+
return chosen;
|
|
2966
|
+
}
|
|
2760
2967
|
var isWin = process.platform === "win32";
|
|
2761
|
-
var
|
|
2762
|
-
|
|
2763
|
-
|
|
2764
|
-
|
|
2765
|
-
|
|
2766
|
-
|
|
2767
|
-
|
|
2768
|
-
|
|
2769
|
-
|
|
2770
|
-
|
|
2771
|
-
|
|
2772
|
-
|
|
2773
|
-
|
|
2774
|
-
|
|
2775
|
-
|
|
2776
|
-
|
|
2777
|
-
|
|
2778
|
-
|
|
2779
|
-
|
|
2780
|
-
|
|
2781
|
-
|
|
2782
|
-
|
|
2783
|
-
|
|
2784
|
-
|
|
2785
|
-
|
|
2786
|
-
|
|
2787
|
-
|
|
2788
|
-
|
|
2789
|
-
|
|
2790
|
-
|
|
2791
|
-
|
|
2792
|
-
|
|
2793
|
-
|
|
2794
|
-
|
|
2795
|
-
|
|
2796
|
-
|
|
2797
|
-
|
|
2798
|
-
|
|
2799
|
-
|
|
2800
|
-
|
|
2801
|
-
|
|
2802
|
-
|
|
2803
|
-
|
|
2968
|
+
var DEFAULT_ALLOWED_COMMANDS = /* @__PURE__ */ new Set([
|
|
2969
|
+
// JS / TS toolchain
|
|
2970
|
+
"node",
|
|
2971
|
+
"npm",
|
|
2972
|
+
"pnpm",
|
|
2973
|
+
"yarn",
|
|
2974
|
+
"npx",
|
|
2975
|
+
"bun",
|
|
2976
|
+
"deno",
|
|
2977
|
+
"tsc",
|
|
2978
|
+
"vitest",
|
|
2979
|
+
"jest",
|
|
2980
|
+
"biome",
|
|
2981
|
+
"eslint",
|
|
2982
|
+
"prettier",
|
|
2983
|
+
// version control
|
|
2984
|
+
"git",
|
|
2985
|
+
// Rust
|
|
2986
|
+
"cargo",
|
|
2987
|
+
"rustc",
|
|
2988
|
+
// Go
|
|
2989
|
+
"go",
|
|
2990
|
+
// Python
|
|
2991
|
+
"python",
|
|
2992
|
+
"python3",
|
|
2993
|
+
"pip",
|
|
2994
|
+
"pip3",
|
|
2995
|
+
// Ruby
|
|
2996
|
+
"ruby",
|
|
2997
|
+
"gem",
|
|
2998
|
+
"bundle",
|
|
2999
|
+
// JVM
|
|
3000
|
+
"java",
|
|
3001
|
+
"javac",
|
|
3002
|
+
"mvn",
|
|
3003
|
+
"gradle",
|
|
3004
|
+
"gradlew",
|
|
3005
|
+
// .NET
|
|
3006
|
+
"dotnet",
|
|
3007
|
+
// C / C++ / native build
|
|
3008
|
+
"make",
|
|
3009
|
+
"cmake",
|
|
3010
|
+
// containers / orchestration (read-only subcommands; see BLOCKED_ARG_PATTERNS)
|
|
3011
|
+
"docker",
|
|
3012
|
+
"kubectl",
|
|
3013
|
+
// common POSIX file/text utilities
|
|
3014
|
+
"ls",
|
|
3015
|
+
"cat",
|
|
3016
|
+
"head",
|
|
3017
|
+
"tail",
|
|
3018
|
+
"wc",
|
|
3019
|
+
"grep",
|
|
3020
|
+
"find",
|
|
3021
|
+
"echo",
|
|
3022
|
+
"mkdir",
|
|
3023
|
+
"cp",
|
|
3024
|
+
"mv",
|
|
3025
|
+
"rm",
|
|
3026
|
+
"touch"
|
|
3027
|
+
]);
|
|
3028
|
+
var allowedCommands = new Set(DEFAULT_ALLOWED_COMMANDS);
|
|
3029
|
+
var normalizeCmd = (c) => c.trim();
|
|
3030
|
+
function configureExecPolicy(opts = {}) {
|
|
3031
|
+
const next = new Set(DEFAULT_ALLOWED_COMMANDS);
|
|
3032
|
+
for (const c of opts.allow ?? []) {
|
|
3033
|
+
const n = normalizeCmd(c);
|
|
3034
|
+
if (n) next.add(n);
|
|
3035
|
+
}
|
|
3036
|
+
for (const c of opts.deny ?? []) next.delete(normalizeCmd(c));
|
|
3037
|
+
allowedCommands = next;
|
|
3038
|
+
}
|
|
3039
|
+
function resetExecPolicy() {
|
|
3040
|
+
allowedCommands = new Set(DEFAULT_ALLOWED_COMMANDS);
|
|
3041
|
+
}
|
|
3042
|
+
function isExecCommandAllowed(cmd) {
|
|
3043
|
+
return allowedCommands.has(normalizeCmd(cmd));
|
|
3044
|
+
}
|
|
3045
|
+
function getExecAllowlist() {
|
|
3046
|
+
return [...allowedCommands].sort();
|
|
3047
|
+
}
|
|
2804
3048
|
var MAX_ARGS = 20;
|
|
2805
3049
|
var MAX_OUTPUT2 = 2e5;
|
|
2806
3050
|
var DEFAULT_TIMEOUT_MS2 = 3e4;
|
|
@@ -2862,7 +3106,7 @@ var execTool = {
|
|
|
2862
3106
|
name: "exec",
|
|
2863
3107
|
category: "Shell",
|
|
2864
3108
|
description: "Execute a **whitelisted, restricted set of commands** with strict argument validation. This is the **preferred and safer** alternative to the `bash` tool for running development tools (node, npm, pnpm, tsc, git, tests, linters, etc.). It prevents arbitrary command injection and limits what the model can do.",
|
|
2865
|
-
usageHint: "PREFERRED SHELL TOOL for most cases.\n\nUse this instead of `bash` whenever possible.\n- `command` must be
|
|
3109
|
+
usageHint: "PREFERRED SHELL TOOL for most cases.\n\nUse this instead of `bash` whenever possible.\n- `command` must be in the allowlist. Defaults cover JS (node/npm/pnpm/yarn/bun/deno/tsc/vitest/eslint/biome), Go (`go build`/`go test`), Rust (cargo), Python (python/pip), Ruby (gem/bundle), JVM (java/mvn/gradle), .NET (dotnet), native (make/cmake), and git. Users can extend it via `tools.exec.allow` in config.\n- Arguments are passed as a clean array (no shell interpretation).\n- `cwd` is validated to stay inside the project.\n- If a command is not allowlisted, the error explains how to add it; for one-off arbitrary commands, fall back to `bash` (with strong justification).\nThis tool significantly reduces the risk compared to full shell access.",
|
|
2866
3110
|
permission: "confirm",
|
|
2867
3111
|
mutating: true,
|
|
2868
3112
|
riskTier: "standard",
|
|
@@ -2916,12 +3160,12 @@ var execTool = {
|
|
|
2916
3160
|
truncated: false,
|
|
2917
3161
|
allowed: false
|
|
2918
3162
|
};
|
|
2919
|
-
if (!(cmd
|
|
3163
|
+
if (!isExecCommandAllowed(cmd)) {
|
|
2920
3164
|
return {
|
|
2921
3165
|
command: cmd,
|
|
2922
3166
|
args: input.args ?? [],
|
|
2923
3167
|
stdout: "",
|
|
2924
|
-
stderr: `Command "${cmd}" not in allowlist.
|
|
3168
|
+
stderr: `Command "${cmd}" not in allowlist. Add it to your ~/.wrongstack/config.json under "tools": { "exec": { "allow": ["${cmd}"] } }, or use the bash tool for one-off arbitrary commands.`,
|
|
2925
3169
|
exitCode: 1,
|
|
2926
3170
|
truncated: false,
|
|
2927
3171
|
allowed: false
|
|
@@ -2964,19 +3208,58 @@ function runCommand(cmd, args, cwd, timeout, signal, sessionId) {
|
|
|
2964
3208
|
let stdout = "";
|
|
2965
3209
|
let stderr = "";
|
|
2966
3210
|
let killed = false;
|
|
3211
|
+
const resolvedOnce = { value: false };
|
|
3212
|
+
const finish = (result) => {
|
|
3213
|
+
if (resolvedOnce.value) return;
|
|
3214
|
+
resolvedOnce.value = true;
|
|
3215
|
+
resolve6(result);
|
|
3216
|
+
};
|
|
2967
3217
|
const startedAt = Date.now();
|
|
2968
3218
|
const spool = createOutputSpool({ tool: `exec-${cmd}`, thresholdBytes: MAX_OUTPUT2 });
|
|
2969
3219
|
const resolved = resolveWin32Command(cmd);
|
|
2970
3220
|
const needsShell = isWin && (resolved.endsWith(".cmd") || resolved.endsWith(".bat"));
|
|
2971
3221
|
const spawnCmd = needsShell ? cmd : resolved;
|
|
2972
3222
|
if (needsShell) assertSafeWin32ShellArgs(args);
|
|
2973
|
-
|
|
2974
|
-
|
|
2975
|
-
|
|
2976
|
-
|
|
2977
|
-
|
|
2978
|
-
|
|
2979
|
-
|
|
3223
|
+
let child;
|
|
3224
|
+
try {
|
|
3225
|
+
child = spawn(spawnCmd, args, {
|
|
3226
|
+
cwd,
|
|
3227
|
+
env: buildChildEnv(sessionId),
|
|
3228
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
3229
|
+
windowsHide: true,
|
|
3230
|
+
...isWin ? {} : { signal },
|
|
3231
|
+
...needsShell ? { shell: true, windowsVerbatimArguments: true } : {}
|
|
3232
|
+
});
|
|
3233
|
+
} catch (err) {
|
|
3234
|
+
spool.finalize();
|
|
3235
|
+
finish({
|
|
3236
|
+
command: cmd,
|
|
3237
|
+
args,
|
|
3238
|
+
stdout: "",
|
|
3239
|
+
stderr: `spawn failed: ${toErrorMessage$1(err)}`,
|
|
3240
|
+
exitCode: 1,
|
|
3241
|
+
truncated: false,
|
|
3242
|
+
allowed: true
|
|
3243
|
+
});
|
|
3244
|
+
return;
|
|
3245
|
+
}
|
|
3246
|
+
child.on("error", (err) => {
|
|
3247
|
+
const isAbort = err && err.code === "ABORT_ERR";
|
|
3248
|
+
const stderrText = isAbort ? `Aborted: ${err.message}` : err.message;
|
|
3249
|
+
clearTimeout(timer);
|
|
3250
|
+
if (isWin) signal.removeEventListener("abort", onAbort);
|
|
3251
|
+
if (typeof pid === "number") registry.unregister(pid);
|
|
3252
|
+
registry.afterCall(Date.now() - startedAt, true);
|
|
3253
|
+
spool.finalize();
|
|
3254
|
+
finish({
|
|
3255
|
+
command: cmd,
|
|
3256
|
+
args,
|
|
3257
|
+
stdout: normalizeCommandOutput(stdout),
|
|
3258
|
+
stderr: stderrText,
|
|
3259
|
+
exitCode: isAbort ? 124 : 1,
|
|
3260
|
+
truncated: Buffer.byteLength(stdout, "utf8") > COMMAND_OUTPUT_MAX_BYTES,
|
|
3261
|
+
allowed: true
|
|
3262
|
+
});
|
|
2980
3263
|
});
|
|
2981
3264
|
const registry = getProcessRegistry();
|
|
2982
3265
|
const pid = child.pid;
|
|
@@ -3016,7 +3299,7 @@ function runCommand(cmd, args, cwd, timeout, signal, sessionId) {
|
|
|
3016
3299
|
const exitCode = killed ? 124 : code ?? 1;
|
|
3017
3300
|
registry.afterCall(durationMs, exitCode !== 0);
|
|
3018
3301
|
const spooled = spool.finalize();
|
|
3019
|
-
|
|
3302
|
+
finish({
|
|
3020
3303
|
command: cmd,
|
|
3021
3304
|
args,
|
|
3022
3305
|
stdout: normalizeCommandOutput(stdout) + (spooled ? spoolNote(spooled) : ""),
|
|
@@ -3026,22 +3309,6 @@ function runCommand(cmd, args, cwd, timeout, signal, sessionId) {
|
|
|
3026
3309
|
allowed: true
|
|
3027
3310
|
});
|
|
3028
3311
|
});
|
|
3029
|
-
child.on("error", (err) => {
|
|
3030
|
-
clearTimeout(timer);
|
|
3031
|
-
if (isWin) signal.removeEventListener("abort", onAbort);
|
|
3032
|
-
if (typeof pid === "number") registry.unregister(pid);
|
|
3033
|
-
registry.afterCall(Date.now() - startedAt, true);
|
|
3034
|
-
spool.finalize();
|
|
3035
|
-
resolve6({
|
|
3036
|
-
command: cmd,
|
|
3037
|
-
args,
|
|
3038
|
-
stdout: normalizeCommandOutput(stdout),
|
|
3039
|
-
stderr: err.message,
|
|
3040
|
-
exitCode: 1,
|
|
3041
|
-
truncated: Buffer.byteLength(stdout, "utf8") > COMMAND_OUTPUT_MAX_BYTES,
|
|
3042
|
-
allowed: true
|
|
3043
|
-
});
|
|
3044
|
-
});
|
|
3045
3312
|
});
|
|
3046
3313
|
}
|
|
3047
3314
|
var TD = new TurndownService({
|
|
@@ -3406,7 +3673,7 @@ async function duckduckgoSearch(query2, num, signal) {
|
|
|
3406
3673
|
truncated: results.length >= num
|
|
3407
3674
|
};
|
|
3408
3675
|
} catch (err) {
|
|
3409
|
-
console.log(JSON.stringify({ level: "debug", event: "search_failed", query: query2, error: toErrorMessage$
|
|
3676
|
+
console.log(JSON.stringify({ level: "debug", event: "search_failed", query: query2, error: toErrorMessage$2(err) }));
|
|
3410
3677
|
return {
|
|
3411
3678
|
query: query2,
|
|
3412
3679
|
results: [{ title: "Search unavailable", url: "", snippet: "Could not reach DuckDuckGo" }],
|
|
@@ -7645,7 +7912,7 @@ function loadDatabaseSync() {
|
|
|
7645
7912
|
DatabaseSyncCtor = req("node:sqlite").DatabaseSync;
|
|
7646
7913
|
} catch (err) {
|
|
7647
7914
|
throw new Error(
|
|
7648
|
-
`The codebase index needs Node's built-in SQLite (node:sqlite), available since Node 22.5. This runtime doesn't provide it: ${toErrorMessage$
|
|
7915
|
+
`The codebase index needs Node's built-in SQLite (node:sqlite), available since Node 22.5. This runtime doesn't provide it: ${toErrorMessage$2(err)}`
|
|
7649
7916
|
);
|
|
7650
7917
|
}
|
|
7651
7918
|
return DatabaseSyncCtor;
|
|
@@ -8982,11 +9249,15 @@ async function tryNativeParse(file, content) {
|
|
|
8982
9249
|
const crateDir = path.join(toolsDir, "syn-parser");
|
|
8983
9250
|
const tmpFile = path.join(crateDir, "src", "input.rs");
|
|
8984
9251
|
await fs7.writeFile(tmpFile, content, "utf8");
|
|
8985
|
-
const proc = spawn(
|
|
8986
|
-
|
|
8987
|
-
|
|
8988
|
-
|
|
8989
|
-
|
|
9252
|
+
const proc = spawn(
|
|
9253
|
+
"cargo",
|
|
9254
|
+
["run", "--manifest-path", path.join(toolsDir, "Cargo.toml")],
|
|
9255
|
+
{
|
|
9256
|
+
cwd: process.cwd(),
|
|
9257
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
9258
|
+
windowsHide: true
|
|
9259
|
+
}
|
|
9260
|
+
);
|
|
8990
9261
|
let stdout = "";
|
|
8991
9262
|
proc.stdout?.on("data", (chunk) => {
|
|
8992
9263
|
stdout += chunk.toString();
|
|
@@ -10332,7 +10603,7 @@ var setWorkingDirTool = {
|
|
|
10332
10603
|
} catch (err) {
|
|
10333
10604
|
return {
|
|
10334
10605
|
current: ctx.workingDir,
|
|
10335
|
-
error: toErrorMessage$
|
|
10606
|
+
error: toErrorMessage$2(err)
|
|
10336
10607
|
};
|
|
10337
10608
|
}
|
|
10338
10609
|
try {
|
|
@@ -10482,7 +10753,11 @@ var taskTool = {
|
|
|
10482
10753
|
const newIds = new Set(input.tasks.map((t) => t.id));
|
|
10483
10754
|
if (newIds.size !== input.tasks.length) {
|
|
10484
10755
|
const seen = /* @__PURE__ */ new Set();
|
|
10485
|
-
const dupes = [...new Set(input.tasks.map((t) => t.id).filter((id) =>
|
|
10756
|
+
const dupes = [...new Set(input.tasks.map((t) => t.id).filter((id) => {
|
|
10757
|
+
if (seen.has(id)) return true;
|
|
10758
|
+
seen.add(id);
|
|
10759
|
+
return false;
|
|
10760
|
+
}))];
|
|
10486
10761
|
early = {
|
|
10487
10762
|
ok: false,
|
|
10488
10763
|
message: `action=replace has duplicate task IDs: ${dupes.join(", ")}. Each task id must be unique.`,
|
|
@@ -10517,7 +10792,7 @@ var taskTool = {
|
|
|
10517
10792
|
}
|
|
10518
10793
|
case "add": {
|
|
10519
10794
|
const t = input.task;
|
|
10520
|
-
if (!t
|
|
10795
|
+
if (!t?.title) {
|
|
10521
10796
|
early = { ok: false, message: "action=add requires `task` with at least `title`.", count: 0, completed: 0, inProgress: 0 };
|
|
10522
10797
|
return f;
|
|
10523
10798
|
}
|
|
@@ -10974,6 +11249,6 @@ var TOOL_ICON_CONFIG = {
|
|
|
10974
11249
|
};
|
|
10975
11250
|
var FALLBACK_ICON = "fallback";
|
|
10976
11251
|
|
|
10977
|
-
export { CircuitBreaker, CircuitOpenError, FALLBACK_ICON, IndexCircuitBreaker, IndexTimeoutError, OPTIONAL_TOOLS, TIER1_TOOLS, TIER2_TOOLS, TIER3_TOOLS, TOOL_ICON_CONFIG, TOOL_ICON_MAP, _resetProcessRegistry, auditTool, bashTool, batchToolUseTool, builtinTools, builtinToolsPack, cancelPendingReindexes, codebaseIndexStats, codebaseIndexTool, codebaseSearchTool, codebaseStatsTool, createGlobalPsSlashCommand, createModeTool, diffTool, documentTool, editTool, enqueueReindex, execTool, fetchTool, forgetTool, formatGlobalStatus, formatInstanceList, formatInstanceSummary, formatTool, getIndexState, getInstanceCount, getPersistentProcessRegistry, getProcessGuardian, getProcessRegistry, getToolIcon, gitTool, globTool, grepTool, indexCircuitBreaker, installTool, isIndexReady, isIndexableFile, isIndexing, jsonTool, lintTool, listInstances, logsTool, onIndexStateChange, outdatedTool, patchTool, planTool, readTool, relatedMemoryTool, rememberTool, replaceTool, resetIndexCircuitBreaker, resetPersistentProcessRegistry, runStartupIndex, scaffoldTool, searchCodebaseIndex, searchMemoryTool, searchTool, shutdownCodebaseIndexHost, startProcessGuardian, stopProcessGuardian, testTool, todoTool, toolHelpTool, toolSearchTool, toolUseTool, treeTool, typecheckTool, writeTool };
|
|
11252
|
+
export { CircuitBreaker, CircuitOpenError, FALLBACK_ICON, IndexCircuitBreaker, IndexTimeoutError, OPTIONAL_TOOLS, TIER1_TOOLS, TIER2_TOOLS, TIER3_TOOLS, TOOL_ICON_CONFIG, TOOL_ICON_MAP, _resetProcessRegistry, auditTool, bashTool, batchToolUseTool, builtinTools, builtinToolsPack, cancelPendingReindexes, codebaseIndexStats, codebaseIndexTool, codebaseSearchTool, codebaseStatsTool, configureExecPolicy, createGlobalPsSlashCommand, createModeTool, diffTool, documentTool, editTool, enqueueReindex, ensureSessionShell, execTool, fetchTool, forgetTool, formatGlobalStatus, formatInstanceList, formatInstanceSummary, formatTool, getExecAllowlist, getIndexState, getInstanceCount, getPersistentProcessRegistry, getProcessGuardian, getProcessRegistry, getToolIcon, gitTool, globTool, grepTool, indexCircuitBreaker, installTool, isExecCommandAllowed, isIndexReady, isIndexableFile, isIndexing, jsonTool, lintTool, listInstances, logsTool, normalizeShell, onIndexStateChange, outdatedTool, patchTool, planTool, readTool, relatedMemoryTool, rememberTool, replaceTool, resetExecPolicy, resetIndexCircuitBreaker, resetPersistentProcessRegistry, resolveSessionShell, runStartupIndex, scaffoldTool, searchCodebaseIndex, searchMemoryTool, searchTool, shutdownCodebaseIndexHost, startProcessGuardian, stopProcessGuardian, testTool, todoTool, toolHelpTool, toolSearchTool, toolUseTool, treeTool, typecheckTool, writeTool };
|
|
10978
11253
|
//# sourceMappingURL=index.js.map
|
|
10979
11254
|
//# sourceMappingURL=index.js.map
|