@probelabs/probe 0.6.0-rc105 → 0.6.0-rc107

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/cjs/index.cjs CHANGED
@@ -1234,7 +1234,7 @@ function createMessagePreview(message, charsPerSide = 200) {
1234
1234
  const end = message.substring(message.length - charsPerSide);
1235
1235
  return `${start}...${end}`;
1236
1236
  }
1237
- var import_zod, searchSchema, querySchema, extractSchema, delegateSchema, attemptCompletionSchema, searchToolDefinition, queryToolDefinition, extractToolDefinition, delegateToolDefinition, attemptCompletionToolDefinition, searchDescription, queryDescription, extractDescription, delegateDescription, DEFAULT_VALID_TOOLS;
1237
+ var import_zod, searchSchema, querySchema, extractSchema, delegateSchema, bashSchema, attemptCompletionSchema, searchToolDefinition, queryToolDefinition, extractToolDefinition, delegateToolDefinition, attemptCompletionToolDefinition, bashToolDefinition, searchDescription, queryDescription, extractDescription, delegateDescription, bashDescription, DEFAULT_VALID_TOOLS;
1238
1238
  var init_common = __esm({
1239
1239
  "src/tools/common.js"() {
1240
1240
  "use strict";
@@ -1266,6 +1266,12 @@ var init_common = __esm({
1266
1266
  delegateSchema = import_zod.z.object({
1267
1267
  task: import_zod.z.string().describe("The task to delegate to a subagent. Be specific about what needs to be accomplished.")
1268
1268
  });
1269
+ bashSchema = import_zod.z.object({
1270
+ command: import_zod.z.string().describe("The bash command to execute"),
1271
+ workingDirectory: import_zod.z.string().optional().describe("Directory to execute the command in (optional)"),
1272
+ timeout: import_zod.z.number().optional().describe("Command timeout in milliseconds (optional)"),
1273
+ env: import_zod.z.record(import_zod.z.string()).optional().describe("Additional environment variables (optional)")
1274
+ });
1269
1275
  attemptCompletionSchema = {
1270
1276
  // Custom validation that requires result parameter but allows direct XML response
1271
1277
  safeParse: (params) => {
@@ -1488,11 +1494,67 @@ Usage Example:
1488
1494
  <attempt_completion>
1489
1495
  I have refactored the search module according to the requirements and verified the tests pass. The module now uses the new BM25 ranking algorithm and has improved error handling.
1490
1496
  </attempt_completion>
1497
+ `;
1498
+ bashToolDefinition = `
1499
+ ## bash
1500
+ Description: Execute bash commands for system exploration and development tasks. This tool has built-in security with allow/deny lists. By default, only safe read-only commands are allowed for code exploration.
1501
+
1502
+ Parameters:
1503
+ - command: (required) The bash command to execute
1504
+ - workingDirectory: (optional) Directory to execute the command in
1505
+ - timeout: (optional) Command timeout in milliseconds
1506
+ - env: (optional) Additional environment variables as an object
1507
+
1508
+ Security: Commands are filtered through allow/deny lists for safety:
1509
+ - Allowed by default: ls, cat, git status, npm list, find, grep, etc.
1510
+ - Denied by default: rm -rf, sudo, npm install, dangerous system commands
1511
+
1512
+ Usage Examples:
1513
+
1514
+ <examples>
1515
+
1516
+ User: What files are in the src directory?
1517
+ <bash>
1518
+ <command>ls -la src/</command>
1519
+ </bash>
1520
+
1521
+ User: Show me the git status
1522
+ <bash>
1523
+ <command>git status</command>
1524
+ </bash>
1525
+
1526
+ User: Find all TypeScript files
1527
+ <bash>
1528
+ <command>find . -name "*.ts" -type f</command>
1529
+ </bash>
1530
+
1531
+ User: Check installed npm packages
1532
+ <bash>
1533
+ <command>npm list --depth=0</command>
1534
+ </bash>
1535
+
1536
+ User: Search for TODO comments in code
1537
+ <bash>
1538
+ <command>grep -r "TODO" src/</command>
1539
+ </bash>
1540
+
1541
+ User: Show recent git commits
1542
+ <bash>
1543
+ <command>git log --oneline -10</command>
1544
+ </bash>
1545
+
1546
+ User: Check system info
1547
+ <bash>
1548
+ <command>uname -a</command>
1549
+ </bash>
1550
+
1551
+ </examples>
1491
1552
  `;
1492
1553
  searchDescription = "Search code in the repository using Elasticsearch-like query syntax. Use this tool first for any code-related questions.";
1493
1554
  queryDescription = "Search code using ast-grep structural pattern matching. Use this tool to find specific code structures like functions, classes, or methods.";
1494
1555
  extractDescription = "Extract code blocks from files based on file paths and optional line numbers. Use this tool to see complete context after finding relevant files.";
1495
1556
  delegateDescription = "Automatically delegate big distinct tasks to specialized probe subagents within the agentic loop. Used by AI agents to break down complex requests into focused, parallel tasks.";
1557
+ bashDescription = "Execute bash commands for system exploration and development tasks. Secure by default with built-in allow/deny lists.";
1496
1558
  DEFAULT_VALID_TOOLS = [
1497
1559
  "search",
1498
1560
  "query",
@@ -1546,7 +1608,7 @@ async function delegate({ task, timeout = 300, debug = false, currentIteration =
1546
1608
  console.error(`[DELEGATE] Using binary at: ${binaryPath}`);
1547
1609
  console.error(`[DELEGATE] Command args: ${args.join(" ")}`);
1548
1610
  }
1549
- return new Promise((resolve2, reject) => {
1611
+ return new Promise((resolve4, reject) => {
1550
1612
  const delegationSpan = tracer ? tracer.createDelegationSpan(sessionId, task) : null;
1551
1613
  const process2 = (0, import_child_process5.spawn)(binaryPath, args, {
1552
1614
  stdio: ["pipe", "pipe", "pipe"],
@@ -1611,7 +1673,7 @@ async function delegate({ task, timeout = 300, debug = false, currentIteration =
1611
1673
  delegationSpan.end();
1612
1674
  }
1613
1675
  }
1614
- resolve2(response);
1676
+ resolve4(response);
1615
1677
  } else {
1616
1678
  const errorMessage = stderr.trim() || `Delegate process failed with exit code ${code}`;
1617
1679
  if (debug) {
@@ -1807,10 +1869,10 @@ var init_vercel = __esm({
1807
1869
  let extractOptions = { path: extractPath };
1808
1870
  if (input_content) {
1809
1871
  const { writeFileSync: writeFileSync2, unlinkSync } = await import("fs");
1810
- const { join: join2 } = await import("path");
1872
+ const { join: join3 } = await import("path");
1811
1873
  const { tmpdir } = await import("os");
1812
1874
  const { randomUUID: randomUUID5 } = await import("crypto");
1813
- tempFilePath = join2(tmpdir(), `probe-extract-${randomUUID5()}.txt`);
1875
+ tempFilePath = join3(tmpdir(), `probe-extract-${randomUUID5()}.txt`);
1814
1876
  writeFileSync2(tempFilePath, input_content);
1815
1877
  if (debug) {
1816
1878
  console.error(`Created temporary file for input content: ${tempFilePath}`);
@@ -1887,6 +1949,1248 @@ var init_vercel = __esm({
1887
1949
  }
1888
1950
  });
1889
1951
 
1952
+ // src/agent/bashDefaults.js
1953
+ var DEFAULT_ALLOW_PATTERNS, DEFAULT_DENY_PATTERNS;
1954
+ var init_bashDefaults = __esm({
1955
+ "src/agent/bashDefaults.js"() {
1956
+ "use strict";
1957
+ DEFAULT_ALLOW_PATTERNS = [
1958
+ // Basic navigation and listing
1959
+ "ls",
1960
+ "dir",
1961
+ "pwd",
1962
+ "cd",
1963
+ "cd:*",
1964
+ // File reading commands
1965
+ "cat",
1966
+ "cat:*",
1967
+ "head",
1968
+ "head:*",
1969
+ "tail",
1970
+ "tail:*",
1971
+ "less",
1972
+ "more",
1973
+ "view",
1974
+ // File information and metadata
1975
+ "file",
1976
+ "file:*",
1977
+ "stat",
1978
+ "stat:*",
1979
+ "wc",
1980
+ "wc:*",
1981
+ "du",
1982
+ "du:*",
1983
+ "df",
1984
+ "df:*",
1985
+ "realpath",
1986
+ "realpath:*",
1987
+ // Search and find commands (read-only) - find restricted to safe operations
1988
+ "find",
1989
+ "find:-name:*",
1990
+ "find:-type:*",
1991
+ "find:-size:*",
1992
+ "find:-mtime:*",
1993
+ "find:-newer:*",
1994
+ "find:-path:*",
1995
+ "find:-iname:*",
1996
+ "find:-maxdepth:*",
1997
+ "find:-mindepth:*",
1998
+ "find:-print",
1999
+ "grep",
2000
+ "grep:*",
2001
+ "egrep",
2002
+ "egrep:*",
2003
+ "fgrep",
2004
+ "fgrep:*",
2005
+ "rg",
2006
+ "rg:*",
2007
+ "ag",
2008
+ "ag:*",
2009
+ "ack",
2010
+ "ack:*",
2011
+ "which",
2012
+ "which:*",
2013
+ "whereis",
2014
+ "whereis:*",
2015
+ "locate",
2016
+ "locate:*",
2017
+ "type",
2018
+ "type:*",
2019
+ "command",
2020
+ "command:*",
2021
+ // Tree and structure visualization
2022
+ "tree",
2023
+ "tree:*",
2024
+ // Git read-only operations
2025
+ "git:status",
2026
+ "git:log",
2027
+ "git:log:*",
2028
+ "git:diff",
2029
+ "git:diff:*",
2030
+ "git:show",
2031
+ "git:show:*",
2032
+ "git:branch",
2033
+ "git:branch:*",
2034
+ "git:tag",
2035
+ "git:tag:*",
2036
+ "git:describe",
2037
+ "git:describe:*",
2038
+ "git:remote",
2039
+ "git:remote:*",
2040
+ "git:config:*",
2041
+ "git:blame",
2042
+ "git:blame:*",
2043
+ "git:shortlog",
2044
+ "git:reflog",
2045
+ "git:ls-files",
2046
+ "git:ls-tree",
2047
+ "git:rev-parse",
2048
+ "git:rev-list",
2049
+ "git:--version",
2050
+ "git:help",
2051
+ "git:help:*",
2052
+ // Package managers (information only)
2053
+ "npm:list",
2054
+ "npm:ls",
2055
+ "npm:view",
2056
+ "npm:info",
2057
+ "npm:show",
2058
+ "npm:outdated",
2059
+ "npm:audit",
2060
+ "npm:--version",
2061
+ "yarn:list",
2062
+ "yarn:info",
2063
+ "yarn:--version",
2064
+ "pnpm:list",
2065
+ "pnpm:--version",
2066
+ "pip:list",
2067
+ "pip:show",
2068
+ "pip:--version",
2069
+ "pip3:list",
2070
+ "pip3:show",
2071
+ "pip3:--version",
2072
+ "gem:list",
2073
+ "gem:--version",
2074
+ "bundle:list",
2075
+ "bundle:show",
2076
+ "bundle:--version",
2077
+ "composer:show",
2078
+ "composer:--version",
2079
+ // Language and runtime versions
2080
+ "node:--version",
2081
+ "node:-v",
2082
+ "python:--version",
2083
+ "python:-V",
2084
+ "python3:--version",
2085
+ "python3:-V",
2086
+ "ruby:--version",
2087
+ "ruby:-v",
2088
+ "go:version",
2089
+ "go:env",
2090
+ "go:list",
2091
+ "go:mod:graph",
2092
+ "rustc:--version",
2093
+ "cargo:--version",
2094
+ "cargo:tree",
2095
+ "cargo:metadata",
2096
+ "java:--version",
2097
+ "java:-version",
2098
+ "javac:--version",
2099
+ "mvn:--version",
2100
+ "gradle:--version",
2101
+ "php:--version",
2102
+ "dotnet:--version",
2103
+ "dotnet:list",
2104
+ // Database client versions (connection info only)
2105
+ "psql:--version",
2106
+ "mysql:--version",
2107
+ "redis-cli:--version",
2108
+ "mongo:--version",
2109
+ "sqlite3:--version",
2110
+ // System information
2111
+ "uname",
2112
+ "uname:*",
2113
+ "hostname",
2114
+ "whoami",
2115
+ "id",
2116
+ "groups",
2117
+ "date",
2118
+ "cal",
2119
+ "uptime",
2120
+ "w",
2121
+ "users",
2122
+ "sleep",
2123
+ "sleep:*",
2124
+ // Environment and shell
2125
+ "env",
2126
+ "printenv",
2127
+ "echo",
2128
+ "echo:*",
2129
+ "printf",
2130
+ "printf:*",
2131
+ "export",
2132
+ "export:*",
2133
+ "set",
2134
+ "unset",
2135
+ // Process information (read-only)
2136
+ "ps",
2137
+ "ps:*",
2138
+ "pgrep",
2139
+ "pgrep:*",
2140
+ "jobs",
2141
+ "top:-n:1",
2142
+ // Network information (read-only)
2143
+ "ifconfig",
2144
+ "ip:addr",
2145
+ "ip:link",
2146
+ "hostname:-I",
2147
+ "ping:-c:*",
2148
+ "traceroute",
2149
+ "nslookup",
2150
+ "dig",
2151
+ // Text processing and utilities (awk removed - too powerful)
2152
+ "sed:-n:*",
2153
+ "cut",
2154
+ "cut:*",
2155
+ "sort",
2156
+ "sort:*",
2157
+ "uniq",
2158
+ "uniq:*",
2159
+ "tr",
2160
+ "tr:*",
2161
+ "column",
2162
+ "column:*",
2163
+ "paste",
2164
+ "paste:*",
2165
+ "join",
2166
+ "join:*",
2167
+ "comm",
2168
+ "comm:*",
2169
+ "diff",
2170
+ "diff:*",
2171
+ "cmp",
2172
+ "cmp:*",
2173
+ "patch:--dry-run:*",
2174
+ // Hashing and encoding (read-only)
2175
+ "md5sum",
2176
+ "md5sum:*",
2177
+ "sha1sum",
2178
+ "sha1sum:*",
2179
+ "sha256sum",
2180
+ "sha256sum:*",
2181
+ "base64",
2182
+ "base64:-d",
2183
+ "od",
2184
+ "od:*",
2185
+ "hexdump",
2186
+ "hexdump:*",
2187
+ // Archive and compression (list/view only)
2188
+ "tar:-tf:*",
2189
+ "tar:-tzf:*",
2190
+ "unzip:-l:*",
2191
+ "zip:-l:*",
2192
+ "gzip:-l:*",
2193
+ "gunzip:-l:*",
2194
+ // Help and documentation
2195
+ "man",
2196
+ "man:*",
2197
+ "--help",
2198
+ "help",
2199
+ "info",
2200
+ "info:*",
2201
+ "whatis",
2202
+ "whatis:*",
2203
+ "apropos",
2204
+ "apropos:*",
2205
+ // Make (dry run and info)
2206
+ "make:-n",
2207
+ "make:--dry-run",
2208
+ "make:-p",
2209
+ "make:--print-data-base",
2210
+ // Docker (read-only operations)
2211
+ "docker:ps",
2212
+ "docker:images",
2213
+ "docker:version",
2214
+ "docker:info",
2215
+ "docker:logs:*",
2216
+ "docker:inspect:*",
2217
+ // Test runners (list/info only)
2218
+ "jest:--listTests",
2219
+ "mocha:--help",
2220
+ "pytest:--collect-only"
2221
+ ];
2222
+ DEFAULT_DENY_PATTERNS = [
2223
+ // Dangerous file operations
2224
+ "rm:-rf",
2225
+ "rm:-f:/",
2226
+ "rm:/",
2227
+ "rm:-rf:*",
2228
+ "rmdir",
2229
+ "chmod:777",
2230
+ "chmod:-R:777",
2231
+ "chown",
2232
+ "chgrp",
2233
+ "dd",
2234
+ "dd:*",
2235
+ "shred",
2236
+ "shred:*",
2237
+ // Dangerous find operations that can execute arbitrary commands
2238
+ "find:-exec:*",
2239
+ "find:*:-exec:*",
2240
+ "find:-execdir:*",
2241
+ "find:*:-execdir:*",
2242
+ "find:-ok:*",
2243
+ "find:*:-ok:*",
2244
+ "find:-okdir:*",
2245
+ "find:*:-okdir:*",
2246
+ // Powerful scripting tools that can execute arbitrary commands
2247
+ "awk",
2248
+ "awk:*",
2249
+ "perl",
2250
+ "perl:*",
2251
+ "python:-c:*",
2252
+ "node:-e:*",
2253
+ // System administration and modification
2254
+ "sudo:*",
2255
+ "su",
2256
+ "su:*",
2257
+ "passwd",
2258
+ "adduser",
2259
+ "useradd",
2260
+ "userdel",
2261
+ "usermod",
2262
+ "groupadd",
2263
+ "groupdel",
2264
+ "visudo",
2265
+ // Package installation and removal
2266
+ "npm:install",
2267
+ "npm:i",
2268
+ "npm:uninstall",
2269
+ "npm:publish",
2270
+ "npm:unpublish",
2271
+ "npm:link",
2272
+ "npm:update",
2273
+ "yarn:install",
2274
+ "yarn:add",
2275
+ "yarn:remove",
2276
+ "yarn:upgrade",
2277
+ "pnpm:install",
2278
+ "pnpm:add",
2279
+ "pnpm:remove",
2280
+ "pip:install",
2281
+ "pip:uninstall",
2282
+ "pip:upgrade",
2283
+ "pip3:install",
2284
+ "pip3:uninstall",
2285
+ "pip3:upgrade",
2286
+ "gem:install",
2287
+ "gem:uninstall",
2288
+ "gem:update",
2289
+ "bundle:install",
2290
+ "bundle:update",
2291
+ "composer:install",
2292
+ "composer:update",
2293
+ "composer:remove",
2294
+ "apt:*",
2295
+ "apt-get:*",
2296
+ "yum:*",
2297
+ "dnf:*",
2298
+ "zypper:*",
2299
+ "brew:install",
2300
+ "brew:uninstall",
2301
+ "brew:upgrade",
2302
+ "conda:install",
2303
+ "conda:remove",
2304
+ "conda:update",
2305
+ // Service and system control
2306
+ "systemctl:*",
2307
+ "service:*",
2308
+ "chkconfig:*",
2309
+ "initctl:*",
2310
+ "upstart:*",
2311
+ // Network operations that could be dangerous
2312
+ "curl:-d:*",
2313
+ "curl:--data:*",
2314
+ "curl:-X:POST:*",
2315
+ "curl:-X:PUT:*",
2316
+ "wget:-O:/",
2317
+ "wget:--post-data:*",
2318
+ "ssh",
2319
+ "ssh:*",
2320
+ "scp",
2321
+ "scp:*",
2322
+ "sftp",
2323
+ "sftp:*",
2324
+ "rsync:*",
2325
+ "nc",
2326
+ "nc:*",
2327
+ "netcat",
2328
+ "netcat:*",
2329
+ "telnet",
2330
+ "telnet:*",
2331
+ "ftp",
2332
+ "ftp:*",
2333
+ // Process control and termination
2334
+ "kill",
2335
+ "kill:*",
2336
+ "killall",
2337
+ "killall:*",
2338
+ "pkill",
2339
+ "pkill:*",
2340
+ "nohup:*",
2341
+ "disown:*",
2342
+ // System control and shutdown
2343
+ "shutdown",
2344
+ "shutdown:*",
2345
+ "reboot",
2346
+ "halt",
2347
+ "poweroff",
2348
+ "init",
2349
+ "telinit",
2350
+ // Kernel and module operations
2351
+ "insmod",
2352
+ "insmod:*",
2353
+ "rmmod",
2354
+ "rmmod:*",
2355
+ "modprobe",
2356
+ "modprobe:*",
2357
+ "sysctl:-w:*",
2358
+ // Dangerous git operations
2359
+ "git:push",
2360
+ "git:push:*",
2361
+ "git:force",
2362
+ "git:reset:--hard:*",
2363
+ "git:clean:-fd",
2364
+ "git:rm:*",
2365
+ "git:commit",
2366
+ "git:merge",
2367
+ "git:rebase",
2368
+ "git:cherry-pick",
2369
+ "git:stash:drop",
2370
+ // File system mounting and partitioning
2371
+ "mount",
2372
+ "mount:*",
2373
+ "umount",
2374
+ "umount:*",
2375
+ "fdisk",
2376
+ "fdisk:*",
2377
+ "parted",
2378
+ "parted:*",
2379
+ "mkfs",
2380
+ "mkfs:*",
2381
+ "fsck",
2382
+ "fsck:*",
2383
+ // Cron and scheduling
2384
+ "crontab",
2385
+ "crontab:*",
2386
+ "at",
2387
+ "at:*",
2388
+ "batch",
2389
+ "batch:*",
2390
+ // Compression with potential overwrite
2391
+ "tar:-xf:*",
2392
+ "unzip",
2393
+ "unzip:*",
2394
+ "gzip:*",
2395
+ "gunzip:*",
2396
+ // Build and compilation that might modify files
2397
+ "make",
2398
+ "make:install",
2399
+ "make:clean",
2400
+ "cargo:build",
2401
+ "cargo:install",
2402
+ "npm:run:build",
2403
+ "yarn:build",
2404
+ "mvn:install",
2405
+ "gradle:build",
2406
+ // Docker operations that could modify state
2407
+ "docker:run",
2408
+ "docker:run:*",
2409
+ "docker:exec",
2410
+ "docker:exec:*",
2411
+ "docker:build",
2412
+ "docker:build:*",
2413
+ "docker:pull",
2414
+ "docker:push",
2415
+ "docker:rm",
2416
+ "docker:rmi",
2417
+ "docker:stop",
2418
+ "docker:start",
2419
+ // Database operations
2420
+ "mysql:-e:DROP",
2421
+ "psql:-c:DROP",
2422
+ "redis-cli:FLUSHALL",
2423
+ "mongo:--eval:*",
2424
+ // Text editors that could modify files
2425
+ "vi",
2426
+ "vi:*",
2427
+ "vim",
2428
+ "vim:*",
2429
+ "nano",
2430
+ "nano:*",
2431
+ "emacs",
2432
+ "emacs:*",
2433
+ "sed:-i:*",
2434
+ "perl:-i:*",
2435
+ // Potentially dangerous utilities
2436
+ "eval",
2437
+ "eval:*",
2438
+ "exec",
2439
+ "exec:*",
2440
+ "source",
2441
+ "source:*",
2442
+ "bash:-c:*",
2443
+ "sh:-c:*",
2444
+ "zsh:-c:*"
2445
+ ];
2446
+ }
2447
+ });
2448
+
2449
+ // src/agent/bashCommandUtils.js
2450
+ function parseSimpleCommand(command) {
2451
+ if (!command || typeof command !== "string") {
2452
+ return {
2453
+ success: false,
2454
+ error: "Command must be a non-empty string",
2455
+ command: null,
2456
+ args: [],
2457
+ isComplex: false
2458
+ };
2459
+ }
2460
+ const trimmed = command.trim();
2461
+ if (!trimmed) {
2462
+ return {
2463
+ success: false,
2464
+ error: "Command cannot be empty",
2465
+ command: null,
2466
+ args: [],
2467
+ isComplex: false
2468
+ };
2469
+ }
2470
+ const complexPatterns = [
2471
+ /\|/,
2472
+ // Pipes
2473
+ /&&/,
2474
+ // Logical AND
2475
+ /\|\|/,
2476
+ // Logical OR
2477
+ /(?<!\\);/,
2478
+ // Command separator (but not escaped \;)
2479
+ /&$/,
2480
+ // Background execution
2481
+ /\$\(/,
2482
+ // Command substitution $()
2483
+ /`/,
2484
+ // Command substitution ``
2485
+ />/,
2486
+ // Redirection >
2487
+ /</,
2488
+ // Redirection <
2489
+ /\*\*/,
2490
+ // Glob patterns (potentially dangerous)
2491
+ /^\s*\{.*,.*\}|\{.*\.\.\.*\}/
2492
+ // Brace expansion like {a,b} or {1..10} (but not find {} placeholders)
2493
+ ];
2494
+ for (const pattern of complexPatterns) {
2495
+ if (pattern.test(trimmed)) {
2496
+ return {
2497
+ success: false,
2498
+ error: "Complex shell commands with pipes, operators, or redirections are not supported for security reasons",
2499
+ command: null,
2500
+ args: [],
2501
+ isComplex: true,
2502
+ detected: pattern.toString()
2503
+ };
2504
+ }
2505
+ }
2506
+ const args = [];
2507
+ let current = "";
2508
+ let inQuotes = false;
2509
+ let quoteChar = "";
2510
+ let escaped = false;
2511
+ for (let i3 = 0; i3 < trimmed.length; i3++) {
2512
+ const char = trimmed[i3];
2513
+ const nextChar = i3 + 1 < trimmed.length ? trimmed[i3 + 1] : "";
2514
+ if (escaped) {
2515
+ current += char;
2516
+ escaped = false;
2517
+ continue;
2518
+ }
2519
+ if (char === "\\" && !inQuotes) {
2520
+ escaped = true;
2521
+ continue;
2522
+ }
2523
+ if (!inQuotes && (char === '"' || char === "'")) {
2524
+ inQuotes = true;
2525
+ quoteChar = char;
2526
+ } else if (inQuotes && char === quoteChar) {
2527
+ inQuotes = false;
2528
+ quoteChar = "";
2529
+ } else if (!inQuotes && char === " ") {
2530
+ if (current.trim()) {
2531
+ args.push(current.trim());
2532
+ current = "";
2533
+ }
2534
+ } else {
2535
+ current += char;
2536
+ }
2537
+ }
2538
+ if (current.trim()) {
2539
+ args.push(current.trim());
2540
+ }
2541
+ if (inQuotes) {
2542
+ return {
2543
+ success: false,
2544
+ error: `Unclosed quote in command: ${quoteChar}`,
2545
+ command: null,
2546
+ args: [],
2547
+ isComplex: false
2548
+ };
2549
+ }
2550
+ if (args.length === 0) {
2551
+ return {
2552
+ success: false,
2553
+ error: "No command found after parsing",
2554
+ command: null,
2555
+ args: [],
2556
+ isComplex: false
2557
+ };
2558
+ }
2559
+ const [baseCommand, ...commandArgs] = args;
2560
+ return {
2561
+ success: true,
2562
+ error: null,
2563
+ command: baseCommand,
2564
+ args: commandArgs,
2565
+ fullArgs: args,
2566
+ isComplex: false,
2567
+ original: command
2568
+ };
2569
+ }
2570
+ function isComplexCommand(command) {
2571
+ const result = parseSimpleCommand(command);
2572
+ return result.isComplex;
2573
+ }
2574
+ function parseCommand(command) {
2575
+ const result = parseSimpleCommand(command);
2576
+ if (!result.success) {
2577
+ return {
2578
+ command: "",
2579
+ args: [],
2580
+ error: result.error,
2581
+ isComplex: result.isComplex
2582
+ };
2583
+ }
2584
+ return {
2585
+ command: result.command,
2586
+ args: result.args,
2587
+ error: null,
2588
+ isComplex: result.isComplex
2589
+ };
2590
+ }
2591
+ function parseCommandForExecution(command) {
2592
+ const result = parseSimpleCommand(command);
2593
+ if (!result.success) {
2594
+ return null;
2595
+ }
2596
+ return result.fullArgs;
2597
+ }
2598
+ var init_bashCommandUtils = __esm({
2599
+ "src/agent/bashCommandUtils.js"() {
2600
+ "use strict";
2601
+ }
2602
+ });
2603
+
2604
+ // src/agent/bashPermissions.js
2605
+ function matchesPattern(parsedCommand, pattern) {
2606
+ if (!parsedCommand || !pattern) return false;
2607
+ const { command, args } = parsedCommand;
2608
+ if (!command) return false;
2609
+ const patternParts = pattern.split(":");
2610
+ const commandName = patternParts[0];
2611
+ if (commandName === "*") {
2612
+ return true;
2613
+ } else if (commandName !== command) {
2614
+ return false;
2615
+ }
2616
+ if (patternParts.length === 1) {
2617
+ return true;
2618
+ }
2619
+ for (let i3 = 1; i3 < patternParts.length; i3++) {
2620
+ const patternArg = patternParts[i3];
2621
+ const argIndex = i3 - 1;
2622
+ if (patternArg === "*") {
2623
+ continue;
2624
+ }
2625
+ if (argIndex >= args.length) {
2626
+ return false;
2627
+ }
2628
+ const actualArg = args[argIndex];
2629
+ if (patternArg !== actualArg) {
2630
+ return false;
2631
+ }
2632
+ }
2633
+ return true;
2634
+ }
2635
+ function matchesAnyPattern(parsedCommand, patterns) {
2636
+ if (!patterns || patterns.length === 0) return false;
2637
+ return patterns.some((pattern) => matchesPattern(parsedCommand, pattern));
2638
+ }
2639
+ var BashPermissionChecker;
2640
+ var init_bashPermissions = __esm({
2641
+ "src/agent/bashPermissions.js"() {
2642
+ "use strict";
2643
+ init_bashDefaults();
2644
+ init_bashCommandUtils();
2645
+ BashPermissionChecker = class {
2646
+ /**
2647
+ * Create a permission checker
2648
+ * @param {Object} config - Configuration options
2649
+ * @param {string[]} [config.allow] - Additional allow patterns
2650
+ * @param {string[]} [config.deny] - Additional deny patterns
2651
+ * @param {boolean} [config.disableDefaultAllow] - Disable default allow list
2652
+ * @param {boolean} [config.disableDefaultDeny] - Disable default deny list
2653
+ * @param {boolean} [config.debug] - Enable debug logging
2654
+ */
2655
+ constructor(config = {}) {
2656
+ this.debug = config.debug || false;
2657
+ this.allowPatterns = [];
2658
+ if (!config.disableDefaultAllow) {
2659
+ this.allowPatterns.push(...DEFAULT_ALLOW_PATTERNS);
2660
+ if (this.debug) {
2661
+ console.log(`[BashPermissions] Added ${DEFAULT_ALLOW_PATTERNS.length} default allow patterns`);
2662
+ }
2663
+ }
2664
+ if (config.allow && Array.isArray(config.allow)) {
2665
+ this.allowPatterns.push(...config.allow);
2666
+ if (this.debug) {
2667
+ console.log(`[BashPermissions] Added ${config.allow.length} custom allow patterns:`, config.allow);
2668
+ }
2669
+ }
2670
+ this.denyPatterns = [];
2671
+ if (!config.disableDefaultDeny) {
2672
+ this.denyPatterns.push(...DEFAULT_DENY_PATTERNS);
2673
+ if (this.debug) {
2674
+ console.log(`[BashPermissions] Added ${DEFAULT_DENY_PATTERNS.length} default deny patterns`);
2675
+ }
2676
+ }
2677
+ if (config.deny && Array.isArray(config.deny)) {
2678
+ this.denyPatterns.push(...config.deny);
2679
+ if (this.debug) {
2680
+ console.log(`[BashPermissions] Added ${config.deny.length} custom deny patterns:`, config.deny);
2681
+ }
2682
+ }
2683
+ if (this.debug) {
2684
+ console.log(`[BashPermissions] Total patterns - Allow: ${this.allowPatterns.length}, Deny: ${this.denyPatterns.length}`);
2685
+ }
2686
+ }
2687
+ /**
2688
+ * Check if a simple command is allowed (rejects complex commands for security)
2689
+ * @param {string} command - Command to check
2690
+ * @returns {Object} Permission result
2691
+ */
2692
+ check(command) {
2693
+ if (!command || typeof command !== "string") {
2694
+ return {
2695
+ allowed: false,
2696
+ reason: "Invalid or empty command",
2697
+ command
2698
+ };
2699
+ }
2700
+ if (isComplexCommand(command)) {
2701
+ return {
2702
+ allowed: false,
2703
+ reason: "Complex shell commands with pipes, operators, or redirections are not supported for security reasons",
2704
+ command,
2705
+ isComplex: true
2706
+ };
2707
+ }
2708
+ const parsed = parseCommand(command);
2709
+ if (parsed.error) {
2710
+ return {
2711
+ allowed: false,
2712
+ reason: parsed.error,
2713
+ command
2714
+ };
2715
+ }
2716
+ if (!parsed.command) {
2717
+ return {
2718
+ allowed: false,
2719
+ reason: "No valid command found",
2720
+ command
2721
+ };
2722
+ }
2723
+ if (this.debug) {
2724
+ console.log(`[BashPermissions] Checking simple command: "${command}"`);
2725
+ console.log(`[BashPermissions] Parsed: ${parsed.command} with args: [${parsed.args.join(", ")}]`);
2726
+ }
2727
+ if (matchesAnyPattern(parsed, this.denyPatterns)) {
2728
+ const matchedPatterns = this.denyPatterns.filter((pattern) => matchesPattern(parsed, pattern));
2729
+ return {
2730
+ allowed: false,
2731
+ reason: `Command matches deny pattern: ${matchedPatterns[0]}`,
2732
+ command,
2733
+ parsed,
2734
+ matchedPatterns
2735
+ };
2736
+ }
2737
+ if (this.allowPatterns.length > 0) {
2738
+ if (!matchesAnyPattern(parsed, this.allowPatterns)) {
2739
+ return {
2740
+ allowed: false,
2741
+ reason: "Command not in allow list",
2742
+ command,
2743
+ parsed
2744
+ };
2745
+ }
2746
+ }
2747
+ const result = {
2748
+ allowed: true,
2749
+ command,
2750
+ parsed,
2751
+ isComplex: false
2752
+ };
2753
+ if (this.debug) {
2754
+ console.log(`[BashPermissions] ALLOWED - command passed all checks`);
2755
+ }
2756
+ return result;
2757
+ }
2758
+ /**
2759
+ * Get configuration summary
2760
+ * @returns {Object} Configuration info
2761
+ */
2762
+ getConfig() {
2763
+ return {
2764
+ allowPatterns: this.allowPatterns.length,
2765
+ denyPatterns: this.denyPatterns.length,
2766
+ totalPatterns: this.allowPatterns.length + this.denyPatterns.length
2767
+ };
2768
+ }
2769
+ };
2770
+ }
2771
+ });
2772
+
2773
+ // src/agent/bashExecutor.js
2774
+ async function executeBashCommand(command, options = {}) {
2775
+ const {
2776
+ workingDirectory = process.cwd(),
2777
+ timeout = 12e4,
2778
+ // 2 minutes default
2779
+ env = {},
2780
+ maxBuffer = 10 * 1024 * 1024,
2781
+ // 10MB
2782
+ debug = false
2783
+ } = options;
2784
+ let cwd = workingDirectory;
2785
+ try {
2786
+ cwd = (0, import_path4.resolve)(cwd);
2787
+ if (!(0, import_fs.existsSync)(cwd)) {
2788
+ throw new Error(`Working directory does not exist: ${cwd}`);
2789
+ }
2790
+ } catch (error2) {
2791
+ return {
2792
+ success: false,
2793
+ error: `Invalid working directory: ${error2.message}`,
2794
+ stdout: "",
2795
+ stderr: "",
2796
+ exitCode: 1,
2797
+ command,
2798
+ workingDirectory: cwd,
2799
+ duration: 0
2800
+ };
2801
+ }
2802
+ const startTime = Date.now();
2803
+ if (debug) {
2804
+ console.log(`[BashExecutor] Executing command: "${command}"`);
2805
+ console.log(`[BashExecutor] Working directory: "${cwd}"`);
2806
+ console.log(`[BashExecutor] Timeout: ${timeout}ms`);
2807
+ }
2808
+ return new Promise((resolve4, reject) => {
2809
+ const processEnv = {
2810
+ ...process.env,
2811
+ ...env
2812
+ };
2813
+ const args = parseCommandForExecution(command);
2814
+ if (!args || args.length === 0) {
2815
+ resolve4({
2816
+ success: false,
2817
+ error: "Failed to parse command",
2818
+ stdout: "",
2819
+ stderr: "",
2820
+ exitCode: 1,
2821
+ command,
2822
+ workingDirectory: cwd,
2823
+ duration: Date.now() - startTime
2824
+ });
2825
+ return;
2826
+ }
2827
+ const [cmd, ...cmdArgs] = args;
2828
+ const child = (0, import_child_process6.spawn)(cmd, cmdArgs, {
2829
+ cwd,
2830
+ env: processEnv,
2831
+ stdio: ["ignore", "pipe", "pipe"],
2832
+ // stdin ignored, capture stdout/stderr
2833
+ shell: false,
2834
+ // For security
2835
+ windowsHide: true
2836
+ });
2837
+ let stdout = "";
2838
+ let stderr = "";
2839
+ let killed = false;
2840
+ let timeoutHandle;
2841
+ if (timeout > 0) {
2842
+ timeoutHandle = setTimeout(() => {
2843
+ if (!killed) {
2844
+ killed = true;
2845
+ child.kill("SIGTERM");
2846
+ setTimeout(() => {
2847
+ if (child.exitCode === null) {
2848
+ child.kill("SIGKILL");
2849
+ }
2850
+ }, 5e3);
2851
+ }
2852
+ }, timeout);
2853
+ }
2854
+ child.stdout.on("data", (data2) => {
2855
+ const chunk = data2.toString();
2856
+ if (stdout.length + chunk.length <= maxBuffer) {
2857
+ stdout += chunk;
2858
+ } else {
2859
+ if (!killed) {
2860
+ killed = true;
2861
+ child.kill("SIGTERM");
2862
+ }
2863
+ }
2864
+ });
2865
+ child.stderr.on("data", (data2) => {
2866
+ const chunk = data2.toString();
2867
+ if (stderr.length + chunk.length <= maxBuffer) {
2868
+ stderr += chunk;
2869
+ } else {
2870
+ if (!killed) {
2871
+ killed = true;
2872
+ child.kill("SIGTERM");
2873
+ }
2874
+ }
2875
+ });
2876
+ child.on("close", (code, signal) => {
2877
+ if (timeoutHandle) {
2878
+ clearTimeout(timeoutHandle);
2879
+ }
2880
+ const duration = Date.now() - startTime;
2881
+ if (debug) {
2882
+ console.log(`[BashExecutor] Command completed - Code: ${code}, Signal: ${signal}, Duration: ${duration}ms`);
2883
+ console.log(`[BashExecutor] Stdout length: ${stdout.length}, Stderr length: ${stderr.length}`);
2884
+ }
2885
+ let success = true;
2886
+ let error2 = "";
2887
+ if (killed) {
2888
+ success = false;
2889
+ if (stdout.length + stderr.length > maxBuffer) {
2890
+ error2 = `Command output exceeded maximum buffer size (${maxBuffer} bytes)`;
2891
+ } else {
2892
+ error2 = `Command timed out after ${timeout}ms`;
2893
+ }
2894
+ } else if (code !== 0) {
2895
+ success = false;
2896
+ error2 = `Command exited with code ${code}`;
2897
+ }
2898
+ resolve4({
2899
+ success,
2900
+ error: error2,
2901
+ stdout: stdout.trim(),
2902
+ stderr: stderr.trim(),
2903
+ exitCode: code,
2904
+ signal,
2905
+ command,
2906
+ workingDirectory: cwd,
2907
+ duration,
2908
+ killed
2909
+ });
2910
+ });
2911
+ child.on("error", (error2) => {
2912
+ if (timeoutHandle) {
2913
+ clearTimeout(timeoutHandle);
2914
+ }
2915
+ if (debug) {
2916
+ console.log(`[BashExecutor] Spawn error:`, error2);
2917
+ }
2918
+ resolve4({
2919
+ success: false,
2920
+ error: `Failed to execute command: ${error2.message}`,
2921
+ stdout: "",
2922
+ stderr: "",
2923
+ exitCode: 1,
2924
+ command,
2925
+ workingDirectory: cwd,
2926
+ duration: Date.now() - startTime
2927
+ });
2928
+ });
2929
+ });
2930
+ }
2931
+ function formatExecutionResult(result, includeMetadata = false) {
2932
+ if (!result) {
2933
+ return "No result available";
2934
+ }
2935
+ let output = "";
2936
+ if (includeMetadata) {
2937
+ output += `Command: ${result.command}
2938
+ `;
2939
+ output += `Working directory: ${result.workingDirectory}
2940
+ `;
2941
+ output += `Duration: ${result.duration}ms
2942
+ `;
2943
+ output += `Exit Code: ${result.exitCode}
2944
+ `;
2945
+ if (result.signal) {
2946
+ output += `Signal: ${result.signal}
2947
+ `;
2948
+ }
2949
+ output += "\n";
2950
+ }
2951
+ if (result.stdout) {
2952
+ if (includeMetadata) {
2953
+ output += "--- STDOUT ---\n";
2954
+ }
2955
+ output += result.stdout;
2956
+ if (includeMetadata && result.stderr) {
2957
+ output += "\n";
2958
+ }
2959
+ }
2960
+ if (result.stderr) {
2961
+ if (includeMetadata) {
2962
+ if (result.stdout) output += "\n";
2963
+ output += "--- STDERR ---\n";
2964
+ } else if (result.stdout) {
2965
+ output += "\n--- STDERR ---\n";
2966
+ }
2967
+ output += result.stderr;
2968
+ }
2969
+ if (!result.success && result.error && !result.stderr) {
2970
+ if (output) output += "\n";
2971
+ output += `Error: ${result.error}`;
2972
+ }
2973
+ if (!result.success && result.exitCode !== void 0 && result.exitCode !== 0) {
2974
+ if (output) output += "\n";
2975
+ output += `Exit code: ${result.exitCode}`;
2976
+ }
2977
+ return output || (result.success ? "Command completed successfully (no output)" : "Command failed (no output)");
2978
+ }
2979
+ function validateExecutionOptions(options = {}) {
2980
+ const errors = [];
2981
+ const warnings = [];
2982
+ if (options.timeout !== void 0) {
2983
+ if (typeof options.timeout !== "number" || options.timeout < 0) {
2984
+ errors.push("timeout must be a non-negative number");
2985
+ } else if (options.timeout > 6e5) {
2986
+ warnings.push("timeout is very high (>10 minutes)");
2987
+ }
2988
+ }
2989
+ if (options.maxBuffer !== void 0) {
2990
+ if (typeof options.maxBuffer !== "number" || options.maxBuffer < 1024) {
2991
+ errors.push("maxBuffer must be at least 1024 bytes");
2992
+ } else if (options.maxBuffer > 100 * 1024 * 1024) {
2993
+ warnings.push("maxBuffer is very high (>100MB)");
2994
+ }
2995
+ }
2996
+ if (options.workingDirectory) {
2997
+ if (typeof options.workingDirectory !== "string") {
2998
+ errors.push("workingDirectory must be a string");
2999
+ } else if (!(0, import_fs.existsSync)(options.workingDirectory)) {
3000
+ errors.push(`workingDirectory does not exist: ${options.workingDirectory}`);
3001
+ }
3002
+ }
3003
+ if (options.env && typeof options.env !== "object") {
3004
+ errors.push("env must be an object");
3005
+ }
3006
+ return {
3007
+ valid: errors.length === 0,
3008
+ errors,
3009
+ warnings
3010
+ };
3011
+ }
3012
+ var import_child_process6, import_path4, import_fs;
3013
+ var init_bashExecutor = __esm({
3014
+ "src/agent/bashExecutor.js"() {
3015
+ "use strict";
3016
+ import_child_process6 = require("child_process");
3017
+ import_path4 = require("path");
3018
+ import_fs = require("fs");
3019
+ init_bashCommandUtils();
3020
+ }
3021
+ });
3022
+
3023
+ // src/tools/bash.js
3024
+ var import_ai2, import_path5, bashTool;
3025
+ var init_bash = __esm({
3026
+ "src/tools/bash.js"() {
3027
+ "use strict";
3028
+ import_ai2 = require("ai");
3029
+ import_path5 = require("path");
3030
+ init_bashPermissions();
3031
+ init_bashExecutor();
3032
+ bashTool = (options = {}) => {
3033
+ const {
3034
+ bashConfig = {},
3035
+ debug = false,
3036
+ defaultPath,
3037
+ allowedFolders = []
3038
+ } = options;
3039
+ const permissionChecker = new BashPermissionChecker({
3040
+ allow: bashConfig.allow,
3041
+ deny: bashConfig.deny,
3042
+ disableDefaultAllow: bashConfig.disableDefaultAllow,
3043
+ disableDefaultDeny: bashConfig.disableDefaultDeny,
3044
+ debug
3045
+ });
3046
+ const getDefaultWorkingDirectory = () => {
3047
+ if (bashConfig.workingDirectory) {
3048
+ return bashConfig.workingDirectory;
3049
+ }
3050
+ if (defaultPath) {
3051
+ return defaultPath;
3052
+ }
3053
+ if (allowedFolders && allowedFolders.length > 0) {
3054
+ return allowedFolders[0];
3055
+ }
3056
+ return process.cwd();
3057
+ };
3058
+ return (0, import_ai2.tool)({
3059
+ name: "bash",
3060
+ description: `Execute bash commands for system exploration and development tasks.
3061
+
3062
+ Security: This tool has built-in security with allow/deny lists. By default, only safe read-only commands are allowed for code exploration.
3063
+
3064
+ Parameters:
3065
+ - command: (required) The bash command to execute
3066
+ - workingDirectory: (optional) Directory to execute command in
3067
+ - timeout: (optional) Command timeout in milliseconds
3068
+ - env: (optional) Additional environment variables
3069
+
3070
+ Examples of allowed commands by default:
3071
+ - File exploration: ls, cat, head, tail, find, grep
3072
+ - Git operations: git status, git log, git diff, git show
3073
+ - Package info: npm list, pip list, cargo --version
3074
+ - System info: whoami, pwd, uname, date
3075
+
3076
+ Dangerous commands are blocked by default (rm -rf, sudo, npm install, etc.)`,
3077
+ inputSchema: {
3078
+ type: "object",
3079
+ properties: {
3080
+ command: {
3081
+ type: "string",
3082
+ description: "The bash command to execute"
3083
+ },
3084
+ workingDirectory: {
3085
+ type: "string",
3086
+ description: "Directory to execute the command in (optional)"
3087
+ },
3088
+ timeout: {
3089
+ type: "number",
3090
+ description: "Command timeout in milliseconds (optional)",
3091
+ minimum: 1e3,
3092
+ maximum: 6e5
3093
+ },
3094
+ env: {
3095
+ type: "object",
3096
+ description: "Additional environment variables (optional)",
3097
+ additionalProperties: {
3098
+ type: "string"
3099
+ }
3100
+ }
3101
+ },
3102
+ required: ["command"],
3103
+ additionalProperties: false
3104
+ },
3105
+ execute: async ({ command, workingDirectory, timeout, env }) => {
3106
+ try {
3107
+ if (command === null || command === void 0 || typeof command !== "string") {
3108
+ return "Error: Command is required and must be a string";
3109
+ }
3110
+ if (command.trim().length === 0) {
3111
+ return "Error: Command cannot be empty";
3112
+ }
3113
+ const permissionResult = permissionChecker.check(command.trim());
3114
+ if (!permissionResult.allowed) {
3115
+ if (debug) {
3116
+ console.log(`[BashTool] Permission denied for command: "${command}"`);
3117
+ console.log(`[BashTool] Reason: ${permissionResult.reason}`);
3118
+ }
3119
+ return `Permission denied: ${permissionResult.reason}
3120
+
3121
+ This command is not allowed by the current security policy.
3122
+
3123
+ Common reasons:
3124
+ 1. The command is in the deny list (potentially dangerous)
3125
+ 2. The command is not in the allow list (not a recognized safe command)
3126
+
3127
+ If you believe this command should be allowed, you can:
3128
+ - Use the --bash-allow option to add specific patterns
3129
+ - Use the --no-default-bash-deny flag to remove default restrictions (not recommended)
3130
+
3131
+ For code exploration, try these safe alternatives:
3132
+ - ls, cat, head, tail for file operations
3133
+ - find, grep, rg for searching
3134
+ - git status, git log, git show for git operations
3135
+ - npm list, pip list for package information`;
3136
+ }
3137
+ const workingDir = workingDirectory || getDefaultWorkingDirectory();
3138
+ if (allowedFolders && allowedFolders.length > 0) {
3139
+ const resolvedWorkingDir = (0, import_path5.resolve)(workingDir);
3140
+ const isAllowed = allowedFolders.some((folder) => {
3141
+ const resolvedFolder = (0, import_path5.resolve)(folder);
3142
+ return resolvedWorkingDir.startsWith(resolvedFolder);
3143
+ });
3144
+ if (!isAllowed) {
3145
+ return `Error: Working directory "${workingDir}" is not within allowed folders: ${allowedFolders.join(", ")}`;
3146
+ }
3147
+ }
3148
+ const executionOptions = {
3149
+ workingDirectory: workingDir,
3150
+ timeout: timeout || bashConfig.timeout || 12e4,
3151
+ env: { ...bashConfig.env, ...env },
3152
+ maxBuffer: bashConfig.maxBuffer,
3153
+ debug
3154
+ };
3155
+ const validation = validateExecutionOptions(executionOptions);
3156
+ if (!validation.valid) {
3157
+ return `Error: Invalid execution options: ${validation.errors.join(", ")}`;
3158
+ }
3159
+ if (validation.warnings.length > 0 && debug) {
3160
+ console.log("[BashTool] Warnings:", validation.warnings);
3161
+ }
3162
+ if (debug) {
3163
+ console.log(`[BashTool] Executing command: "${command}"`);
3164
+ console.log(`[BashTool] Working directory: "${workingDir}"`);
3165
+ console.log(`[BashTool] Timeout: ${executionOptions.timeout}ms`);
3166
+ }
3167
+ const result = await executeBashCommand(command.trim(), executionOptions);
3168
+ if (debug) {
3169
+ console.log(`[BashTool] Command completed - Success: ${result.success}, Duration: ${result.duration}ms`);
3170
+ }
3171
+ const formattedResult = formatExecutionResult(result, debug);
3172
+ if (!result.success) {
3173
+ let errorInfo = `
3174
+
3175
+ Command failed with exit code ${result.exitCode}`;
3176
+ if (result.killed) {
3177
+ errorInfo += ` (${result.error})`;
3178
+ }
3179
+ return formattedResult + errorInfo;
3180
+ }
3181
+ return formattedResult;
3182
+ } catch (error2) {
3183
+ if (debug) {
3184
+ console.error("[BashTool] Execution error:", error2);
3185
+ }
3186
+ return `Error executing bash command: ${error2.message}`;
3187
+ }
3188
+ }
3189
+ });
3190
+ };
3191
+ }
3192
+ });
3193
+
1890
3194
  // src/tools/langchain.js
1891
3195
  function createSearchTool() {
1892
3196
  return {
@@ -2104,6 +3408,10 @@ __export(tools_exports, {
2104
3408
  DEFAULT_SYSTEM_MESSAGE: () => DEFAULT_SYSTEM_MESSAGE,
2105
3409
  attemptCompletionSchema: () => attemptCompletionSchema,
2106
3410
  attemptCompletionToolDefinition: () => attemptCompletionToolDefinition,
3411
+ bashDescription: () => bashDescription,
3412
+ bashSchema: () => bashSchema,
3413
+ bashTool: () => bashTool,
3414
+ bashToolDefinition: () => bashToolDefinition,
2107
3415
  createExtractTool: () => createExtractTool,
2108
3416
  createQueryTool: () => createQueryTool,
2109
3417
  createSearchTool: () => createSearchTool,
@@ -2124,16 +3432,19 @@ var init_tools = __esm({
2124
3432
  "src/tools/index.js"() {
2125
3433
  "use strict";
2126
3434
  init_vercel();
3435
+ init_bash();
2127
3436
  init_langchain();
2128
3437
  init_common();
2129
3438
  init_system_message();
2130
3439
  init_vercel();
3440
+ init_bash();
2131
3441
  init_system_message();
2132
3442
  tools = {
2133
3443
  searchTool: searchTool(),
2134
3444
  queryTool: queryTool(),
2135
3445
  extractTool: extractTool(),
2136
3446
  delegateTool: delegateTool(),
3447
+ bashTool: bashTool(),
2137
3448
  DEFAULT_SYSTEM_MESSAGE
2138
3449
  };
2139
3450
  }
@@ -2146,10 +3457,10 @@ async function listFilesByLevel(options) {
2146
3457
  maxFiles = 100,
2147
3458
  respectGitignore = true
2148
3459
  } = options;
2149
- if (!import_fs.default.existsSync(directory)) {
3460
+ if (!import_fs2.default.existsSync(directory)) {
2150
3461
  throw new Error(`Directory does not exist: ${directory}`);
2151
3462
  }
2152
- const gitDirExists = import_fs.default.existsSync(import_path4.default.join(directory, ".git"));
3463
+ const gitDirExists = import_fs2.default.existsSync(import_path6.default.join(directory, ".git"));
2153
3464
  if (gitDirExists && respectGitignore) {
2154
3465
  try {
2155
3466
  return await listFilesUsingGit(directory, maxFiles);
@@ -2164,8 +3475,8 @@ async function listFilesUsingGit(directory, maxFiles) {
2164
3475
  const { stdout } = await execAsync4("git ls-files", { cwd: directory });
2165
3476
  const files = stdout.split("\n").filter(Boolean);
2166
3477
  const sortedFiles = files.sort((a3, b3) => {
2167
- const depthA = a3.split(import_path4.default.sep).length;
2168
- const depthB = b3.split(import_path4.default.sep).length;
3478
+ const depthA = a3.split(import_path6.default.sep).length;
3479
+ const depthB = b3.split(import_path6.default.sep).length;
2169
3480
  return depthA - depthB;
2170
3481
  });
2171
3482
  return sortedFiles.slice(0, maxFiles);
@@ -2180,19 +3491,19 @@ async function listFilesByLevelManually(directory, maxFiles, respectGitignore) {
2180
3491
  while (queue.length > 0 && result.length < maxFiles) {
2181
3492
  const { dir, level } = queue.shift();
2182
3493
  try {
2183
- const entries = import_fs.default.readdirSync(dir, { withFileTypes: true });
3494
+ const entries = import_fs2.default.readdirSync(dir, { withFileTypes: true });
2184
3495
  const files = entries.filter((entry) => entry.isFile());
2185
3496
  for (const file of files) {
2186
3497
  if (result.length >= maxFiles) break;
2187
- const filePath = import_path4.default.join(dir, file.name);
2188
- const relativePath = import_path4.default.relative(directory, filePath);
3498
+ const filePath = import_path6.default.join(dir, file.name);
3499
+ const relativePath = import_path6.default.relative(directory, filePath);
2189
3500
  if (shouldIgnore(relativePath, ignorePatterns)) continue;
2190
3501
  result.push(relativePath);
2191
3502
  }
2192
3503
  const dirs = entries.filter((entry) => entry.isDirectory());
2193
3504
  for (const subdir of dirs) {
2194
- const subdirPath = import_path4.default.join(dir, subdir.name);
2195
- const relativeSubdirPath = import_path4.default.relative(directory, subdirPath);
3505
+ const subdirPath = import_path6.default.join(dir, subdir.name);
3506
+ const relativeSubdirPath = import_path6.default.relative(directory, subdirPath);
2196
3507
  if (shouldIgnore(relativeSubdirPath, ignorePatterns)) continue;
2197
3508
  if (subdir.name === "node_modules" || subdir.name === ".git") continue;
2198
3509
  queue.push({ dir: subdirPath, level: level + 1 });
@@ -2204,12 +3515,12 @@ async function listFilesByLevelManually(directory, maxFiles, respectGitignore) {
2204
3515
  return result;
2205
3516
  }
2206
3517
  function loadGitignorePatterns(directory) {
2207
- const gitignorePath = import_path4.default.join(directory, ".gitignore");
2208
- if (!import_fs.default.existsSync(gitignorePath)) {
3518
+ const gitignorePath = import_path6.default.join(directory, ".gitignore");
3519
+ if (!import_fs2.default.existsSync(gitignorePath)) {
2209
3520
  return [];
2210
3521
  }
2211
3522
  try {
2212
- const content = import_fs.default.readFileSync(gitignorePath, "utf8");
3523
+ const content = import_fs2.default.readFileSync(gitignorePath, "utf8");
2213
3524
  return content.split("\n").map((line) => line.trim()).filter((line) => line && !line.startsWith("#"));
2214
3525
  } catch (error2) {
2215
3526
  console.error(`Warning: Could not read .gitignore: ${error2.message}`);
@@ -2227,15 +3538,15 @@ function shouldIgnore(filePath, ignorePatterns) {
2227
3538
  }
2228
3539
  return false;
2229
3540
  }
2230
- var import_fs, import_path4, import_util5, import_child_process6, execAsync4;
3541
+ var import_fs2, import_path6, import_util5, import_child_process7, execAsync4;
2231
3542
  var init_file_lister = __esm({
2232
3543
  "src/utils/file-lister.js"() {
2233
3544
  "use strict";
2234
- import_fs = __toESM(require("fs"), 1);
2235
- import_path4 = __toESM(require("path"), 1);
3545
+ import_fs2 = __toESM(require("fs"), 1);
3546
+ import_path6 = __toESM(require("path"), 1);
2236
3547
  import_util5 = require("util");
2237
- import_child_process6 = require("child_process");
2238
- execAsync4 = (0, import_util5.promisify)(import_child_process6.exec);
3548
+ import_child_process7 = require("child_process");
3549
+ execAsync4 = (0, import_util5.promisify)(import_child_process7.exec);
2239
3550
  }
2240
3551
  });
2241
3552
 
@@ -4390,7 +5701,7 @@ var require_headStream = __commonJS({
4390
5701
  if ((0, stream_type_check_1.isReadableStream)(stream)) {
4391
5702
  return (0, headStream_browser_1.headStream)(stream, bytes);
4392
5703
  }
4393
- return new Promise((resolve2, reject) => {
5704
+ return new Promise((resolve4, reject) => {
4394
5705
  const collector = new Collector();
4395
5706
  collector.limit = bytes;
4396
5707
  stream.pipe(collector);
@@ -4401,7 +5712,7 @@ var require_headStream = __commonJS({
4401
5712
  collector.on("error", reject);
4402
5713
  collector.on("finish", function() {
4403
5714
  const bytes2 = new Uint8Array(Buffer.concat(this.buffers));
4404
- resolve2(bytes2);
5715
+ resolve4(bytes2);
4405
5716
  });
4406
5717
  });
4407
5718
  };
@@ -4659,21 +5970,21 @@ var require_dist_cjs15 = __commonJS({
4659
5970
  let sendBody = true;
4660
5971
  if (expect === "100-continue") {
4661
5972
  sendBody = await Promise.race([
4662
- new Promise((resolve2) => {
4663
- timeoutId = Number(timing.setTimeout(() => resolve2(true), Math.max(MIN_WAIT_TIME, maxContinueTimeoutMs)));
5973
+ new Promise((resolve4) => {
5974
+ timeoutId = Number(timing.setTimeout(() => resolve4(true), Math.max(MIN_WAIT_TIME, maxContinueTimeoutMs)));
4664
5975
  }),
4665
- new Promise((resolve2) => {
5976
+ new Promise((resolve4) => {
4666
5977
  httpRequest.on("continue", () => {
4667
5978
  timing.clearTimeout(timeoutId);
4668
- resolve2(true);
5979
+ resolve4(true);
4669
5980
  });
4670
5981
  httpRequest.on("response", () => {
4671
5982
  timing.clearTimeout(timeoutId);
4672
- resolve2(false);
5983
+ resolve4(false);
4673
5984
  });
4674
5985
  httpRequest.on("error", () => {
4675
5986
  timing.clearTimeout(timeoutId);
4676
- resolve2(false);
5987
+ resolve4(false);
4677
5988
  });
4678
5989
  })
4679
5990
  ]);
@@ -4709,13 +6020,13 @@ var require_dist_cjs15 = __commonJS({
4709
6020
  constructor(options) {
4710
6021
  this.socketWarningTimestamp = 0;
4711
6022
  this.metadata = { handlerProtocol: "http/1.1" };
4712
- this.configProvider = new Promise((resolve2, reject) => {
6023
+ this.configProvider = new Promise((resolve4, reject) => {
4713
6024
  if (typeof options === "function") {
4714
6025
  options().then((_options) => {
4715
- resolve2(this.resolveDefaultConfig(_options));
6026
+ resolve4(this.resolveDefaultConfig(_options));
4716
6027
  }).catch(reject);
4717
6028
  } else {
4718
- resolve2(this.resolveDefaultConfig(options));
6029
+ resolve4(this.resolveDefaultConfig(options));
4719
6030
  }
4720
6031
  });
4721
6032
  }
@@ -4799,7 +6110,7 @@ or increase socketAcquisitionWarningTimeout=(millis) in the NodeHttpHandler conf
4799
6110
  return new Promise((_resolve, _reject) => {
4800
6111
  let writeRequestBodyPromise = void 0;
4801
6112
  const timeouts = [];
4802
- const resolve2 = /* @__PURE__ */ __name(async (arg) => {
6113
+ const resolve4 = /* @__PURE__ */ __name(async (arg) => {
4803
6114
  await writeRequestBodyPromise;
4804
6115
  timeouts.forEach(timing.clearTimeout);
4805
6116
  _resolve(arg);
@@ -4869,7 +6180,7 @@ or increase socketAcquisitionWarningTimeout=(millis) in the NodeHttpHandler conf
4869
6180
  headers: getTransformedHeaders(res.headers),
4870
6181
  body: res
4871
6182
  });
4872
- resolve2({ response: httpResponse });
6183
+ resolve4({ response: httpResponse });
4873
6184
  });
4874
6185
  req.on("error", (err) => {
4875
6186
  if (NODEJS_TIMEOUT_ERROR_CODES.includes(err.code)) {
@@ -5058,13 +6369,13 @@ or increase socketAcquisitionWarningTimeout=(millis) in the NodeHttpHandler conf
5058
6369
  constructor(options) {
5059
6370
  this.metadata = { handlerProtocol: "h2" };
5060
6371
  this.connectionManager = new NodeHttp2ConnectionManager({});
5061
- this.configProvider = new Promise((resolve2, reject) => {
6372
+ this.configProvider = new Promise((resolve4, reject) => {
5062
6373
  if (typeof options === "function") {
5063
6374
  options().then((opts) => {
5064
- resolve2(opts || {});
6375
+ resolve4(opts || {});
5065
6376
  }).catch(reject);
5066
6377
  } else {
5067
- resolve2(options || {});
6378
+ resolve4(options || {});
5068
6379
  }
5069
6380
  });
5070
6381
  }
@@ -5097,7 +6408,7 @@ or increase socketAcquisitionWarningTimeout=(millis) in the NodeHttpHandler conf
5097
6408
  return new Promise((_resolve, _reject) => {
5098
6409
  let fulfilled = false;
5099
6410
  let writeRequestBodyPromise = void 0;
5100
- const resolve2 = /* @__PURE__ */ __name(async (arg) => {
6411
+ const resolve4 = /* @__PURE__ */ __name(async (arg) => {
5101
6412
  await writeRequestBodyPromise;
5102
6413
  _resolve(arg);
5103
6414
  }, "resolve");
@@ -5153,7 +6464,7 @@ or increase socketAcquisitionWarningTimeout=(millis) in the NodeHttpHandler conf
5153
6464
  body: req
5154
6465
  });
5155
6466
  fulfilled = true;
5156
- resolve2({ response: httpResponse });
6467
+ resolve4({ response: httpResponse });
5157
6468
  if (disableConcurrentStreams) {
5158
6469
  session.close();
5159
6470
  this.connectionManager.deleteSession(authority, session);
@@ -5242,7 +6553,7 @@ or increase socketAcquisitionWarningTimeout=(millis) in the NodeHttpHandler conf
5242
6553
  if (isReadableStreamInstance(stream)) {
5243
6554
  return collectReadableStream(stream);
5244
6555
  }
5245
- return new Promise((resolve2, reject) => {
6556
+ return new Promise((resolve4, reject) => {
5246
6557
  const collector = new Collector();
5247
6558
  stream.pipe(collector);
5248
6559
  stream.on("error", (err) => {
@@ -5252,7 +6563,7 @@ or increase socketAcquisitionWarningTimeout=(millis) in the NodeHttpHandler conf
5252
6563
  collector.on("error", reject);
5253
6564
  collector.on("finish", function() {
5254
6565
  const bytes = new Uint8Array(Buffer.concat(this.bufferedBytes));
5255
- resolve2(bytes);
6566
+ resolve4(bytes);
5256
6567
  });
5257
6568
  });
5258
6569
  }, "streamCollector");
@@ -5317,7 +6628,7 @@ var require_dist_cjs16 = __commonJS({
5317
6628
  }
5318
6629
  __name(createRequest, "createRequest");
5319
6630
  function requestTimeout(timeoutInMs = 0) {
5320
- return new Promise((resolve2, reject) => {
6631
+ return new Promise((resolve4, reject) => {
5321
6632
  if (timeoutInMs) {
5322
6633
  setTimeout(() => {
5323
6634
  const timeoutError = new Error(`Request did not complete within ${timeoutInMs} ms`);
@@ -5444,7 +6755,7 @@ var require_dist_cjs16 = __commonJS({
5444
6755
  ];
5445
6756
  if (abortSignal) {
5446
6757
  raceOfPromises.push(
5447
- new Promise((resolve2, reject) => {
6758
+ new Promise((resolve4, reject) => {
5448
6759
  const onAbort = /* @__PURE__ */ __name(() => {
5449
6760
  const abortError = new Error("Request aborted");
5450
6761
  abortError.name = "AbortError";
@@ -5512,7 +6823,7 @@ var require_dist_cjs16 = __commonJS({
5512
6823
  }
5513
6824
  __name(collectStream, "collectStream");
5514
6825
  function readToBase64(blob) {
5515
- return new Promise((resolve2, reject) => {
6826
+ return new Promise((resolve4, reject) => {
5516
6827
  const reader = new FileReader();
5517
6828
  reader.onloadend = () => {
5518
6829
  if (reader.readyState !== 2) {
@@ -5521,7 +6832,7 @@ var require_dist_cjs16 = __commonJS({
5521
6832
  const result = reader.result ?? "";
5522
6833
  const commaIndex = result.indexOf(",");
5523
6834
  const dataOffset = commaIndex > -1 ? commaIndex + 1 : result.length;
5524
- resolve2(result.substring(dataOffset));
6835
+ resolve4(result.substring(dataOffset));
5525
6836
  };
5526
6837
  reader.onabort = () => reject(new Error("Read aborted"));
5527
6838
  reader.onerror = () => reject(reader.error);
@@ -6008,9 +7319,10 @@ var TypeRegistry;
6008
7319
  var init_TypeRegistry = __esm({
6009
7320
  "node_modules/@smithy/core/dist-es/submodules/schema/TypeRegistry.js"() {
6010
7321
  TypeRegistry = class _TypeRegistry {
6011
- constructor(namespace, schemas = /* @__PURE__ */ new Map()) {
7322
+ constructor(namespace, schemas = /* @__PURE__ */ new Map(), exceptions = /* @__PURE__ */ new Map()) {
6012
7323
  this.namespace = namespace;
6013
7324
  this.schemas = schemas;
7325
+ this.exceptions = exceptions;
6014
7326
  }
6015
7327
  static for(namespace) {
6016
7328
  if (!_TypeRegistry.registries.has(namespace)) {
@@ -6020,8 +7332,7 @@ var init_TypeRegistry = __esm({
6020
7332
  }
6021
7333
  register(shapeId, schema) {
6022
7334
  const qualifiedName = this.normalizeShapeId(shapeId);
6023
- const registry = _TypeRegistry.for(this.getNamespace(shapeId));
6024
- registry.schemas.set(qualifiedName, schema);
7335
+ this.schemas.set(qualifiedName, schema);
6025
7336
  }
6026
7337
  getSchema(shapeId) {
6027
7338
  const id = this.normalizeShapeId(shapeId);
@@ -6030,6 +7341,12 @@ var init_TypeRegistry = __esm({
6030
7341
  }
6031
7342
  return this.schemas.get(id);
6032
7343
  }
7344
+ registerError(errorSchema, ctor) {
7345
+ this.exceptions.set(errorSchema, ctor);
7346
+ }
7347
+ getErrorCtor(errorSchema) {
7348
+ return this.exceptions.get(errorSchema);
7349
+ }
6033
7350
  getBaseException() {
6034
7351
  for (const [id, schema] of this.schemas.entries()) {
6035
7352
  if (id.startsWith("smithy.ts.sdk.synthetic.") && id.endsWith("ServiceException")) {
@@ -6041,9 +7358,9 @@ var init_TypeRegistry = __esm({
6041
7358
  find(predicate) {
6042
7359
  return [...this.schemas.values()].find(predicate);
6043
7360
  }
6044
- destroy() {
6045
- _TypeRegistry.registries.delete(this.namespace);
7361
+ clear() {
6046
7362
  this.schemas.clear();
7363
+ this.exceptions.clear();
6047
7364
  }
6048
7365
  normalizeShapeId(shapeId) {
6049
7366
  if (shapeId.includes("#")) {
@@ -6191,7 +7508,7 @@ var init_ErrorSchema = __esm({
6191
7508
  traits,
6192
7509
  memberNames,
6193
7510
  memberList,
6194
- ctor
7511
+ ctor: null
6195
7512
  });
6196
7513
  }
6197
7514
  });
@@ -7160,11 +8477,11 @@ function __metadata(metadataKey, metadataValue) {
7160
8477
  }
7161
8478
  function __awaiter(thisArg, _arguments, P, generator) {
7162
8479
  function adopt(value) {
7163
- return value instanceof P ? value : new P(function(resolve2) {
7164
- resolve2(value);
8480
+ return value instanceof P ? value : new P(function(resolve4) {
8481
+ resolve4(value);
7165
8482
  });
7166
8483
  }
7167
- return new (P || (P = Promise))(function(resolve2, reject) {
8484
+ return new (P || (P = Promise))(function(resolve4, reject) {
7168
8485
  function fulfilled(value) {
7169
8486
  try {
7170
8487
  step(generator.next(value));
@@ -7180,7 +8497,7 @@ function __awaiter(thisArg, _arguments, P, generator) {
7180
8497
  }
7181
8498
  }
7182
8499
  function step(result) {
7183
- result.done ? resolve2(result.value) : adopt(result.value).then(fulfilled, rejected);
8500
+ result.done ? resolve4(result.value) : adopt(result.value).then(fulfilled, rejected);
7184
8501
  }
7185
8502
  step((generator = generator.apply(thisArg, _arguments || [])).next());
7186
8503
  });
@@ -7371,14 +8688,14 @@ function __asyncValues(o3) {
7371
8688
  }, i3);
7372
8689
  function verb(n3) {
7373
8690
  i3[n3] = o3[n3] && function(v3) {
7374
- return new Promise(function(resolve2, reject) {
7375
- v3 = o3[n3](v3), settle(resolve2, reject, v3.done, v3.value);
8691
+ return new Promise(function(resolve4, reject) {
8692
+ v3 = o3[n3](v3), settle(resolve4, reject, v3.done, v3.value);
7376
8693
  });
7377
8694
  };
7378
8695
  }
7379
- function settle(resolve2, reject, d3, v3) {
8696
+ function settle(resolve4, reject, d3, v3) {
7380
8697
  Promise.resolve(v3).then(function(v4) {
7381
- resolve2({ value: v4, done: d3 });
8698
+ resolve4({ value: v4, done: d3 });
7382
8699
  }, reject);
7383
8700
  }
7384
8701
  }
@@ -12349,16 +13666,18 @@ var init_SmithyRpcV2CborProtocol = __esm({
12349
13666
  if (dataObject.Message) {
12350
13667
  dataObject.message = dataObject.Message;
12351
13668
  }
12352
- const baseExceptionSchema = TypeRegistry.for("smithy.ts.sdk.synthetic." + namespace).getBaseException();
13669
+ const synthetic = TypeRegistry.for("smithy.ts.sdk.synthetic." + namespace);
13670
+ const baseExceptionSchema = synthetic.getBaseException();
12353
13671
  if (baseExceptionSchema) {
12354
- const ErrorCtor = baseExceptionSchema.ctor;
12355
- throw Object.assign(new ErrorCtor({ name: errorName }), errorMetadata, dataObject);
13672
+ const ErrorCtor2 = synthetic.getErrorCtor(baseExceptionSchema);
13673
+ throw Object.assign(new ErrorCtor2({ name: errorName }), errorMetadata, dataObject);
12356
13674
  }
12357
13675
  throw Object.assign(new Error(errorName), errorMetadata, dataObject);
12358
13676
  }
12359
13677
  const ns = NormalizedSchema.of(errorSchema);
13678
+ const ErrorCtor = registry.getErrorCtor(errorSchema);
12360
13679
  const message = dataObject.message ?? dataObject.Message ?? "Unknown";
12361
- const exception = new errorSchema.ctor(message);
13680
+ const exception = new ErrorCtor(message);
12362
13681
  const output = {};
12363
13682
  for (const [name14, member] of ns.structIterator()) {
12364
13683
  output[name14] = this.deserializer.readValue(member, dataObject[name14]);
@@ -18024,7 +19343,7 @@ var require_dist_cjs37 = __commonJS({
18024
19343
  );
18025
19344
  }
18026
19345
  waitForReady(socket, connectionTimeout) {
18027
- return new Promise((resolve2, reject) => {
19346
+ return new Promise((resolve4, reject) => {
18028
19347
  const timeout = setTimeout(() => {
18029
19348
  this.removeNotUsableSockets(socket.url);
18030
19349
  reject({
@@ -18035,7 +19354,7 @@ var require_dist_cjs37 = __commonJS({
18035
19354
  }, connectionTimeout);
18036
19355
  socket.onopen = () => {
18037
19356
  clearTimeout(timeout);
18038
- resolve2();
19357
+ resolve4();
18039
19358
  };
18040
19359
  });
18041
19360
  }
@@ -18044,10 +19363,10 @@ var require_dist_cjs37 = __commonJS({
18044
19363
  let socketErrorOccurred = false;
18045
19364
  let reject = /* @__PURE__ */ __name(() => {
18046
19365
  }, "reject");
18047
- let resolve2 = /* @__PURE__ */ __name(() => {
19366
+ let resolve4 = /* @__PURE__ */ __name(() => {
18048
19367
  }, "resolve");
18049
19368
  socket.onmessage = (event) => {
18050
- resolve2({
19369
+ resolve4({
18051
19370
  done: false,
18052
19371
  value: new Uint8Array(event.data)
18053
19372
  });
@@ -18063,7 +19382,7 @@ var require_dist_cjs37 = __commonJS({
18063
19382
  if (streamError) {
18064
19383
  reject(streamError);
18065
19384
  } else {
18066
- resolve2({
19385
+ resolve4({
18067
19386
  done: true,
18068
19387
  value: void 0
18069
19388
  // unchecked because done=true.
@@ -18074,7 +19393,7 @@ var require_dist_cjs37 = __commonJS({
18074
19393
  [Symbol.asyncIterator]: () => ({
18075
19394
  next: /* @__PURE__ */ __name(() => {
18076
19395
  return new Promise((_resolve, _reject) => {
18077
- resolve2 = _resolve;
19396
+ resolve4 = _resolve;
18078
19397
  reject = _reject;
18079
19398
  });
18080
19399
  }, "next")
@@ -18597,13 +19916,13 @@ var require_dist_cjs42 = __commonJS({
18597
19916
  ...data2.default && { default: data2.default }
18598
19917
  }
18599
19918
  ), "getConfigData");
18600
- var import_path9 = require("path");
19919
+ var import_path11 = require("path");
18601
19920
  var import_getHomeDir = require_getHomeDir();
18602
19921
  var ENV_CONFIG_PATH = "AWS_CONFIG_FILE";
18603
- var getConfigFilepath = /* @__PURE__ */ __name(() => process.env[ENV_CONFIG_PATH] || (0, import_path9.join)((0, import_getHomeDir.getHomeDir)(), ".aws", "config"), "getConfigFilepath");
19922
+ var getConfigFilepath = /* @__PURE__ */ __name(() => process.env[ENV_CONFIG_PATH] || (0, import_path11.join)((0, import_getHomeDir.getHomeDir)(), ".aws", "config"), "getConfigFilepath");
18604
19923
  var import_getHomeDir2 = require_getHomeDir();
18605
19924
  var ENV_CREDENTIALS_PATH = "AWS_SHARED_CREDENTIALS_FILE";
18606
- var getCredentialsFilepath = /* @__PURE__ */ __name(() => process.env[ENV_CREDENTIALS_PATH] || (0, import_path9.join)((0, import_getHomeDir2.getHomeDir)(), ".aws", "credentials"), "getCredentialsFilepath");
19925
+ var getCredentialsFilepath = /* @__PURE__ */ __name(() => process.env[ENV_CREDENTIALS_PATH] || (0, import_path11.join)((0, import_getHomeDir2.getHomeDir)(), ".aws", "credentials"), "getCredentialsFilepath");
18607
19926
  var import_getHomeDir3 = require_getHomeDir();
18608
19927
  var prefixKeyRegex = /^([\w-]+)\s(["'])?([\w-@\+\.%:/]+)\2$/;
18609
19928
  var profileNameBlockList = ["__proto__", "profile __proto__"];
@@ -18661,11 +19980,11 @@ var require_dist_cjs42 = __commonJS({
18661
19980
  const relativeHomeDirPrefix = "~/";
18662
19981
  let resolvedFilepath = filepath;
18663
19982
  if (filepath.startsWith(relativeHomeDirPrefix)) {
18664
- resolvedFilepath = (0, import_path9.join)(homeDir, filepath.slice(2));
19983
+ resolvedFilepath = (0, import_path11.join)(homeDir, filepath.slice(2));
18665
19984
  }
18666
19985
  let resolvedConfigFilepath = configFilepath;
18667
19986
  if (configFilepath.startsWith(relativeHomeDirPrefix)) {
18668
- resolvedConfigFilepath = (0, import_path9.join)(homeDir, configFilepath.slice(2));
19987
+ resolvedConfigFilepath = (0, import_path11.join)(homeDir, configFilepath.slice(2));
18669
19988
  }
18670
19989
  const parsedFiles = await Promise.all([
18671
19990
  (0, import_slurpFile.slurpFile)(resolvedConfigFilepath, {
@@ -19320,7 +20639,7 @@ var require_dist_cjs46 = __commonJS({
19320
20639
  this.refillTokenBucket();
19321
20640
  if (amount > this.currentCapacity) {
19322
20641
  const delay = (amount - this.currentCapacity) / this.fillRate * 1e3;
19323
- await new Promise((resolve2) => _DefaultRateLimiter.setTimeoutFn(resolve2, delay));
20642
+ await new Promise((resolve4) => _DefaultRateLimiter.setTimeoutFn(resolve4, delay));
19324
20643
  }
19325
20644
  this.currentCapacity = this.currentCapacity - amount;
19326
20645
  }
@@ -19711,7 +21030,7 @@ var require_dist_cjs47 = __commonJS({
19711
21030
  const delayFromResponse = getDelayFromRetryAfterHeader(err.$response);
19712
21031
  const delay = Math.max(delayFromResponse || 0, delayFromDecider);
19713
21032
  totalDelay += delay;
19714
- await new Promise((resolve2) => setTimeout(resolve2, delay));
21033
+ await new Promise((resolve4) => setTimeout(resolve4, delay));
19715
21034
  continue;
19716
21035
  }
19717
21036
  if (!err.$metadata) {
@@ -19871,7 +21190,7 @@ var require_dist_cjs47 = __commonJS({
19871
21190
  attempts = retryToken.getRetryCount();
19872
21191
  const delay = retryToken.getRetryDelay();
19873
21192
  totalRetryDelay += delay;
19874
- await new Promise((resolve2) => setTimeout(resolve2, delay));
21193
+ await new Promise((resolve4) => setTimeout(resolve4, delay));
19875
21194
  }
19876
21195
  }
19877
21196
  } else {
@@ -20214,7 +21533,7 @@ var require_dist_cjs49 = __commonJS({
20214
21533
  var import_buffer = require("buffer");
20215
21534
  var import_http = require("http");
20216
21535
  function httpRequest(options) {
20217
- return new Promise((resolve2, reject) => {
21536
+ return new Promise((resolve4, reject) => {
20218
21537
  const req = (0, import_http.request)({
20219
21538
  method: "GET",
20220
21539
  ...options,
@@ -20243,7 +21562,7 @@ var require_dist_cjs49 = __commonJS({
20243
21562
  chunks.push(chunk);
20244
21563
  });
20245
21564
  res.on("end", () => {
20246
- resolve2(import_buffer.Buffer.concat(chunks));
21565
+ resolve4(import_buffer.Buffer.concat(chunks));
20247
21566
  req.destroy();
20248
21567
  });
20249
21568
  });
@@ -20678,7 +21997,7 @@ var require_retry_wrapper = __commonJS({
20678
21997
  try {
20679
21998
  return await toRetry();
20680
21999
  } catch (e3) {
20681
- await new Promise((resolve2) => setTimeout(resolve2, delayMs));
22000
+ await new Promise((resolve4) => setTimeout(resolve4, delayMs));
20682
22001
  }
20683
22002
  }
20684
22003
  return await toRetry();
@@ -21122,7 +22441,7 @@ var require_dist_cjs53 = __commonJS({
21122
22441
  calculateBodyLength: () => calculateBodyLength3
21123
22442
  });
21124
22443
  module2.exports = __toCommonJS2(index_exports2);
21125
- var import_fs7 = require("fs");
22444
+ var import_fs8 = require("fs");
21126
22445
  var calculateBodyLength3 = /* @__PURE__ */ __name((body) => {
21127
22446
  if (!body) {
21128
22447
  return 0;
@@ -21136,9 +22455,9 @@ var require_dist_cjs53 = __commonJS({
21136
22455
  } else if (typeof body.start === "number" && typeof body.end === "number") {
21137
22456
  return body.end + 1 - body.start;
21138
22457
  } else if (typeof body.path === "string" || Buffer.isBuffer(body.path)) {
21139
- return (0, import_fs7.lstatSync)(body.path).size;
22458
+ return (0, import_fs8.lstatSync)(body.path).size;
21140
22459
  } else if (typeof body.fd === "number") {
21141
- return (0, import_fs7.fstatSync)(body.fd).size;
22460
+ return (0, import_fs8.fstatSync)(body.fd).size;
21142
22461
  }
21143
22462
  throw new Error(`Body Length computation failed for ${body}`);
21144
22463
  }, "calculateBodyLength");
@@ -23176,8 +24495,8 @@ var require_dist_cjs57 = __commonJS({
23176
24495
  }
23177
24496
  }, "validateTokenKey");
23178
24497
  var import_shared_ini_file_loader = require_dist_cjs42();
23179
- var import_fs7 = require("fs");
23180
- var { writeFile } = import_fs7.promises;
24498
+ var import_fs8 = require("fs");
24499
+ var { writeFile } = import_fs8.promises;
23181
24500
  var writeSSOTokenToFile = /* @__PURE__ */ __name((id, ssoToken) => {
23182
24501
  const tokenFilepath = (0, import_shared_ini_file_loader.getSSOTokenFilepath)(id);
23183
24502
  const tokenString = JSON.stringify(ssoToken, null, 2);
@@ -24819,7 +26138,7 @@ var require_dist_cjs59 = __commonJS({
24819
26138
  module2.exports = __toCommonJS2(index_exports2);
24820
26139
  var import_property_provider2 = require_dist_cjs24();
24821
26140
  var import_shared_ini_file_loader = require_dist_cjs42();
24822
- var import_child_process8 = require("child_process");
26141
+ var import_child_process9 = require("child_process");
24823
26142
  var import_util7 = require("util");
24824
26143
  var import_client7 = (init_client(), __toCommonJS(client_exports));
24825
26144
  var getValidatedProcessCredentials = /* @__PURE__ */ __name((profileName, data2, profiles) => {
@@ -24856,7 +26175,7 @@ var require_dist_cjs59 = __commonJS({
24856
26175
  if (profiles[profileName]) {
24857
26176
  const credentialProcess = profile["credential_process"];
24858
26177
  if (credentialProcess !== void 0) {
24859
- const execPromise = (0, import_util7.promisify)(import_shared_ini_file_loader.externalDataInterceptor?.getTokenRecord?.().exec ?? import_child_process8.exec);
26178
+ const execPromise = (0, import_util7.promisify)(import_shared_ini_file_loader.externalDataInterceptor?.getTokenRecord?.().exec ?? import_child_process9.exec);
24860
26179
  try {
24861
26180
  const { stdout } = await execPromise(credentialProcess);
24862
26181
  let data2;
@@ -25595,7 +26914,7 @@ var require_dist_cjs64 = __commonJS({
25595
26914
  streamEnded = true;
25596
26915
  });
25597
26916
  while (!generationEnded) {
25598
- const value = await new Promise((resolve2) => setTimeout(() => resolve2(records.shift()), 0));
26917
+ const value = await new Promise((resolve4) => setTimeout(() => resolve4(records.shift()), 0));
25599
26918
  if (value) {
25600
26919
  yield value;
25601
26920
  }
@@ -28972,16 +30291,16 @@ function prepareTools(mode) {
28972
30291
  }
28973
30292
  const toolWarnings = [];
28974
30293
  const bedrockTools = [];
28975
- for (const tool2 of tools2) {
28976
- if (tool2.type === "provider-defined") {
28977
- toolWarnings.push({ type: "unsupported-tool", tool: tool2 });
30294
+ for (const tool3 of tools2) {
30295
+ if (tool3.type === "provider-defined") {
30296
+ toolWarnings.push({ type: "unsupported-tool", tool: tool3 });
28978
30297
  } else {
28979
30298
  bedrockTools.push({
28980
30299
  toolSpec: {
28981
- name: tool2.name,
28982
- description: tool2.description,
30300
+ name: tool3.name,
30301
+ description: tool3.description,
28983
30302
  inputSchema: {
28984
- json: tool2.parameters
30303
+ json: tool3.parameters
28985
30304
  }
28986
30305
  }
28987
30306
  });
@@ -29992,8 +31311,8 @@ function checkAttemptCompleteRecovery(cleanedXmlString, validTools = []) {
29992
31311
  function hasOtherToolTags(xmlString, validTools = []) {
29993
31312
  const defaultTools = ["search", "query", "extract", "listFiles", "searchFiles", "implement", "attempt_completion"];
29994
31313
  const toolsToCheck = validTools.length > 0 ? validTools : defaultTools;
29995
- for (const tool2 of toolsToCheck) {
29996
- if (tool2 !== "attempt_completion" && xmlString.includes(`<${tool2}`)) {
31314
+ for (const tool3 of toolsToCheck) {
31315
+ if (tool3 !== "attempt_completion" && xmlString.includes(`<${tool3}`)) {
29997
31316
  return true;
29998
31317
  }
29999
31318
  }
@@ -30021,12 +31340,16 @@ var init_xmlParsingUtils = __esm({
30021
31340
 
30022
31341
  // src/agent/tools.js
30023
31342
  function createTools(configOptions) {
30024
- return {
31343
+ const tools2 = {
30025
31344
  searchTool: searchTool(configOptions),
30026
31345
  queryTool: queryTool(configOptions),
30027
31346
  extractTool: extractTool(configOptions),
30028
31347
  delegateTool: delegateTool(configOptions)
30029
31348
  };
31349
+ if (configOptions.enableBash) {
31350
+ tools2.bashTool = bashTool(configOptions);
31351
+ }
31352
+ return tools2;
30030
31353
  }
30031
31354
  function parseXmlToolCallWithThinking(xmlString, validTools) {
30032
31355
  const { cleanedXmlString, recoveryResult } = processXmlWithThinkingAndRecovery(xmlString, validTools);
@@ -30170,26 +31493,33 @@ function createWrappedTools(baseTools) {
30170
31493
  baseTools.delegateTool.execute
30171
31494
  );
30172
31495
  }
31496
+ if (baseTools.bashTool) {
31497
+ wrappedTools.bashToolInstance = wrapToolWithEmitter(
31498
+ baseTools.bashTool,
31499
+ "bash",
31500
+ baseTools.bashTool.execute
31501
+ );
31502
+ }
30173
31503
  return wrappedTools;
30174
31504
  }
30175
- var import_child_process7, import_util6, import_crypto4, import_events, import_fs2, import_fs3, import_path5, import_glob, toolCallEmitter, activeToolExecutions, wrapToolWithEmitter, listFilesTool, searchFilesTool, listFilesToolInstance, searchFilesToolInstance;
31505
+ var import_child_process8, import_util6, import_crypto4, import_events, import_fs3, import_fs4, import_path7, import_glob, toolCallEmitter, activeToolExecutions, wrapToolWithEmitter, listFilesTool, searchFilesTool, listFilesToolInstance, searchFilesToolInstance;
30176
31506
  var init_probeTool = __esm({
30177
31507
  "src/agent/probeTool.js"() {
30178
31508
  "use strict";
30179
31509
  init_index();
30180
- import_child_process7 = require("child_process");
31510
+ import_child_process8 = require("child_process");
30181
31511
  import_util6 = require("util");
30182
31512
  import_crypto4 = require("crypto");
30183
31513
  import_events = require("events");
30184
- import_fs2 = __toESM(require("fs"), 1);
30185
- import_fs3 = require("fs");
30186
- import_path5 = __toESM(require("path"), 1);
31514
+ import_fs3 = __toESM(require("fs"), 1);
31515
+ import_fs4 = require("fs");
31516
+ import_path7 = __toESM(require("path"), 1);
30187
31517
  import_glob = require("glob");
30188
31518
  toolCallEmitter = new import_events.EventEmitter();
30189
31519
  activeToolExecutions = /* @__PURE__ */ new Map();
30190
- wrapToolWithEmitter = (tool2, toolName, baseExecute) => {
31520
+ wrapToolWithEmitter = (tool3, toolName, baseExecute) => {
30191
31521
  return {
30192
- ...tool2,
31522
+ ...tool3,
30193
31523
  // Spread schema, description etc.
30194
31524
  execute: async (params) => {
30195
31525
  const debug = process.env.DEBUG === "1";
@@ -30271,9 +31601,9 @@ var init_probeTool = __esm({
30271
31601
  execute: async (params) => {
30272
31602
  const { directory = ".", workingDirectory } = params;
30273
31603
  const baseCwd = workingDirectory || process.cwd();
30274
- const secureBaseDir = import_path5.default.resolve(baseCwd);
30275
- const targetDir = import_path5.default.resolve(secureBaseDir, directory);
30276
- if (!targetDir.startsWith(secureBaseDir + import_path5.default.sep) && targetDir !== secureBaseDir) {
31604
+ const secureBaseDir = import_path7.default.resolve(baseCwd);
31605
+ const targetDir = import_path7.default.resolve(secureBaseDir, directory);
31606
+ if (!targetDir.startsWith(secureBaseDir + import_path7.default.sep) && targetDir !== secureBaseDir) {
30277
31607
  throw new Error("Path traversal attempt detected. Access denied.");
30278
31608
  }
30279
31609
  try {
@@ -30296,9 +31626,9 @@ var init_probeTool = __esm({
30296
31626
  throw new Error("Pattern is required for file search");
30297
31627
  }
30298
31628
  const baseCwd = workingDirectory || process.cwd();
30299
- const secureBaseDir = import_path5.default.resolve(baseCwd);
30300
- const targetDir = import_path5.default.resolve(secureBaseDir, directory);
30301
- if (!targetDir.startsWith(secureBaseDir + import_path5.default.sep) && targetDir !== secureBaseDir) {
31629
+ const secureBaseDir = import_path7.default.resolve(baseCwd);
31630
+ const targetDir = import_path7.default.resolve(secureBaseDir, directory);
31631
+ if (!targetDir.startsWith(secureBaseDir + import_path7.default.sep) && targetDir !== secureBaseDir) {
30302
31632
  throw new Error("Path traversal attempt detected. Access denied.");
30303
31633
  }
30304
31634
  try {
@@ -30330,7 +31660,7 @@ function createMockProvider() {
30330
31660
  provider: "mock",
30331
31661
  // Mock the doGenerate method used by Vercel AI SDK
30332
31662
  doGenerate: async ({ messages, tools: tools2 }) => {
30333
- await new Promise((resolve2) => setTimeout(resolve2, 10));
31663
+ await new Promise((resolve4) => setTimeout(resolve4, 10));
30334
31664
  return {
30335
31665
  text: "This is a mock response for testing",
30336
31666
  toolCalls: [],
@@ -30901,11 +32231,19 @@ ${decodedContent}
30901
32231
  if (trimmedLine.match(/\[[^\]]*\]/)) {
30902
32232
  modifiedLine = modifiedLine.replace(/\[([^\]]*)\]/g, (match, content) => {
30903
32233
  if (content.trim().startsWith('"') && content.trim().endsWith('"')) {
32234
+ const innerContent = content.trim().slice(1, -1);
32235
+ if (innerContent.includes('"') || innerContent.includes("'")) {
32236
+ wasFixed = true;
32237
+ const decodedContent = decodeHtmlEntities(innerContent);
32238
+ const safeContent = decodedContent.replace(/"/g, "&quot;").replace(/'/g, "&#39;");
32239
+ return `["${safeContent}"]`;
32240
+ }
30904
32241
  return match;
30905
32242
  }
30906
32243
  if (needsQuoting(content)) {
30907
32244
  wasFixed = true;
30908
- const safeContent = content.replace(/"/g, "'");
32245
+ const decodedContent = decodeHtmlEntities(content);
32246
+ const safeContent = decodedContent.replace(/"/g, "&quot;").replace(/'/g, "&#39;");
30909
32247
  return `["${safeContent}"]`;
30910
32248
  }
30911
32249
  return match;
@@ -30914,11 +32252,19 @@ ${decodedContent}
30914
32252
  if (trimmedLine.match(/\{[^{}]*\}/)) {
30915
32253
  modifiedLine = modifiedLine.replace(/\{([^{}]*)\}/g, (match, content) => {
30916
32254
  if (content.trim().startsWith('"') && content.trim().endsWith('"')) {
32255
+ const innerContent = content.trim().slice(1, -1);
32256
+ if (innerContent.includes('"') || innerContent.includes("'")) {
32257
+ wasFixed = true;
32258
+ const decodedContent = decodeHtmlEntities(innerContent);
32259
+ const safeContent = decodedContent.replace(/"/g, "&quot;").replace(/'/g, "&#39;");
32260
+ return `{"${safeContent}"}`;
32261
+ }
30917
32262
  return match;
30918
32263
  }
30919
32264
  if (needsQuoting(content)) {
30920
32265
  wasFixed = true;
30921
- const safeContent = content.replace(/"/g, "'");
32266
+ const decodedContent = decodeHtmlEntities(content);
32267
+ const safeContent = decodedContent.replace(/"/g, "&quot;").replace(/'/g, "&#39;");
30922
32268
  return `{"${safeContent}"}`;
30923
32269
  }
30924
32270
  return match;
@@ -31084,11 +32430,19 @@ ${fixedContent}
31084
32430
  if (trimmedLine.match(/\[[^\]]*\]/)) {
31085
32431
  modifiedLine = modifiedLine.replace(/\[([^\]]*)\]/g, (match, content) => {
31086
32432
  if (content.trim().startsWith('"') && content.trim().endsWith('"')) {
32433
+ const innerContent = content.trim().slice(1, -1);
32434
+ if (innerContent.includes('"') || innerContent.includes("'")) {
32435
+ wasFixed = true;
32436
+ const decodedContent = decodeHtmlEntities(innerContent);
32437
+ const safeContent = decodedContent.replace(/"/g, "&quot;").replace(/'/g, "&#39;");
32438
+ return `["${safeContent}"]`;
32439
+ }
31087
32440
  return match;
31088
32441
  }
31089
32442
  if (needsQuoting(content)) {
31090
32443
  wasFixed = true;
31091
- const safeContent = content.replace(/"/g, "'");
32444
+ const decodedContent = decodeHtmlEntities(content);
32445
+ const safeContent = decodedContent.replace(/"/g, "&quot;").replace(/'/g, "&#39;");
31092
32446
  return `["${safeContent}"]`;
31093
32447
  }
31094
32448
  return match;
@@ -31097,11 +32451,19 @@ ${fixedContent}
31097
32451
  if (trimmedLine.match(/\{[^{}]*\}/)) {
31098
32452
  modifiedLine = modifiedLine.replace(/\{([^{}]*)\}/g, (match, content) => {
31099
32453
  if (content.trim().startsWith('"') && content.trim().endsWith('"')) {
32454
+ const innerContent = content.trim().slice(1, -1);
32455
+ if (innerContent.includes('"') || innerContent.includes("'")) {
32456
+ wasFixed = true;
32457
+ const decodedContent = decodeHtmlEntities(innerContent);
32458
+ const safeContent = decodedContent.replace(/"/g, "&quot;").replace(/'/g, "&#39;");
32459
+ return `{"${safeContent}"}`;
32460
+ }
31100
32461
  return match;
31101
32462
  }
31102
32463
  if (needsQuoting(content)) {
31103
32464
  wasFixed = true;
31104
- const safeContent = content.replace(/"/g, "'");
32465
+ const decodedContent = decodeHtmlEntities(content);
32466
+ const safeContent = decodedContent.replace(/"/g, "&quot;").replace(/'/g, "&#39;");
31105
32467
  return `{"${safeContent}"}`;
31106
32468
  }
31107
32469
  return match;
@@ -31326,6 +32688,8 @@ var init_schemaUtils = __esm({
31326
32688
  "&amp;": "&",
31327
32689
  "&quot;": '"',
31328
32690
  "&#39;": "'",
32691
+ "&apos;": "'",
32692
+ // Also handle XML/HTML5 apostrophe entity
31329
32693
  "&nbsp;": " "
31330
32694
  };
31331
32695
  MermaidFixingAgent = class {
@@ -31501,11 +32865,11 @@ function loadMCPConfigurationFromPath(configPath) {
31501
32865
  if (!configPath) {
31502
32866
  throw new Error("Config path is required");
31503
32867
  }
31504
- if (!(0, import_fs4.existsSync)(configPath)) {
32868
+ if (!(0, import_fs5.existsSync)(configPath)) {
31505
32869
  throw new Error(`MCP configuration file not found: ${configPath}`);
31506
32870
  }
31507
32871
  try {
31508
- const content = (0, import_fs4.readFileSync)(configPath, "utf8");
32872
+ const content = (0, import_fs5.readFileSync)(configPath, "utf8");
31509
32873
  const config = JSON.parse(content);
31510
32874
  if (process.env.DEBUG === "1") {
31511
32875
  console.error(`[MCP] Loaded configuration from: ${configPath}`);
@@ -31520,19 +32884,19 @@ function loadMCPConfiguration() {
31520
32884
  // Environment variable path
31521
32885
  process.env.MCP_CONFIG_PATH,
31522
32886
  // Local project paths
31523
- (0, import_path6.join)(process.cwd(), ".mcp", "config.json"),
31524
- (0, import_path6.join)(process.cwd(), "mcp.config.json"),
32887
+ (0, import_path8.join)(process.cwd(), ".mcp", "config.json"),
32888
+ (0, import_path8.join)(process.cwd(), "mcp.config.json"),
31525
32889
  // Home directory paths
31526
- (0, import_path6.join)((0, import_os3.homedir)(), ".config", "probe", "mcp.json"),
31527
- (0, import_path6.join)((0, import_os3.homedir)(), ".mcp", "config.json"),
32890
+ (0, import_path8.join)((0, import_os3.homedir)(), ".config", "probe", "mcp.json"),
32891
+ (0, import_path8.join)((0, import_os3.homedir)(), ".mcp", "config.json"),
31528
32892
  // Claude-style config location
31529
- (0, import_path6.join)((0, import_os3.homedir)(), "Library", "Application Support", "Claude", "mcp_config.json")
32893
+ (0, import_path8.join)((0, import_os3.homedir)(), "Library", "Application Support", "Claude", "mcp_config.json")
31530
32894
  ].filter(Boolean);
31531
32895
  let config = null;
31532
32896
  for (const configPath of configPaths) {
31533
- if ((0, import_fs4.existsSync)(configPath)) {
32897
+ if ((0, import_fs5.existsSync)(configPath)) {
31534
32898
  try {
31535
- const content = (0, import_fs4.readFileSync)(configPath, "utf8");
32899
+ const content = (0, import_fs5.readFileSync)(configPath, "utf8");
31536
32900
  config = JSON.parse(content);
31537
32901
  if (process.env.DEBUG === "1") {
31538
32902
  console.error(`[MCP] Loaded configuration from: ${configPath}`);
@@ -31628,22 +32992,22 @@ function parseEnabledServers(config) {
31628
32992
  }
31629
32993
  return servers;
31630
32994
  }
31631
- var import_fs4, import_path6, import_os3, import_url4, __filename4, __dirname4, DEFAULT_CONFIG;
32995
+ var import_fs5, import_path8, import_os3, import_url4, __filename4, __dirname4, DEFAULT_CONFIG;
31632
32996
  var init_config = __esm({
31633
32997
  "src/agent/mcp/config.js"() {
31634
32998
  "use strict";
31635
- import_fs4 = require("fs");
31636
- import_path6 = require("path");
32999
+ import_fs5 = require("fs");
33000
+ import_path8 = require("path");
31637
33001
  import_os3 = require("os");
31638
33002
  import_url4 = require("url");
31639
33003
  __filename4 = (0, import_url4.fileURLToPath)("file:///");
31640
- __dirname4 = (0, import_path6.dirname)(__filename4);
33004
+ __dirname4 = (0, import_path8.dirname)(__filename4);
31641
33005
  DEFAULT_CONFIG = {
31642
33006
  mcpServers: {
31643
33007
  // Example probe server configuration
31644
33008
  "probe-local": {
31645
33009
  command: "node",
31646
- args: [(0, import_path6.join)(__dirname4, "../../../examples/chat/mcpServer.js")],
33010
+ args: [(0, import_path8.join)(__dirname4, "../../../examples/chat/mcpServer.js")],
31647
33011
  transport: "stdio",
31648
33012
  enabled: false
31649
33013
  },
@@ -31800,12 +33164,12 @@ var init_client2 = __esm({
31800
33164
  });
31801
33165
  const toolsResponse = await client.listTools();
31802
33166
  if (toolsResponse && toolsResponse.tools) {
31803
- for (const tool2 of toolsResponse.tools) {
31804
- const qualifiedName = `${name14}_${tool2.name}`;
33167
+ for (const tool3 of toolsResponse.tools) {
33168
+ const qualifiedName = `${name14}_${tool3.name}`;
31805
33169
  this.tools.set(qualifiedName, {
31806
- ...tool2,
33170
+ ...tool3,
31807
33171
  serverName: name14,
31808
- originalName: tool2.name
33172
+ originalName: tool3.name
31809
33173
  });
31810
33174
  if (this.debug) {
31811
33175
  console.error(`[MCP] Registered tool: ${qualifiedName}`);
@@ -31827,20 +33191,20 @@ var init_client2 = __esm({
31827
33191
  * @param {Object} args - Tool arguments
31828
33192
  */
31829
33193
  async callTool(toolName, args) {
31830
- const tool2 = this.tools.get(toolName);
31831
- if (!tool2) {
33194
+ const tool3 = this.tools.get(toolName);
33195
+ if (!tool3) {
31832
33196
  throw new Error(`Unknown tool: ${toolName}`);
31833
33197
  }
31834
- const clientInfo = this.clients.get(tool2.serverName);
33198
+ const clientInfo = this.clients.get(tool3.serverName);
31835
33199
  if (!clientInfo) {
31836
- throw new Error(`Server ${tool2.serverName} not connected`);
33200
+ throw new Error(`Server ${tool3.serverName} not connected`);
31837
33201
  }
31838
33202
  try {
31839
33203
  if (this.debug) {
31840
33204
  console.error(`[MCP] Calling ${toolName} with args:`, args);
31841
33205
  }
31842
33206
  const result = await clientInfo.client.callTool({
31843
- name: tool2.originalName,
33207
+ name: tool3.originalName,
31844
33208
  arguments: args
31845
33209
  });
31846
33210
  return result;
@@ -31855,11 +33219,11 @@ var init_client2 = __esm({
31855
33219
  */
31856
33220
  getTools() {
31857
33221
  const tools2 = {};
31858
- for (const [name14, tool2] of this.tools.entries()) {
33222
+ for (const [name14, tool3] of this.tools.entries()) {
31859
33223
  tools2[name14] = {
31860
- description: tool2.description,
31861
- inputSchema: tool2.inputSchema,
31862
- serverName: tool2.serverName
33224
+ description: tool3.description,
33225
+ inputSchema: tool3.inputSchema,
33226
+ serverName: tool3.serverName
31863
33227
  };
31864
33228
  }
31865
33229
  return tools2;
@@ -31870,10 +33234,10 @@ var init_client2 = __esm({
31870
33234
  */
31871
33235
  getVercelTools() {
31872
33236
  const tools2 = {};
31873
- for (const [name14, tool2] of this.tools.entries()) {
33237
+ for (const [name14, tool3] of this.tools.entries()) {
31874
33238
  tools2[name14] = {
31875
- description: tool2.description,
31876
- inputSchema: tool2.inputSchema,
33239
+ description: tool3.description,
33240
+ inputSchema: tool3.inputSchema,
31877
33241
  execute: async (args) => {
31878
33242
  const result = await this.callTool(name14, args);
31879
33243
  if (result.content && result.content[0]) {
@@ -31910,9 +33274,9 @@ var init_client2 = __esm({
31910
33274
  });
31911
33275
 
31912
33276
  // src/agent/mcp/xmlBridge.js
31913
- function mcpToolToXmlDefinition(name14, tool2) {
31914
- const description = tool2.description || "MCP tool";
31915
- const inputSchema = tool2.inputSchema || tool2.parameters || {};
33277
+ function mcpToolToXmlDefinition(name14, tool3) {
33278
+ const description = tool3.description || "MCP tool";
33279
+ const inputSchema = tool3.inputSchema || tool3.parameters || {};
31916
33280
  let paramDocs = "";
31917
33281
  if (inputSchema.properties) {
31918
33282
  paramDocs = "\n\nParameters (provide as JSON object):";
@@ -32072,8 +33436,8 @@ var init_xmlBridge = __esm({
32072
33436
  const result = await this.mcpManager.initialize(mcpConfigs);
32073
33437
  const vercelTools = this.mcpManager.getVercelTools();
32074
33438
  this.mcpTools = vercelTools;
32075
- for (const [name14, tool2] of Object.entries(vercelTools)) {
32076
- this.xmlDefinitions[name14] = mcpToolToXmlDefinition(name14, tool2);
33439
+ for (const [name14, tool3] of Object.entries(vercelTools)) {
33440
+ this.xmlDefinitions[name14] = mcpToolToXmlDefinition(name14, tool3);
32077
33441
  }
32078
33442
  if (this.debug) {
32079
33443
  console.error(`[MCP] Loaded ${Object.keys(vercelTools).length} MCP tools from ${result.connected} server(s)`);
@@ -32110,12 +33474,12 @@ var init_xmlBridge = __esm({
32110
33474
  if (this.debug) {
32111
33475
  console.error(`[MCP] Executing MCP tool: ${toolName} with params:`, params);
32112
33476
  }
32113
- const tool2 = this.mcpTools[toolName];
32114
- if (!tool2) {
33477
+ const tool3 = this.mcpTools[toolName];
33478
+ if (!tool3) {
32115
33479
  throw new Error(`Unknown MCP tool: ${toolName}`);
32116
33480
  }
32117
33481
  try {
32118
- const result = await tool2.execute(params);
33482
+ const result = await tool3.execute(params);
32119
33483
  return {
32120
33484
  success: true,
32121
33485
  toolName,
@@ -32167,7 +33531,7 @@ var ProbeAgent_exports = {};
32167
33531
  __export(ProbeAgent_exports, {
32168
33532
  ProbeAgent: () => ProbeAgent
32169
33533
  });
32170
- var import_anthropic, import_openai, import_google, import_ai2, import_crypto5, import_events2, import_fs5, import_promises, import_path7, MAX_TOOL_ITERATIONS, MAX_HISTORY_MESSAGES, SUPPORTED_IMAGE_EXTENSIONS, MAX_IMAGE_FILE_SIZE, ProbeAgent;
33534
+ var import_anthropic, import_openai, import_google, import_ai3, import_crypto5, import_events2, import_fs6, import_promises, import_path9, MAX_TOOL_ITERATIONS, MAX_HISTORY_MESSAGES, SUPPORTED_IMAGE_EXTENSIONS, MAX_IMAGE_FILE_SIZE, ProbeAgent;
32171
33535
  var init_ProbeAgent = __esm({
32172
33536
  "src/agent/ProbeAgent.js"() {
32173
33537
  "use strict";
@@ -32175,12 +33539,12 @@ var init_ProbeAgent = __esm({
32175
33539
  import_openai = require("@ai-sdk/openai");
32176
33540
  import_google = require("@ai-sdk/google");
32177
33541
  init_dist3();
32178
- import_ai2 = require("ai");
33542
+ import_ai3 = require("ai");
32179
33543
  import_crypto5 = require("crypto");
32180
33544
  import_events2 = require("events");
32181
- import_fs5 = require("fs");
33545
+ import_fs6 = require("fs");
32182
33546
  import_promises = require("fs/promises");
32183
- import_path7 = require("path");
33547
+ import_path9 = require("path");
32184
33548
  init_tokenCounter();
32185
33549
  init_tools2();
32186
33550
  init_common();
@@ -32224,6 +33588,8 @@ var init_ProbeAgent = __esm({
32224
33588
  this.outline = !!options.outline;
32225
33589
  this.maxResponseTokens = options.maxResponseTokens || parseInt(process.env.MAX_RESPONSE_TOKENS || "0", 10) || null;
32226
33590
  this.disableMermaidValidation = !!options.disableMermaidValidation;
33591
+ this.enableBash = !!options.enableBash;
33592
+ this.bashConfig = options.bashConfig || {};
32227
33593
  if (options.allowedFolders && Array.isArray(options.allowedFolders)) {
32228
33594
  this.allowedFolders = options.allowedFolders;
32229
33595
  } else if (options.path) {
@@ -32267,7 +33633,9 @@ var init_ProbeAgent = __esm({
32267
33633
  debug: this.debug,
32268
33634
  defaultPath: this.allowedFolders.length > 0 ? this.allowedFolders[0] : process.cwd(),
32269
33635
  allowedFolders: this.allowedFolders,
32270
- outline: this.outline
33636
+ outline: this.outline,
33637
+ enableBash: this.enableBash,
33638
+ bashConfig: this.bashConfig
32271
33639
  };
32272
33640
  const baseTools = createTools(configOptions);
32273
33641
  const wrappedTools = createWrappedTools(baseTools);
@@ -32279,6 +33647,9 @@ var init_ProbeAgent = __esm({
32279
33647
  listFiles: listFilesToolInstance,
32280
33648
  searchFiles: searchFilesToolInstance
32281
33649
  };
33650
+ if (this.enableBash && wrappedTools.bashToolInstance) {
33651
+ this.toolImplementations.bash = wrappedTools.bashToolInstance;
33652
+ }
32282
33653
  this.wrappedTools = wrappedTools;
32283
33654
  }
32284
33655
  /**
@@ -32465,13 +33836,13 @@ var init_ProbeAgent = __esm({
32465
33836
  const allowedDirs = this.allowedFolders && this.allowedFolders.length > 0 ? this.allowedFolders : [process.cwd()];
32466
33837
  let absolutePath;
32467
33838
  let isPathAllowed = false;
32468
- if ((0, import_path7.isAbsolute)(imagePath)) {
33839
+ if ((0, import_path9.isAbsolute)(imagePath)) {
32469
33840
  absolutePath = imagePath;
32470
- isPathAllowed = allowedDirs.some((dir) => absolutePath.startsWith((0, import_path7.resolve)(dir)));
33841
+ isPathAllowed = allowedDirs.some((dir) => absolutePath.startsWith((0, import_path9.resolve)(dir)));
32471
33842
  } else {
32472
33843
  for (const dir of allowedDirs) {
32473
- const resolvedPath3 = (0, import_path7.resolve)(dir, imagePath);
32474
- if (resolvedPath3.startsWith((0, import_path7.resolve)(dir))) {
33844
+ const resolvedPath3 = (0, import_path9.resolve)(dir, imagePath);
33845
+ if (resolvedPath3.startsWith((0, import_path9.resolve)(dir))) {
32475
33846
  absolutePath = resolvedPath3;
32476
33847
  isPathAllowed = true;
32477
33848
  break;
@@ -32966,7 +34337,7 @@ You are working with a repository located at: ${searchDirectory}
32966
34337
  try {
32967
34338
  const executeAIRequest = async () => {
32968
34339
  const messagesForAI = this.prepareMessagesWithImages(currentMessages);
32969
- const result = await (0, import_ai2.streamText)({
34340
+ const result = await (0, import_ai3.streamText)({
32970
34341
  model: this.provider(this.model),
32971
34342
  messages: messagesForAI,
32972
34343
  maxTokens: maxResponseTokens,
@@ -33643,12 +35014,12 @@ function initializeSimpleTelemetryFromOptions(options) {
33643
35014
  });
33644
35015
  return telemetry;
33645
35016
  }
33646
- var import_fs6, import_path8, SimpleTelemetry, SimpleAppTracer;
35017
+ var import_fs7, import_path10, SimpleTelemetry, SimpleAppTracer;
33647
35018
  var init_simpleTelemetry = __esm({
33648
35019
  "src/agent/simpleTelemetry.js"() {
33649
35020
  "use strict";
33650
- import_fs6 = require("fs");
33651
- import_path8 = require("path");
35021
+ import_fs7 = require("fs");
35022
+ import_path10 = require("path");
33652
35023
  SimpleTelemetry = class {
33653
35024
  constructor(options = {}) {
33654
35025
  this.serviceName = options.serviceName || "probe-agent";
@@ -33662,11 +35033,11 @@ var init_simpleTelemetry = __esm({
33662
35033
  }
33663
35034
  initializeFileExporter() {
33664
35035
  try {
33665
- const dir = (0, import_path8.dirname)(this.filePath);
33666
- if (!(0, import_fs6.existsSync)(dir)) {
33667
- (0, import_fs6.mkdirSync)(dir, { recursive: true });
35036
+ const dir = (0, import_path10.dirname)(this.filePath);
35037
+ if (!(0, import_fs7.existsSync)(dir)) {
35038
+ (0, import_fs7.mkdirSync)(dir, { recursive: true });
33668
35039
  }
33669
- this.stream = (0, import_fs6.createWriteStream)(this.filePath, { flags: "a" });
35040
+ this.stream = (0, import_fs7.createWriteStream)(this.filePath, { flags: "a" });
33670
35041
  this.stream.on("error", (error2) => {
33671
35042
  console.error(`[SimpleTelemetry] Stream error: ${error2.message}`);
33672
35043
  });
@@ -33727,20 +35098,20 @@ var init_simpleTelemetry = __esm({
33727
35098
  }
33728
35099
  async flush() {
33729
35100
  if (this.stream) {
33730
- return new Promise((resolve2) => {
33731
- this.stream.once("drain", resolve2);
35101
+ return new Promise((resolve4) => {
35102
+ this.stream.once("drain", resolve4);
33732
35103
  if (!this.stream.writableNeedDrain) {
33733
- resolve2();
35104
+ resolve4();
33734
35105
  }
33735
35106
  });
33736
35107
  }
33737
35108
  }
33738
35109
  async shutdown() {
33739
35110
  if (this.stream) {
33740
- return new Promise((resolve2) => {
35111
+ return new Promise((resolve4) => {
33741
35112
  this.stream.end(() => {
33742
35113
  console.log(`[SimpleTelemetry] File stream closed: ${this.filePath}`);
33743
- resolve2();
35114
+ resolve4();
33744
35115
  });
33745
35116
  });
33746
35117
  }
@@ -33867,6 +35238,9 @@ __export(index_exports, {
33867
35238
  SimpleTelemetry: () => SimpleTelemetry,
33868
35239
  attemptCompletionSchema: () => attemptCompletionSchema,
33869
35240
  attemptCompletionToolDefinition: () => attemptCompletionToolDefinition,
35241
+ bashSchema: () => bashSchema,
35242
+ bashTool: () => bashTool,
35243
+ bashToolDefinition: () => bashToolDefinition,
33870
35244
  delegate: () => delegate,
33871
35245
  delegateSchema: () => delegateSchema,
33872
35246
  delegateTool: () => delegateTool,
@@ -33903,6 +35277,7 @@ var init_index = __esm({
33903
35277
  init_system_message();
33904
35278
  init_common();
33905
35279
  init_vercel();
35280
+ init_bash();
33906
35281
  init_ProbeAgent();
33907
35282
  init_simpleTelemetry();
33908
35283
  }
@@ -33916,6 +35291,9 @@ init_index();
33916
35291
  SimpleTelemetry,
33917
35292
  attemptCompletionSchema,
33918
35293
  attemptCompletionToolDefinition,
35294
+ bashSchema,
35295
+ bashTool,
35296
+ bashToolDefinition,
33919
35297
  delegate,
33920
35298
  delegateSchema,
33921
35299
  delegateTool,