@probelabs/probe 0.6.0-rc255 → 0.6.0-rc257

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.
Files changed (31) hide show
  1. package/README.md +5 -5
  2. package/bin/binaries/probe-v0.6.0-rc257-aarch64-apple-darwin.tar.gz +0 -0
  3. package/bin/binaries/probe-v0.6.0-rc257-aarch64-unknown-linux-musl.tar.gz +0 -0
  4. package/bin/binaries/probe-v0.6.0-rc257-x86_64-apple-darwin.tar.gz +0 -0
  5. package/bin/binaries/{probe-v0.6.0-rc255-x86_64-pc-windows-msvc.zip → probe-v0.6.0-rc257-x86_64-pc-windows-msvc.zip} +0 -0
  6. package/bin/binaries/probe-v0.6.0-rc257-x86_64-unknown-linux-musl.tar.gz +0 -0
  7. package/build/agent/FallbackManager.js +4 -4
  8. package/build/agent/ProbeAgent.js +23 -17
  9. package/build/agent/bashDefaults.js +175 -97
  10. package/build/agent/bashPermissions.js +98 -45
  11. package/build/agent/index.js +335 -205
  12. package/build/agent/mcp/xmlBridge.js +3 -2
  13. package/build/agent/schemaUtils.js +127 -0
  14. package/build/tools/bash.js +2 -2
  15. package/build/tools/common.js +20 -3
  16. package/cjs/agent/ProbeAgent.cjs +343 -203
  17. package/cjs/index.cjs +343 -203
  18. package/package.json +1 -1
  19. package/src/agent/FallbackManager.js +4 -4
  20. package/src/agent/ProbeAgent.js +23 -17
  21. package/src/agent/bashDefaults.js +175 -97
  22. package/src/agent/bashPermissions.js +98 -45
  23. package/src/agent/index.js +4 -4
  24. package/src/agent/mcp/xmlBridge.js +3 -2
  25. package/src/agent/schemaUtils.js +127 -0
  26. package/src/tools/bash.js +2 -2
  27. package/src/tools/common.js +20 -3
  28. package/bin/binaries/probe-v0.6.0-rc255-aarch64-apple-darwin.tar.gz +0 -0
  29. package/bin/binaries/probe-v0.6.0-rc255-aarch64-unknown-linux-musl.tar.gz +0 -0
  30. package/bin/binaries/probe-v0.6.0-rc255-x86_64-apple-darwin.tar.gz +0 -0
  31. package/bin/binaries/probe-v0.6.0-rc255-x86_64-unknown-linux-musl.tar.gz +0 -0
@@ -10373,6 +10373,10 @@ function getValidParamsForTool(toolName) {
10373
10373
  }
10374
10374
  return [];
10375
10375
  }
10376
+ function unescapeXmlEntities(str) {
10377
+ if (typeof str !== "string") return str;
10378
+ return str.replace(/&lt;/g, "<").replace(/&gt;/g, ">").replace(/&quot;/g, '"').replace(/&apos;/g, "'").replace(/&amp;/g, "&");
10379
+ }
10376
10380
  function parseXmlToolCall(xmlString, validTools = DEFAULT_VALID_TOOLS) {
10377
10381
  let earliestToolName = null;
10378
10382
  let earliestOpenIndex = Infinity;
@@ -10429,10 +10433,10 @@ function parseXmlToolCall(xmlString, validTools = DEFAULT_VALID_TOOLS) {
10429
10433
  }
10430
10434
  paramCloseIndex = nextTagIndex;
10431
10435
  }
