@wrongstack/tools 0.276.4 → 0.277.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 +21 -8
- package/dist/audit.js.map +1 -1
- package/dist/bash.js.map +1 -1
- package/dist/builtin.js +661 -57
- package/dist/builtin.js.map +1 -1
- package/dist/exec.js +534 -9
- package/dist/exec.js.map +1 -1
- package/dist/fetch.js +7 -3
- package/dist/fetch.js.map +1 -1
- package/dist/format.js +22 -9
- package/dist/format.js.map +1 -1
- package/dist/index.js +662 -58
- package/dist/index.js.map +1 -1
- package/dist/install.js +21 -8
- package/dist/install.js.map +1 -1
- package/dist/lint.js +21 -8
- package/dist/lint.js.map +1 -1
- package/dist/memory.js +1 -1
- package/dist/memory.js.map +1 -1
- package/dist/outdated.js +20 -7
- package/dist/outdated.js.map +1 -1
- package/dist/pack.js +661 -57
- package/dist/pack.js.map +1 -1
- package/dist/search.js +113 -36
- package/dist/search.js.map +1 -1
- package/dist/test.js +21 -8
- package/dist/test.js.map +1 -1
- package/dist/typecheck.js +21 -8
- package/dist/typecheck.js.map +1 -1
- package/package.json +9 -5
package/dist/index.js
CHANGED
|
@@ -10,7 +10,7 @@ import { statSync, mkdirSync, createWriteStream } from 'node:fs';
|
|
|
10
10
|
import { toErrorMessage as toErrorMessage$1 } from '@wrongstack/core/utils/error';
|
|
11
11
|
import * as dns from 'node:dns/promises';
|
|
12
12
|
import * as net from 'node:net';
|
|
13
|
-
import { Agent } from 'undici';
|
|
13
|
+
import { Agent, fetch } from 'undici';
|
|
14
14
|
import TurndownService from 'turndown';
|
|
15
15
|
import { toErrorMessage as toErrorMessage$2 } from '@wrongstack/core/utils';
|
|
16
16
|
import { randomUUID } from 'node:crypto';
|
|
@@ -2762,16 +2762,28 @@ function resolvePowerShell(cmd) {
|
|
|
2762
2762
|
}
|
|
2763
2763
|
return resolved;
|
|
2764
2764
|
}
|
|
2765
|
-
var WIN32_SHELL_META = /[
|
|
2765
|
+
var WIN32_SHELL_META = /[&|<>"\r\n\0]/;
|
|
2766
2766
|
function assertSafeWin32ShellArgs(args) {
|
|
2767
|
-
for (const
|
|
2768
|
-
if (typeof
|
|
2767
|
+
for (const arg of args) {
|
|
2768
|
+
if (typeof arg === "string" && WIN32_SHELL_META.test(arg)) {
|
|
2769
2769
|
throw new Error(
|
|
2770
|
-
|
|
2770
|
+
'win32 cmd shim spawn: argument contains a shell metacharacter (one of & | < > ", or a newline) that could enable command injection through the .cmd/.bat wrapper - refusing to run. Offending argument: ' + JSON.stringify(arg)
|
|
2771
2771
|
);
|
|
2772
2772
|
}
|
|
2773
2773
|
}
|
|
2774
2774
|
}
|
|
2775
|
+
function buildWin32CmdShimInvocation(command, args = []) {
|
|
2776
|
+
assertSafeWin32ShellArgs([command, ...args]);
|
|
2777
|
+
const line = ["call", quoteWin32CmdArg(command), ...args.map(quoteWin32CmdArg)].join(" ");
|
|
2778
|
+
return {
|
|
2779
|
+
command: process.env["COMSPEC"] ?? "cmd.exe",
|
|
2780
|
+
args: ["/d", "/c", line],
|
|
2781
|
+
windowsVerbatimArguments: true
|
|
2782
|
+
};
|
|
2783
|
+
}
|
|
2784
|
+
function quoteWin32CmdArg(arg) {
|
|
2785
|
+
return `"${arg}"`;
|
|
2786
|
+
}
|
|
2775
2787
|
|
|
2776
2788
|
// src/bash.ts
|
|
2777
2789
|
var MAX_OUTPUT = 32768;
|
|
@@ -3313,10 +3325,20 @@ var DEFAULT_ALLOWED_COMMANDS = /* @__PURE__ */ new Set([
|
|
|
3313
3325
|
// C / C++ / native build
|
|
3314
3326
|
"make",
|
|
3315
3327
|
"cmake",
|
|
3328
|
+
"ninja",
|
|
3329
|
+
"clang",
|
|
3330
|
+
"clang-cl",
|
|
3331
|
+
"gcc",
|
|
3332
|
+
"g++",
|
|
3333
|
+
"link",
|
|
3334
|
+
"msbuild",
|
|
3316
3335
|
// containers / orchestration
|
|
3317
3336
|
"docker",
|
|
3318
3337
|
"podman",
|
|
3319
3338
|
"kubectl",
|
|
3339
|
+
// network (read-only intent; destructive ops still blocked by BLOCKED_ARG_PATTERNS)
|
|
3340
|
+
"curl",
|
|
3341
|
+
"wget",
|
|
3320
3342
|
// common POSIX file/text utilities
|
|
3321
3343
|
"pwd",
|
|
3322
3344
|
"ls",
|
|
@@ -3336,7 +3358,509 @@ var DEFAULT_ALLOWED_COMMANDS = /* @__PURE__ */ new Set([
|
|
|
3336
3358
|
"cp",
|
|
3337
3359
|
"mv",
|
|
3338
3360
|
"rm",
|
|
3339
|
-
"touch"
|
|
3361
|
+
"touch",
|
|
3362
|
+
"tar",
|
|
3363
|
+
// Windows-native tooling (win32). All non-destructive binaries; per-arg
|
|
3364
|
+
// safety is still enforced by BLOCKED_ARG_PATTERNS + the destructive-ops
|
|
3365
|
+
// gate in bash-kill-guard.ts. `gh` is included even though it lives at
|
|
3366
|
+
// "C:\Program Files\GitHub CLI\gh.exe" — resolveWin32Command handles the
|
|
3367
|
+
// space in the path.
|
|
3368
|
+
"gh",
|
|
3369
|
+
"where",
|
|
3370
|
+
"tasklist",
|
|
3371
|
+
"systeminfo",
|
|
3372
|
+
"wmic",
|
|
3373
|
+
"sc",
|
|
3374
|
+
"netstat",
|
|
3375
|
+
"ipconfig",
|
|
3376
|
+
"nslookup",
|
|
3377
|
+
"tracert",
|
|
3378
|
+
"pathping",
|
|
3379
|
+
// Windows shell interpreters. Without these, `exec` cannot run cmd builtins
|
|
3380
|
+
// (`dir`, `type`, `copy`, …) or any PowerShell cmdlet on Windows — a major
|
|
3381
|
+
// gap since those are the platform's primary shells. Arbitrary execution
|
|
3382
|
+
// through `cmd /c …` / `powershell -c …` is NOT a new hole: the permission
|
|
3383
|
+
// policy reconstructs the full command line (shellCommandLineFromInput) and
|
|
3384
|
+
// still runs it through the YOLO destructive classifier, so a genuinely
|
|
3385
|
+
// destructive `cmd /c del /s /q C:\…` continues to require confirmation.
|
|
3386
|
+
"cmd",
|
|
3387
|
+
"cmd.exe",
|
|
3388
|
+
"powershell",
|
|
3389
|
+
"powershell.exe",
|
|
3390
|
+
"pwsh",
|
|
3391
|
+
"pwsh.exe",
|
|
3392
|
+
// [core] Extended default allowlist (added 4b3d18d1 + this commit). All
|
|
3393
|
+
// non-destructive, broadly-used dev binaries. Per-arg safety is still
|
|
3394
|
+
// enforced by BLOCKED_ARG_PATTERNS + bash-kill-guard.ts.
|
|
3395
|
+
// --- Archives & compression ---
|
|
3396
|
+
"7z",
|
|
3397
|
+
"7za",
|
|
3398
|
+
"bzip2",
|
|
3399
|
+
"gzip",
|
|
3400
|
+
"xz",
|
|
3401
|
+
"unzip",
|
|
3402
|
+
"zip",
|
|
3403
|
+
"gtar",
|
|
3404
|
+
"bsdtar",
|
|
3405
|
+
"star",
|
|
3406
|
+
"pax",
|
|
3407
|
+
"cpio",
|
|
3408
|
+
// --- Android / mobile dev ---
|
|
3409
|
+
"adb",
|
|
3410
|
+
"fastboot",
|
|
3411
|
+
"sdkmanager",
|
|
3412
|
+
// --- DevOps / config mgmt ---
|
|
3413
|
+
"ansible",
|
|
3414
|
+
"ansible-playbook",
|
|
3415
|
+
"ansible-vault",
|
|
3416
|
+
"ansible-lint",
|
|
3417
|
+
"ansible-galaxy",
|
|
3418
|
+
"molecule",
|
|
3419
|
+
// --- Cloud CLIs ---
|
|
3420
|
+
"aws",
|
|
3421
|
+
"aws-vault",
|
|
3422
|
+
"awslocal",
|
|
3423
|
+
"az",
|
|
3424
|
+
"azcopy",
|
|
3425
|
+
"gcloud",
|
|
3426
|
+
"gsutil",
|
|
3427
|
+
"doctl",
|
|
3428
|
+
"linode-cli",
|
|
3429
|
+
// --- Native / C / C++ / linker tools ---
|
|
3430
|
+
"clang++",
|
|
3431
|
+
"clang-format",
|
|
3432
|
+
"clang-tidy",
|
|
3433
|
+
"clangd",
|
|
3434
|
+
"lld",
|
|
3435
|
+
"lldb",
|
|
3436
|
+
"ctest",
|
|
3437
|
+
"gmake",
|
|
3438
|
+
"meson",
|
|
3439
|
+
"conan",
|
|
3440
|
+
"vcpkg",
|
|
3441
|
+
"cl",
|
|
3442
|
+
"rc",
|
|
3443
|
+
"mt",
|
|
3444
|
+
"dumpbin",
|
|
3445
|
+
"dotnet-format",
|
|
3446
|
+
// --- Image / media / binary tools ---
|
|
3447
|
+
"convert",
|
|
3448
|
+
"ffmpeg",
|
|
3449
|
+
"ffprobe",
|
|
3450
|
+
"magick",
|
|
3451
|
+
"gs",
|
|
3452
|
+
"exiftool",
|
|
3453
|
+
// --- HTTP / fetch ---
|
|
3454
|
+
"wget2",
|
|
3455
|
+
"aria2c",
|
|
3456
|
+
"axel",
|
|
3457
|
+
"httpie",
|
|
3458
|
+
"hey",
|
|
3459
|
+
"ab",
|
|
3460
|
+
"wrk",
|
|
3461
|
+
"http",
|
|
3462
|
+
// --- Diff / patch / merge ---
|
|
3463
|
+
"diff",
|
|
3464
|
+
"diff3",
|
|
3465
|
+
"patch",
|
|
3466
|
+
"meld",
|
|
3467
|
+
"kdiff3",
|
|
3468
|
+
"kompare",
|
|
3469
|
+
// --- Encoding / file inspection ---
|
|
3470
|
+
"dos2unix",
|
|
3471
|
+
"unix2dos",
|
|
3472
|
+
"iconv",
|
|
3473
|
+
"file",
|
|
3474
|
+
"stat",
|
|
3475
|
+
"xxd",
|
|
3476
|
+
"hexdump",
|
|
3477
|
+
"od",
|
|
3478
|
+
"base64",
|
|
3479
|
+
// --- SSH / crypto / signing ---
|
|
3480
|
+
"ssh",
|
|
3481
|
+
"ssh-add",
|
|
3482
|
+
"ssh-keygen",
|
|
3483
|
+
"ssh-keyscan",
|
|
3484
|
+
"scp",
|
|
3485
|
+
"sftp",
|
|
3486
|
+
"rsync",
|
|
3487
|
+
"gpg",
|
|
3488
|
+
"gpg2",
|
|
3489
|
+
"gpg-agent",
|
|
3490
|
+
"openssl",
|
|
3491
|
+
"step",
|
|
3492
|
+
"keytool",
|
|
3493
|
+
// --- Search ---
|
|
3494
|
+
"egrep",
|
|
3495
|
+
"fgrep",
|
|
3496
|
+
"ag",
|
|
3497
|
+
"ack",
|
|
3498
|
+
"sift",
|
|
3499
|
+
"ugrep",
|
|
3500
|
+
"fd",
|
|
3501
|
+
"fdfind",
|
|
3502
|
+
"jq",
|
|
3503
|
+
"yq",
|
|
3504
|
+
"xq",
|
|
3505
|
+
"fx",
|
|
3506
|
+
"gron",
|
|
3507
|
+
// --- K8s / container ecosystem ---
|
|
3508
|
+
"kubectl.exe",
|
|
3509
|
+
"kubeadm",
|
|
3510
|
+
"kubelet",
|
|
3511
|
+
"helm",
|
|
3512
|
+
"k9s",
|
|
3513
|
+
"kustomize",
|
|
3514
|
+
"skaffold",
|
|
3515
|
+
"tilt",
|
|
3516
|
+
"minikube",
|
|
3517
|
+
"kind",
|
|
3518
|
+
"k3d",
|
|
3519
|
+
"k3s",
|
|
3520
|
+
"docker-compose",
|
|
3521
|
+
"buildah",
|
|
3522
|
+
"skopeo",
|
|
3523
|
+
"nerdctl",
|
|
3524
|
+
"ctr",
|
|
3525
|
+
"ctr.exe",
|
|
3526
|
+
// --- Databases ---
|
|
3527
|
+
"sqlite3",
|
|
3528
|
+
"sqlite",
|
|
3529
|
+
"psql",
|
|
3530
|
+
"pg_dump",
|
|
3531
|
+
"pg_restore",
|
|
3532
|
+
"mysql",
|
|
3533
|
+
"mysqladmin",
|
|
3534
|
+
"mysqldump",
|
|
3535
|
+
"mariadb",
|
|
3536
|
+
"mariadb-dump",
|
|
3537
|
+
"redis-cli",
|
|
3538
|
+
"redis-server",
|
|
3539
|
+
"memcached",
|
|
3540
|
+
"etcdctl",
|
|
3541
|
+
"consul",
|
|
3542
|
+
"vault",
|
|
3543
|
+
"nomad",
|
|
3544
|
+
"mongosh",
|
|
3545
|
+
"mongo",
|
|
3546
|
+
"mongoexport",
|
|
3547
|
+
"mongoimport",
|
|
3548
|
+
"mongodump",
|
|
3549
|
+
"mongorestore",
|
|
3550
|
+
// --- Windows extended (read-mostly ops) ---
|
|
3551
|
+
"taskkill",
|
|
3552
|
+
"gpupdate",
|
|
3553
|
+
"gpresult",
|
|
3554
|
+
"hostname",
|
|
3555
|
+
"whoami",
|
|
3556
|
+
"who",
|
|
3557
|
+
"net",
|
|
3558
|
+
"net1",
|
|
3559
|
+
// --- VCS ecosystem ---
|
|
3560
|
+
"glab",
|
|
3561
|
+
"hub",
|
|
3562
|
+
"tea",
|
|
3563
|
+
"git-lfs",
|
|
3564
|
+
"tig",
|
|
3565
|
+
"lazygit",
|
|
3566
|
+
// --- POSIX text utilities (extended; duplicates of pwd/ls/cat/head/tail/wc/
|
|
3567
|
+
// grep/find/echo/awk/mkdir/cp/mv/rm/touch from the base list above are
|
|
3568
|
+
// omitted — the Set is de-duplicated at runtime but a clean literal is
|
|
3569
|
+
// easier to maintain) ---
|
|
3570
|
+
"gawk",
|
|
3571
|
+
"tr",
|
|
3572
|
+
"cut",
|
|
3573
|
+
"paste",
|
|
3574
|
+
"join",
|
|
3575
|
+
"comm",
|
|
3576
|
+
"expand",
|
|
3577
|
+
"unexpand",
|
|
3578
|
+
"fold",
|
|
3579
|
+
"fmt",
|
|
3580
|
+
"nl",
|
|
3581
|
+
"pr",
|
|
3582
|
+
"column",
|
|
3583
|
+
"tsort",
|
|
3584
|
+
"tty",
|
|
3585
|
+
"ul",
|
|
3586
|
+
"units",
|
|
3587
|
+
"factor",
|
|
3588
|
+
"seq",
|
|
3589
|
+
"shuf",
|
|
3590
|
+
"look",
|
|
3591
|
+
"yes",
|
|
3592
|
+
"true",
|
|
3593
|
+
"false",
|
|
3594
|
+
"test",
|
|
3595
|
+
"[",
|
|
3596
|
+
"printf",
|
|
3597
|
+
"env",
|
|
3598
|
+
"tree",
|
|
3599
|
+
"locate",
|
|
3600
|
+
"which",
|
|
3601
|
+
"whereis",
|
|
3602
|
+
"type",
|
|
3603
|
+
"hash",
|
|
3604
|
+
"pushd",
|
|
3605
|
+
"popd",
|
|
3606
|
+
"dirs",
|
|
3607
|
+
"history",
|
|
3608
|
+
"fc",
|
|
3609
|
+
"jobs",
|
|
3610
|
+
"bg",
|
|
3611
|
+
"fg",
|
|
3612
|
+
"wait",
|
|
3613
|
+
"ulimit",
|
|
3614
|
+
"umask",
|
|
3615
|
+
"nice",
|
|
3616
|
+
"nohup",
|
|
3617
|
+
"timeout",
|
|
3618
|
+
"time",
|
|
3619
|
+
"trap",
|
|
3620
|
+
"exit",
|
|
3621
|
+
"return",
|
|
3622
|
+
"source",
|
|
3623
|
+
".",
|
|
3624
|
+
"alias",
|
|
3625
|
+
"unalias",
|
|
3626
|
+
"set",
|
|
3627
|
+
"unset",
|
|
3628
|
+
"export",
|
|
3629
|
+
"readonly",
|
|
3630
|
+
"typeset",
|
|
3631
|
+
"declare",
|
|
3632
|
+
"local",
|
|
3633
|
+
"eval",
|
|
3634
|
+
"exec",
|
|
3635
|
+
// --- Process / system inspection ---
|
|
3636
|
+
"htop",
|
|
3637
|
+
"top",
|
|
3638
|
+
"atop",
|
|
3639
|
+
"glances",
|
|
3640
|
+
"iotop",
|
|
3641
|
+
"nethogs",
|
|
3642
|
+
"iftop",
|
|
3643
|
+
"lsof",
|
|
3644
|
+
"strace",
|
|
3645
|
+
"ltrace",
|
|
3646
|
+
"sysstat",
|
|
3647
|
+
"vmstat",
|
|
3648
|
+
"iostat",
|
|
3649
|
+
"mpstat",
|
|
3650
|
+
"sar",
|
|
3651
|
+
"free",
|
|
3652
|
+
"df",
|
|
3653
|
+
"du",
|
|
3654
|
+
"mount",
|
|
3655
|
+
"umount",
|
|
3656
|
+
"lsblk",
|
|
3657
|
+
"blkid",
|
|
3658
|
+
"kill",
|
|
3659
|
+
"killall",
|
|
3660
|
+
"pkill",
|
|
3661
|
+
"pgrep",
|
|
3662
|
+
"pidof",
|
|
3663
|
+
"ps",
|
|
3664
|
+
"ps.exe",
|
|
3665
|
+
// --- Network inspection ---
|
|
3666
|
+
"ip",
|
|
3667
|
+
"ss",
|
|
3668
|
+
"route",
|
|
3669
|
+
"arp",
|
|
3670
|
+
"arping",
|
|
3671
|
+
"ping",
|
|
3672
|
+
"ping6",
|
|
3673
|
+
"hping3",
|
|
3674
|
+
"mtr",
|
|
3675
|
+
"tracepath",
|
|
3676
|
+
"tcpdump",
|
|
3677
|
+
"nmap",
|
|
3678
|
+
"netcat",
|
|
3679
|
+
"nc",
|
|
3680
|
+
"ncat",
|
|
3681
|
+
"socat",
|
|
3682
|
+
// --- Sync / backup ---
|
|
3683
|
+
"rclone",
|
|
3684
|
+
"restic",
|
|
3685
|
+
"borg",
|
|
3686
|
+
"duplicati",
|
|
3687
|
+
"duplicacy",
|
|
3688
|
+
"syncthing",
|
|
3689
|
+
"syncthing-cli",
|
|
3690
|
+
// --- Permissions / users / ACLs (POSIX) ---
|
|
3691
|
+
"useradd",
|
|
3692
|
+
"userdel",
|
|
3693
|
+
"usermod",
|
|
3694
|
+
"groupadd",
|
|
3695
|
+
"groupdel",
|
|
3696
|
+
"groupmod",
|
|
3697
|
+
"chown",
|
|
3698
|
+
"chmod",
|
|
3699
|
+
"chgrp",
|
|
3700
|
+
"getfacl",
|
|
3701
|
+
"setfacl",
|
|
3702
|
+
"setcap",
|
|
3703
|
+
"getcap",
|
|
3704
|
+
// --- Crypto / cert mgmt (extended) ---
|
|
3705
|
+
"certbot",
|
|
3706
|
+
"mkcert",
|
|
3707
|
+
"jarsigner",
|
|
3708
|
+
// --- Editors ---
|
|
3709
|
+
"subl",
|
|
3710
|
+
"code",
|
|
3711
|
+
"code-insiders",
|
|
3712
|
+
"cursor",
|
|
3713
|
+
"atom",
|
|
3714
|
+
"nano",
|
|
3715
|
+
"vim",
|
|
3716
|
+
"nvim",
|
|
3717
|
+
"vi",
|
|
3718
|
+
"emacs",
|
|
3719
|
+
"helix",
|
|
3720
|
+
"hx",
|
|
3721
|
+
"micro",
|
|
3722
|
+
"jed",
|
|
3723
|
+
"ed",
|
|
3724
|
+
"ex",
|
|
3725
|
+
"mg",
|
|
3726
|
+
// --- Terminal multiplexers ---
|
|
3727
|
+
"asciinema",
|
|
3728
|
+
"script",
|
|
3729
|
+
"scriptreplay",
|
|
3730
|
+
"expect",
|
|
3731
|
+
"screen",
|
|
3732
|
+
"tmux",
|
|
3733
|
+
"byobu",
|
|
3734
|
+
"dtach",
|
|
3735
|
+
"abduco",
|
|
3736
|
+
// --- Calculators / REPLs / scientific ---
|
|
3737
|
+
"bc",
|
|
3738
|
+
"dc",
|
|
3739
|
+
"calc",
|
|
3740
|
+
"qalc",
|
|
3741
|
+
"genius",
|
|
3742
|
+
"octave",
|
|
3743
|
+
"R",
|
|
3744
|
+
"Rscript",
|
|
3745
|
+
"julia",
|
|
3746
|
+
"irb",
|
|
3747
|
+
"pry",
|
|
3748
|
+
"ghci",
|
|
3749
|
+
"stack",
|
|
3750
|
+
"cabal",
|
|
3751
|
+
"ghc",
|
|
3752
|
+
// --- PHP / Lua / Perl / Ruby ecosystem (extended) ---
|
|
3753
|
+
"php8",
|
|
3754
|
+
"php7",
|
|
3755
|
+
"phpcs",
|
|
3756
|
+
"phpcbf",
|
|
3757
|
+
"phpmd",
|
|
3758
|
+
"phpstan",
|
|
3759
|
+
"psalm",
|
|
3760
|
+
"lua",
|
|
3761
|
+
"lua5.1",
|
|
3762
|
+
"lua5.2",
|
|
3763
|
+
"lua5.3",
|
|
3764
|
+
"lua5.4",
|
|
3765
|
+
"luarocks",
|
|
3766
|
+
"perl",
|
|
3767
|
+
"cpan",
|
|
3768
|
+
"prove",
|
|
3769
|
+
"plackup",
|
|
3770
|
+
"rake",
|
|
3771
|
+
"rspec",
|
|
3772
|
+
"jekyll",
|
|
3773
|
+
"node-gyp",
|
|
3774
|
+
"node-pre-gyp",
|
|
3775
|
+
// --- JS / TS toolchain (extended) ---
|
|
3776
|
+
"electron",
|
|
3777
|
+
"electron-builder",
|
|
3778
|
+
"electron-forge",
|
|
3779
|
+
"vite-preview",
|
|
3780
|
+
"swc",
|
|
3781
|
+
"swc-cli",
|
|
3782
|
+
"swcpack",
|
|
3783
|
+
"mocha",
|
|
3784
|
+
"chai",
|
|
3785
|
+
"jasmine",
|
|
3786
|
+
"puppeteer",
|
|
3787
|
+
"lighthouse",
|
|
3788
|
+
// --- Linters / formatters (extended) ---
|
|
3789
|
+
"tslint",
|
|
3790
|
+
"stylelint",
|
|
3791
|
+
"htmlhint",
|
|
3792
|
+
"jshint",
|
|
3793
|
+
"jslint",
|
|
3794
|
+
"jscs",
|
|
3795
|
+
// --- Document conversion ---
|
|
3796
|
+
"pandoc",
|
|
3797
|
+
"weasyprint",
|
|
3798
|
+
"wkhtmltopdf",
|
|
3799
|
+
"wkhtmltoimage",
|
|
3800
|
+
"prince",
|
|
3801
|
+
"mdp",
|
|
3802
|
+
"markdown",
|
|
3803
|
+
"multimarkdown",
|
|
3804
|
+
"cmark",
|
|
3805
|
+
"cmark-gfm",
|
|
3806
|
+
// --- Office / spreadsheet ---
|
|
3807
|
+
"soffice",
|
|
3808
|
+
"libreoffice",
|
|
3809
|
+
"unoconv",
|
|
3810
|
+
"abiword",
|
|
3811
|
+
"gnumeric",
|
|
3812
|
+
// --- Spell / grammar ---
|
|
3813
|
+
"aspell",
|
|
3814
|
+
"hunspell",
|
|
3815
|
+
"enchant",
|
|
3816
|
+
"languagetool",
|
|
3817
|
+
// --- Source-highlight / diff tools ---
|
|
3818
|
+
"delta",
|
|
3819
|
+
"bat",
|
|
3820
|
+
"ccat",
|
|
3821
|
+
"hl",
|
|
3822
|
+
"highlight",
|
|
3823
|
+
"source-highlight",
|
|
3824
|
+
"ansifilter",
|
|
3825
|
+
// --- Job schedulers ---
|
|
3826
|
+
"pueue",
|
|
3827
|
+
"task-spooler",
|
|
3828
|
+
"ts",
|
|
3829
|
+
"at",
|
|
3830
|
+
"atd",
|
|
3831
|
+
"anacron",
|
|
3832
|
+
"fcron",
|
|
3833
|
+
"cronie",
|
|
3834
|
+
"systemd-run",
|
|
3835
|
+
"systemd-cat",
|
|
3836
|
+
// --- Plotting / visualization ---
|
|
3837
|
+
"gnuplot",
|
|
3838
|
+
"gnuplot-nox",
|
|
3839
|
+
"veusz",
|
|
3840
|
+
"scidavis",
|
|
3841
|
+
"grace",
|
|
3842
|
+
"xmgrace",
|
|
3843
|
+
"labplot",
|
|
3844
|
+
// --- Security / recon (network + web) ---
|
|
3845
|
+
"masscan",
|
|
3846
|
+
"zmap",
|
|
3847
|
+
"rustscan",
|
|
3848
|
+
"amass",
|
|
3849
|
+
"subfinder",
|
|
3850
|
+
"httpx",
|
|
3851
|
+
"nuclei",
|
|
3852
|
+
"naabu",
|
|
3853
|
+
"katana",
|
|
3854
|
+
"dnsx",
|
|
3855
|
+
"assetfinder",
|
|
3856
|
+
"findomain",
|
|
3857
|
+
"gau",
|
|
3858
|
+
"waybackurls",
|
|
3859
|
+
"httprobe",
|
|
3860
|
+
"meg",
|
|
3861
|
+
"subjack",
|
|
3862
|
+
"sublert",
|
|
3863
|
+
"chaos"
|
|
3340
3864
|
]);
|
|
3341
3865
|
var allowedCommands = new Set(DEFAULT_ALLOWED_COMMANDS);
|
|
3342
3866
|
var normalizeCmd = (c) => c.trim();
|
|
@@ -3559,17 +4083,18 @@ function runCommand(cmd, args, cwd, timeout, signal, sessionId) {
|
|
|
3559
4083
|
const spool = createOutputSpool({ tool: `exec-${cmd}`, thresholdBytes: MAX_OUTPUT2 });
|
|
3560
4084
|
const resolved = resolveWin32Command(cmd);
|
|
3561
4085
|
const needsShell = isWin2 && (resolved.endsWith(".cmd") || resolved.endsWith(".bat"));
|
|
3562
|
-
const
|
|
3563
|
-
|
|
4086
|
+
const shim = needsShell ? buildWin32CmdShimInvocation(resolved, args) : null;
|
|
4087
|
+
const spawnCmd = shim?.command ?? resolved;
|
|
4088
|
+
const spawnArgs = shim?.args ?? args;
|
|
3564
4089
|
let child;
|
|
3565
4090
|
try {
|
|
3566
|
-
child = spawn(spawnCmd,
|
|
4091
|
+
child = spawn(spawnCmd, spawnArgs, {
|
|
3567
4092
|
cwd,
|
|
3568
4093
|
env: buildChildEnv(sessionId),
|
|
3569
4094
|
stdio: ["ignore", "pipe", "pipe"],
|
|
3570
4095
|
windowsHide: true,
|
|
3571
4096
|
...isWin2 ? {} : { signal },
|
|
3572
|
-
...
|
|
4097
|
+
...shim ? { windowsVerbatimArguments: shim.windowsVerbatimArguments } : {}
|
|
3573
4098
|
});
|
|
3574
4099
|
} catch (err) {
|
|
3575
4100
|
spool.finalize();
|
|
@@ -3664,6 +4189,7 @@ TD.addRule("stripDangerousElements", {
|
|
|
3664
4189
|
});
|
|
3665
4190
|
var MAX_BYTES2 = 131072;
|
|
3666
4191
|
var TIMEOUT_MS = 2e4;
|
|
4192
|
+
var nativeGlobalFetch = globalThis.fetch;
|
|
3667
4193
|
var ALLOW_PRIVATE = process.env["WRONGSTACK_FETCH_ALLOW_PRIVATE"] === "1";
|
|
3668
4194
|
if (ALLOW_PRIVATE && !process.env["CI"]) {
|
|
3669
4195
|
console.warn(
|
|
@@ -3713,6 +4239,9 @@ function getPinnedDispatcher() {
|
|
|
3713
4239
|
}
|
|
3714
4240
|
return pinnedAgent;
|
|
3715
4241
|
}
|
|
4242
|
+
function dispatcherFetch() {
|
|
4243
|
+
return globalThis.fetch === nativeGlobalFetch ? fetch : globalThis.fetch;
|
|
4244
|
+
}
|
|
3716
4245
|
var _beforeExitRegistered = false;
|
|
3717
4246
|
if (!_beforeExitRegistered) {
|
|
3718
4247
|
_beforeExitRegistered = true;
|
|
@@ -3748,7 +4277,7 @@ async function guardedFetch(url, maxRedirects, signal, headers = {
|
|
|
3748
4277
|
headers,
|
|
3749
4278
|
dispatcher: getPinnedDispatcher()
|
|
3750
4279
|
};
|
|
3751
|
-
const res = await
|
|
4280
|
+
const res = await dispatcherFetch()(currentUrl, init);
|
|
3752
4281
|
if (res.status < 300 || res.status > 399) {
|
|
3753
4282
|
return res;
|
|
3754
4283
|
}
|
|
@@ -3776,7 +4305,7 @@ var fetchTool = {
|
|
|
3776
4305
|
category: "Network",
|
|
3777
4306
|
description: "Fetch a URL and return its content. HTML pages are automatically converted to clean markdown. This tool has strong SSRF protections (private IPs, localhost, and cloud metadata endpoints are blocked by default).",
|
|
3778
4307
|
usageHint: "Use this when you need external information (documentation, API responses, web pages, etc.).\n\nSecurity notes:\n- Only HTTPS is allowed by default.\n- Internal/private networks are blocked unless explicitly enabled via environment variable.\n- Redirects are followed but re-validated at each hop.\n- Output is capped (128KB by default) to avoid flooding context.\nPrefer this over raw `bash curl` or `bash wget`.",
|
|
3779
|
-
permission: "
|
|
4308
|
+
permission: "auto",
|
|
3780
4309
|
mutating: false,
|
|
3781
4310
|
capabilities: ["net.outbound"],
|
|
3782
4311
|
icon: "web",
|
|
@@ -4017,7 +4546,7 @@ var searchTool = {
|
|
|
4017
4546
|
category: "Search",
|
|
4018
4547
|
description: "Perform a web search and return results with title, URL, and snippet. Use this when you need up-to-date external information that is not in the local codebase. Results are cached (5 min TTL) and deduplicated by URL.",
|
|
4019
4548
|
usageHint: "Good for: API documentation, error messages, library usage examples, current best practices.\n\n- Prefer specific queries over very broad ones.\n- Results go through the guarded fetch system (same protections as the `fetch` tool).\n- Supports duckduckgo (default), google, and bing sources.\n- Set `skip_cache: true` to force a fresh search.\n- This is often better than the model trying to recall outdated knowledge.",
|
|
4020
|
-
permission: "
|
|
4549
|
+
permission: "auto",
|
|
4021
4550
|
mutating: false,
|
|
4022
4551
|
capabilities: ["net.outbound"],
|
|
4023
4552
|
icon: "search",
|
|
@@ -4080,15 +4609,15 @@ var searchTool = {
|
|
|
4080
4609
|
};
|
|
4081
4610
|
yield {
|
|
4082
4611
|
type: "partial_output",
|
|
4083
|
-
text: `${results.length} cached results from ${source}`,
|
|
4084
|
-
data: { count: results.length, cached: true }
|
|
4612
|
+
text: `${results.length} cached results from ${entry.source}`,
|
|
4613
|
+
data: { count: results.length, cached: true, source: entry.source }
|
|
4085
4614
|
};
|
|
4086
4615
|
yield {
|
|
4087
4616
|
type: "final",
|
|
4088
4617
|
output: {
|
|
4089
4618
|
query: input.query,
|
|
4090
4619
|
results: results.slice(0, num),
|
|
4091
|
-
source,
|
|
4620
|
+
source: entry.source,
|
|
4092
4621
|
truncated: results.length >= num,
|
|
4093
4622
|
cached: true
|
|
4094
4623
|
}
|
|
@@ -4102,6 +4631,7 @@ var searchTool = {
|
|
|
4102
4631
|
data: { source, query: input.query, cached: false }
|
|
4103
4632
|
};
|
|
4104
4633
|
let rawResults;
|
|
4634
|
+
let effectiveSource = source;
|
|
4105
4635
|
switch (source) {
|
|
4106
4636
|
case "duckduckgo":
|
|
4107
4637
|
rawResults = await duckduckgoSearch(input.query, num, opts.signal);
|
|
@@ -4118,24 +4648,24 @@ var searchTool = {
|
|
|
4118
4648
|
field: "source"
|
|
4119
4649
|
});
|
|
4120
4650
|
}
|
|
4121
|
-
|
|
4122
|
-
|
|
4123
|
-
|
|
4124
|
-
|
|
4125
|
-
|
|
4126
|
-
|
|
4127
|
-
|
|
4128
|
-
|
|
4129
|
-
|
|
4651
|
+
let ranked = rankSearchResults(rawResults, input.query);
|
|
4652
|
+
if (source !== "duckduckgo" && shouldFallbackToDuckDuckGo(ranked, input.query)) {
|
|
4653
|
+
yield {
|
|
4654
|
+
type: "log",
|
|
4655
|
+
text: `${source} returned no relevant static results; falling back to duckduckgo`,
|
|
4656
|
+
data: { source, fallback: "duckduckgo", query: input.query }
|
|
4657
|
+
};
|
|
4658
|
+
rawResults = await duckduckgoSearch(input.query, num, opts.signal);
|
|
4659
|
+
ranked = rankSearchResults(rawResults, input.query);
|
|
4660
|
+
effectiveSource = "duckduckgo";
|
|
4130
4661
|
}
|
|
4131
|
-
const ranked = scoreResults(deduped, input.query);
|
|
4132
4662
|
const finalResults = ranked.slice(0, num);
|
|
4133
|
-
cache.set(cacheKey, { results: ranked, timestamp: Date.now() });
|
|
4663
|
+
cache.set(cacheKey, { results: ranked, source: effectiveSource, timestamp: Date.now() });
|
|
4134
4664
|
pruneStaleCacheEntries();
|
|
4135
4665
|
yield {
|
|
4136
4666
|
type: "partial_output",
|
|
4137
|
-
text: `${finalResults.length} results from ${
|
|
4138
|
-
data: { count: finalResults.length, cached: false }
|
|
4667
|
+
text: `${finalResults.length} results from ${effectiveSource}`,
|
|
4668
|
+
data: { count: finalResults.length, cached: false, source: effectiveSource }
|
|
4139
4669
|
};
|
|
4140
4670
|
yield {
|
|
4141
4671
|
type: "final",
|
|
@@ -4146,7 +4676,7 @@ var searchTool = {
|
|
|
4146
4676
|
url: r.url,
|
|
4147
4677
|
snippet: r.snippet
|
|
4148
4678
|
})),
|
|
4149
|
-
source,
|
|
4679
|
+
source: effectiveSource,
|
|
4150
4680
|
truncated: finalResults.length >= num,
|
|
4151
4681
|
cached: false
|
|
4152
4682
|
}
|
|
@@ -4159,6 +4689,19 @@ function pruneStaleCacheEntries() {
|
|
|
4159
4689
|
if (entry.timestamp < cutoff) cache.delete(key);
|
|
4160
4690
|
}
|
|
4161
4691
|
}
|
|
4692
|
+
function rankSearchResults(results, query) {
|
|
4693
|
+
const seenUrls = /* @__PURE__ */ new Set();
|
|
4694
|
+
const deduped = [];
|
|
4695
|
+
for (const r of results) {
|
|
4696
|
+
const noQuery = r.url.split("?")[0] ?? r.url;
|
|
4697
|
+
const normalized = noQuery.split("#")[0] ?? r.url;
|
|
4698
|
+
if (!seenUrls.has(normalized) && r.url.startsWith("http")) {
|
|
4699
|
+
seenUrls.add(normalized);
|
|
4700
|
+
deduped.push(r);
|
|
4701
|
+
}
|
|
4702
|
+
}
|
|
4703
|
+
return scoreResults(deduped, query);
|
|
4704
|
+
}
|
|
4162
4705
|
function scoreResults(results, query) {
|
|
4163
4706
|
const terms = query.toLowerCase().split(/\s+/).filter((t) => t.length > 0);
|
|
4164
4707
|
return results.map((r) => {
|
|
@@ -4172,6 +4715,15 @@ function scoreResults(results, query) {
|
|
|
4172
4715
|
return { ...r, score };
|
|
4173
4716
|
}).sort((a, b) => b.score - a.score);
|
|
4174
4717
|
}
|
|
4718
|
+
function shouldFallbackToDuckDuckGo(results, query) {
|
|
4719
|
+
if (results.length === 0) return true;
|
|
4720
|
+
const terms = query.toLowerCase().split(/\s+/).filter((t) => t.length >= 3);
|
|
4721
|
+
if (terms.length === 0) return false;
|
|
4722
|
+
return !results.some((r) => {
|
|
4723
|
+
const haystack = `${r.title} ${r.url} ${r.snippet}`.toLowerCase();
|
|
4724
|
+
return terms.some((term) => haystack.includes(term));
|
|
4725
|
+
});
|
|
4726
|
+
}
|
|
4175
4727
|
async function duckduckgoSearch(query, num, signal) {
|
|
4176
4728
|
const encoded = encodeURIComponent(query);
|
|
4177
4729
|
const url = `https://lite.duckduckgo.com/lite/?q=${encoded}&kd=-1&kl=wt-wt`;
|
|
@@ -4196,14 +4748,19 @@ function takeFrom(iter, max) {
|
|
|
4196
4748
|
}
|
|
4197
4749
|
function parseDuckDuckGo(html, num) {
|
|
4198
4750
|
const results = [];
|
|
4199
|
-
const
|
|
4200
|
-
const
|
|
4751
|
+
const linkRegex = /<a\b([^>]*\bclass=(["'])[^"']*\bresult-link\b[^"']*\2[^>]*)>([\s\S]*?)<\/a>/gi;
|
|
4752
|
+
const snippetRegex = /<([a-z0-9]+)\b([^>]*\bclass=(["'])[^"']*\bresult-snippet\b[^"']*\3[^>]*)>([\s\S]*?)<\/\1>/gi;
|
|
4201
4753
|
const linkMatches = takeFrom(
|
|
4202
|
-
[...html.matchAll(
|
|
4754
|
+
[...html.matchAll(linkRegex)].map((m) => {
|
|
4755
|
+
const attrs = expectDefined(m[1]);
|
|
4756
|
+
const href = getHtmlAttr(attrs, "href");
|
|
4757
|
+
const title = stripTags(expectDefined(m[3]));
|
|
4758
|
+
return href && title ? { url: normalizeDuckDuckGoUrl(href), title } : void 0;
|
|
4759
|
+
}).filter((m) => m !== void 0),
|
|
4203
4760
|
num
|
|
4204
4761
|
);
|
|
4205
4762
|
const snippetMatches = takeFrom(
|
|
4206
|
-
[...html.matchAll(
|
|
4763
|
+
[...html.matchAll(snippetRegex)].filter((m) => m[4]).map((m) => stripTags(expectDefined(m[4]))),
|
|
4207
4764
|
num
|
|
4208
4765
|
);
|
|
4209
4766
|
for (let i = 0; i < linkMatches.length && i < num; i++) {
|
|
@@ -4219,6 +4776,24 @@ function parseDuckDuckGo(html, num) {
|
|
|
4219
4776
|
}
|
|
4220
4777
|
return results;
|
|
4221
4778
|
}
|
|
4779
|
+
function getHtmlAttr(attrs, name) {
|
|
4780
|
+
const quoted = new RegExp(`\\b${name}\\s*=\\s*(["'])(.*?)\\1`, "i").exec(attrs);
|
|
4781
|
+
if (quoted?.[2]) return decodeHtmlEntities(quoted[2]);
|
|
4782
|
+
const unquoted = new RegExp(`\\b${name}\\s*=\\s*([^\\s>]+)`, "i").exec(attrs);
|
|
4783
|
+
return unquoted?.[1] ? decodeHtmlEntities(unquoted[1]) : void 0;
|
|
4784
|
+
}
|
|
4785
|
+
function normalizeDuckDuckGoUrl(raw) {
|
|
4786
|
+
if (raw.startsWith("//")) return `https:${raw}`;
|
|
4787
|
+
if (!raw.startsWith("/")) return raw;
|
|
4788
|
+
if (!raw.startsWith("/l/")) return raw;
|
|
4789
|
+
try {
|
|
4790
|
+
const url = new URL(raw, "https://duckduckgo.com");
|
|
4791
|
+
const uddg = url.searchParams.get("uddg");
|
|
4792
|
+
return uddg?.startsWith("http") ? uddg : url.toString();
|
|
4793
|
+
} catch {
|
|
4794
|
+
return raw;
|
|
4795
|
+
}
|
|
4796
|
+
}
|
|
4222
4797
|
async function googleSearch(query, num, signal) {
|
|
4223
4798
|
const encoded = encodeURIComponent(query);
|
|
4224
4799
|
const url = `https://www.google.com/search?q=${encoded}&hl=en`;
|
|
@@ -4260,29 +4835,53 @@ async function bingSearch(query, num, signal) {
|
|
|
4260
4835
|
}
|
|
4261
4836
|
function parseBingResults(html, num) {
|
|
4262
4837
|
const results = [];
|
|
4263
|
-
const
|
|
4264
|
-
const
|
|
4265
|
-
const entries = takeFrom(
|
|
4266
|
-
|
|
4267
|
-
|
|
4268
|
-
|
|
4269
|
-
|
|
4270
|
-
|
|
4271
|
-
|
|
4272
|
-
|
|
4838
|
+
const blocks = [...html.matchAll(/<li\b[^>]*class=(["'])[^"']*\bb_algo\b[^"']*\1[^>]*>([\s\S]*?)(?=<li\b[^>]*class=(["'])[^"']*\bb_algo\b[^"']*\3|<\/ol>)/gi)].map((m) => expectDefined(m[2]));
|
|
4839
|
+
const candidates = blocks.length > 0 ? blocks : [html];
|
|
4840
|
+
const entries = takeFrom(candidates.flatMap((block) => {
|
|
4841
|
+
const titleMatch = /<h2[^>]*>\s*<a\b([^>]*)>([\s\S]*?)<\/a>\s*<\/h2>/i.exec(block);
|
|
4842
|
+
if (!titleMatch) return [];
|
|
4843
|
+
const href = getHtmlAttr(expectDefined(titleMatch[1]), "href");
|
|
4844
|
+
const title = stripTags(expectDefined(titleMatch[2]));
|
|
4845
|
+
if (!href || !title) return [];
|
|
4846
|
+
const snippetMatch = /<p\b[^>]*class=(["'])[^"']*\b(?:b_paractl|b_lineclamp\d*)\b[^"']*\1[^>]*>([\s\S]*?)<\/p>/i.exec(block) ?? /<p\b[^>]*>([\s\S]*?)<\/p>/i.exec(block);
|
|
4847
|
+
const snippet = snippetMatch ? stripTags(expectDefined(snippetMatch.at(-1))) : "";
|
|
4848
|
+
return [{ url: normalizeBingUrl(href), title, snippet, score: 1 }];
|
|
4849
|
+
}), num);
|
|
4273
4850
|
for (let i = 0; i < entries.length; i++) {
|
|
4274
4851
|
const entry = entries[i];
|
|
4275
4852
|
if (entry) {
|
|
4276
4853
|
results.push({
|
|
4277
4854
|
title: entry.title ?? "",
|
|
4278
4855
|
url: entry.url ?? "",
|
|
4279
|
-
snippet:
|
|
4856
|
+
snippet: entry.snippet ?? "",
|
|
4280
4857
|
score: 1
|
|
4281
4858
|
});
|
|
4282
4859
|
}
|
|
4283
4860
|
}
|
|
4284
4861
|
return results;
|
|
4285
4862
|
}
|
|
4863
|
+
function normalizeBingUrl(raw) {
|
|
4864
|
+
try {
|
|
4865
|
+
const url = new URL(raw);
|
|
4866
|
+
if (url.hostname.endsWith("bing.com") && url.pathname.startsWith("/ck/")) {
|
|
4867
|
+
const encoded = url.searchParams.get("u");
|
|
4868
|
+
const decoded = decodeBingTarget(encoded);
|
|
4869
|
+
if (decoded?.startsWith("http")) return decoded;
|
|
4870
|
+
}
|
|
4871
|
+
} catch {
|
|
4872
|
+
}
|
|
4873
|
+
return raw;
|
|
4874
|
+
}
|
|
4875
|
+
function decodeBingTarget(encoded) {
|
|
4876
|
+
if (!encoded) return void 0;
|
|
4877
|
+
const payload = encoded.startsWith("a1") ? encoded.slice(2) : encoded;
|
|
4878
|
+
try {
|
|
4879
|
+
const padded = payload.replace(/-/g, "+").replace(/_/g, "/").padEnd(Math.ceil(payload.length / 4) * 4, "=");
|
|
4880
|
+
return Buffer.from(padded, "base64").toString("utf8");
|
|
4881
|
+
} catch {
|
|
4882
|
+
return void 0;
|
|
4883
|
+
}
|
|
4884
|
+
}
|
|
4286
4885
|
async function fetchWithTimeout(url, signal, timeoutMs) {
|
|
4287
4886
|
const controller = new AbortController();
|
|
4288
4887
|
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
@@ -4310,7 +4909,10 @@ function anySignal(...signals) {
|
|
|
4310
4909
|
return AbortSignal.any(signals);
|
|
4311
4910
|
}
|
|
4312
4911
|
function stripTags(html) {
|
|
4313
|
-
return html.replace(/<[^>]+>/g, "")
|
|
4912
|
+
return decodeHtmlEntities(html.replace(/<[^>]+>/g, "")).trim();
|
|
4913
|
+
}
|
|
4914
|
+
function decodeHtmlEntities(text) {
|
|
4915
|
+
return text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, '"').replace(/'/g, "'");
|
|
4314
4916
|
}
|
|
4315
4917
|
var todoTool = {
|
|
4316
4918
|
name: "todo",
|
|
@@ -5880,15 +6482,16 @@ async function* spawnStream(opts) {
|
|
|
5880
6482
|
const spool = createOutputSpool({ tool: opts.cmd, thresholdBytes: max });
|
|
5881
6483
|
const resolved = resolveWin32Command(opts.cmd);
|
|
5882
6484
|
const needsShell = isWin3 && (resolved.endsWith(".cmd") || resolved.endsWith(".bat"));
|
|
5883
|
-
const
|
|
5884
|
-
|
|
5885
|
-
const
|
|
6485
|
+
const shim = needsShell ? buildWin32CmdShimInvocation(resolved, opts.args) : null;
|
|
6486
|
+
const cmd = shim?.command ?? resolved;
|
|
6487
|
+
const args = shim?.args ?? opts.args;
|
|
6488
|
+
const child = spawn(cmd, args, {
|
|
5886
6489
|
cwd: opts.cwd,
|
|
5887
6490
|
env: buildChildEnv(),
|
|
5888
6491
|
stdio: ["ignore", "pipe", "pipe"],
|
|
5889
6492
|
windowsHide: true,
|
|
5890
6493
|
...isWin3 ? {} : { signal: opts.signal },
|
|
5891
|
-
...
|
|
6494
|
+
...shim ? { windowsVerbatimArguments: shim.windowsVerbatimArguments } : {}
|
|
5892
6495
|
});
|
|
5893
6496
|
const registry = getProcessRegistry();
|
|
5894
6497
|
const pid = child.pid;
|
|
@@ -6135,7 +6738,7 @@ var formatTool = {
|
|
|
6135
6738
|
usageHint: "RUN REGULARLY:\n\n- Use on changed files before committing.\n- `check: true` verifies formatting without making changes (useful in CI-like flows).\nThis project has very consistent formatting expectations. Always ensure your changes are formatted.",
|
|
6136
6739
|
permission: "confirm",
|
|
6137
6740
|
mutating: true,
|
|
6138
|
-
capabilities: ["fs.write", "shell.
|
|
6741
|
+
capabilities: ["fs.write", "shell.restricted"],
|
|
6139
6742
|
icon: "code",
|
|
6140
6743
|
timeoutMs: 6e4,
|
|
6141
6744
|
inputSchema: {
|
|
@@ -6788,9 +7391,10 @@ function runOutdated(manager, args, cwd, signal) {
|
|
|
6788
7391
|
const MAX = 1e5;
|
|
6789
7392
|
const resolved = resolveWin32Command(manager);
|
|
6790
7393
|
const needsShell = process.platform === "win32" && (resolved.endsWith(".cmd") || resolved.endsWith(".bat"));
|
|
6791
|
-
const
|
|
6792
|
-
|
|
6793
|
-
const
|
|
7394
|
+
const shim = needsShell ? buildWin32CmdShimInvocation(resolved, args) : null;
|
|
7395
|
+
const spawnCmd = shim?.command ?? resolved;
|
|
7396
|
+
const spawnArgs = shim?.args ?? args;
|
|
7397
|
+
const child = spawn(spawnCmd, spawnArgs, { cwd, signal, env: buildChildEnv(), stdio: ["ignore", "pipe", "pipe"], windowsHide: true, ...shim ? { windowsVerbatimArguments: shim.windowsVerbatimArguments } : {} });
|
|
6794
7398
|
child.stdout?.on("data", (c) => {
|
|
6795
7399
|
if (stdout.length < MAX) stdout += c.toString();
|
|
6796
7400
|
});
|
|
@@ -7395,9 +7999,9 @@ var designTool = {
|
|
|
7395
7999
|
category: "Design",
|
|
7396
8000
|
description: 'Browse, load, customize, and enforce curated frontend/mobile UI design kits. Use BEFORE writing UI code to commit to one coherent, modern, responsive, dark/light, accessible design. Actions: "list" (menu), "use" (load+pin a kit for a stack), "foundations" (baseline), "set" (override kit colors/tokens), "materialize" (write the tokens to a real theme file \u2014 CSS @theme/OKLCH or native), "verify" (scan UI files for off-palette colors).',
|
|
7397
8001
|
usageHint: 'Flow: `design {action:"use", kit:"minimal-clarity", stack:"web"}` \u2192 optionally `design {action:"set", set:{primary:"oklch(62% 0.2 25)"}}` \u2192 `design {action:"materialize"}` to write tokens to disk \u2192 implement against them \u2192 `design {action:"verify"}`.',
|
|
7398
|
-
permission: "
|
|
7399
|
-
mutating:
|
|
7400
|
-
capabilities: [],
|
|
8002
|
+
permission: "confirm",
|
|
8003
|
+
mutating: true,
|
|
8004
|
+
capabilities: ["fs.write"],
|
|
7401
8005
|
timeoutMs: 15e3,
|
|
7402
8006
|
inputSchema: {
|
|
7403
8007
|
type: "object",
|
|
@@ -7998,7 +8602,7 @@ function rememberTool(memory) {
|
|
|
7998
8602
|
category: "Session",
|
|
7999
8603
|
description: "Persist facts, conventions, decisions, and preferences into long-term memory. Memories survive restarts and are scored for relevance in future sessions.",
|
|
8000
8604
|
usageHint: "Persist facts, conventions, decisions, and preferences into long-term memory.\n\nWHEN TO USE:\n- Project conventions discovered during a task (build tool, lint rules, code style)\n- Architecture decisions made (chose X over Y, decided to use pattern Z)\n- User preferences expressed (prefers short names, always uses pnpm)\n- Anti-patterns identified (never do X, avoid pattern Y)\n- File/location references useful across sessions\n\nWHEN NOT TO USE:\n- Temporary task state or progress \u2192 use `todo`\n- One-off debugging notes\n- Information already obvious from the codebase\n\nAlways include `type` and `priority`. Use 1-3 `tags` for grouping.\nBetter to remember a fact now than rediscover it next session.",
|
|
8001
|
-
permission: "
|
|
8605
|
+
permission: "confirm",
|
|
8002
8606
|
mutating: true,
|
|
8003
8607
|
timeoutMs: 2e3,
|
|
8004
8608
|
capabilities: ["memory.write"],
|