10432
- let paramValue = innerContent.substring(
10436
+ let paramValue = unescapeXmlEntities(innerContent.substring(
10433
10437
  paramOpenIndex + paramOpenTag.length,
10434
10438
  paramCloseIndex
10435
- ).trim();
10439
+ ).trim());
10436
10440
  if (paramValue.toLowerCase() === "true") {
10437
10441
  paramValue = true;
10438
10442
  } else if (paramValue.toLowerCase() === "false") {
@@ -10446,7 +10450,7 @@ function parseXmlToolCall(xmlString, validTools = DEFAULT_VALID_TOOLS) {
10446
10450
  params[paramName] = paramValue;
10447
10451
  }
10448
10452
  if (toolName === "attempt_completion") {
10449
- params["result"] = innerContent.trim();
10453
+ params["result"] = unescapeXmlEntities(innerContent.trim());
10450
10454
  if (params.command) {
10451
10455
  delete params.command;
10452
10456
  }
@@ -11555,95 +11559,102 @@ var init_bashDefaults = __esm({
11555
11559
  "dir",
11556
11560
  "pwd",
11557
11561
  "cd",
11558
- "cd:*",
11559
11562
  // File reading commands
11560
11563
  "cat",
11561
- "cat:*",
11562
11564
  "head",
11563
- "head:*",
11564
11565
  "tail",
11565
- "tail:*",
11566
11566
  "less",
11567
11567
  "more",
11568
11568
  "view",
11569
11569
  // File information and metadata
11570
11570
  "file",
11571
- "file:*",
11572
11571
  "stat",
11573
- "stat:*",
11574
11572
  "wc",
11575
- "wc:*",
11576
11573
  "du",
11577
- "du:*",
11578
11574
  "df",
11579
- "df:*",
11580
11575
  "realpath",
11581
- "realpath:*",
11582
- // Search and find commands (read-only) - find restricted to safe operations
11576
+ // Search and find commands (read-only)
11577
+ // Note: bare 'find' allows all find variants; dangerous ones (find -exec) are blocked by deny list
11583
11578
  "find",
11584
- "find:-name:*",
11585
- "find:-type:*",
11586
- "find:-size:*",
11587
- "find:-mtime:*",
11588
- "find:-newer:*",
11589
- "find:-path:*",
11590
- "find:-iname:*",
11591
- "find:-maxdepth:*",
11592
- "find:-mindepth:*",
11593
- "find:-print",
11594
11579
  "grep",
11595
- "grep:*",
11596
11580
  "egrep",
11597
- "egrep:*",
11598
11581
  "fgrep",
11599
- "fgrep:*",
11600
11582
  "rg",
11601
- "rg:*",
11602
11583
  "ag",
11603
- "ag:*",
11604
11584
  "ack",
11605
- "ack:*",
11606
11585
  "which",
11607
- "which:*",
11608
11586
  "whereis",
11609
- "whereis:*",
11610
11587
  "locate",
11611
- "locate:*",
11612
11588
  "type",
11613
- "type:*",
11614
11589
  "command",
11615
- "command:*",
11616
11590
  // Tree and structure visualization
11617
11591
  "tree",
11618
- "tree:*",
11619
11592
  // Git read-only operations
11620
11593
  "git:status",
11621
11594
  "git:log",
11622
- "git:log:*",
11623
11595
  "git:diff",
11624
- "git:diff:*",
11625
11596
  "git:show",
11626
- "git:show:*",
11627
11597
  "git:branch",
11628
- "git:branch:*",
11629
11598
  "git:tag",
11630
- "git:tag:*",
11631
11599
  "git:describe",
11632
- "git:describe:*",
11633
11600
  "git:remote",
11634
- "git:remote:*",
11635
- "git:config:*",
11601
+ "git:config",
11636
11602
  "git:blame",
11637
- "git:blame:*",
11638
11603
  "git:shortlog",
11639
11604
  "git:reflog",
11640
11605
  "git:ls-files",
11641
11606
  "git:ls-tree",
11607
+ "git:ls-remote",
11642
11608
  "git:rev-parse",
11643
11609
  "git:rev-list",
11610
+ "git:cat-file",
11611
+ "git:diff-tree",
11612
+ "git:diff-files",
11613
+ "git:diff-index",
11614
+ "git:for-each-ref",
11615
+ "git:merge-base",
11616
+ "git:name-rev",
11617
+ "git:count-objects",
11618
+ "git:verify-commit",
11619
+ "git:verify-tag",
11620
+ "git:check-ignore",
11621
+ "git:check-attr",
11622
+ "git:stash:list",
11623
+ "git:stash:show",
11624
+ "git:worktree:list",
11625
+ "git:notes:list",
11626
+ "git:notes:show",
11644
11627
  "git:--version",
11645
11628
  "git:help",
11646
- "git:help:*",
11629
+ // GitHub CLI (gh) read-only operations
11630
+ "gh:--version",
11631
+ "gh:help",
11632
+ "gh:status",
11633
+ "gh:auth:status",
11634
+ "gh:issue:list",
11635
+ "gh:issue:view",
11636
+ "gh:issue:status",
11637
+ "gh:pr:list",
11638
+ "gh:pr:view",
11639
+ "gh:pr:status",
11640
+ "gh:pr:diff",
11641
+ "gh:pr:checks",
11642
+ "gh:repo:list",
11643
+ "gh:repo:view",
11644
+ "gh:release:list",
11645
+ "gh:release:view",
11646
+ "gh:run:list",
11647
+ "gh:run:view",
11648
+ "gh:workflow:list",
11649
+ "gh:workflow:view",
11650
+ "gh:gist:list",
11651
+ "gh:gist:view",
11652
+ "gh:search:issues",
11653
+ "gh:search:prs",
11654
+ "gh:search:repos",
11655
+ "gh:search:code",
11656
+ "gh:search:commits",
11657
+ "gh:api",
11647
11658
  // Package managers (information only)
11648
11659
  "npm:list",
11649
11660
  "npm:ls",
@@ -11704,7 +11715,6 @@ var init_bashDefaults = __esm({
11704
11715
  "sqlite3:--version",
11705
11716
  // System information
11706
11717
  "uname",
11707
- "uname:*",
11708
11718
  "hostname",
11709
11719
  "whoami",
11710
11720
  "id",
@@ -11715,23 +11725,17 @@ var init_bashDefaults = __esm({
11715
11725
  "w",
11716
11726
  "users",
11717
11727
  "sleep",
11718
- "sleep:*",
11719
11728
  // Environment and shell
11720
11729
  "env",
11721
11730
  "printenv",
11722
11731
  "echo",
11723
- "echo:*",
11724
11732
  "printf",
11725
- "printf:*",
11726
11733
  "export",
11727
- "export:*",
11728
11734
  "set",
11729
11735
  "unset",
11730
11736
  // Process information (read-only)
11731
11737
  "ps",
11732
- "ps:*",
11733
11738
  "pgrep",
11734
- "pgrep:*",
11735
11739
  "jobs",
11736
11740
  "top:-n:1",
11737
11741
  // Network information (read-only)
@@ -11746,39 +11750,24 @@ var init_bashDefaults = __esm({
11746
11750
  // Text processing and utilities (awk removed - too powerful)
11747
11751
  "sed:-n:*",
11748
11752
  "cut",
11749
- "cut:*",
11750
11753
  "sort",
11751
- "sort:*",
11752
11754
  "uniq",
11753
- "uniq:*",
11754
11755
  "tr",
11755
- "tr:*",
11756
11756
  "column",
11757
- "column:*",
11758
11757
  "paste",
11759
- "paste:*",
11760
11758
  "join",
11761
- "join:*",
11762
11759
  "comm",
11763
- "comm:*",
11764
11760
  "diff",
11765
- "diff:*",
11766
11761
  "cmp",
11767
- "cmp:*",
11768
11762
  "patch:--dry-run:*",
11769
11763
  // Hashing and encoding (read-only)
11770
11764
  "md5sum",
11771
- "md5sum:*",
11772
11765
  "sha1sum",
11773
- "sha1sum:*",
11774
11766
  "sha256sum",
11775
- "sha256sum:*",
11776
11767
  "base64",
11777
11768
  "base64:-d",
11778
11769
  "od",
11779
- "od:*",
11780
11770
  "hexdump",
11781
- "hexdump:*",
11782
11771
  // Archive and compression (list/view only)
11783
11772
  "tar:-tf:*",
11784
11773
  "tar:-tzf:*",
@@ -11788,15 +11777,11 @@ var init_bashDefaults = __esm({
11788
11777
  "gunzip:-l:*",
11789
11778
  // Help and documentation
11790
11779
  "man",
11791
- "man:*",
11792
11780
  "--help",
11793
11781
  "help",
11794
11782
  "info",
11795
- "info:*",
11796
11783
  "whatis",
11797
- "whatis:*",
11798
11784
  "apropos",
11799
- "apropos:*",
11800
11785
  // Make (dry run and info)
11801
11786
  "make:-n",
11802
11787
  "make:--dry-run",
@@ -11819,36 +11804,30 @@ var init_bashDefaults = __esm({
11819
11804
  "rm:-rf",
11820
11805
  "rm:-f:/",
11821
11806
  "rm:/",
11822
- "rm:-rf:*",
11823
11807
  "rmdir",
11824
11808
  "chmod:777",
11825
11809
  "chmod:-R:777",
11826
11810
  "chown",
11827
11811
  "chgrp",
11828
11812
  "dd",
11829
- "dd:*",
11830
11813
  "shred",
11831
- "shred:*",
11832
11814
  // Dangerous find operations that can execute arbitrary commands
11833
- "find:-exec:*",
11834
- "find:*:-exec:*",
11835
- "find:-execdir:*",
11836
- "find:*:-execdir:*",
11837
- "find:-ok:*",
11838
- "find:*:-ok:*",
11839
- "find:-okdir:*",
11840
- "find:*:-okdir:*",
11815
+ "find:-exec",
11816
+ "find:*:-exec",
11817
+ "find:-execdir",
11818
+ "find:*:-execdir",
11819
+ "find:-ok",
11820
+ "find:*:-ok",
11821
+ "find:-okdir",
11822
+ "find:*:-okdir",
11841
11823
  // Powerful scripting tools that can execute arbitrary commands
11842
11824
  "awk",
11843
- "awk:*",
11844
11825
  "perl",
11845
- "perl:*",
11846
11826
  "python:-c:*",
11847
11827
  "node:-e:*",
11848
11828
  // System administration and modification
11849
- "sudo:*",
11829
+ "sudo",
11850
11830
  "su",
11851
- "su:*",
11852
11831
  "passwd",
11853
11832
  "adduser",
11854
11833
  "useradd",
@@ -11886,11 +11865,11 @@ var init_bashDefaults = __esm({
11886
11865
  "composer:install",
11887
11866
  "composer:update",
11888
11867
  "composer:remove",
11889
- "apt:*",
11890
- "apt-get:*",
11891
- "yum:*",
11892
- "dnf:*",
11893
- "zypper:*",
11868
+ "apt",
11869
+ "apt-get",
11870
+ "yum",
11871
+ "dnf",
11872
+ "zypper",
11894
11873
  "brew:install",
11895
11874
  "brew:uninstall",
11896
11875
  "brew:upgrade",
@@ -11898,11 +11877,11 @@ var init_bashDefaults = __esm({
11898
11877
  "conda:remove",
11899
11878
  "conda:update",
11900
11879
  // Service and system control
11901
- "systemctl:*",
11902
- "service:*",
11903
- "chkconfig:*",
11904
- "initctl:*",
11905
- "upstart:*",
11880
+ "systemctl",
11881
+ "service",
11882
+ "chkconfig",
11883
+ "initctl",
11884
+ "upstart",
11906
11885
  // Network operations that could be dangerous
11907
11886
  "curl:-d:*",
11908
11887
  "curl:--data:*",
@@ -11911,32 +11890,21 @@ var init_bashDefaults = __esm({
11911
11890
  "wget:-O:/",
11912
11891
  "wget:--post-data:*",
11913
11892
  "ssh",
11914
- "ssh:*",
11915
11893
  "scp",
11916
- "scp:*",
11917
11894
  "sftp",
11918
- "sftp:*",
11919
- "rsync:*",
11895
+ "rsync",
11920
11896
  "nc",
11921
- "nc:*",
11922
11897
  "netcat",
11923
- "netcat:*",
11924
11898
  "telnet",
11925
- "telnet:*",
11926
11899
  "ftp",
11927
- "ftp:*",
11928
11900
  // Process control and termination
11929
11901
  "kill",
11930
- "kill:*",
11931
11902
  "killall",
11932
- "killall:*",
11933
11903
  "pkill",
11934
- "pkill:*",
11935
- "nohup:*",
11936
- "disown:*",
11904
+ "nohup",
11905
+ "disown",
11937
11906
  // System control and shutdown
11938
11907
  "shutdown",
11939
- "shutdown:*",
11940
11908
  "reboot",
11941
11909
  "halt",
11942
11910
  "poweroff",
@@ -11944,50 +11912,92 @@ var init_bashDefaults = __esm({
11944
11912
  "telinit",
11945
11913
  // Kernel and module operations
11946
11914
  "insmod",
11947
- "insmod:*",
11948
11915
  "rmmod",
11949
- "rmmod:*",
11950
11916
  "modprobe",
11951
- "modprobe:*",
11952
11917
  "sysctl:-w:*",
11953
11918
  // Dangerous git operations
11954
11919
  "git:push",
11955
- "git:push:*",
11956
11920
  "git:force",
11957
- "git:reset:--hard:*",
11958
- "git:clean:-fd",
11959
- "git:rm:*",
11921
+ "git:reset",
11922
+ "git:clean",
11923
+ "git:rm",
11960
11924
  "git:commit",
11961
11925
  "git:merge",
11962
11926
  "git:rebase",
11963
11927
  "git:cherry-pick",
11964
11928
  "git:stash:drop",
11929
+ "git:stash:pop",
11930
+ "git:stash:push",
11931
+ "git:stash:clear",
11932
+ "git:branch:-d",
11933
+ "git:branch:-D",
11934
+ "git:branch:--delete",
11935
+ "git:tag:-d",
11936
+ "git:tag:--delete",
11937
+ "git:remote:remove",
11938
+ "git:remote:rm",
11939
+ "git:checkout:--force",
11940
+ "git:checkout:-f",
11941
+ "git:submodule:deinit",
11942
+ "git:notes:add",
11943
+ "git:notes:remove",
11944
+ "git:worktree:add",
11945
+ "git:worktree:remove",
11946
+ // Dangerous GitHub CLI (gh) write operations
11947
+ "gh:issue:create",
11948
+ "gh:issue:close",
11949
+ "gh:issue:delete",
11950
+ "gh:issue:edit",
11951
+ "gh:issue:reopen",
11952
+ "gh:issue:comment",
11953
+ "gh:pr:create",
11954
+ "gh:pr:close",
11955
+ "gh:pr:merge",
11956
+ "gh:pr:edit",
11957
+ "gh:pr:reopen",
11958
+ "gh:pr:review",
11959
+ "gh:pr:comment",
11960
+ "gh:repo:create",
11961
+ "gh:repo:delete",
11962
+ "gh:repo:fork",
11963
+ "gh:repo:rename",
11964
+ "gh:repo:archive",
11965
+ "gh:repo:clone",
11966
+ "gh:release:create",
11967
+ "gh:release:delete",
11968
+ "gh:release:edit",
11969
+ "gh:run:cancel",
11970
+ "gh:run:rerun",
11971
+ "gh:workflow:run",
11972
+ "gh:workflow:enable",
11973
+ "gh:workflow:disable",
11974
+ "gh:gist:create",
11975
+ "gh:gist:delete",
11976
+ "gh:gist:edit",
11977
+ "gh:secret:set",
11978
+ "gh:secret:delete",
11979
+ "gh:variable:set",
11980
+ "gh:variable:delete",
11981
+ "gh:label:create",
11982
+ "gh:label:delete",
11983
+ "gh:ssh-key:add",
11984
+ "gh:ssh-key:delete",
11965
11985
  // File system mounting and partitioning
11966
11986
  "mount",
11967
- "mount:*",
11968
11987
  "umount",
11969
- "umount:*",
11970
11988
  "fdisk",
11971
- "fdisk:*",
11972
11989
  "parted",
11973
- "parted:*",
11974
11990
  "mkfs",
11975
- "mkfs:*",
11976
11991
  "fsck",
11977
- "fsck:*",
11978
11992
  // Cron and scheduling
11979
11993
  "crontab",
11980
- "crontab:*",
11981
11994
  "at",
11982
- "at:*",
11983
11995
  "batch",
11984
- "batch:*",
11985
11996
  // Compression with potential overwrite
11986
11997
  "tar:-xf:*",
11987
11998
  "unzip",
11988
- "unzip:*",
11989
- "gzip:*",
11990
- "gunzip:*",
11999
+ "gzip",
12000
+ "gunzip",
11991
12001
  // Build and compilation that might modify files
11992
12002
  "make",
11993
12003
  "make:install",
@@ -12000,11 +12010,8 @@ var init_bashDefaults = __esm({
12000
12010
  "gradle:build",
12001
12011
  // Docker operations that could modify state
12002
12012
  "docker:run",
12003
- "docker:run:*",
12004
12013
  "docker:exec",
12005
- "docker:exec:*",
12006
12014
  "docker:build",
12007
- "docker:build:*",
12008
12015
  "docker:pull",
12009
12016
  "docker:push",
12010
12017
  "docker:rm",
@@ -12018,22 +12025,15 @@ var init_bashDefaults = __esm({
12018
12025
  "mongo:--eval:*",
12019
12026
  // Text editors that could modify files
12020
12027
  "vi",
12021
- "vi:*",
12022
12028
  "vim",
12023
- "vim:*",
12024
12029
  "nano",
12025
- "nano:*",
12026
12030
  "emacs",
12027
- "emacs:*",
12028
12031
  "sed:-i:*",
12029
12032
  "perl:-i:*",
12030
12033
  // Potentially dangerous utilities
12031
12034
  "eval",
12032
- "eval:*",
12033
12035
  "exec",
12034
- "exec:*",
12035
12036
  "source",
12036
- "source:*",
12037
12037
  "bash:-c:*",
12038
12038
  "sh:-c:*",
12039
12039
  "zsh:-c:*"
@@ -12312,9 +12312,19 @@ var init_bashPermissions = __esm({
12312
12312
  BashPermissionChecker = class {
12313
12313
  /**
12314
12314
  * Create a permission checker
12315
+ *
12316
+ * Priority order (highest to lowest):
12317
+ * 1. Custom deny — always blocks (user explicitly blocked it)
12318
+ * 2. Custom allow — overrides default deny (user explicitly allowed it)
12319
+ * 3. Default deny — blocks by default
12320
+ * 4. Allow list — allows recognized safe commands
12321
+ *
12322
+ * This means `--bash-allow "git:push"` overrides the default deny for git:push
12323
+ * without requiring `--no-default-bash-deny`.
12324
+ *
12315
12325
  * @param {Object} config - Configuration options
12316
- * @param {string[]} [config.allow] - Additional allow patterns
12317
- * @param {string[]} [config.deny] - Additional deny patterns
12326
+ * @param {string[]} [config.allow] - Additional allow patterns (override default deny)
12327
+ * @param {string[]} [config.deny] - Additional deny patterns (always win)
12318
12328
  * @param {boolean} [config.disableDefaultAllow] - Disable default allow list
12319
12329
  * @param {boolean} [config.disableDefaultDeny] - Disable default deny list
12320
12330
  * @param {boolean} [config.debug] - Enable debug logging
@@ -12323,40 +12333,22 @@ var init_bashPermissions = __esm({
12323
12333
  constructor(config = {}) {
12324
12334
  this.debug = config.debug || false;
12325
12335
  this.tracer = config.tracer || null;
12326
- this.allowPatterns = [];
12327
- if (!config.disableDefaultAllow) {
12328
- this.allowPatterns.push(...DEFAULT_ALLOW_PATTERNS);
12329
- if (this.debug) {
12330
- console.log(`[BashPermissions] Added ${DEFAULT_ALLOW_PATTERNS.length} default allow patterns`);
12331
- }
12332
- }
12333
- if (config.allow && Array.isArray(config.allow)) {
12334
- this.allowPatterns.push(...config.allow);
12335
- if (this.debug) {
12336
- console.log(`[BashPermissions] Added ${config.allow.length} custom allow patterns:`, config.allow);
12337
- }
12338
- }
12339
- this.denyPatterns = [];
12340
- if (!config.disableDefaultDeny) {
12341
- this.denyPatterns.push(...DEFAULT_DENY_PATTERNS);
12342
- if (this.debug) {
12343
- console.log(`[BashPermissions] Added ${DEFAULT_DENY_PATTERNS.length} default deny patterns`);
12344
- }
12345
- }
12346
- if (config.deny && Array.isArray(config.deny)) {
12347
- this.denyPatterns.push(...config.deny);
12348
- if (this.debug) {
12349
- console.log(`[BashPermissions] Added ${config.deny.length} custom deny patterns:`, config.deny);
12350
- }
12351
- }
12336
+ this.defaultAllowPatterns = config.disableDefaultAllow ? [] : [...DEFAULT_ALLOW_PATTERNS];
12337
+ this.customAllowPatterns = config.allow && Array.isArray(config.allow) ? [...config.allow] : [];
12338
+ this.allowPatterns = [...this.defaultAllowPatterns, ...this.customAllowPatterns];
12339
+ this.defaultDenyPatterns = config.disableDefaultDeny ? [] : [...DEFAULT_DENY_PATTERNS];
12340
+ this.customDenyPatterns = config.deny && Array.isArray(config.deny) ? [...config.deny] : [];
12341
+ this.denyPatterns = [...this.defaultDenyPatterns, ...this.customDenyPatterns];
12352
12342
  if (this.debug) {
12343
+ console.log(`[BashPermissions] Default allow: ${this.defaultAllowPatterns.length}, Custom allow: ${this.customAllowPatterns.length}`);
12344
+ console.log(`[BashPermissions] Default deny: ${this.defaultDenyPatterns.length}, Custom deny: ${this.customDenyPatterns.length}`);
12353
12345
  console.log(`[BashPermissions] Total patterns - Allow: ${this.allowPatterns.length}, Deny: ${this.denyPatterns.length}`);
12354
12346
  }
12355
12347
  this.recordBashEvent("permissions.initialized", {
12356
12348
  allowPatternCount: this.allowPatterns.length,
12357
12349
  denyPatternCount: this.denyPatterns.length,
12358
- hasCustomAllowPatterns: !!(config.allow && config.allow.length > 0),
12359
- hasCustomDenyPatterns: !!(config.deny && config.deny.length > 0),
12350
+ hasCustomAllowPatterns: this.customAllowPatterns.length > 0,
12351
+ hasCustomDenyPatterns: this.customDenyPatterns.length > 0,
12360
12352
  disableDefaultAllow: !!config.disableDefaultAllow,
12361
12353
  disableDefaultDeny: !!config.disableDefaultDeny
12362
12354
  });
@@ -12426,8 +12418,11 @@ var init_bashPermissions = __esm({
12426
12418
  console.log(`[BashPermissions] Checking simple command: "${command}"`);
12427
12419
  console.log(`[BashPermissions] Parsed: ${parsed.command} with args: [${parsed.args.join(", ")}]`);
12428
12420
  }
12429
- if (matchesAnyPattern(parsed, this.denyPatterns)) {
12430
- const matchedPatterns = this.denyPatterns.filter((pattern) => matchesPattern(parsed, pattern));
12421
+ if (matchesAnyPattern(parsed, this.customDenyPatterns)) {
12422
+ const matchedPatterns = this.customDenyPatterns.filter((pattern) => matchesPattern(parsed, pattern));
12423
+ if (this.debug) {
12424
+ console.log(`[BashPermissions] DENIED - matches custom deny pattern: ${matchedPatterns[0]}`);
12425
+ }
12431
12426
  const result2 = {
12432
12427
  allowed: false,
12433
12428
  reason: `Command matches deny pattern: ${matchedPatterns[0]}`,
@@ -12440,7 +12435,31 @@ var init_bashPermissions = __esm({
12440
12435
  parsedCommand: parsed.command,
12441
12436
  reason: "matches_deny_pattern",
12442
12437
  matchedPattern: matchedPatterns[0],
12443
- isComplex: false
12438
+ isComplex: false,
12439
+ isCustomDeny: true
12440
+ });
12441
+ return result2;
12442
+ }
12443
+ const matchesCustomAllow = matchesAnyPattern(parsed, this.customAllowPatterns);
12444
+ if (!matchesCustomAllow && matchesAnyPattern(parsed, this.defaultDenyPatterns)) {
12445
+ const matchedPatterns = this.defaultDenyPatterns.filter((pattern) => matchesPattern(parsed, pattern));
12446
+ if (this.debug) {
12447
+ console.log(`[BashPermissions] DENIED - matches default deny pattern: ${matchedPatterns[0]}`);
12448
+ }
12449
+ const result2 = {
12450
+ allowed: false,
12451
+ reason: `Command matches deny pattern: ${matchedPatterns[0]}`,
12452
+ command,
12453
+ parsed,
12454
+ matchedPatterns
12455
+ };
12456
+ this.recordBashEvent("permission.denied", {
12457
+ command,
12458
+ parsedCommand: parsed.command,
12459
+ reason: "matches_deny_pattern",
12460
+ matchedPattern: matchedPatterns[0],
12461
+ isComplex: false,
12462
+ isCustomDeny: false
12444
12463
  });
12445
12464
  return result2;
12446
12465
  }
@@ -12465,15 +12484,21 @@ var init_bashPermissions = __esm({
12465
12484
  allowed: true,
12466
12485
  command,
12467
12486
  parsed,
12468
- isComplex: false
12487
+ isComplex: false,
12488
+ overriddenDeny: matchesCustomAllow && matchesAnyPattern(parsed, this.defaultDenyPatterns)
12469
12489
  };
12470
12490
  if (this.debug) {
12471
- console.log(`[BashPermissions] ALLOWED - command passed all checks`);
12491
+ if (result.overriddenDeny) {
12492
+ console.log(`[BashPermissions] ALLOWED - custom allow overrides default deny`);
12493
+ } else {
12494
+ console.log(`[BashPermissions] ALLOWED - command passed all checks`);
12495
+ }
12472
12496
  }
12473
12497
  this.recordBashEvent("permission.allowed", {
12474
12498
  command,
12475
12499
  parsedCommand: parsed.command,
12476
- isComplex: false
12500
+ isComplex: false,
12501
+ overriddenDeny: result.overriddenDeny || false
12477
12502
  });
12478
12503
  return result;
12479
12504
  }
@@ -12642,9 +12667,19 @@ var init_bashPermissions = __esm({
12642
12667
  deniedReason = parsed.error || "Component contains nested complex constructs";
12643
12668
  break;
12644
12669
  }
12645
- if (matchesAnyPattern(parsed, this.denyPatterns)) {
12670
+ if (matchesAnyPattern(parsed, this.customDenyPatterns)) {
12671
+ if (this.debug) {
12672
+ console.log(`[BashPermissions] Component "${component}" matches custom deny pattern`);
12673
+ }
12674
+ allAllowed = false;
12675
+ deniedComponent = component;
12676
+ deniedReason = "Component matches deny pattern";
12677
+ break;
12678
+ }
12679
+ const componentMatchesCustomAllow = matchesAnyPattern(parsed, this.customAllowPatterns);
12680
+ if (!componentMatchesCustomAllow && matchesAnyPattern(parsed, this.defaultDenyPatterns)) {
12646
12681
  if (this.debug) {
12647
- console.log(`[BashPermissions] Component "${component}" matches deny pattern`);
12682
+ console.log(`[BashPermissions] Component "${component}" matches default deny pattern`);
12648
12683
  }
12649
12684
  allAllowed = false;
12650
12685
  deniedComponent = component;
@@ -12724,6 +12759,10 @@ var init_bashPermissions = __esm({
12724
12759
  return {
12725
12760
  allowPatterns: this.allowPatterns.length,
12726
12761
  denyPatterns: this.denyPatterns.length,
12762
+ customAllowPatterns: this.customAllowPatterns.length,
12763
+ customDenyPatterns: this.customDenyPatterns.length,
12764
+ defaultAllowPatterns: this.defaultAllowPatterns.length,
12765
+ defaultDenyPatterns: this.defaultDenyPatterns.length,
12727
12766
  totalPatterns: this.allowPatterns.length + this.denyPatterns.length
12728
12767
  };
12729
12768
  }
@@ -13105,8 +13144,8 @@ Common reasons:
13105
13144
  2. The command is not in the allow list (not a recognized safe command)
13106
13145
 
13107
13146
  If you believe this command should be allowed, you can:
13108
- - Use the --bash-allow option to add specific patterns
13109
- - Use the --no-default-bash-deny flag to remove default restrictions (not recommended)
13147
+ - Use the --bash-allow option to add specific patterns (overrides default deny list)
13148
+ Example: --bash-allow "git:push" allows git push while keeping all other deny rules
13110
13149
 
13111
13150
  For code exploration, try these safe alternatives:
13112
13151
  - ls, cat, head, tail for file operations
@@ -69576,6 +69615,7 @@ __export(schemaUtils_exports, {
69576
69615
  replaceMermaidDiagramsInMarkdown: () => replaceMermaidDiagramsInMarkdown,
69577
69616
  sanitizeMarkdownEscapesInJson: () => sanitizeMarkdownEscapesInJson,
69578
69617
  tryAutoWrapForSimpleSchema: () => tryAutoWrapForSimpleSchema,
69618
+ tryExtractValidJsonPrefix: () => tryExtractValidJsonPrefix,
69579
69619
  tryMaidAutoFix: () => tryMaidAutoFix,
69580
69620
  validateAndFixMermaidResponse: () => validateAndFixMermaidResponse,
69581
69621
  validateJsonResponse: () => validateJsonResponse,
@@ -69962,6 +70002,13 @@ function validateJsonResponse(response, options = {}) {
69962
70002
  errorPosition = response.indexOf(problematicToken);
69963
70003
  }
69964
70004
  }
70005
+ const prefixResult = tryExtractValidJsonPrefix(responseToValidate, { schema, debug });
70006
+ if (prefixResult && prefixResult.isValid) {
70007
+ if (debug) {
70008
+ console.log(`[DEBUG] JSON validation: Recovered valid JSON prefix (${prefixResult.extracted.length} chars) from response with trailing content`);
70009
+ }
70010
+ return { isValid: true, parsed: prefixResult.parsed };
70011
+ }
69965
70012
  let enhancedError = error.message;
69966
70013
  let errorContext = null;
69967
70014
  if (errorPosition !== null && errorPosition >= 0 && response && response.length > 0) {
@@ -70012,6 +70059,84 @@ ${errorContext.pointer}`);
70012
70059
  };
70013
70060
  }
70014
70061
  }
70062
+ function tryExtractValidJsonPrefix(response, options = {}) {
70063
+ const { schema = null, debug = false } = options;
70064
+ if (!response || typeof response !== "string") {
70065
+ return null;
70066
+ }
70067
+ const trimmed = response.trim();
70068
+ if (trimmed.length === 0) {
70069
+ return null;
70070
+ }
70071
+ const firstChar = trimmed[0];
70072
+ if (firstChar !== "{" && firstChar !== "[") {
70073
+ return null;
70074
+ }
70075
+ try {
70076
+ JSON.parse(trimmed);
70077
+ return null;
70078
+ } catch {
70079
+ }
70080
+ const openChar = firstChar;
70081
+ const closeChar = openChar === "{" ? "}" : "]";
70082
+ let depth = 0;
70083
+ let inString = false;
70084
+ let escapeNext = false;
70085
+ let endPos = -1;
70086
+ for (let i = 0; i < trimmed.length; i++) {
70087
+ const char = trimmed[i];
70088
+ if (escapeNext) {
70089
+ escapeNext = false;
70090
+ continue;
70091
+ }
70092
+ if (char === "\\" && inString) {
70093
+ escapeNext = true;
70094
+ continue;
70095
+ }
70096
+ if (char === '"') {
70097
+ inString = !inString;
70098
+ continue;
70099
+ }
70100
+ if (inString) {
70101
+ continue;
70102
+ }
70103
+ if (char === openChar) {
70104
+ depth++;
70105
+ } else if (char === closeChar) {
70106
+ depth--;
70107
+ if (depth === 0) {
70108
+ endPos = i + 1;
70109
+ break;
70110
+ }
70111
+ }
70112
+ }
70113
+ if (endPos <= 0 || endPos >= trimmed.length) {
70114
+ return null;
70115
+ }
70116
+ const remainder = trimmed.substring(endPos).trim();
70117
+ if (remainder.length === 0) {
70118
+ return null;
70119
+ }
70120
+ const prefix = trimmed.substring(0, endPos);
70121
+ try {
70122
+ const parsed = JSON.parse(prefix);
70123
+ if (debug) {
70124
+ console.log(`[DEBUG] tryExtractValidJsonPrefix: Extracted valid JSON prefix (${prefix.length} chars), stripped trailing content (${remainder.length} chars)`);
70125
+ }
70126
+ if (schema) {
70127
+ const schemaValidation = validateJsonResponse(prefix, { debug, schema });
70128
+ if (!schemaValidation.isValid) {
70129
+ if (debug) {
70130
+ console.log(`[DEBUG] tryExtractValidJsonPrefix: Prefix is valid JSON but fails schema validation: ${schemaValidation.error}`);
70131
+ }
70132
+ return null;
70133
+ }
70134
+ }
70135
+ return { isValid: true, parsed, extracted: prefix };
70136
+ } catch {
70137
+ return null;
70138
+ }
70139
+ }
70015
70140
  function validateXmlResponse(response) {
70016
70141
  const xmlPattern = /<\/?[\w\s="'.-]+>/g;
70017
70142
  const tags = response.match(xmlPattern);
@@ -72113,7 +72238,7 @@ function parseXmlMcpToolCall(xmlString, mcpToolNames = []) {
72113
72238
  let match2;
72114
72239
  while ((match2 = paramPattern.exec(content)) !== null) {
72115
72240
  const [, paramName, paramValue] = match2;
72116
- params[paramName] = paramValue.trim();
72241
+ params[paramName] = unescapeXmlEntities(paramValue.trim());
72117
72242
  }
72118
72243
  }
72119
72244
  return { toolName, params };
@@ -72163,7 +72288,7 @@ function parseNativeXmlTool(xmlString, toolName) {
72163
72288
  while ((match2 = paramPattern.exec(content)) !== null) {
72164
72289
  const [, paramName, paramValue] = match2;
72165
72290
  if (paramName !== "params") {
72166
- params[paramName] = paramValue.trim();
72291
+ params[paramName] = unescapeXmlEntities(paramValue.trim());
72167
72292
  }
72168
72293
  }
72169
72294
  if (Object.keys(params).length > 0) {
@@ -72178,6 +72303,7 @@ var init_xmlBridge = __esm({
72178
72303
  init_client();
72179
72304
  init_config();
72180
72305
  init_xmlParsingUtils();
72306
+ init_common();
72181
72307
  MCPXmlBridge = class {
72182
72308
  constructor(options = {}) {
72183
72309
  this.debug = options.debug || false;
@@ -80391,10 +80517,10 @@ var init_FallbackManager = __esm({
80391
80517
  // Use custom provider list
80392
80518
  };
80393
80519
  DEFAULT_MODELS = {
80394
- anthropic: "claude-sonnet-4-5-20250929",
80395
- openai: "gpt-4o",
80396
- google: "gemini-2.0-flash-exp",
80397
- bedrock: "anthropic.claude-sonnet-4-20250514-v1:0"
80520
+ anthropic: "claude-sonnet-4-6",
80521
+ openai: "gpt-5.2",
80522
+ google: "gemini-2.5-flash",
80523
+ bedrock: "anthropic.claude-sonnet-4-6"
80398
80524
  };
80399
80525
  FallbackManager = class {
80400
80526
  /**
@@ -82914,7 +83040,7 @@ var init_ProbeAgent = __esm({
82914
83040
  }
82915
83041
  this.clientApiProvider = "claude-code";
82916
83042
  this.provider = null;
82917
- this.model = this.clientApiModel || "claude-3-5-sonnet-20241022";
83043
+ this.model = this.clientApiModel || "claude-sonnet-4-6";
82918
83044
  this.apiType = "claude-code";
82919
83045
  } else if (codexAvailable) {
82920
83046
  if (this.debug) {
@@ -82923,7 +83049,7 @@ var init_ProbeAgent = __esm({
82923
83049
  }
82924
83050
  this.clientApiProvider = "codex";
82925
83051
  this.provider = null;
82926
- this.model = this.clientApiModel || "gpt-4o";
83052
+ this.model = this.clientApiModel || "gpt-5.2";
82927
83053
  this.apiType = "codex";
82928
83054
  } else {
82929
83055
  throw new Error("No API key provided and neither claude nor codex command found. Please either:\n1. Set an API key: ANTHROPIC_API_KEY, OPENAI_API_KEY, GOOGLE_GENERATIVE_AI_API_KEY, or AWS credentials\n2. Install claude command from https://docs.claude.com/en/docs/claude-code\n3. Install codex command from https://openai.com/codex");
@@ -83161,7 +83287,7 @@ var init_ProbeAgent = __esm({
83161
83287
  }
83162
83288
  if (this.clientApiProvider === "claude-code" || process.env.USE_CLAUDE_CODE === "true") {
83163
83289
  this.provider = null;
83164
- this.model = modelName || "claude-3-5-sonnet-20241022";
83290
+ this.model = modelName || "claude-sonnet-4-6";
83165
83291
  this.apiType = "claude-code";
83166
83292
  if (this.debug) {
83167
83293
  console.log("[DEBUG] Claude Code engine selected - will use built-in access if available");
@@ -83528,7 +83654,7 @@ var init_ProbeAgent = __esm({
83528
83654
  apiKey,
83529
83655
  ...apiUrl && { baseURL: apiUrl }
83530
83656
  });
83531
- this.model = modelName || "claude-sonnet-4-5-20250929";
83657
+ this.model = modelName || "claude-sonnet-4-6";
83532
83658
  this.apiType = "anthropic";
83533
83659
  if (this.debug) {
83534
83660
  console.log(`Using Anthropic API with model: ${this.model}${apiUrl ? ` (URL: ${apiUrl})` : ""}`);
@@ -83543,7 +83669,7 @@ var init_ProbeAgent = __esm({
83543
83669
  apiKey,
83544
83670
  ...apiUrl && { baseURL: apiUrl }
83545
83671
  });
83546
- this.model = modelName || "gpt-5-thinking";
83672
+ this.model = modelName || "gpt-5.2";
83547
83673
  this.apiType = "openai";
83548
83674
  if (this.debug) {
83549
83675
  console.log(`Using OpenAI API with model: ${this.model}${apiUrl ? ` (URL: ${apiUrl})` : ""}`);
@@ -83647,7 +83773,7 @@ var init_ProbeAgent = __esm({
83647
83773
  config.baseURL = baseURL;
83648
83774
  }
83649
83775
  this.provider = createAmazonBedrock2(config);
83650
- this.model = modelName || "anthropic.claude-sonnet-4-20250514-v1:0";
83776
+ this.model = modelName || "anthropic.claude-sonnet-4-6";
83651
83777
  this.apiType = "bedrock";
83652
83778
  if (this.debug) {
83653
83779
  const authMethod = apiKey ? "API Key" : "AWS Credentials";
@@ -83706,7 +83832,7 @@ var init_ProbeAgent = __esm({
83706
83832
  allowedTools: this.allowedTools,
83707
83833
  // Pass tool filtering configuration
83708
83834
  model: this.model
83709
- // Pass model name (e.g., gpt-4o, o3, etc.)
83835
+ // Pass model name (e.g., gpt-5.2, o3, etc.)
83710
83836
  });
83711
83837
  if (this.debug) {
83712
83838
  console.log("[DEBUG] Using Codex CLI engine with Probe tools");
@@ -84802,8 +84928,8 @@ You are working with a workspace. Available paths: ${workspaceDesc}
84802
84928
  let currentIteration = 0;
84803
84929
  let completionAttempted = false;
84804
84930
  let finalResult = "I was unable to complete your request due to reaching the maximum number of tool iterations.";
84805
- const baseMaxIterations = this.maxIterations || MAX_TOOL_ITERATIONS;
84806
- const maxIterations = options.schema ? baseMaxIterations + 4 : baseMaxIterations;
84931
+ const baseMaxIterations = options._maxIterationsOverride || this.maxIterations || MAX_TOOL_ITERATIONS;
84932
+ const maxIterations = options._maxIterationsOverride ? baseMaxIterations : options.schema ? baseMaxIterations + 4 : baseMaxIterations;
84807
84933
  const isClaudeCode = this.clientApiProvider === "claude-code" || process.env.USE_CLAUDE_CODE === "true";
84808
84934
  const isCodex = this.clientApiProvider === "codex" || process.env.USE_CODEX === "true";
84809
84935
  if (isClaudeCode) {
@@ -84961,9 +85087,7 @@ You are working with a workspace. Available paths: ${workspaceDesc}
84961
85087
  let maxResponseTokens = this.maxResponseTokens;
84962
85088
  if (!maxResponseTokens) {
84963
85089
  maxResponseTokens = 4e3;
84964
- if (this.model && this.model.includes("opus") || this.model && this.model.includes("sonnet") || this.model && this.model.startsWith("gpt-4-")) {
84965
- maxResponseTokens = 8192;
84966
- } else if (this.model && this.model.startsWith("gpt-4o")) {
85090
+ if (this.model && this.model.includes("opus") || this.model && this.model.includes("sonnet") || this.model && this.model.startsWith("gpt-4") || this.model && this.model.startsWith("gpt-5")) {
84967
85091
  maxResponseTokens = 8192;
84968
85092
  } else if (this.model && this.model.startsWith("gemini")) {
84969
85093
  maxResponseTokens = 32e3;
@@ -86040,13 +86164,16 @@ Convert your previous response content into actual JSON data that follows this s
86040
86164
  options.schema,
86041
86165
  0
86042
86166
  );
86167
+ const { schema: _unusedSchema1, ...schemaDefCorrectionOptions } = options;
86043
86168
  finalResult = await this.answer(schemaDefinitionPrompt, [], {
86044
- ...options,
86169
+ ...schemaDefCorrectionOptions,
86045
86170
  _schemaFormatted: true,
86046
86171
  _skipValidation: true,
86047
86172
  // Skip validation in recursive correction calls to prevent loops
86048
- _completionPromptProcessed: true
86173
+ _completionPromptProcessed: true,
86049
86174
  // Prevent cascading completion prompts in retry calls
86175
+ _maxIterationsOverride: 3
86176
+ // Correction should complete in 1-2 iterations (issue #447)
86050
86177
  });
86051
86178
  finalResult = cleanSchemaResponse(finalResult);
86052
86179
  validation = validateJsonResponse(finalResult);
@@ -86094,15 +86221,18 @@ Convert your previous response content into actual JSON data that follows this s
86094
86221
  retryCount
86095
86222
  );
86096
86223
  }
86224
+ const { schema: _unusedSchema2, ...correctionOptions } = options;
86097
86225
  finalResult = await this.answer(correctionPrompt, [], {
86098
- ...options,
86226
+ ...correctionOptions,
86099
86227
  _schemaFormatted: true,
86100
86228
  _skipValidation: true,
86101
86229
  // Skip validation in recursive correction calls to prevent loops
86102
86230
  _disableTools: true,
86103
86231
  // Only allow attempt_completion - prevent AI from using search/query tools
86104
- _completionPromptProcessed: true
86232
+ _completionPromptProcessed: true,
86105
86233
  // Prevent cascading completion prompts in retry calls
86234
+ _maxIterationsOverride: 3
86235
+ // Correction should complete in 1-2 iterations (issue #447)
86106
86236
  });
86107
86237
  finalResult = cleanSchemaResponse(finalResult);
86108
86238
  validation = validateJsonResponse(finalResult, { debug: this.debug });
@@ -87721,7 +87851,7 @@ Please reformat your previous response to match this schema exactly. Only return
87721
87851
  if (!validation.isValid) {
87722
87852
  const correctionPrompt = createJsonCorrectionPrompt(result, schema, validation.error);
87723
87853
  try {
87724
- result = await agent.answer(correctionPrompt, [], { schema, _schemaFormatted: true, _disableTools: true });
87854
+ result = await agent.answer(correctionPrompt, [], { schema, _schemaFormatted: true, _disableTools: true, _maxIterationsOverride: 3 });
87725
87855
  result = cleanSchemaResponse(result);
87726
87856
  const finalValidation = validateJsonResponse(result);
87727
87857
  if (!finalValidation.isValid && args.debug) {
@@ -88012,11 +88142,11 @@ Please reformat your previous response to match this schema exactly. Only return
88012
88142
  if (appTracer) {
88013
88143
  result = await appTracer.withSpan(
88014
88144
  "agent.json_correction",
88015
- () => agent.answer(correctionPrompt, [], { schema, _schemaFormatted: true, _disableTools: true }),
88145
+ () => agent.answer(correctionPrompt, [], { schema, _schemaFormatted: true, _disableTools: true, _maxIterationsOverride: 3 }),
88016
88146
  { "original_error": validation.error }
88017
88147
  );
88018
88148
  } else {
88019
- result = await agent.answer(correctionPrompt, [], { schema, _schemaFormatted: true, _disableTools: true });
88149
+ result = await agent.answer(correctionPrompt, [], { schema, _schemaFormatted: true, _disableTools: true, _maxIterationsOverride: 3 });
88020
88150
  }
88021
88151
  result = cleanSchemaResponse(result);
88022
88152
  const finalValidation = validateJsonResponse(result);