@probelabs/visor 0.1.49 → 0.1.51

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- process.env.VISOR_VERSION = '0.1.49';
2
+ process.env.VISOR_VERSION = '0.1.51';
3
3
  /******/ (() => { // webpackBootstrap
4
4
  /******/ var __webpack_modules__ = ({
5
5
 
@@ -94138,11 +94138,12 @@ ${prContext}
94138
94138
  */
94139
94139
  formatPRContext(prInfo) {
94140
94140
  // Check if this is an issue (not a PR)
94141
- const isIssue = prInfo.isIssue === true;
94141
+ const prContextInfo = prInfo;
94142
+ const isIssue = prContextInfo.isIssue === true;
94142
94143
  // Check if we should include code context (diffs)
94143
- const isPRContext = prInfo.isPRContext === true;
94144
+ const isPRContext = prContextInfo.isPRContext === true;
94144
94145
  // In PR context, always include diffs. Otherwise check the flag.
94145
- const includeCodeContext = isPRContext || prInfo.includeCodeContext !== false;
94146
+ const includeCodeContext = isPRContext || prContextInfo.includeCodeContext !== false;
94146
94147
  // Log the decision for transparency
94147
94148
  const log = this.config.debug ? console.error : () => { };
94148
94149
  if (isPRContext) {
@@ -94486,12 +94487,16 @@ ${prInfo.fullDiff ? this.escapeXml(prInfo.fullDiff) : ''}
94486
94487
  if (this.config.provider) {
94487
94488
  // Map claude-code to anthropic for ProbeAgent compatibility
94488
94489
  // Map bedrock to anthropic temporarily until ProbeAgent adds bedrock type
94489
- options.provider =
94490
- this.config.provider === 'claude-code'
94491
- ? 'anthropic'
94492
- : this.config.provider === 'bedrock'
94493
- ? 'anthropic'
94494
- : this.config.provider;
94490
+ const providerOverride = this.config.provider === 'claude-code' || this.config.provider === 'bedrock'
94491
+ ? 'anthropic'
94492
+ : this.config.provider === 'anthropic' ||
94493
+ this.config.provider === 'openai' ||
94494
+ this.config.provider === 'google'
94495
+ ? this.config.provider
94496
+ : undefined;
94497
+ if (providerOverride) {
94498
+ options.provider = providerOverride;
94499
+ }
94495
94500
  }
94496
94501
  if (this.config.model) {
94497
94502
  options.model = this.config.model;
@@ -95230,7 +95235,6 @@ class CheckExecutionEngine {
95230
95235
  const result = await tasks[taskIndex]();
95231
95236
  results[taskIndex] = { status: 'fulfilled', value: result };
95232
95237
  // Check if we should stop due to fail-fast
95233
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
95234
95238
  if (failFast && this.shouldFailFast(result)) {
95235
95239
  shouldStop = true;
95236
95240
  break;
@@ -95263,7 +95267,11 @@ class CheckExecutionEngine {
95263
95267
  // Store config for use in filtering
95264
95268
  this.config = config;
95265
95269
  // Determine where to send log messages based on output format
95266
- const logFn = outputFormat === 'json' || outputFormat === 'sarif' ? console.error : console.log;
95270
+ const logFn = outputFormat === 'json' || outputFormat === 'sarif'
95271
+ ? debug
95272
+ ? console.error
95273
+ : () => { }
95274
+ : console.log;
95267
95275
  // Only output debug messages if debug mode is enabled
95268
95276
  if (debug) {
95269
95277
  logFn(`🔧 Debug: executeReviewChecks called with checks: ${JSON.stringify(checks)}`);
@@ -95385,7 +95393,11 @@ class CheckExecutionEngine {
95385
95393
  */
95386
95394
  async executeGroupedChecks(prInfo, checks, timeout, config, outputFormat, debug, maxParallelism, failFast, tagFilter) {
95387
95395
  // Determine where to send log messages based on output format
95388
- const logFn = outputFormat === 'json' || outputFormat === 'sarif' ? console.error : console.log;
95396
+ const logFn = outputFormat === 'json' || outputFormat === 'sarif'
95397
+ ? debug
95398
+ ? console.error
95399
+ : () => { }
95400
+ : console.log;
95389
95401
  // Only output debug messages if debug mode is enabled
95390
95402
  if (debug) {
95391
95403
  logFn(`🔧 Debug: executeGroupedChecks called with checks: ${JSON.stringify(checks)}`);
@@ -95465,6 +95477,7 @@ class CheckExecutionEngine {
95465
95477
  // Pass any provider-specific config
95466
95478
  ...checkConfig,
95467
95479
  };
95480
+ providerConfig.forEach = checkConfig.forEach;
95468
95481
  const result = await provider.execute(prInfo, providerConfig);
95469
95482
  // Render the check content using the appropriate template
95470
95483
  const content = await this.renderCheckContent(checkName, result, checkConfig, prInfo);
@@ -95490,6 +95503,7 @@ class CheckExecutionEngine {
95490
95503
  */
95491
95504
  async convertReviewSummaryToGroupedResults(reviewSummary, checks, config, prInfo) {
95492
95505
  const groupedResults = {};
95506
+ const contentMap = reviewSummary.__contents;
95493
95507
  // Process each check individually
95494
95508
  for (const checkName of checks) {
95495
95509
  const checkConfig = config?.checks?.[checkName];
@@ -95502,6 +95516,10 @@ class CheckExecutionEngine {
95502
95516
  issues: checkIssues,
95503
95517
  debug: reviewSummary.debug,
95504
95518
  };
95519
+ if (contentMap?.[checkName]) {
95520
+ const summaryWithContent = checkSummary;
95521
+ summaryWithContent.content = contentMap[checkName];
95522
+ }
95505
95523
  // Render content for this check
95506
95524
  const content = await this.renderCheckContent(checkName, checkSummary, checkConfig, prInfo);
95507
95525
  const checkResult = {
@@ -95583,11 +95601,15 @@ class CheckExecutionEngine {
95583
95601
  * Render check content using the appropriate template
95584
95602
  */
95585
95603
  async renderCheckContent(checkName, reviewSummary, checkConfig, _prInfo) {
95604
+ const directContent = reviewSummary.content;
95605
+ if (typeof directContent === 'string' && directContent.trim()) {
95606
+ return directContent.trim();
95607
+ }
95586
95608
  // Import the liquid template system
95587
- const { Liquid } = await Promise.resolve().then(() => __importStar(__nccwpck_require__(48694)));
95609
+ const { createExtendedLiquid } = await Promise.resolve().then(() => __importStar(__nccwpck_require__(33042)));
95588
95610
  const fs = await Promise.resolve().then(() => __importStar(__nccwpck_require__(91943)));
95589
95611
  const path = await Promise.resolve().then(() => __importStar(__nccwpck_require__(16928)));
95590
- const liquid = new Liquid({
95612
+ const liquid = createExtendedLiquid({
95591
95613
  trimTagLeft: false,
95592
95614
  trimTagRight: false,
95593
95615
  trimOutputLeft: false,
@@ -95768,6 +95790,7 @@ class CheckExecutionEngine {
95768
95790
  const provider = this.providerRegistry.getProviderOrThrow(providerType);
95769
95791
  this.setProviderWebhookContext(provider);
95770
95792
  // Create provider config for this specific check
95793
+ const extendedCheckConfig = checkConfig;
95771
95794
  const providerConfig = {
95772
95795
  type: providerType,
95773
95796
  prompt: checkConfig.prompt,
@@ -95778,9 +95801,11 @@ class CheckExecutionEngine {
95778
95801
  checkName: checkName, // Add checkName for sessionID
95779
95802
  eventContext: prInfo.eventContext, // Pass event context for templates
95780
95803
  transform: checkConfig.transform,
95781
- level: checkConfig.level,
95782
- message: checkConfig.message,
95804
+ transform_js: checkConfig.transform_js,
95805
+ level: extendedCheckConfig.level,
95806
+ message: extendedCheckConfig.message,
95783
95807
  env: checkConfig.env,
95808
+ forEach: checkConfig.forEach,
95784
95809
  ai: {
95785
95810
  timeout: timeout || 600000,
95786
95811
  debug: debug,
@@ -95797,9 +95822,10 @@ class CheckExecutionEngine {
95797
95822
  const depResult = results.get(depId);
95798
95823
  dependencyResults.set(depId, depResult);
95799
95824
  // Check if this dependency has forEach enabled
95800
- if (depResult.isForEach && depResult.forEachItems) {
95825
+ const depForEachResult = depResult;
95826
+ if (depForEachResult.isForEach && Array.isArray(depForEachResult.forEachItems)) {
95801
95827
  isForEachDependent = true;
95802
- forEachItems = depResult.forEachItems;
95828
+ forEachItems = depForEachResult.forEachItems;
95803
95829
  forEachParentName = depId;
95804
95830
  }
95805
95831
  }
@@ -95836,17 +95862,22 @@ class CheckExecutionEngine {
95836
95862
  log(`🔄 Debug: Check "${checkName}" depends on forEach check "${forEachParentName}", executing ${forEachItems.length} times`);
95837
95863
  const allIssues = [];
95838
95864
  const allOutputs = [];
95839
- // Execute check for each item in the forEach array
95840
- for (let itemIndex = 0; itemIndex < forEachItems.length; itemIndex++) {
95841
- const item = forEachItems[itemIndex];
95865
+ const aggregatedContents = [];
95866
+ const itemTasks = forEachItems.map((item, itemIndex) => async () => {
95842
95867
  // Create modified dependency results with current item
95843
95868
  const forEachDependencyResults = new Map();
95844
95869
  for (const [depName, depResult] of dependencyResults) {
95845
95870
  if (depName === forEachParentName) {
95846
- // Replace the entire forEach parent result with just the current item
95847
- // This ensures that outputs.fetch-tickets contains the individual item
95848
- const modifiedResult = item;
95871
+ const modifiedResult = {
95872
+ issues: [],
95873
+ output: item,
95874
+ };
95849
95875
  forEachDependencyResults.set(depName, modifiedResult);
95876
+ const rawResult = {
95877
+ issues: [],
95878
+ output: forEachItems,
95879
+ };
95880
+ forEachDependencyResults.set(`${depName}-raw`, rawResult);
95850
95881
  }
95851
95882
  else {
95852
95883
  forEachDependencyResults.set(depName, depResult);
@@ -95854,24 +95885,49 @@ class CheckExecutionEngine {
95854
95885
  }
95855
95886
  log(`🔄 Debug: Executing check "${checkName}" for item ${itemIndex + 1}/${forEachItems.length}`);
95856
95887
  const itemResult = await provider.execute(prInfo, providerConfig, forEachDependencyResults, sessionInfo);
95857
- // Collect issues from each iteration
95888
+ return { index: itemIndex, itemResult };
95889
+ });
95890
+ const forEachConcurrency = Math.max(1, Math.min(forEachItems.length, effectiveMaxParallelism));
95891
+ if (debug && forEachConcurrency > 1) {
95892
+ log(`🔄 Debug: Limiting forEach concurrency for check "${checkName}" to ${forEachConcurrency}`);
95893
+ }
95894
+ const forEachResults = await this.executeWithLimitedParallelism(itemTasks, forEachConcurrency, false);
95895
+ for (const result of forEachResults) {
95896
+ if (result.status === 'rejected') {
95897
+ throw result.reason;
95898
+ }
95899
+ const { itemResult } = result.value;
95858
95900
  if (itemResult.issues) {
95859
95901
  allIssues.push(...itemResult.issues);
95860
95902
  }
95861
- // Collect outputs from each iteration
95862
- if (itemResult.output) {
95863
- allOutputs.push(itemResult.output);
95903
+ const resultWithOutput = itemResult;
95904
+ if (resultWithOutput.output !== undefined) {
95905
+ allOutputs.push(resultWithOutput.output);
95906
+ }
95907
+ const itemContent = resultWithOutput.content;
95908
+ if (typeof itemContent === 'string' && itemContent.trim()) {
95909
+ aggregatedContents.push(itemContent.trim());
95864
95910
  }
95865
95911
  }
95912
+ const finalOutput = allOutputs.length > 0 ? allOutputs : undefined;
95866
95913
  finalResult = {
95867
95914
  issues: allIssues,
95868
- output: allOutputs.length > 0 ? allOutputs : undefined,
95915
+ ...(finalOutput !== undefined ? { output: finalOutput } : {}),
95869
95916
  };
95917
+ if (aggregatedContents.length > 0) {
95918
+ finalResult.content =
95919
+ aggregatedContents.join('\n');
95920
+ }
95870
95921
  log(`🔄 Debug: Completed forEach execution for check "${checkName}", total issues: ${allIssues.length}`);
95871
95922
  }
95872
95923
  else {
95873
95924
  // Normal single execution
95874
95925
  finalResult = await provider.execute(prInfo, providerConfig, dependencyResults, sessionInfo);
95926
+ if (process.env.DEBUG && checkConfig.forEach) {
95927
+ const finalResultWithOutput = finalResult;
95928
+ const outputPreview = JSON.stringify(finalResultWithOutput.output).slice(0, 200);
95929
+ console.log(`🔧 Debug: Check "${checkName}" provider returned:`, outputPreview);
95930
+ }
95875
95931
  log(`🔧 Debug: Completed check: ${checkName}, issues found: ${(finalResult.issues || []).length}`);
95876
95932
  }
95877
95933
  // Add group, schema, template info and timestamp to issues from config
@@ -95913,28 +95969,39 @@ class CheckExecutionEngine {
95913
95969
  if (result.status === 'fulfilled' && result.value.result && !result.value.error) {
95914
95970
  const reviewResult = result.value.result;
95915
95971
  // Handle forEach logic - process array outputs
95916
- if (checkConfig?.forEach && reviewResult.output) {
95917
- let outputArray = reviewResult.output;
95918
- // Ensure output is an array
95919
- if (!Array.isArray(outputArray)) {
95920
- // Try to parse as JSON if it's a string
95921
- if (typeof outputArray === 'string') {
95922
- try {
95923
- const parsed = JSON.parse(outputArray);
95924
- outputArray = Array.isArray(parsed) ? parsed : [parsed];
95925
- }
95926
- catch {
95927
- outputArray = [outputArray];
95928
- }
95972
+ const reviewSummaryWithOutput = reviewResult;
95973
+ if (checkConfig?.forEach && reviewSummaryWithOutput.output !== undefined) {
95974
+ if (process.env.DEBUG) {
95975
+ console.log(`🔧 Debug: Raw output for forEach check ${checkName}:`, Array.isArray(reviewSummaryWithOutput.output)
95976
+ ? `array(${reviewSummaryWithOutput.output.length})`
95977
+ : typeof reviewSummaryWithOutput.output);
95978
+ }
95979
+ const rawOutput = reviewSummaryWithOutput.output;
95980
+ let normalizedOutput;
95981
+ if (Array.isArray(rawOutput)) {
95982
+ normalizedOutput = rawOutput;
95983
+ }
95984
+ else if (typeof rawOutput === 'string') {
95985
+ try {
95986
+ const parsed = JSON.parse(rawOutput);
95987
+ normalizedOutput = Array.isArray(parsed) ? parsed : [parsed];
95929
95988
  }
95930
- else {
95931
- outputArray = [outputArray];
95989
+ catch {
95990
+ normalizedOutput = [rawOutput];
95932
95991
  }
95933
95992
  }
95934
- log(`🔄 Debug: Check "${checkName}" has forEach enabled, processing ${outputArray.length} items`);
95993
+ else if (rawOutput === undefined || rawOutput === null) {
95994
+ normalizedOutput = [];
95995
+ }
95996
+ else {
95997
+ normalizedOutput = [rawOutput];
95998
+ }
95999
+ if (process.env.DEBUG) {
96000
+ console.log(`🔧 Debug: Check "${checkName}" forEach output:`, JSON.stringify(normalizedOutput).slice(0, 200));
96001
+ }
95935
96002
  // Store the array for iteration by dependent checks
95936
- reviewResult.forEachItems = outputArray;
95937
- reviewResult.isForEach = true;
96003
+ reviewSummaryWithOutput.forEachItems = normalizedOutput;
96004
+ reviewSummaryWithOutput.isForEach = true;
95938
96005
  }
95939
96006
  results.set(checkName, reviewResult);
95940
96007
  }
@@ -96177,6 +96244,7 @@ class CheckExecutionEngine {
96177
96244
  aggregateDependencyAwareResults(results, dependencyGraph, debug, stoppedEarly) {
96178
96245
  const aggregatedIssues = [];
96179
96246
  const debugInfo = [];
96247
+ const contentMap = {};
96180
96248
  // Add execution plan info
96181
96249
  const stats = dependency_resolver_1.DependencyResolver.getExecutionStats(dependencyGraph);
96182
96250
  const executionInfo = [
@@ -96209,9 +96277,16 @@ class CheckExecutionEngine {
96209
96277
  }
96210
96278
  // Issues are already prefixed and enriched with group/schema info
96211
96279
  aggregatedIssues.push(...(result.issues || []));
96280
+ const resultSummary = result;
96281
+ const resultContent = resultSummary.content;
96282
+ if (typeof resultContent === 'string' && resultContent.trim()) {
96283
+ contentMap[checkName] = resultContent.trim();
96284
+ }
96212
96285
  }
96213
96286
  }
96214
- console.error(`🔧 Debug: Aggregated ${aggregatedIssues.length} issues from ${results.size} dependency-aware checks`);
96287
+ if (debug) {
96288
+ console.error(`🔧 Debug: Aggregated ${aggregatedIssues.length} issues from ${results.size} dependency-aware checks`);
96289
+ }
96215
96290
  // Apply issue suppression filtering
96216
96291
  const suppressionEnabled = this.config?.output?.suppressionEnabled !== false;
96217
96292
  const issueFilter = new issue_filter_1.IssueFilter(suppressionEnabled);
@@ -96253,10 +96328,14 @@ class CheckExecutionEngine {
96253
96328
  };
96254
96329
  }
96255
96330
  }
96256
- return {
96331
+ const summary = {
96257
96332
  issues: filteredIssues,
96258
96333
  debug: aggregatedDebug,
96259
96334
  };
96335
+ if (Object.keys(contentMap).length > 0) {
96336
+ summary.__contents = contentMap;
96337
+ }
96338
+ return summary;
96260
96339
  }
96261
96340
  /**
96262
96341
  * Aggregate results from parallel check execution (legacy method)
@@ -96326,7 +96405,9 @@ class CheckExecutionEngine {
96326
96405
  });
96327
96406
  }
96328
96407
  });
96329
- console.error(`🔧 Debug: Aggregated ${aggregatedIssues.length} issues from ${results.length} checks`);
96408
+ if (debug) {
96409
+ console.error(`🔧 Debug: Aggregated ${aggregatedIssues.length} issues from ${results.length} checks`);
96410
+ }
96330
96411
  // Apply issue suppression filtering
96331
96412
  const suppressionEnabled = this.config?.output?.suppressionEnabled !== false;
96332
96413
  const issueFilter = new issue_filter_1.IssueFilter(suppressionEnabled);
@@ -96546,14 +96627,36 @@ class CheckExecutionEngine {
96546
96627
  /**
96547
96628
  * Check if a task result should trigger fail-fast behavior
96548
96629
  */
96630
+ isFailFastCandidate(value) {
96631
+ if (typeof value !== 'object' || value === null) {
96632
+ return false;
96633
+ }
96634
+ const candidate = value;
96635
+ if (candidate.error !== undefined && typeof candidate.error !== 'string') {
96636
+ return false;
96637
+ }
96638
+ if (candidate.result !== undefined) {
96639
+ if (typeof candidate.result !== 'object' || candidate.result === null) {
96640
+ return false;
96641
+ }
96642
+ const issues = candidate.result.issues;
96643
+ if (issues !== undefined && !Array.isArray(issues)) {
96644
+ return false;
96645
+ }
96646
+ }
96647
+ return true;
96648
+ }
96549
96649
  shouldFailFast(result) {
96550
- // If the result has an error property, it's a failed check
96551
- if (result?.error) {
96650
+ if (!this.isFailFastCandidate(result)) {
96651
+ return false;
96652
+ }
96653
+ if (result.error) {
96552
96654
  return true;
96553
96655
  }
96554
96656
  // If the result has a result with critical or error issues, it should fail fast
96555
- if (result?.result?.issues) {
96556
- return (result.result.issues || []).some((issue) => issue.severity === 'error' || issue.severity === 'critical');
96657
+ const issues = result.result?.issues;
96658
+ if (Array.isArray(issues)) {
96659
+ return issues.some(issue => issue?.severity === 'error' || issue?.severity === 'critical');
96557
96660
  }
96558
96661
  return false;
96559
96662
  }
@@ -96939,6 +97042,9 @@ async function main() {
96939
97042
  const filteredArgv = process.argv.filter(arg => arg !== '--cli');
96940
97043
  // Parse arguments using the CLI class
96941
97044
  const options = cli.parseArgs(filteredArgv);
97045
+ const explicitChecks = options.checks.length > 0
97046
+ ? new Set(options.checks.map(check => check.toString()))
97047
+ : null;
96942
97048
  // Set environment variables early for proper logging in all modules
96943
97049
  process.env.VISOR_OUTPUT_FORMAT = options.output;
96944
97050
  process.env.VISOR_DEBUG = options.debug ? 'true' : 'false';
@@ -96992,7 +97098,7 @@ async function main() {
96992
97098
  .catch(() => configManager.getDefaultConfig());
96993
97099
  }
96994
97100
  // Determine checks to run and validate check types early
96995
- const checksToRun = options.checks.length > 0 ? options.checks : Object.keys(config.checks || {});
97101
+ let checksToRun = options.checks.length > 0 ? options.checks : Object.keys(config.checks || {});
96996
97102
  // Validate that all requested checks exist in the configuration
96997
97103
  const availableChecks = Object.keys(config.checks || {});
96998
97104
  const invalidChecks = checksToRun.filter(check => !availableChecks.includes(check));
@@ -97000,8 +97106,28 @@ async function main() {
97000
97106
  console.error(`❌ Error: No configuration found for check: ${invalidChecks[0]}`);
97001
97107
  process.exit(1);
97002
97108
  }
97109
+ // Include dependencies of requested checks
97110
+ const checksWithDependencies = new Set(checksToRun);
97111
+ const addDependencies = (checkName) => {
97112
+ const checkConfig = config.checks?.[checkName];
97113
+ if (checkConfig?.depends_on) {
97114
+ for (const dep of checkConfig.depends_on) {
97115
+ if (!checksWithDependencies.has(dep)) {
97116
+ checksWithDependencies.add(dep);
97117
+ addDependencies(dep); // Recursively add dependencies of dependencies
97118
+ }
97119
+ }
97120
+ }
97121
+ };
97122
+ // Add all dependencies
97123
+ for (const check of checksToRun) {
97124
+ addDependencies(check);
97125
+ }
97126
+ // Update checksToRun to include dependencies
97127
+ checksToRun = Array.from(checksWithDependencies);
97003
97128
  // Use stderr for status messages when outputting formatted results to stdout
97004
- const logFn = console.error;
97129
+ // Suppress all status messages when outputting JSON to avoid breaking parsers
97130
+ const logFn = options.output === 'json' ? () => { } : console.error;
97005
97131
  // Determine if we should include code context (diffs)
97006
97132
  // In CLI mode (local), we do smart detection. PR mode always includes context.
97007
97133
  const isPRContext = false; // This is CLI mode, not GitHub Action
@@ -97047,14 +97173,14 @@ async function main() {
97047
97173
  console.error('❌ Error: Not a git repository. Run "git init" to initialize a repository.');
97048
97174
  process.exit(1);
97049
97175
  }
97176
+ logFn('🔍 Visor - AI-powered code review tool');
97177
+ logFn(`Configuration version: ${config.version}`);
97178
+ logFn(`Configuration source: ${options.configPath || 'default search locations'}`);
97050
97179
  // Check if there are any changes to analyze (only when code context is needed)
97051
97180
  if (includeCodeContext && repositoryInfo.files.length === 0) {
97052
97181
  console.error('❌ Error: No changes to analyze. Make some file changes first.');
97053
97182
  process.exit(1);
97054
97183
  }
97055
- logFn('🔍 Visor - AI-powered code review tool');
97056
- logFn(`Configuration version: ${config.version}`);
97057
- logFn(`Configuration source: ${options.configPath || 'default search locations'}`);
97058
97184
  // Show registered providers if in debug mode
97059
97185
  if (options.debug) {
97060
97186
  const { CheckProviderRegistry } = await Promise.resolve().then(() => __importStar(__nccwpck_require__(57140)));
@@ -97077,26 +97203,52 @@ async function main() {
97077
97203
  // Convert repository info to PRInfo format
97078
97204
  const prInfo = analyzer.toPRInfo(repositoryInfo, includeCodeContext);
97079
97205
  // Store the includeCodeContext flag in prInfo for downstream use
97080
- prInfo.includeCodeContext = includeCodeContext;
97206
+ const prInfoWithContext = prInfo;
97207
+ prInfoWithContext.includeCodeContext = includeCodeContext;
97081
97208
  // Execute checks with proper parameters
97082
97209
  const groupedResults = await engine.executeGroupedChecks(prInfo, checksToRun, options.timeout, config, options.output, options.debug || false, options.maxParallelism, options.failFast, tagFilter);
97210
+ const shouldFilterResults = explicitChecks && explicitChecks.size > 0 && !explicitChecks.has('all');
97211
+ const groupedResultsToUse = shouldFilterResults
97212
+ ? Object.fromEntries(Object.entries(groupedResults)
97213
+ .map(([group, checkResults]) => [
97214
+ group,
97215
+ checkResults.filter(check => explicitChecks.has(check.checkName)),
97216
+ ])
97217
+ .filter(([, checkResults]) => checkResults.length > 0))
97218
+ : groupedResults;
97219
+ if (shouldFilterResults) {
97220
+ for (const [group, checkResults] of Object.entries(groupedResults)) {
97221
+ for (const check of checkResults) {
97222
+ if (check.issues && check.issues.length > 0 && !explicitChecks.has(check.checkName)) {
97223
+ if (!groupedResultsToUse[group]) {
97224
+ groupedResultsToUse[group] = [];
97225
+ }
97226
+ const alreadyIncluded = groupedResultsToUse[group].some(existing => existing.checkName === check.checkName);
97227
+ if (!alreadyIncluded) {
97228
+ groupedResultsToUse[group].push(check);
97229
+ }
97230
+ }
97231
+ }
97232
+ }
97233
+ }
97234
+ const executedCheckNames = Array.from(new Set(Object.values(groupedResultsToUse).flatMap((checks) => checks.map(check => check.checkName))));
97083
97235
  // Format output based on format type
97084
97236
  let output;
97085
97237
  if (options.output === 'json') {
97086
- output = JSON.stringify(groupedResults, null, 2);
97238
+ output = JSON.stringify(groupedResultsToUse, null, 2);
97087
97239
  }
97088
97240
  else if (options.output === 'sarif') {
97089
97241
  // Build analysis result and format as SARIF
97090
97242
  const analysisResult = {
97091
97243
  repositoryInfo,
97092
97244
  reviewSummary: {
97093
- issues: Object.values(groupedResults)
97245
+ issues: Object.values(groupedResultsToUse)
97094
97246
  .flatMap((r) => r.map((check) => check.issues || []).flat())
97095
97247
  .flat(),
97096
97248
  },
97097
97249
  executionTime: 0,
97098
97250
  timestamp: new Date().toISOString(),
97099
- checksExecuted: checksToRun,
97251
+ checksExecuted: executedCheckNames,
97100
97252
  };
97101
97253
  output = output_formatters_1.OutputFormatters.formatAsSarif(analysisResult);
97102
97254
  }
@@ -97105,13 +97257,13 @@ async function main() {
97105
97257
  const analysisResult = {
97106
97258
  repositoryInfo,
97107
97259
  reviewSummary: {
97108
- issues: Object.values(groupedResults)
97260
+ issues: Object.values(groupedResultsToUse)
97109
97261
  .flatMap((r) => r.map((check) => check.issues || []).flat())
97110
97262
  .flat(),
97111
97263
  },
97112
97264
  executionTime: 0,
97113
97265
  timestamp: new Date().toISOString(),
97114
- checksExecuted: checksToRun,
97266
+ checksExecuted: executedCheckNames,
97115
97267
  };
97116
97268
  output = output_formatters_1.OutputFormatters.formatAsMarkdown(analysisResult);
97117
97269
  }
@@ -97120,19 +97272,19 @@ async function main() {
97120
97272
  const analysisResult = {
97121
97273
  repositoryInfo,
97122
97274
  reviewSummary: {
97123
- issues: Object.values(groupedResults)
97275
+ issues: Object.values(groupedResultsToUse)
97124
97276
  .flatMap((r) => r.map((check) => check.issues || []).flat())
97125
97277
  .flat(),
97126
97278
  },
97127
97279
  executionTime: 0,
97128
97280
  timestamp: new Date().toISOString(),
97129
- checksExecuted: checksToRun,
97281
+ checksExecuted: executedCheckNames,
97130
97282
  };
97131
97283
  output = output_formatters_1.OutputFormatters.formatAsTable(analysisResult, { showDetails: true });
97132
97284
  }
97133
97285
  console.log(output);
97134
97286
  // Check for critical issues
97135
- const allResults = Object.values(groupedResults).flat();
97287
+ const allResults = Object.values(groupedResultsToUse).flat();
97136
97288
  const criticalCount = allResults.reduce((sum, result) => {
97137
97289
  const issues = result.issues || [];
97138
97290
  return (sum + issues.filter((issue) => issue.severity === 'critical').length);
@@ -101355,6 +101507,108 @@ class IssueFilter {
101355
101507
  exports.IssueFilter = IssueFilter;
101356
101508
 
101357
101509
 
101510
+ /***/ }),
101511
+
101512
+ /***/ 33042:
101513
+ /***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
101514
+
101515
+ "use strict";
101516
+
101517
+ var __importDefault = (this && this.__importDefault) || function (mod) {
101518
+ return (mod && mod.__esModule) ? mod : { "default": mod };
101519
+ };
101520
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
101521
+ exports.ReadFileTag = void 0;
101522
+ exports.configureLiquidWithExtensions = configureLiquidWithExtensions;
101523
+ exports.createExtendedLiquid = createExtendedLiquid;
101524
+ const liquidjs_1 = __nccwpck_require__(48694);
101525
+ const promises_1 = __importDefault(__nccwpck_require__(91943));
101526
+ const path_1 = __importDefault(__nccwpck_require__(16928));
101527
+ /**
101528
+ * Custom ReadFile tag for Liquid templates
101529
+ * Usage: {% readfile "path/to/file.txt" %}
101530
+ * or with variable: {% readfile filename %}
101531
+ */
101532
+ class ReadFileTag extends liquidjs_1.Tag {
101533
+ filepath;
101534
+ constructor(token, remainTokens, liquid) {
101535
+ super(token, remainTokens, liquid);
101536
+ this.filepath = new liquidjs_1.Value(token.args, liquid);
101537
+ }
101538
+ *render(ctx, emitter) {
101539
+ const filePath = yield this.filepath.value(ctx, false);
101540
+ // Validate the path
101541
+ if (!filePath || typeof filePath !== 'string') {
101542
+ emitter.write('[Error: Invalid file path]');
101543
+ return;
101544
+ }
101545
+ // Security: Resolve path relative to project root to prevent directory traversal
101546
+ const projectRoot = process.cwd();
101547
+ const resolvedPath = path_1.default.resolve(projectRoot, filePath.toString());
101548
+ // Ensure the resolved path is within the project directory
101549
+ if (!resolvedPath.startsWith(projectRoot)) {
101550
+ emitter.write('[Error: File path escapes project directory]');
101551
+ return;
101552
+ }
101553
+ // Read the file content
101554
+ try {
101555
+ const content = yield promises_1.default.readFile(resolvedPath, 'utf-8');
101556
+ emitter.write(content);
101557
+ }
101558
+ catch (error) {
101559
+ // Handle file read errors gracefully
101560
+ const errorMessage = error instanceof Error
101561
+ ? error.message
101562
+ : error?.code || 'Unknown error';
101563
+ emitter.write(`[Error reading file: ${errorMessage}]`);
101564
+ }
101565
+ }
101566
+ }
101567
+ exports.ReadFileTag = ReadFileTag;
101568
+ /**
101569
+ * Configure a Liquid instance with custom extensions
101570
+ */
101571
+ function configureLiquidWithExtensions(liquid) {
101572
+ // Register the readfile tag
101573
+ liquid.registerTag('readfile', ReadFileTag);
101574
+ // Register parse_json filter to parse JSON strings into objects
101575
+ liquid.registerFilter('parse_json', (value) => {
101576
+ if (typeof value !== 'string') {
101577
+ return value;
101578
+ }
101579
+ try {
101580
+ return JSON.parse(value);
101581
+ }
101582
+ catch {
101583
+ // Return original value if parsing fails
101584
+ return value;
101585
+ }
101586
+ });
101587
+ // Register to_json filter as alias for json (for consistency)
101588
+ liquid.registerFilter('to_json', (value) => {
101589
+ try {
101590
+ return JSON.stringify(value);
101591
+ }
101592
+ catch {
101593
+ return '[Error: Unable to serialize to JSON]';
101594
+ }
101595
+ });
101596
+ }
101597
+ /**
101598
+ * Create a new Liquid instance with custom extensions
101599
+ */
101600
+ function createExtendedLiquid(options = {}) {
101601
+ const liquid = new liquidjs_1.Liquid({
101602
+ cache: false,
101603
+ strictFilters: false,
101604
+ strictVariables: false,
101605
+ ...options,
101606
+ });
101607
+ configureLiquidWithExtensions(liquid);
101608
+ return liquid;
101609
+ }
101610
+
101611
+
101358
101612
  /***/ }),
101359
101613
 
101360
101614
  /***/ 25508:
@@ -102190,7 +102444,7 @@ const check_provider_interface_1 = __nccwpck_require__(14131);
102190
102444
  const ai_review_service_1 = __nccwpck_require__(51796);
102191
102445
  const env_resolver_1 = __nccwpck_require__(58749);
102192
102446
  const issue_filter_1 = __nccwpck_require__(36879);
102193
- const liquidjs_1 = __nccwpck_require__(48694);
102447
+ const liquid_extensions_1 = __nccwpck_require__(33042);
102194
102448
  const promises_1 = __importDefault(__nccwpck_require__(91943));
102195
102449
  const path_1 = __importDefault(__nccwpck_require__(16928));
102196
102450
  const claude_code_types_1 = __nccwpck_require__(21710);
@@ -102203,7 +102457,7 @@ class AICheckProvider extends check_provider_interface_1.CheckProvider {
102203
102457
  constructor() {
102204
102458
  super();
102205
102459
  this.aiReviewService = new ai_review_service_1.AIReviewService();
102206
- this.liquidEngine = new liquidjs_1.Liquid();
102460
+ this.liquidEngine = (0, liquid_extensions_1.createExtendedLiquid)();
102207
102461
  }
102208
102462
  getName() {
102209
102463
  return 'ai';
@@ -102243,8 +102497,10 @@ class AICheckProvider extends check_provider_interface_1.CheckProvider {
102243
102497
  }
102244
102498
  }
102245
102499
  // Validate check-level MCP servers if present
102246
- if (cfg.ai_mcp_servers) {
102247
- if (!this.validateMcpServers(cfg.ai_mcp_servers)) {
102500
+ const checkLevelMcpServers = cfg
102501
+ .ai_mcp_servers;
102502
+ if (checkLevelMcpServers) {
102503
+ if (!this.validateMcpServers(checkLevelMcpServers)) {
102248
102504
  return false;
102249
102505
  }
102250
102506
  }
@@ -102262,10 +102518,10 @@ class AICheckProvider extends check_provider_interface_1.CheckProvider {
102262
102518
  return false;
102263
102519
  }
102264
102520
  const config = serverConfig;
102265
- if (!config.command || typeof config.command !== 'string') {
102521
+ if (typeof config.command !== 'string') {
102266
102522
  return false;
102267
102523
  }
102268
- if (config.args && !Array.isArray(config.args)) {
102524
+ if (config.args !== undefined && !Array.isArray(config.args)) {
102269
102525
  return false;
102270
102526
  }
102271
102527
  }
@@ -102504,9 +102760,10 @@ class AICheckProvider extends check_provider_interface_1.CheckProvider {
102504
102760
  outputs: dependencyResults
102505
102761
  ? Object.fromEntries(Array.from(dependencyResults.entries()).map(([checkName, result]) => [
102506
102762
  checkName,
102507
- // If the result has a direct output field, use it directly
102508
- // Otherwise, expose the entire result
102509
- result.output !== undefined ? result.output : result,
102763
+ (() => {
102764
+ const summary = result;
102765
+ return summary.output !== undefined ? summary.output : summary;
102766
+ })(),
102510
102767
  ]))
102511
102768
  : {},
102512
102769
  };
@@ -102532,7 +102789,7 @@ class AICheckProvider extends check_provider_interface_1.CheckProvider {
102532
102789
  return tools;
102533
102790
  }
102534
102791
  const createSdkMcpServer = mcpModule.createSdkMcpServer || mcpModule.default?.createSdkMcpServer;
102535
- if (createSdkMcpServer) {
102792
+ if (typeof createSdkMcpServer === 'function') {
102536
102793
  for (const [serverName, serverConfig] of Object.entries(aiConfig.mcpServers)) {
102537
102794
  try {
102538
102795
  // Create MCP server instance
@@ -102543,8 +102800,8 @@ class AICheckProvider extends check_provider_interface_1.CheckProvider {
102543
102800
  env: { ...process.env, ...serverConfig.env },
102544
102801
  });
102545
102802
  // Add server tools to available tools
102546
- const serverTools = await server.listTools();
102547
- tools.push(...serverTools.map((tool) => ({
102803
+ const serverTools = (await server.listTools());
102804
+ tools.push(...serverTools.map(tool => ({
102548
102805
  name: tool.name,
102549
102806
  server: serverName,
102550
102807
  })));
@@ -102615,7 +102872,7 @@ class AICheckProvider extends check_provider_interface_1.CheckProvider {
102615
102872
  // Setup MCP tools from multiple configuration levels
102616
102873
  const mcpServers = {};
102617
102874
  // 1. Start with global MCP servers (from visor config root)
102618
- const globalConfig = config; // Cast to access potential global config
102875
+ const globalConfig = config;
102619
102876
  if (globalConfig.ai_mcp_servers) {
102620
102877
  Object.assign(mcpServers, globalConfig.ai_mcp_servers);
102621
102878
  }
@@ -102928,10 +103185,13 @@ exports.ClaudeCodeCheckProvider = exports.ClaudeCodeAPIKeyMissingError = exports
102928
103185
  const check_provider_interface_1 = __nccwpck_require__(14131);
102929
103186
  const env_resolver_1 = __nccwpck_require__(58749);
102930
103187
  const issue_filter_1 = __nccwpck_require__(36879);
102931
- const liquidjs_1 = __nccwpck_require__(48694);
103188
+ const liquid_extensions_1 = __nccwpck_require__(33042);
102932
103189
  const promises_1 = __importDefault(__nccwpck_require__(91943));
102933
103190
  const path_1 = __importDefault(__nccwpck_require__(16928));
102934
103191
  const claude_code_types_1 = __nccwpck_require__(21710);
103192
+ function isClaudeCodeConstructor(value) {
103193
+ return typeof value === 'function';
103194
+ }
102935
103195
  /**
102936
103196
  * Error thrown when Claude Code SDK is not installed
102937
103197
  */
@@ -102961,7 +103221,7 @@ class ClaudeCodeCheckProvider extends check_provider_interface_1.CheckProvider {
102961
103221
  claudeCodeClient = null;
102962
103222
  constructor() {
102963
103223
  super();
102964
- this.liquidEngine = new liquidjs_1.Liquid();
103224
+ this.liquidEngine = (0, liquid_extensions_1.createExtendedLiquid)();
102965
103225
  }
102966
103226
  getName() {
102967
103227
  return 'claude-code';
@@ -103026,8 +103286,8 @@ class ClaudeCodeCheckProvider extends check_provider_interface_1.CheckProvider {
103026
103286
  if (!claudeCodeModule) {
103027
103287
  throw new ClaudeCodeSDKNotInstalledError();
103028
103288
  }
103029
- const ClaudeCode = claudeCodeModule.ClaudeCode || claudeCodeModule.default?.ClaudeCode;
103030
- if (!ClaudeCode) {
103289
+ const ClaudeCodeCtor = claudeCodeModule.ClaudeCode || claudeCodeModule.default?.ClaudeCode;
103290
+ if (!isClaudeCodeConstructor(ClaudeCodeCtor)) {
103031
103291
  throw new Error('ClaudeCode class not found in @anthropic/claude-code-sdk');
103032
103292
  }
103033
103293
  // Initialize with API key from environment
@@ -103036,7 +103296,7 @@ class ClaudeCodeCheckProvider extends check_provider_interface_1.CheckProvider {
103036
103296
  throw new ClaudeCodeAPIKeyMissingError();
103037
103297
  }
103038
103298
  try {
103039
- const client = new ClaudeCode({
103299
+ const client = new ClaudeCodeCtor({
103040
103300
  apiKey,
103041
103301
  });
103042
103302
  this.claudeCodeClient = client;
@@ -103067,7 +103327,7 @@ class ClaudeCodeCheckProvider extends check_provider_interface_1.CheckProvider {
103067
103327
  return tools;
103068
103328
  }
103069
103329
  const createSdkMcpServer = mcpModule.createSdkMcpServer || mcpModule.default?.createSdkMcpServer;
103070
- if (createSdkMcpServer) {
103330
+ if (typeof createSdkMcpServer === 'function') {
103071
103331
  for (const [serverName, serverConfig] of Object.entries(config.mcpServers)) {
103072
103332
  try {
103073
103333
  // Create MCP server instance
@@ -103078,8 +103338,8 @@ class ClaudeCodeCheckProvider extends check_provider_interface_1.CheckProvider {
103078
103338
  env: { ...process.env, ...serverConfig.env },
103079
103339
  });
103080
103340
  // Add server tools to available tools
103081
- const serverTools = await server.listTools();
103082
- tools.push(...serverTools.map((tool) => ({
103341
+ const serverTools = (await server.listTools());
103342
+ tools.push(...serverTools.map(tool => ({
103083
103343
  name: tool.name,
103084
103344
  server: serverName,
103085
103345
  })));
@@ -103303,7 +103563,10 @@ class ClaudeCodeCheckProvider extends check_provider_interface_1.CheckProvider {
103303
103563
  checkName,
103304
103564
  // If the result has a direct output field, use it directly
103305
103565
  // Otherwise, expose the entire result
103306
- result.output !== undefined ? result.output : result,
103566
+ (() => {
103567
+ const summary = result;
103568
+ return summary.output !== undefined ? summary.output : summary;
103569
+ })(),
103307
103570
  ]))
103308
103571
  : {},
103309
103572
  };
@@ -103385,7 +103648,6 @@ class ClaudeCodeCheckProvider extends check_provider_interface_1.CheckProvider {
103385
103648
  }
103386
103649
  // Parse the response
103387
103650
  const result = this.parseStructuredResponse(response.content);
103388
- // Add debug information if needed by casting to any
103389
103651
  result.debug = {
103390
103652
  prompt: processedPrompt,
103391
103653
  rawResponse: response.content,
@@ -103399,7 +103661,7 @@ class ClaudeCodeCheckProvider extends check_provider_interface_1.CheckProvider {
103399
103661
  errors: [],
103400
103662
  checksExecuted: [config.checkName || 'claude-code-check'],
103401
103663
  parallelExecution: false,
103402
- timestamp: Date.now(),
103664
+ timestamp: new Date().toISOString(),
103403
103665
  // Claude Code specific debug info
103404
103666
  sessionId: response.session_id,
103405
103667
  turnCount: response.turn_count,
@@ -103590,8 +103852,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
103590
103852
  Object.defineProperty(exports, "__esModule", ({ value: true }));
103591
103853
  exports.CommandCheckProvider = void 0;
103592
103854
  const check_provider_interface_1 = __nccwpck_require__(14131);
103593
- const liquidjs_1 = __nccwpck_require__(48694);
103594
103855
  const sandboxjs_1 = __importDefault(__nccwpck_require__(29083));
103856
+ const liquid_extensions_1 = __nccwpck_require__(33042);
103595
103857
  /**
103596
103858
  * Check provider that executes shell commands and captures their output
103597
103859
  * Supports JSON parsing and integration with forEach functionality
@@ -103601,7 +103863,7 @@ class CommandCheckProvider extends check_provider_interface_1.CheckProvider {
103601
103863
  sandbox;
103602
103864
  constructor() {
103603
103865
  super();
103604
- this.liquid = new liquidjs_1.Liquid({
103866
+ this.liquid = (0, liquid_extensions_1.createExtendedLiquid)({
103605
103867
  cache: false,
103606
103868
  strictFilters: false,
103607
103869
  strictVariables: false,
@@ -103652,11 +103914,17 @@ class CommandCheckProvider extends check_provider_interface_1.CheckProvider {
103652
103914
  outputs: this.buildOutputContext(dependencyResults),
103653
103915
  env: this.getSafeEnvironmentVariables(),
103654
103916
  };
103917
+ if (process.env.DEBUG) {
103918
+ console.log('🔧 Debug: Template outputs keys:', Object.keys(templateContext.outputs || {}));
103919
+ }
103655
103920
  try {
103656
103921
  // Render the command with Liquid templates if needed
103657
103922
  let renderedCommand = command;
103658
103923
  if (command.includes('{{') || command.includes('{%')) {
103659
- renderedCommand = await this.liquid.parseAndRender(command, templateContext);
103924
+ renderedCommand = await this.renderCommandTemplate(command, templateContext);
103925
+ }
103926
+ if (process.env.DEBUG) {
103927
+ console.log('🔧 Debug: Rendered command:', renderedCommand);
103660
103928
  }
103661
103929
  // Prepare environment variables - convert all to strings
103662
103930
  const scriptEnv = {};
@@ -103687,16 +103955,18 @@ class CommandCheckProvider extends check_provider_interface_1.CheckProvider {
103687
103955
  if (stderr && process.env.DEBUG) {
103688
103956
  console.error(`Command stderr: ${stderr}`);
103689
103957
  }
103690
- // Try to parse output as JSON
103691
- let output = stdout.trim();
103958
+ // Keep raw output for transforms
103959
+ const rawOutput = stdout.trim();
103960
+ // Try to parse output as JSON for default behavior
103961
+ let output = rawOutput;
103692
103962
  try {
103693
103963
  // Attempt to parse as JSON
103694
- const parsed = JSON.parse(stdout.trim());
103964
+ const parsed = JSON.parse(rawOutput);
103695
103965
  output = parsed;
103696
103966
  }
103697
103967
  catch {
103698
103968
  // If not JSON, keep as string
103699
- output = stdout.trim();
103969
+ output = rawOutput;
103700
103970
  }
103701
103971
  // Apply transform if specified (Liquid or JavaScript)
103702
103972
  let finalOutput = output;
@@ -103705,7 +103975,7 @@ class CommandCheckProvider extends check_provider_interface_1.CheckProvider {
103705
103975
  try {
103706
103976
  const transformContext = {
103707
103977
  ...templateContext,
103708
- output,
103978
+ output: output, // Use parsed output for Liquid (object if JSON, string otherwise)
103709
103979
  };
103710
103980
  const rendered = await this.liquid.parseAndRender(transform, transformContext);
103711
103981
  // Try to parse the transformed result as JSON
@@ -103734,21 +104004,64 @@ class CommandCheckProvider extends check_provider_interface_1.CheckProvider {
103734
104004
  // Then apply JavaScript transform if present
103735
104005
  if (transformJs) {
103736
104006
  try {
104007
+ // For transform_js, provide a JSON-smart wrapper that:
104008
+ // - behaves like a string when coerced (so JSON.parse(output) still works)
104009
+ // - exposes parsed JSON properties if stdout is valid JSON (so output.key works)
103737
104010
  const jsContext = {
103738
- output: finalOutput,
104011
+ output: this.makeJsonSmart(rawOutput),
103739
104012
  pr: templateContext.pr,
103740
104013
  files: templateContext.files,
103741
- outputs: templateContext.outputs,
104014
+ outputs: this.makeOutputsJsonSmart(templateContext.outputs),
103742
104015
  env: templateContext.env,
103743
- // Helper functions
103744
- JSON: JSON,
103745
104016
  };
103746
104017
  // Compile and execute the JavaScript expression
103747
- const exec = this.sandbox.compile(`
103748
- const { output, pr, files, outputs, env, JSON } = scope;
103749
- return (${transformJs.trim()});
103750
- `);
104018
+ // Use direct property access instead of destructuring to avoid syntax issues
104019
+ const trimmedTransform = transformJs.trim();
104020
+ let transformExpression;
104021
+ if (/return\s+/.test(trimmedTransform)) {
104022
+ transformExpression = `(() => {\n${trimmedTransform}\n})()`;
104023
+ }
104024
+ else {
104025
+ const lines = trimmedTransform.split('\n');
104026
+ if (lines.length > 1) {
104027
+ const lastLine = lines[lines.length - 1].trim();
104028
+ const remaining = lines.slice(0, -1).join('\n');
104029
+ if (lastLine && !lastLine.includes('}') && !lastLine.includes('{')) {
104030
+ const returnTarget = lastLine.replace(/;$/, '');
104031
+ transformExpression = `(() => {\n${remaining}\nreturn ${returnTarget};\n})()`;
104032
+ }
104033
+ else {
104034
+ transformExpression = `(${trimmedTransform})`;
104035
+ }
104036
+ }
104037
+ else {
104038
+ transformExpression = `(${trimmedTransform})`;
104039
+ }
104040
+ }
104041
+ const code = `
104042
+ const output = scope.output;
104043
+ const pr = scope.pr;
104044
+ const files = scope.files;
104045
+ const outputs = scope.outputs;
104046
+ const env = scope.env;
104047
+ return ${transformExpression};
104048
+ `;
104049
+ if (process.env.DEBUG) {
104050
+ console.log('🔧 Debug: JavaScript transform code:', code);
104051
+ console.log('🔧 Debug: JavaScript context:', jsContext);
104052
+ }
104053
+ const exec = this.sandbox.compile(code);
103751
104054
  finalOutput = exec({ scope: jsContext }).run();
104055
+ if (process.env.DEBUG) {
104056
+ try {
104057
+ const preview = JSON.stringify(finalOutput);
104058
+ console.log('🔧 Debug: transform_js result:', typeof preview === 'string' ? preview.slice(0, 200) : String(preview).slice(0, 200));
104059
+ }
104060
+ catch {
104061
+ const preview = String(finalOutput);
104062
+ console.log('🔧 Debug: transform_js result:', preview.slice(0, 200));
104063
+ }
104064
+ }
103752
104065
  }
103753
104066
  catch (error) {
103754
104067
  return {
@@ -103765,12 +104078,57 @@ class CommandCheckProvider extends check_provider_interface_1.CheckProvider {
103765
104078
  };
103766
104079
  }
103767
104080
  }
103768
- // Return the output as part of the review summary
103769
- // The output will be available to dependent checks
103770
- return {
103771
- issues: [],
103772
- output: finalOutput,
104081
+ // Extract structured issues when the command returns them (skip for forEach parents)
104082
+ let issues = [];
104083
+ let outputForDependents = finalOutput;
104084
+ let content;
104085
+ let extracted = null;
104086
+ const trimmedRawOutput = typeof rawOutput === 'string' ? rawOutput.trim() : undefined;
104087
+ const commandConfig = config;
104088
+ const isForEachParent = commandConfig.forEach === true;
104089
+ if (!isForEachParent) {
104090
+ extracted = this.extractIssuesFromOutput(finalOutput);
104091
+ if (!extracted && typeof finalOutput === 'string') {
104092
+ // Attempt to parse string output as JSON and extract issues again
104093
+ try {
104094
+ const parsed = JSON.parse(finalOutput);
104095
+ extracted = this.extractIssuesFromOutput(parsed);
104096
+ if (extracted) {
104097
+ issues = extracted.issues;
104098
+ outputForDependents = extracted.remainingOutput;
104099
+ }
104100
+ }
104101
+ catch {
104102
+ // Ignore JSON parse errors – leave output as-is
104103
+ }
104104
+ }
104105
+ else if (extracted) {
104106
+ issues = extracted.issues;
104107
+ outputForDependents = extracted.remainingOutput;
104108
+ }
104109
+ if (!issues.length && this.shouldTreatAsTextOutput(trimmedRawOutput)) {
104110
+ content = trimmedRawOutput;
104111
+ }
104112
+ else if (issues.length && typeof extracted?.remainingOutput === 'string') {
104113
+ const trimmed = extracted.remainingOutput.trim();
104114
+ if (trimmed) {
104115
+ content = trimmed;
104116
+ }
104117
+ }
104118
+ }
104119
+ if (!content && this.shouldTreatAsTextOutput(trimmedRawOutput) && !isForEachParent) {
104120
+ content = trimmedRawOutput;
104121
+ }
104122
+ // Return the output and issues as part of the review summary so dependent checks can use them
104123
+ const result = {
104124
+ issues,
104125
+ output: outputForDependents,
104126
+ ...(content ? { content } : {}),
103773
104127
  };
104128
+ if (process.env.DEBUG && transformJs) {
104129
+ console.log(`🔧 Debug: Command provider returning output:`, JSON.stringify(result.output).slice(0, 200));
104130
+ }
104131
+ return result;
103774
104132
  }
103775
104133
  catch (error) {
103776
104134
  const errorMessage = error instanceof Error ? error.message : 'Unknown error';
@@ -103796,10 +104154,92 @@ class CommandCheckProvider extends check_provider_interface_1.CheckProvider {
103796
104154
  for (const [checkName, result] of dependencyResults) {
103797
104155
  // If the result has a direct output field, use it directly
103798
104156
  // Otherwise, expose the entire result as-is
103799
- outputs[checkName] = result.output !== undefined ? result.output : result;
104157
+ const summary = result;
104158
+ const value = summary.output !== undefined ? summary.output : summary;
104159
+ outputs[checkName] = this.makeJsonSmart(value);
103800
104160
  }
103801
104161
  return outputs;
103802
104162
  }
104163
+ /**
104164
+ * Wrap a value with JSON-smart behavior:
104165
+ * - If it's a JSON string, expose parsed properties via Proxy (e.g., value.key)
104166
+ * - When coerced to string (toString/valueOf/Symbol.toPrimitive), return the original raw string
104167
+ * - If parsing fails or value is not a string, return the value unchanged
104168
+ */
104169
+ makeJsonSmart(value) {
104170
+ if (typeof value !== 'string') {
104171
+ return value;
104172
+ }
104173
+ const raw = value;
104174
+ let parsed;
104175
+ try {
104176
+ parsed = JSON.parse(raw);
104177
+ }
104178
+ catch {
104179
+ // Not JSON, return original string
104180
+ return raw;
104181
+ }
104182
+ // Use a boxed string so string methods still work via Proxy fallback
104183
+ const boxed = new String(raw);
104184
+ const handler = {
104185
+ get(target, prop, receiver) {
104186
+ if (prop === 'toString' || prop === 'valueOf') {
104187
+ return () => raw;
104188
+ }
104189
+ if (prop === Symbol.toPrimitive) {
104190
+ return () => raw;
104191
+ }
104192
+ if (parsed != null && (typeof parsed === 'object' || Array.isArray(parsed))) {
104193
+ if (prop in parsed) {
104194
+ return parsed[prop];
104195
+ }
104196
+ }
104197
+ return Reflect.get(target, prop, receiver);
104198
+ },
104199
+ has(_target, prop) {
104200
+ if (parsed != null && (typeof parsed === 'object' || Array.isArray(parsed))) {
104201
+ if (prop in parsed)
104202
+ return true;
104203
+ }
104204
+ return false;
104205
+ },
104206
+ ownKeys(_target) {
104207
+ if (parsed != null && (typeof parsed === 'object' || Array.isArray(parsed))) {
104208
+ try {
104209
+ return Reflect.ownKeys(parsed);
104210
+ }
104211
+ catch {
104212
+ return [];
104213
+ }
104214
+ }
104215
+ return [];
104216
+ },
104217
+ getOwnPropertyDescriptor(_target, prop) {
104218
+ if (parsed != null && (typeof parsed === 'object' || Array.isArray(parsed))) {
104219
+ const descriptor = Object.getOwnPropertyDescriptor(parsed, prop);
104220
+ if (descriptor)
104221
+ return descriptor;
104222
+ }
104223
+ return {
104224
+ configurable: true,
104225
+ enumerable: true,
104226
+ writable: false,
104227
+ value: undefined,
104228
+ };
104229
+ },
104230
+ };
104231
+ return new Proxy(boxed, handler);
104232
+ }
104233
+ /**
104234
+ * Recursively apply JSON-smart wrapper to outputs object values
104235
+ */
104236
+ makeOutputsJsonSmart(outputs) {
104237
+ const wrapped = {};
104238
+ for (const [k, v] of Object.entries(outputs || {})) {
104239
+ wrapped[k] = this.makeJsonSmart(v);
104240
+ }
104241
+ return wrapped;
104242
+ }
103803
104243
  getSafeEnvironmentVariables() {
103804
104244
  const safeVars = {};
103805
104245
  const allowedPrefixes = ['CI_', 'GITHUB_', 'RUNNER_', 'NODE_', 'npm_', 'PATH', 'HOME', 'USER'];
@@ -103838,6 +104278,190 @@ class CommandCheckProvider extends check_provider_interface_1.CheckProvider {
103838
104278
  'Optional: Transform template for processing output',
103839
104279
  ];
103840
104280
  }
104281
+ extractIssuesFromOutput(output) {
104282
+ if (output === null || output === undefined) {
104283
+ return null;
104284
+ }
104285
+ // If output is already a string, do not treat it as issues here (caller may try parsing JSON)
104286
+ if (typeof output === 'string') {
104287
+ return null;
104288
+ }
104289
+ if (Array.isArray(output)) {
104290
+ const issues = this.normalizeIssueArray(output);
104291
+ if (issues) {
104292
+ return { issues, remainingOutput: undefined };
104293
+ }
104294
+ return null;
104295
+ }
104296
+ if (typeof output === 'object') {
104297
+ const record = output;
104298
+ if (Array.isArray(record.issues)) {
104299
+ const issues = this.normalizeIssueArray(record.issues);
104300
+ if (!issues) {
104301
+ return null;
104302
+ }
104303
+ const remaining = { ...record };
104304
+ delete remaining.issues;
104305
+ const remainingKeys = Object.keys(remaining);
104306
+ const remainingOutput = remainingKeys.length > 0 ? remaining : undefined;
104307
+ return {
104308
+ issues,
104309
+ remainingOutput,
104310
+ };
104311
+ }
104312
+ const singleIssue = this.normalizeIssue(record);
104313
+ if (singleIssue) {
104314
+ return { issues: [singleIssue], remainingOutput: undefined };
104315
+ }
104316
+ }
104317
+ return null;
104318
+ }
104319
+ shouldTreatAsTextOutput(value) {
104320
+ if (!value) {
104321
+ return false;
104322
+ }
104323
+ const trimmed = value.trim();
104324
+ if (!trimmed) {
104325
+ return false;
104326
+ }
104327
+ // Heuristic: consider it JSON-like if it starts with { or [ and ends with } or ]
104328
+ const startsJson = (trimmed.startsWith('{') && trimmed.endsWith('}')) ||
104329
+ (trimmed.startsWith('[') && trimmed.endsWith(']'));
104330
+ return !startsJson;
104331
+ }
104332
+ normalizeIssueArray(values) {
104333
+ const normalized = [];
104334
+ for (const value of values) {
104335
+ const issue = this.normalizeIssue(value);
104336
+ if (!issue) {
104337
+ return null;
104338
+ }
104339
+ normalized.push(issue);
104340
+ }
104341
+ return normalized;
104342
+ }
104343
+ normalizeIssue(raw) {
104344
+ if (!raw || typeof raw !== 'object') {
104345
+ return null;
104346
+ }
104347
+ const data = raw;
104348
+ const message = this.toTrimmedString(data.message || data.text || data.description || data.summary);
104349
+ if (!message) {
104350
+ return null;
104351
+ }
104352
+ const allowedSeverities = new Set(['info', 'warning', 'error', 'critical']);
104353
+ const severityRaw = this.toTrimmedString(data.severity || data.level || data.priority);
104354
+ let severity = 'warning';
104355
+ if (severityRaw) {
104356
+ const lower = severityRaw.toLowerCase();
104357
+ if (allowedSeverities.has(lower)) {
104358
+ severity = lower;
104359
+ }
104360
+ else if (['fatal', 'high'].includes(lower)) {
104361
+ severity = 'error';
104362
+ }
104363
+ else if (['medium', 'moderate'].includes(lower)) {
104364
+ severity = 'warning';
104365
+ }
104366
+ else if (['low', 'minor'].includes(lower)) {
104367
+ severity = 'info';
104368
+ }
104369
+ }
104370
+ const allowedCategories = new Set([
104371
+ 'security',
104372
+ 'performance',
104373
+ 'style',
104374
+ 'logic',
104375
+ 'documentation',
104376
+ ]);
104377
+ const categoryRaw = this.toTrimmedString(data.category || data.type || data.group);
104378
+ let category = 'logic';
104379
+ if (categoryRaw && allowedCategories.has(categoryRaw.toLowerCase())) {
104380
+ category = categoryRaw.toLowerCase();
104381
+ }
104382
+ const file = this.toTrimmedString(data.file || data.path || data.filename) || 'system';
104383
+ const line = this.toNumber(data.line || data.startLine || data.lineNumber) ?? 0;
104384
+ const endLine = this.toNumber(data.endLine || data.end_line || data.stopLine);
104385
+ const suggestion = this.toTrimmedString(data.suggestion);
104386
+ const replacement = this.toTrimmedString(data.replacement);
104387
+ const ruleId = this.toTrimmedString(data.ruleId || data.rule || data.id || data.check) || 'command';
104388
+ return {
104389
+ file,
104390
+ line,
104391
+ endLine: endLine ?? undefined,
104392
+ ruleId,
104393
+ message,
104394
+ severity,
104395
+ category,
104396
+ suggestion: suggestion || undefined,
104397
+ replacement: replacement || undefined,
104398
+ };
104399
+ }
104400
+ toTrimmedString(value) {
104401
+ if (typeof value === 'string') {
104402
+ const trimmed = value.trim();
104403
+ return trimmed.length > 0 ? trimmed : null;
104404
+ }
104405
+ if (value !== null && value !== undefined && typeof value.toString === 'function') {
104406
+ const converted = String(value).trim();
104407
+ return converted.length > 0 ? converted : null;
104408
+ }
104409
+ return null;
104410
+ }
104411
+ toNumber(value) {
104412
+ if (value === null || value === undefined) {
104413
+ return null;
104414
+ }
104415
+ const num = Number(value);
104416
+ if (Number.isFinite(num)) {
104417
+ return Math.trunc(num);
104418
+ }
104419
+ return null;
104420
+ }
104421
+ async renderCommandTemplate(template, context) {
104422
+ try {
104423
+ return await this.liquid.parseAndRender(template, context);
104424
+ }
104425
+ catch (error) {
104426
+ if (process.env.DEBUG) {
104427
+ console.warn('🔧 Debug: Liquid rendering failed, falling back to JS evaluation:', error);
104428
+ }
104429
+ return this.renderWithJsExpressions(template, context);
104430
+ }
104431
+ }
104432
+ renderWithJsExpressions(template, context) {
104433
+ const scope = {
104434
+ pr: context.pr,
104435
+ files: context.files,
104436
+ outputs: context.outputs,
104437
+ env: context.env,
104438
+ };
104439
+ const expressionRegex = /\{\{\s*([^{}]+?)\s*\}\}/g;
104440
+ return template.replace(expressionRegex, (_match, expr) => {
104441
+ const expression = String(expr).trim();
104442
+ if (!expression) {
104443
+ return '';
104444
+ }
104445
+ try {
104446
+ const evalCode = `
104447
+ const pr = scope.pr;
104448
+ const files = scope.files;
104449
+ const outputs = scope.outputs;
104450
+ const env = scope.env;
104451
+ return (${expression});
104452
+ `;
104453
+ const evaluator = this.sandbox.compile(evalCode);
104454
+ const result = evaluator({ scope }).run();
104455
+ return result === undefined || result === null ? '' : String(result);
104456
+ }
104457
+ catch (evaluationError) {
104458
+ if (process.env.DEBUG) {
104459
+ console.warn('🔧 Debug: Failed to evaluate expression:', expression, evaluationError);
104460
+ }
104461
+ return '';
104462
+ }
104463
+ });
104464
+ }
103841
104465
  }
103842
104466
  exports.CommandCheckProvider = CommandCheckProvider;
103843
104467
 
@@ -103853,7 +104477,7 @@ Object.defineProperty(exports, "__esModule", ({ value: true }));
103853
104477
  exports.HttpCheckProvider = void 0;
103854
104478
  const check_provider_interface_1 = __nccwpck_require__(14131);
103855
104479
  const issue_filter_1 = __nccwpck_require__(36879);
103856
- const liquidjs_1 = __nccwpck_require__(48694);
104480
+ const liquid_extensions_1 = __nccwpck_require__(33042);
103857
104481
  /**
103858
104482
  * Check provider that sends data to an HTTP endpoint, typically used as an output/notification provider
103859
104483
  */
@@ -103861,7 +104485,7 @@ class HttpCheckProvider extends check_provider_interface_1.CheckProvider {
103861
104485
  liquid;
103862
104486
  constructor() {
103863
104487
  super();
103864
- this.liquid = new liquidjs_1.Liquid();
104488
+ this.liquid = (0, liquid_extensions_1.createExtendedLiquid)();
103865
104489
  }
103866
104490
  getName() {
103867
104491
  return 'http';
@@ -104082,7 +104706,7 @@ exports.HttpCheckProvider = HttpCheckProvider;
104082
104706
  Object.defineProperty(exports, "__esModule", ({ value: true }));
104083
104707
  exports.HttpClientProvider = void 0;
104084
104708
  const check_provider_interface_1 = __nccwpck_require__(14131);
104085
- const liquidjs_1 = __nccwpck_require__(48694);
104709
+ const liquid_extensions_1 = __nccwpck_require__(33042);
104086
104710
  /**
104087
104711
  * Check provider that fetches data from HTTP endpoints
104088
104712
  */
@@ -104090,7 +104714,7 @@ class HttpClientProvider extends check_provider_interface_1.CheckProvider {
104090
104714
  liquid;
104091
104715
  constructor() {
104092
104716
  super();
104093
- this.liquid = new liquidjs_1.Liquid();
104717
+ this.liquid = (0, liquid_extensions_1.createExtendedLiquid)();
104094
104718
  }
104095
104719
  getName() {
104096
104720
  return 'http_client';
@@ -104311,7 +104935,7 @@ exports.HttpClientProvider = HttpClientProvider;
104311
104935
  Object.defineProperty(exports, "__esModule", ({ value: true }));
104312
104936
  exports.HttpInputProvider = void 0;
104313
104937
  const check_provider_interface_1 = __nccwpck_require__(14131);
104314
- const liquidjs_1 = __nccwpck_require__(48694);
104938
+ const liquid_extensions_1 = __nccwpck_require__(33042);
104315
104939
  /**
104316
104940
  * Check provider that receives input from HTTP webhooks and makes it available to dependent checks
104317
104941
  */
@@ -104320,7 +104944,7 @@ class HttpInputProvider extends check_provider_interface_1.CheckProvider {
104320
104944
  webhookContext;
104321
104945
  constructor() {
104322
104946
  super();
104323
- this.liquid = new liquidjs_1.Liquid();
104947
+ this.liquid = (0, liquid_extensions_1.createExtendedLiquid)();
104324
104948
  }
104325
104949
  /**
104326
104950
  * Set webhook context for accessing webhook data
@@ -104446,7 +105070,7 @@ exports.HttpInputProvider = HttpInputProvider;
104446
105070
  Object.defineProperty(exports, "__esModule", ({ value: true }));
104447
105071
  exports.LogCheckProvider = void 0;
104448
105072
  const check_provider_interface_1 = __nccwpck_require__(14131);
104449
- const liquidjs_1 = __nccwpck_require__(48694);
105073
+ const liquid_extensions_1 = __nccwpck_require__(33042);
104450
105074
  /**
104451
105075
  * Check provider that outputs debugging and logging information.
104452
105076
  * Useful for troubleshooting check workflows and understanding execution flow.
@@ -104455,7 +105079,7 @@ class LogCheckProvider extends check_provider_interface_1.CheckProvider {
104455
105079
  liquid;
104456
105080
  constructor() {
104457
105081
  super();
104458
- this.liquid = new liquidjs_1.Liquid({
105082
+ this.liquid = (0, liquid_extensions_1.createExtendedLiquid)({
104459
105083
  strictVariables: false,
104460
105084
  strictFilters: false,
104461
105085
  });
@@ -104542,7 +105166,8 @@ class LogCheckProvider extends check_provider_interface_1.CheckProvider {
104542
105166
  issues: result.issues || [],
104543
105167
  };
104544
105168
  // Add outputs namespace for accessing dependency results directly
104545
- outputs[checkName] = result.output !== undefined ? result.output : result;
105169
+ const summary = result;
105170
+ outputs[checkName] = summary.output !== undefined ? summary.output : summary;
104546
105171
  }
104547
105172
  context.dependencies = dependencies;
104548
105173
  context.outputs = outputs;
@@ -105248,16 +105873,16 @@ class ConfigLoader {
105248
105873
  const outputFormat = process.env.VISOR_OUTPUT_FORMAT;
105249
105874
  const logFn = outputFormat === 'json' || outputFormat === 'sarif' ? console.error : console.log;
105250
105875
  logFn(`⬇️ Fetching remote configuration from: ${url}`);
105876
+ const controller = new AbortController();
105877
+ const timeoutMs = this.options.timeout ?? 30000;
105878
+ const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
105251
105879
  try {
105252
- const controller = new AbortController();
105253
- const timeoutId = setTimeout(() => controller.abort(), this.options.timeout || 30000);
105254
105880
  const response = await fetch(url, {
105255
105881
  signal: controller.signal,
105256
105882
  headers: {
105257
105883
  'User-Agent': 'Visor/1.0',
105258
105884
  },
105259
105885
  });
105260
- clearTimeout(timeoutId);
105261
105886
  if (!response.ok) {
105262
105887
  throw new Error(`Failed to fetch config: ${response.status} ${response.statusText}`);
105263
105888
  }
@@ -105281,12 +105906,15 @@ class ConfigLoader {
105281
105906
  catch (error) {
105282
105907
  if (error instanceof Error) {
105283
105908
  if (error.name === 'AbortError') {
105284
- throw new Error(`Timeout fetching configuration from ${url} (${this.options.timeout}ms)`);
105909
+ throw new Error(`Timeout fetching configuration from ${url} (${timeoutMs}ms)`);
105285
105910
  }
105286
105911
  throw new Error(`Failed to fetch remote configuration from ${url}: ${error.message}`);
105287
105912
  }
105288
105913
  throw error;
105289
105914
  }
105915
+ finally {
105916
+ clearTimeout(timeoutId);
105917
+ }
105290
105918
  }
105291
105919
  /**
105292
105920
  * Load bundled default configuration
@@ -125875,7 +126503,7 @@ function createMessagePreview(message, charsPerSide = 200) {
125875
126503
  const end = message.substring(message.length - charsPerSide);
125876
126504
  return `${start}...${end}`;
125877
126505
  }
125878
- var import_zod, searchSchema, querySchema, extractSchema, delegateSchema, attemptCompletionSchema, searchToolDefinition, queryToolDefinition, extractToolDefinition, delegateToolDefinition, attemptCompletionToolDefinition, searchDescription, queryDescription, extractDescription, delegateDescription, DEFAULT_VALID_TOOLS;
126506
+ var import_zod, searchSchema, querySchema, extractSchema, delegateSchema, bashSchema, attemptCompletionSchema, searchToolDefinition, queryToolDefinition, extractToolDefinition, delegateToolDefinition, attemptCompletionToolDefinition, bashToolDefinition, searchDescription, queryDescription, extractDescription, delegateDescription, bashDescription, DEFAULT_VALID_TOOLS;
125879
126507
  var init_common = __esm({
125880
126508
  "src/tools/common.js"() {
125881
126509
  "use strict";
@@ -125907,6 +126535,12 @@ var init_common = __esm({
125907
126535
  delegateSchema = import_zod.z.object({
125908
126536
  task: import_zod.z.string().describe("The task to delegate to a subagent. Be specific about what needs to be accomplished.")
125909
126537
  });
126538
+ bashSchema = import_zod.z.object({
126539
+ command: import_zod.z.string().describe("The bash command to execute"),
126540
+ workingDirectory: import_zod.z.string().optional().describe("Directory to execute the command in (optional)"),
126541
+ timeout: import_zod.z.number().optional().describe("Command timeout in milliseconds (optional)"),
126542
+ env: import_zod.z.record(import_zod.z.string()).optional().describe("Additional environment variables (optional)")
126543
+ });
125910
126544
  attemptCompletionSchema = {
125911
126545
  // Custom validation that requires result parameter but allows direct XML response
125912
126546
  safeParse: (params) => {
@@ -126129,11 +126763,67 @@ Usage Example:
126129
126763
  <attempt_completion>
126130
126764
  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.
126131
126765
  </attempt_completion>
126766
+ `;
126767
+ bashToolDefinition = `
126768
+ ## bash
126769
+ 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.
126770
+
126771
+ Parameters:
126772
+ - command: (required) The bash command to execute
126773
+ - workingDirectory: (optional) Directory to execute the command in
126774
+ - timeout: (optional) Command timeout in milliseconds
126775
+ - env: (optional) Additional environment variables as an object
126776
+
126777
+ Security: Commands are filtered through allow/deny lists for safety:
126778
+ - Allowed by default: ls, cat, git status, npm list, find, grep, etc.
126779
+ - Denied by default: rm -rf, sudo, npm install, dangerous system commands
126780
+
126781
+ Usage Examples:
126782
+
126783
+ <examples>
126784
+
126785
+ User: What files are in the src directory?
126786
+ <bash>
126787
+ <command>ls -la src/</command>
126788
+ </bash>
126789
+
126790
+ User: Show me the git status
126791
+ <bash>
126792
+ <command>git status</command>
126793
+ </bash>
126794
+
126795
+ User: Find all TypeScript files
126796
+ <bash>
126797
+ <command>find . -name "*.ts" -type f</command>
126798
+ </bash>
126799
+
126800
+ User: Check installed npm packages
126801
+ <bash>
126802
+ <command>npm list --depth=0</command>
126803
+ </bash>
126804
+
126805
+ User: Search for TODO comments in code
126806
+ <bash>
126807
+ <command>grep -r "TODO" src/</command>
126808
+ </bash>
126809
+
126810
+ User: Show recent git commits
126811
+ <bash>
126812
+ <command>git log --oneline -10</command>
126813
+ </bash>
126814
+
126815
+ User: Check system info
126816
+ <bash>
126817
+ <command>uname -a</command>
126818
+ </bash>
126819
+
126820
+ </examples>
126132
126821
  `;
126133
126822
  searchDescription = "Search code in the repository using Elasticsearch-like query syntax. Use this tool first for any code-related questions.";
126134
126823
  queryDescription = "Search code using ast-grep structural pattern matching. Use this tool to find specific code structures like functions, classes, or methods.";
126135
126824
  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.";
126136
126825
  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.";
126826
+ bashDescription = "Execute bash commands for system exploration and development tasks. Secure by default with built-in allow/deny lists.";
126137
126827
  DEFAULT_VALID_TOOLS = [
126138
126828
  "search",
126139
126829
  "query",
@@ -126187,7 +126877,7 @@ async function delegate({ task, timeout = 300, debug = false, currentIteration =
126187
126877
  console.error(`[DELEGATE] Using binary at: ${binaryPath}`);
126188
126878
  console.error(`[DELEGATE] Command args: ${args.join(" ")}`);
126189
126879
  }
126190
- return new Promise((resolve2, reject) => {
126880
+ return new Promise((resolve4, reject) => {
126191
126881
  const delegationSpan = tracer ? tracer.createDelegationSpan(sessionId, task) : null;
126192
126882
  const process2 = (0, import_child_process5.spawn)(binaryPath, args, {
126193
126883
  stdio: ["pipe", "pipe", "pipe"],
@@ -126252,7 +126942,7 @@ async function delegate({ task, timeout = 300, debug = false, currentIteration =
126252
126942
  delegationSpan.end();
126253
126943
  }
126254
126944
  }
126255
- resolve2(response);
126945
+ resolve4(response);
126256
126946
  } else {
126257
126947
  const errorMessage = stderr.trim() || `Delegate process failed with exit code ${code}`;
126258
126948
  if (debug) {
@@ -126448,10 +127138,10 @@ var init_vercel = __esm({
126448
127138
  let extractOptions = { path: extractPath };
126449
127139
  if (input_content) {
126450
127140
  const { writeFileSync: writeFileSync2, unlinkSync } = await Promise.resolve(/* import() */).then(__nccwpck_require__.t.bind(__nccwpck_require__, 79896, 23));
126451
- const { join: join2 } = await Promise.resolve(/* import() */).then(__nccwpck_require__.t.bind(__nccwpck_require__, 16928, 23));
127141
+ const { join: join3 } = await Promise.resolve(/* import() */).then(__nccwpck_require__.t.bind(__nccwpck_require__, 16928, 23));
126452
127142
  const { tmpdir } = await Promise.resolve(/* import() */).then(__nccwpck_require__.t.bind(__nccwpck_require__, 70857, 23));
126453
127143
  const { randomUUID: randomUUID5 } = await Promise.resolve(/* import() */).then(__nccwpck_require__.t.bind(__nccwpck_require__, 76982, 23));
126454
- tempFilePath = join2(tmpdir(), `probe-extract-${randomUUID5()}.txt`);
127144
+ tempFilePath = join3(tmpdir(), `probe-extract-${randomUUID5()}.txt`);
126455
127145
  writeFileSync2(tempFilePath, input_content);
126456
127146
  if (debug) {
126457
127147
  console.error(`Created temporary file for input content: ${tempFilePath}`);
@@ -126528,6 +127218,1248 @@ var init_vercel = __esm({
126528
127218
  }
126529
127219
  });
126530
127220
 
127221
+ // src/agent/bashDefaults.js
127222
+ var DEFAULT_ALLOW_PATTERNS, DEFAULT_DENY_PATTERNS;
127223
+ var init_bashDefaults = __esm({
127224
+ "src/agent/bashDefaults.js"() {
127225
+ "use strict";
127226
+ DEFAULT_ALLOW_PATTERNS = [
127227
+ // Basic navigation and listing
127228
+ "ls",
127229
+ "dir",
127230
+ "pwd",
127231
+ "cd",
127232
+ "cd:*",
127233
+ // File reading commands
127234
+ "cat",
127235
+ "cat:*",
127236
+ "head",
127237
+ "head:*",
127238
+ "tail",
127239
+ "tail:*",
127240
+ "less",
127241
+ "more",
127242
+ "view",
127243
+ // File information and metadata
127244
+ "file",
127245
+ "file:*",
127246
+ "stat",
127247
+ "stat:*",
127248
+ "wc",
127249
+ "wc:*",
127250
+ "du",
127251
+ "du:*",
127252
+ "df",
127253
+ "df:*",
127254
+ "realpath",
127255
+ "realpath:*",
127256
+ // Search and find commands (read-only) - find restricted to safe operations
127257
+ "find",
127258
+ "find:-name:*",
127259
+ "find:-type:*",
127260
+ "find:-size:*",
127261
+ "find:-mtime:*",
127262
+ "find:-newer:*",
127263
+ "find:-path:*",
127264
+ "find:-iname:*",
127265
+ "find:-maxdepth:*",
127266
+ "find:-mindepth:*",
127267
+ "find:-print",
127268
+ "grep",
127269
+ "grep:*",
127270
+ "egrep",
127271
+ "egrep:*",
127272
+ "fgrep",
127273
+ "fgrep:*",
127274
+ "rg",
127275
+ "rg:*",
127276
+ "ag",
127277
+ "ag:*",
127278
+ "ack",
127279
+ "ack:*",
127280
+ "which",
127281
+ "which:*",
127282
+ "whereis",
127283
+ "whereis:*",
127284
+ "locate",
127285
+ "locate:*",
127286
+ "type",
127287
+ "type:*",
127288
+ "command",
127289
+ "command:*",
127290
+ // Tree and structure visualization
127291
+ "tree",
127292
+ "tree:*",
127293
+ // Git read-only operations
127294
+ "git:status",
127295
+ "git:log",
127296
+ "git:log:*",
127297
+ "git:diff",
127298
+ "git:diff:*",
127299
+ "git:show",
127300
+ "git:show:*",
127301
+ "git:branch",
127302
+ "git:branch:*",
127303
+ "git:tag",
127304
+ "git:tag:*",
127305
+ "git:describe",
127306
+ "git:describe:*",
127307
+ "git:remote",
127308
+ "git:remote:*",
127309
+ "git:config:*",
127310
+ "git:blame",
127311
+ "git:blame:*",
127312
+ "git:shortlog",
127313
+ "git:reflog",
127314
+ "git:ls-files",
127315
+ "git:ls-tree",
127316
+ "git:rev-parse",
127317
+ "git:rev-list",
127318
+ "git:--version",
127319
+ "git:help",
127320
+ "git:help:*",
127321
+ // Package managers (information only)
127322
+ "npm:list",
127323
+ "npm:ls",
127324
+ "npm:view",
127325
+ "npm:info",
127326
+ "npm:show",
127327
+ "npm:outdated",
127328
+ "npm:audit",
127329
+ "npm:--version",
127330
+ "yarn:list",
127331
+ "yarn:info",
127332
+ "yarn:--version",
127333
+ "pnpm:list",
127334
+ "pnpm:--version",
127335
+ "pip:list",
127336
+ "pip:show",
127337
+ "pip:--version",
127338
+ "pip3:list",
127339
+ "pip3:show",
127340
+ "pip3:--version",
127341
+ "gem:list",
127342
+ "gem:--version",
127343
+ "bundle:list",
127344
+ "bundle:show",
127345
+ "bundle:--version",
127346
+ "composer:show",
127347
+ "composer:--version",
127348
+ // Language and runtime versions
127349
+ "node:--version",
127350
+ "node:-v",
127351
+ "python:--version",
127352
+ "python:-V",
127353
+ "python3:--version",
127354
+ "python3:-V",
127355
+ "ruby:--version",
127356
+ "ruby:-v",
127357
+ "go:version",
127358
+ "go:env",
127359
+ "go:list",
127360
+ "go:mod:graph",
127361
+ "rustc:--version",
127362
+ "cargo:--version",
127363
+ "cargo:tree",
127364
+ "cargo:metadata",
127365
+ "java:--version",
127366
+ "java:-version",
127367
+ "javac:--version",
127368
+ "mvn:--version",
127369
+ "gradle:--version",
127370
+ "php:--version",
127371
+ "dotnet:--version",
127372
+ "dotnet:list",
127373
+ // Database client versions (connection info only)
127374
+ "psql:--version",
127375
+ "mysql:--version",
127376
+ "redis-cli:--version",
127377
+ "mongo:--version",
127378
+ "sqlite3:--version",
127379
+ // System information
127380
+ "uname",
127381
+ "uname:*",
127382
+ "hostname",
127383
+ "whoami",
127384
+ "id",
127385
+ "groups",
127386
+ "date",
127387
+ "cal",
127388
+ "uptime",
127389
+ "w",
127390
+ "users",
127391
+ "sleep",
127392
+ "sleep:*",
127393
+ // Environment and shell
127394
+ "env",
127395
+ "printenv",
127396
+ "echo",
127397
+ "echo:*",
127398
+ "printf",
127399
+ "printf:*",
127400
+ "export",
127401
+ "export:*",
127402
+ "set",
127403
+ "unset",
127404
+ // Process information (read-only)
127405
+ "ps",
127406
+ "ps:*",
127407
+ "pgrep",
127408
+ "pgrep:*",
127409
+ "jobs",
127410
+ "top:-n:1",
127411
+ // Network information (read-only)
127412
+ "ifconfig",
127413
+ "ip:addr",
127414
+ "ip:link",
127415
+ "hostname:-I",
127416
+ "ping:-c:*",
127417
+ "traceroute",
127418
+ "nslookup",
127419
+ "dig",
127420
+ // Text processing and utilities (awk removed - too powerful)
127421
+ "sed:-n:*",
127422
+ "cut",
127423
+ "cut:*",
127424
+ "sort",
127425
+ "sort:*",
127426
+ "uniq",
127427
+ "uniq:*",
127428
+ "tr",
127429
+ "tr:*",
127430
+ "column",
127431
+ "column:*",
127432
+ "paste",
127433
+ "paste:*",
127434
+ "join",
127435
+ "join:*",
127436
+ "comm",
127437
+ "comm:*",
127438
+ "diff",
127439
+ "diff:*",
127440
+ "cmp",
127441
+ "cmp:*",
127442
+ "patch:--dry-run:*",
127443
+ // Hashing and encoding (read-only)
127444
+ "md5sum",
127445
+ "md5sum:*",
127446
+ "sha1sum",
127447
+ "sha1sum:*",
127448
+ "sha256sum",
127449
+ "sha256sum:*",
127450
+ "base64",
127451
+ "base64:-d",
127452
+ "od",
127453
+ "od:*",
127454
+ "hexdump",
127455
+ "hexdump:*",
127456
+ // Archive and compression (list/view only)
127457
+ "tar:-tf:*",
127458
+ "tar:-tzf:*",
127459
+ "unzip:-l:*",
127460
+ "zip:-l:*",
127461
+ "gzip:-l:*",
127462
+ "gunzip:-l:*",
127463
+ // Help and documentation
127464
+ "man",
127465
+ "man:*",
127466
+ "--help",
127467
+ "help",
127468
+ "info",
127469
+ "info:*",
127470
+ "whatis",
127471
+ "whatis:*",
127472
+ "apropos",
127473
+ "apropos:*",
127474
+ // Make (dry run and info)
127475
+ "make:-n",
127476
+ "make:--dry-run",
127477
+ "make:-p",
127478
+ "make:--print-data-base",
127479
+ // Docker (read-only operations)
127480
+ "docker:ps",
127481
+ "docker:images",
127482
+ "docker:version",
127483
+ "docker:info",
127484
+ "docker:logs:*",
127485
+ "docker:inspect:*",
127486
+ // Test runners (list/info only)
127487
+ "jest:--listTests",
127488
+ "mocha:--help",
127489
+ "pytest:--collect-only"
127490
+ ];
127491
+ DEFAULT_DENY_PATTERNS = [
127492
+ // Dangerous file operations
127493
+ "rm:-rf",
127494
+ "rm:-f:/",
127495
+ "rm:/",
127496
+ "rm:-rf:*",
127497
+ "rmdir",
127498
+ "chmod:777",
127499
+ "chmod:-R:777",
127500
+ "chown",
127501
+ "chgrp",
127502
+ "dd",
127503
+ "dd:*",
127504
+ "shred",
127505
+ "shred:*",
127506
+ // Dangerous find operations that can execute arbitrary commands
127507
+ "find:-exec:*",
127508
+ "find:*:-exec:*",
127509
+ "find:-execdir:*",
127510
+ "find:*:-execdir:*",
127511
+ "find:-ok:*",
127512
+ "find:*:-ok:*",
127513
+ "find:-okdir:*",
127514
+ "find:*:-okdir:*",
127515
+ // Powerful scripting tools that can execute arbitrary commands
127516
+ "awk",
127517
+ "awk:*",
127518
+ "perl",
127519
+ "perl:*",
127520
+ "python:-c:*",
127521
+ "node:-e:*",
127522
+ // System administration and modification
127523
+ "sudo:*",
127524
+ "su",
127525
+ "su:*",
127526
+ "passwd",
127527
+ "adduser",
127528
+ "useradd",
127529
+ "userdel",
127530
+ "usermod",
127531
+ "groupadd",
127532
+ "groupdel",
127533
+ "visudo",
127534
+ // Package installation and removal
127535
+ "npm:install",
127536
+ "npm:i",
127537
+ "npm:uninstall",
127538
+ "npm:publish",
127539
+ "npm:unpublish",
127540
+ "npm:link",
127541
+ "npm:update",
127542
+ "yarn:install",
127543
+ "yarn:add",
127544
+ "yarn:remove",
127545
+ "yarn:upgrade",
127546
+ "pnpm:install",
127547
+ "pnpm:add",
127548
+ "pnpm:remove",
127549
+ "pip:install",
127550
+ "pip:uninstall",
127551
+ "pip:upgrade",
127552
+ "pip3:install",
127553
+ "pip3:uninstall",
127554
+ "pip3:upgrade",
127555
+ "gem:install",
127556
+ "gem:uninstall",
127557
+ "gem:update",
127558
+ "bundle:install",
127559
+ "bundle:update",
127560
+ "composer:install",
127561
+ "composer:update",
127562
+ "composer:remove",
127563
+ "apt:*",
127564
+ "apt-get:*",
127565
+ "yum:*",
127566
+ "dnf:*",
127567
+ "zypper:*",
127568
+ "brew:install",
127569
+ "brew:uninstall",
127570
+ "brew:upgrade",
127571
+ "conda:install",
127572
+ "conda:remove",
127573
+ "conda:update",
127574
+ // Service and system control
127575
+ "systemctl:*",
127576
+ "service:*",
127577
+ "chkconfig:*",
127578
+ "initctl:*",
127579
+ "upstart:*",
127580
+ // Network operations that could be dangerous
127581
+ "curl:-d:*",
127582
+ "curl:--data:*",
127583
+ "curl:-X:POST:*",
127584
+ "curl:-X:PUT:*",
127585
+ "wget:-O:/",
127586
+ "wget:--post-data:*",
127587
+ "ssh",
127588
+ "ssh:*",
127589
+ "scp",
127590
+ "scp:*",
127591
+ "sftp",
127592
+ "sftp:*",
127593
+ "rsync:*",
127594
+ "nc",
127595
+ "nc:*",
127596
+ "netcat",
127597
+ "netcat:*",
127598
+ "telnet",
127599
+ "telnet:*",
127600
+ "ftp",
127601
+ "ftp:*",
127602
+ // Process control and termination
127603
+ "kill",
127604
+ "kill:*",
127605
+ "killall",
127606
+ "killall:*",
127607
+ "pkill",
127608
+ "pkill:*",
127609
+ "nohup:*",
127610
+ "disown:*",
127611
+ // System control and shutdown
127612
+ "shutdown",
127613
+ "shutdown:*",
127614
+ "reboot",
127615
+ "halt",
127616
+ "poweroff",
127617
+ "init",
127618
+ "telinit",
127619
+ // Kernel and module operations
127620
+ "insmod",
127621
+ "insmod:*",
127622
+ "rmmod",
127623
+ "rmmod:*",
127624
+ "modprobe",
127625
+ "modprobe:*",
127626
+ "sysctl:-w:*",
127627
+ // Dangerous git operations
127628
+ "git:push",
127629
+ "git:push:*",
127630
+ "git:force",
127631
+ "git:reset:--hard:*",
127632
+ "git:clean:-fd",
127633
+ "git:rm:*",
127634
+ "git:commit",
127635
+ "git:merge",
127636
+ "git:rebase",
127637
+ "git:cherry-pick",
127638
+ "git:stash:drop",
127639
+ // File system mounting and partitioning
127640
+ "mount",
127641
+ "mount:*",
127642
+ "umount",
127643
+ "umount:*",
127644
+ "fdisk",
127645
+ "fdisk:*",
127646
+ "parted",
127647
+ "parted:*",
127648
+ "mkfs",
127649
+ "mkfs:*",
127650
+ "fsck",
127651
+ "fsck:*",
127652
+ // Cron and scheduling
127653
+ "crontab",
127654
+ "crontab:*",
127655
+ "at",
127656
+ "at:*",
127657
+ "batch",
127658
+ "batch:*",
127659
+ // Compression with potential overwrite
127660
+ "tar:-xf:*",
127661
+ "unzip",
127662
+ "unzip:*",
127663
+ "gzip:*",
127664
+ "gunzip:*",
127665
+ // Build and compilation that might modify files
127666
+ "make",
127667
+ "make:install",
127668
+ "make:clean",
127669
+ "cargo:build",
127670
+ "cargo:install",
127671
+ "npm:run:build",
127672
+ "yarn:build",
127673
+ "mvn:install",
127674
+ "gradle:build",
127675
+ // Docker operations that could modify state
127676
+ "docker:run",
127677
+ "docker:run:*",
127678
+ "docker:exec",
127679
+ "docker:exec:*",
127680
+ "docker:build",
127681
+ "docker:build:*",
127682
+ "docker:pull",
127683
+ "docker:push",
127684
+ "docker:rm",
127685
+ "docker:rmi",
127686
+ "docker:stop",
127687
+ "docker:start",
127688
+ // Database operations
127689
+ "mysql:-e:DROP",
127690
+ "psql:-c:DROP",
127691
+ "redis-cli:FLUSHALL",
127692
+ "mongo:--eval:*",
127693
+ // Text editors that could modify files
127694
+ "vi",
127695
+ "vi:*",
127696
+ "vim",
127697
+ "vim:*",
127698
+ "nano",
127699
+ "nano:*",
127700
+ "emacs",
127701
+ "emacs:*",
127702
+ "sed:-i:*",
127703
+ "perl:-i:*",
127704
+ // Potentially dangerous utilities
127705
+ "eval",
127706
+ "eval:*",
127707
+ "exec",
127708
+ "exec:*",
127709
+ "source",
127710
+ "source:*",
127711
+ "bash:-c:*",
127712
+ "sh:-c:*",
127713
+ "zsh:-c:*"
127714
+ ];
127715
+ }
127716
+ });
127717
+
127718
+ // src/agent/bashCommandUtils.js
127719
+ function parseSimpleCommand(command) {
127720
+ if (!command || typeof command !== "string") {
127721
+ return {
127722
+ success: false,
127723
+ error: "Command must be a non-empty string",
127724
+ command: null,
127725
+ args: [],
127726
+ isComplex: false
127727
+ };
127728
+ }
127729
+ const trimmed = command.trim();
127730
+ if (!trimmed) {
127731
+ return {
127732
+ success: false,
127733
+ error: "Command cannot be empty",
127734
+ command: null,
127735
+ args: [],
127736
+ isComplex: false
127737
+ };
127738
+ }
127739
+ const complexPatterns = [
127740
+ /\|/,
127741
+ // Pipes
127742
+ /&&/,
127743
+ // Logical AND
127744
+ /\|\|/,
127745
+ // Logical OR
127746
+ /(?<!\\);/,
127747
+ // Command separator (but not escaped \;)
127748
+ /&$/,
127749
+ // Background execution
127750
+ /\$\(/,
127751
+ // Command substitution $()
127752
+ /`/,
127753
+ // Command substitution ``
127754
+ />/,
127755
+ // Redirection >
127756
+ /</,
127757
+ // Redirection <
127758
+ /\*\*/,
127759
+ // Glob patterns (potentially dangerous)
127760
+ /^\s*\{.*,.*\}|\{.*\.\.\.*\}/
127761
+ // Brace expansion like {a,b} or {1..10} (but not find {} placeholders)
127762
+ ];
127763
+ for (const pattern of complexPatterns) {
127764
+ if (pattern.test(trimmed)) {
127765
+ return {
127766
+ success: false,
127767
+ error: "Complex shell commands with pipes, operators, or redirections are not supported for security reasons",
127768
+ command: null,
127769
+ args: [],
127770
+ isComplex: true,
127771
+ detected: pattern.toString()
127772
+ };
127773
+ }
127774
+ }
127775
+ const args = [];
127776
+ let current = "";
127777
+ let inQuotes = false;
127778
+ let quoteChar = "";
127779
+ let escaped = false;
127780
+ for (let i3 = 0; i3 < trimmed.length; i3++) {
127781
+ const char = trimmed[i3];
127782
+ const nextChar = i3 + 1 < trimmed.length ? trimmed[i3 + 1] : "";
127783
+ if (escaped) {
127784
+ current += char;
127785
+ escaped = false;
127786
+ continue;
127787
+ }
127788
+ if (char === "\\" && !inQuotes) {
127789
+ escaped = true;
127790
+ continue;
127791
+ }
127792
+ if (!inQuotes && (char === '"' || char === "'")) {
127793
+ inQuotes = true;
127794
+ quoteChar = char;
127795
+ } else if (inQuotes && char === quoteChar) {
127796
+ inQuotes = false;
127797
+ quoteChar = "";
127798
+ } else if (!inQuotes && char === " ") {
127799
+ if (current.trim()) {
127800
+ args.push(current.trim());
127801
+ current = "";
127802
+ }
127803
+ } else {
127804
+ current += char;
127805
+ }
127806
+ }
127807
+ if (current.trim()) {
127808
+ args.push(current.trim());
127809
+ }
127810
+ if (inQuotes) {
127811
+ return {
127812
+ success: false,
127813
+ error: `Unclosed quote in command: ${quoteChar}`,
127814
+ command: null,
127815
+ args: [],
127816
+ isComplex: false
127817
+ };
127818
+ }
127819
+ if (args.length === 0) {
127820
+ return {
127821
+ success: false,
127822
+ error: "No command found after parsing",
127823
+ command: null,
127824
+ args: [],
127825
+ isComplex: false
127826
+ };
127827
+ }
127828
+ const [baseCommand, ...commandArgs] = args;
127829
+ return {
127830
+ success: true,
127831
+ error: null,
127832
+ command: baseCommand,
127833
+ args: commandArgs,
127834
+ fullArgs: args,
127835
+ isComplex: false,
127836
+ original: command
127837
+ };
127838
+ }
127839
+ function isComplexCommand(command) {
127840
+ const result = parseSimpleCommand(command);
127841
+ return result.isComplex;
127842
+ }
127843
+ function parseCommand(command) {
127844
+ const result = parseSimpleCommand(command);
127845
+ if (!result.success) {
127846
+ return {
127847
+ command: "",
127848
+ args: [],
127849
+ error: result.error,
127850
+ isComplex: result.isComplex
127851
+ };
127852
+ }
127853
+ return {
127854
+ command: result.command,
127855
+ args: result.args,
127856
+ error: null,
127857
+ isComplex: result.isComplex
127858
+ };
127859
+ }
127860
+ function parseCommandForExecution(command) {
127861
+ const result = parseSimpleCommand(command);
127862
+ if (!result.success) {
127863
+ return null;
127864
+ }
127865
+ return result.fullArgs;
127866
+ }
127867
+ var init_bashCommandUtils = __esm({
127868
+ "src/agent/bashCommandUtils.js"() {
127869
+ "use strict";
127870
+ }
127871
+ });
127872
+
127873
+ // src/agent/bashPermissions.js
127874
+ function matchesPattern(parsedCommand, pattern) {
127875
+ if (!parsedCommand || !pattern) return false;
127876
+ const { command, args } = parsedCommand;
127877
+ if (!command) return false;
127878
+ const patternParts = pattern.split(":");
127879
+ const commandName = patternParts[0];
127880
+ if (commandName === "*") {
127881
+ return true;
127882
+ } else if (commandName !== command) {
127883
+ return false;
127884
+ }
127885
+ if (patternParts.length === 1) {
127886
+ return true;
127887
+ }
127888
+ for (let i3 = 1; i3 < patternParts.length; i3++) {
127889
+ const patternArg = patternParts[i3];
127890
+ const argIndex = i3 - 1;
127891
+ if (patternArg === "*") {
127892
+ continue;
127893
+ }
127894
+ if (argIndex >= args.length) {
127895
+ return false;
127896
+ }
127897
+ const actualArg = args[argIndex];
127898
+ if (patternArg !== actualArg) {
127899
+ return false;
127900
+ }
127901
+ }
127902
+ return true;
127903
+ }
127904
+ function matchesAnyPattern(parsedCommand, patterns) {
127905
+ if (!patterns || patterns.length === 0) return false;
127906
+ return patterns.some((pattern) => matchesPattern(parsedCommand, pattern));
127907
+ }
127908
+ var BashPermissionChecker;
127909
+ var init_bashPermissions = __esm({
127910
+ "src/agent/bashPermissions.js"() {
127911
+ "use strict";
127912
+ init_bashDefaults();
127913
+ init_bashCommandUtils();
127914
+ BashPermissionChecker = class {
127915
+ /**
127916
+ * Create a permission checker
127917
+ * @param {Object} config - Configuration options
127918
+ * @param {string[]} [config.allow] - Additional allow patterns
127919
+ * @param {string[]} [config.deny] - Additional deny patterns
127920
+ * @param {boolean} [config.disableDefaultAllow] - Disable default allow list
127921
+ * @param {boolean} [config.disableDefaultDeny] - Disable default deny list
127922
+ * @param {boolean} [config.debug] - Enable debug logging
127923
+ */
127924
+ constructor(config = {}) {
127925
+ this.debug = config.debug || false;
127926
+ this.allowPatterns = [];
127927
+ if (!config.disableDefaultAllow) {
127928
+ this.allowPatterns.push(...DEFAULT_ALLOW_PATTERNS);
127929
+ if (this.debug) {
127930
+ console.log(`[BashPermissions] Added ${DEFAULT_ALLOW_PATTERNS.length} default allow patterns`);
127931
+ }
127932
+ }
127933
+ if (config.allow && Array.isArray(config.allow)) {
127934
+ this.allowPatterns.push(...config.allow);
127935
+ if (this.debug) {
127936
+ console.log(`[BashPermissions] Added ${config.allow.length} custom allow patterns:`, config.allow);
127937
+ }
127938
+ }
127939
+ this.denyPatterns = [];
127940
+ if (!config.disableDefaultDeny) {
127941
+ this.denyPatterns.push(...DEFAULT_DENY_PATTERNS);
127942
+ if (this.debug) {
127943
+ console.log(`[BashPermissions] Added ${DEFAULT_DENY_PATTERNS.length} default deny patterns`);
127944
+ }
127945
+ }
127946
+ if (config.deny && Array.isArray(config.deny)) {
127947
+ this.denyPatterns.push(...config.deny);
127948
+ if (this.debug) {
127949
+ console.log(`[BashPermissions] Added ${config.deny.length} custom deny patterns:`, config.deny);
127950
+ }
127951
+ }
127952
+ if (this.debug) {
127953
+ console.log(`[BashPermissions] Total patterns - Allow: ${this.allowPatterns.length}, Deny: ${this.denyPatterns.length}`);
127954
+ }
127955
+ }
127956
+ /**
127957
+ * Check if a simple command is allowed (rejects complex commands for security)
127958
+ * @param {string} command - Command to check
127959
+ * @returns {Object} Permission result
127960
+ */
127961
+ check(command) {
127962
+ if (!command || typeof command !== "string") {
127963
+ return {
127964
+ allowed: false,
127965
+ reason: "Invalid or empty command",
127966
+ command
127967
+ };
127968
+ }
127969
+ if (isComplexCommand(command)) {
127970
+ return {
127971
+ allowed: false,
127972
+ reason: "Complex shell commands with pipes, operators, or redirections are not supported for security reasons",
127973
+ command,
127974
+ isComplex: true
127975
+ };
127976
+ }
127977
+ const parsed = parseCommand(command);
127978
+ if (parsed.error) {
127979
+ return {
127980
+ allowed: false,
127981
+ reason: parsed.error,
127982
+ command
127983
+ };
127984
+ }
127985
+ if (!parsed.command) {
127986
+ return {
127987
+ allowed: false,
127988
+ reason: "No valid command found",
127989
+ command
127990
+ };
127991
+ }
127992
+ if (this.debug) {
127993
+ console.log(`[BashPermissions] Checking simple command: "${command}"`);
127994
+ console.log(`[BashPermissions] Parsed: ${parsed.command} with args: [${parsed.args.join(", ")}]`);
127995
+ }
127996
+ if (matchesAnyPattern(parsed, this.denyPatterns)) {
127997
+ const matchedPatterns = this.denyPatterns.filter((pattern) => matchesPattern(parsed, pattern));
127998
+ return {
127999
+ allowed: false,
128000
+ reason: `Command matches deny pattern: ${matchedPatterns[0]}`,
128001
+ command,
128002
+ parsed,
128003
+ matchedPatterns
128004
+ };
128005
+ }
128006
+ if (this.allowPatterns.length > 0) {
128007
+ if (!matchesAnyPattern(parsed, this.allowPatterns)) {
128008
+ return {
128009
+ allowed: false,
128010
+ reason: "Command not in allow list",
128011
+ command,
128012
+ parsed
128013
+ };
128014
+ }
128015
+ }
128016
+ const result = {
128017
+ allowed: true,
128018
+ command,
128019
+ parsed,
128020
+ isComplex: false
128021
+ };
128022
+ if (this.debug) {
128023
+ console.log(`[BashPermissions] ALLOWED - command passed all checks`);
128024
+ }
128025
+ return result;
128026
+ }
128027
+ /**
128028
+ * Get configuration summary
128029
+ * @returns {Object} Configuration info
128030
+ */
128031
+ getConfig() {
128032
+ return {
128033
+ allowPatterns: this.allowPatterns.length,
128034
+ denyPatterns: this.denyPatterns.length,
128035
+ totalPatterns: this.allowPatterns.length + this.denyPatterns.length
128036
+ };
128037
+ }
128038
+ };
128039
+ }
128040
+ });
128041
+
128042
+ // src/agent/bashExecutor.js
128043
+ async function executeBashCommand(command, options = {}) {
128044
+ const {
128045
+ workingDirectory = process.cwd(),
128046
+ timeout = 12e4,
128047
+ // 2 minutes default
128048
+ env = {},
128049
+ maxBuffer = 10 * 1024 * 1024,
128050
+ // 10MB
128051
+ debug = false
128052
+ } = options;
128053
+ let cwd = workingDirectory;
128054
+ try {
128055
+ cwd = (0, import_path4.resolve)(cwd);
128056
+ if (!(0, import_fs.existsSync)(cwd)) {
128057
+ throw new Error(`Working directory does not exist: ${cwd}`);
128058
+ }
128059
+ } catch (error2) {
128060
+ return {
128061
+ success: false,
128062
+ error: `Invalid working directory: ${error2.message}`,
128063
+ stdout: "",
128064
+ stderr: "",
128065
+ exitCode: 1,
128066
+ command,
128067
+ workingDirectory: cwd,
128068
+ duration: 0
128069
+ };
128070
+ }
128071
+ const startTime = Date.now();
128072
+ if (debug) {
128073
+ console.log(`[BashExecutor] Executing command: "${command}"`);
128074
+ console.log(`[BashExecutor] Working directory: "${cwd}"`);
128075
+ console.log(`[BashExecutor] Timeout: ${timeout}ms`);
128076
+ }
128077
+ return new Promise((resolve4, reject) => {
128078
+ const processEnv = {
128079
+ ...process.env,
128080
+ ...env
128081
+ };
128082
+ const args = parseCommandForExecution(command);
128083
+ if (!args || args.length === 0) {
128084
+ resolve4({
128085
+ success: false,
128086
+ error: "Failed to parse command",
128087
+ stdout: "",
128088
+ stderr: "",
128089
+ exitCode: 1,
128090
+ command,
128091
+ workingDirectory: cwd,
128092
+ duration: Date.now() - startTime
128093
+ });
128094
+ return;
128095
+ }
128096
+ const [cmd, ...cmdArgs] = args;
128097
+ const child = (0, import_child_process6.spawn)(cmd, cmdArgs, {
128098
+ cwd,
128099
+ env: processEnv,
128100
+ stdio: ["ignore", "pipe", "pipe"],
128101
+ // stdin ignored, capture stdout/stderr
128102
+ shell: false,
128103
+ // For security
128104
+ windowsHide: true
128105
+ });
128106
+ let stdout = "";
128107
+ let stderr = "";
128108
+ let killed = false;
128109
+ let timeoutHandle;
128110
+ if (timeout > 0) {
128111
+ timeoutHandle = setTimeout(() => {
128112
+ if (!killed) {
128113
+ killed = true;
128114
+ child.kill("SIGTERM");
128115
+ setTimeout(() => {
128116
+ if (child.exitCode === null) {
128117
+ child.kill("SIGKILL");
128118
+ }
128119
+ }, 5e3);
128120
+ }
128121
+ }, timeout);
128122
+ }
128123
+ child.stdout.on("data", (data2) => {
128124
+ const chunk = data2.toString();
128125
+ if (stdout.length + chunk.length <= maxBuffer) {
128126
+ stdout += chunk;
128127
+ } else {
128128
+ if (!killed) {
128129
+ killed = true;
128130
+ child.kill("SIGTERM");
128131
+ }
128132
+ }
128133
+ });
128134
+ child.stderr.on("data", (data2) => {
128135
+ const chunk = data2.toString();
128136
+ if (stderr.length + chunk.length <= maxBuffer) {
128137
+ stderr += chunk;
128138
+ } else {
128139
+ if (!killed) {
128140
+ killed = true;
128141
+ child.kill("SIGTERM");
128142
+ }
128143
+ }
128144
+ });
128145
+ child.on("close", (code, signal) => {
128146
+ if (timeoutHandle) {
128147
+ clearTimeout(timeoutHandle);
128148
+ }
128149
+ const duration = Date.now() - startTime;
128150
+ if (debug) {
128151
+ console.log(`[BashExecutor] Command completed - Code: ${code}, Signal: ${signal}, Duration: ${duration}ms`);
128152
+ console.log(`[BashExecutor] Stdout length: ${stdout.length}, Stderr length: ${stderr.length}`);
128153
+ }
128154
+ let success = true;
128155
+ let error2 = "";
128156
+ if (killed) {
128157
+ success = false;
128158
+ if (stdout.length + stderr.length > maxBuffer) {
128159
+ error2 = `Command output exceeded maximum buffer size (${maxBuffer} bytes)`;
128160
+ } else {
128161
+ error2 = `Command timed out after ${timeout}ms`;
128162
+ }
128163
+ } else if (code !== 0) {
128164
+ success = false;
128165
+ error2 = `Command exited with code ${code}`;
128166
+ }
128167
+ resolve4({
128168
+ success,
128169
+ error: error2,
128170
+ stdout: stdout.trim(),
128171
+ stderr: stderr.trim(),
128172
+ exitCode: code,
128173
+ signal,
128174
+ command,
128175
+ workingDirectory: cwd,
128176
+ duration,
128177
+ killed
128178
+ });
128179
+ });
128180
+ child.on("error", (error2) => {
128181
+ if (timeoutHandle) {
128182
+ clearTimeout(timeoutHandle);
128183
+ }
128184
+ if (debug) {
128185
+ console.log(`[BashExecutor] Spawn error:`, error2);
128186
+ }
128187
+ resolve4({
128188
+ success: false,
128189
+ error: `Failed to execute command: ${error2.message}`,
128190
+ stdout: "",
128191
+ stderr: "",
128192
+ exitCode: 1,
128193
+ command,
128194
+ workingDirectory: cwd,
128195
+ duration: Date.now() - startTime
128196
+ });
128197
+ });
128198
+ });
128199
+ }
128200
+ function formatExecutionResult(result, includeMetadata = false) {
128201
+ if (!result) {
128202
+ return "No result available";
128203
+ }
128204
+ let output = "";
128205
+ if (includeMetadata) {
128206
+ output += `Command: ${result.command}
128207
+ `;
128208
+ output += `Working directory: ${result.workingDirectory}
128209
+ `;
128210
+ output += `Duration: ${result.duration}ms
128211
+ `;
128212
+ output += `Exit Code: ${result.exitCode}
128213
+ `;
128214
+ if (result.signal) {
128215
+ output += `Signal: ${result.signal}
128216
+ `;
128217
+ }
128218
+ output += "\n";
128219
+ }
128220
+ if (result.stdout) {
128221
+ if (includeMetadata) {
128222
+ output += "--- STDOUT ---\n";
128223
+ }
128224
+ output += result.stdout;
128225
+ if (includeMetadata && result.stderr) {
128226
+ output += "\n";
128227
+ }
128228
+ }
128229
+ if (result.stderr) {
128230
+ if (includeMetadata) {
128231
+ if (result.stdout) output += "\n";
128232
+ output += "--- STDERR ---\n";
128233
+ } else if (result.stdout) {
128234
+ output += "\n--- STDERR ---\n";
128235
+ }
128236
+ output += result.stderr;
128237
+ }
128238
+ if (!result.success && result.error && !result.stderr) {
128239
+ if (output) output += "\n";
128240
+ output += `Error: ${result.error}`;
128241
+ }
128242
+ if (!result.success && result.exitCode !== void 0 && result.exitCode !== 0) {
128243
+ if (output) output += "\n";
128244
+ output += `Exit code: ${result.exitCode}`;
128245
+ }
128246
+ return output || (result.success ? "Command completed successfully (no output)" : "Command failed (no output)");
128247
+ }
128248
+ function validateExecutionOptions(options = {}) {
128249
+ const errors = [];
128250
+ const warnings = [];
128251
+ if (options.timeout !== void 0) {
128252
+ if (typeof options.timeout !== "number" || options.timeout < 0) {
128253
+ errors.push("timeout must be a non-negative number");
128254
+ } else if (options.timeout > 6e5) {
128255
+ warnings.push("timeout is very high (>10 minutes)");
128256
+ }
128257
+ }
128258
+ if (options.maxBuffer !== void 0) {
128259
+ if (typeof options.maxBuffer !== "number" || options.maxBuffer < 1024) {
128260
+ errors.push("maxBuffer must be at least 1024 bytes");
128261
+ } else if (options.maxBuffer > 100 * 1024 * 1024) {
128262
+ warnings.push("maxBuffer is very high (>100MB)");
128263
+ }
128264
+ }
128265
+ if (options.workingDirectory) {
128266
+ if (typeof options.workingDirectory !== "string") {
128267
+ errors.push("workingDirectory must be a string");
128268
+ } else if (!(0, import_fs.existsSync)(options.workingDirectory)) {
128269
+ errors.push(`workingDirectory does not exist: ${options.workingDirectory}`);
128270
+ }
128271
+ }
128272
+ if (options.env && typeof options.env !== "object") {
128273
+ errors.push("env must be an object");
128274
+ }
128275
+ return {
128276
+ valid: errors.length === 0,
128277
+ errors,
128278
+ warnings
128279
+ };
128280
+ }
128281
+ var import_child_process6, import_path4, import_fs;
128282
+ var init_bashExecutor = __esm({
128283
+ "src/agent/bashExecutor.js"() {
128284
+ "use strict";
128285
+ import_child_process6 = __nccwpck_require__(35317);
128286
+ import_path4 = __nccwpck_require__(16928);
128287
+ import_fs = __nccwpck_require__(79896);
128288
+ init_bashCommandUtils();
128289
+ }
128290
+ });
128291
+
128292
+ // src/tools/bash.js
128293
+ var import_ai2, import_path5, bashTool;
128294
+ var init_bash = __esm({
128295
+ "src/tools/bash.js"() {
128296
+ "use strict";
128297
+ import_ai2 = __nccwpck_require__(86619);
128298
+ import_path5 = __nccwpck_require__(16928);
128299
+ init_bashPermissions();
128300
+ init_bashExecutor();
128301
+ bashTool = (options = {}) => {
128302
+ const {
128303
+ bashConfig = {},
128304
+ debug = false,
128305
+ defaultPath,
128306
+ allowedFolders = []
128307
+ } = options;
128308
+ const permissionChecker = new BashPermissionChecker({
128309
+ allow: bashConfig.allow,
128310
+ deny: bashConfig.deny,
128311
+ disableDefaultAllow: bashConfig.disableDefaultAllow,
128312
+ disableDefaultDeny: bashConfig.disableDefaultDeny,
128313
+ debug
128314
+ });
128315
+ const getDefaultWorkingDirectory = () => {
128316
+ if (bashConfig.workingDirectory) {
128317
+ return bashConfig.workingDirectory;
128318
+ }
128319
+ if (defaultPath) {
128320
+ return defaultPath;
128321
+ }
128322
+ if (allowedFolders && allowedFolders.length > 0) {
128323
+ return allowedFolders[0];
128324
+ }
128325
+ return process.cwd();
128326
+ };
128327
+ return (0, import_ai2.tool)({
128328
+ name: "bash",
128329
+ description: `Execute bash commands for system exploration and development tasks.
128330
+
128331
+ Security: This tool has built-in security with allow/deny lists. By default, only safe read-only commands are allowed for code exploration.
128332
+
128333
+ Parameters:
128334
+ - command: (required) The bash command to execute
128335
+ - workingDirectory: (optional) Directory to execute command in
128336
+ - timeout: (optional) Command timeout in milliseconds
128337
+ - env: (optional) Additional environment variables
128338
+
128339
+ Examples of allowed commands by default:
128340
+ - File exploration: ls, cat, head, tail, find, grep
128341
+ - Git operations: git status, git log, git diff, git show
128342
+ - Package info: npm list, pip list, cargo --version
128343
+ - System info: whoami, pwd, uname, date
128344
+
128345
+ Dangerous commands are blocked by default (rm -rf, sudo, npm install, etc.)`,
128346
+ inputSchema: {
128347
+ type: "object",
128348
+ properties: {
128349
+ command: {
128350
+ type: "string",
128351
+ description: "The bash command to execute"
128352
+ },
128353
+ workingDirectory: {
128354
+ type: "string",
128355
+ description: "Directory to execute the command in (optional)"
128356
+ },
128357
+ timeout: {
128358
+ type: "number",
128359
+ description: "Command timeout in milliseconds (optional)",
128360
+ minimum: 1e3,
128361
+ maximum: 6e5
128362
+ },
128363
+ env: {
128364
+ type: "object",
128365
+ description: "Additional environment variables (optional)",
128366
+ additionalProperties: {
128367
+ type: "string"
128368
+ }
128369
+ }
128370
+ },
128371
+ required: ["command"],
128372
+ additionalProperties: false
128373
+ },
128374
+ execute: async ({ command, workingDirectory, timeout, env }) => {
128375
+ try {
128376
+ if (command === null || command === void 0 || typeof command !== "string") {
128377
+ return "Error: Command is required and must be a string";
128378
+ }
128379
+ if (command.trim().length === 0) {
128380
+ return "Error: Command cannot be empty";
128381
+ }
128382
+ const permissionResult = permissionChecker.check(command.trim());
128383
+ if (!permissionResult.allowed) {
128384
+ if (debug) {
128385
+ console.log(`[BashTool] Permission denied for command: "${command}"`);
128386
+ console.log(`[BashTool] Reason: ${permissionResult.reason}`);
128387
+ }
128388
+ return `Permission denied: ${permissionResult.reason}
128389
+
128390
+ This command is not allowed by the current security policy.
128391
+
128392
+ Common reasons:
128393
+ 1. The command is in the deny list (potentially dangerous)
128394
+ 2. The command is not in the allow list (not a recognized safe command)
128395
+
128396
+ If you believe this command should be allowed, you can:
128397
+ - Use the --bash-allow option to add specific patterns
128398
+ - Use the --no-default-bash-deny flag to remove default restrictions (not recommended)
128399
+
128400
+ For code exploration, try these safe alternatives:
128401
+ - ls, cat, head, tail for file operations
128402
+ - find, grep, rg for searching
128403
+ - git status, git log, git show for git operations
128404
+ - npm list, pip list for package information`;
128405
+ }
128406
+ const workingDir = workingDirectory || getDefaultWorkingDirectory();
128407
+ if (allowedFolders && allowedFolders.length > 0) {
128408
+ const resolvedWorkingDir = (0, import_path5.resolve)(workingDir);
128409
+ const isAllowed = allowedFolders.some((folder) => {
128410
+ const resolvedFolder = (0, import_path5.resolve)(folder);
128411
+ return resolvedWorkingDir.startsWith(resolvedFolder);
128412
+ });
128413
+ if (!isAllowed) {
128414
+ return `Error: Working directory "${workingDir}" is not within allowed folders: ${allowedFolders.join(", ")}`;
128415
+ }
128416
+ }
128417
+ const executionOptions = {
128418
+ workingDirectory: workingDir,
128419
+ timeout: timeout || bashConfig.timeout || 12e4,
128420
+ env: { ...bashConfig.env, ...env },
128421
+ maxBuffer: bashConfig.maxBuffer,
128422
+ debug
128423
+ };
128424
+ const validation = validateExecutionOptions(executionOptions);
128425
+ if (!validation.valid) {
128426
+ return `Error: Invalid execution options: ${validation.errors.join(", ")}`;
128427
+ }
128428
+ if (validation.warnings.length > 0 && debug) {
128429
+ console.log("[BashTool] Warnings:", validation.warnings);
128430
+ }
128431
+ if (debug) {
128432
+ console.log(`[BashTool] Executing command: "${command}"`);
128433
+ console.log(`[BashTool] Working directory: "${workingDir}"`);
128434
+ console.log(`[BashTool] Timeout: ${executionOptions.timeout}ms`);
128435
+ }
128436
+ const result = await executeBashCommand(command.trim(), executionOptions);
128437
+ if (debug) {
128438
+ console.log(`[BashTool] Command completed - Success: ${result.success}, Duration: ${result.duration}ms`);
128439
+ }
128440
+ const formattedResult = formatExecutionResult(result, debug);
128441
+ if (!result.success) {
128442
+ let errorInfo = `
128443
+
128444
+ Command failed with exit code ${result.exitCode}`;
128445
+ if (result.killed) {
128446
+ errorInfo += ` (${result.error})`;
128447
+ }
128448
+ return formattedResult + errorInfo;
128449
+ }
128450
+ return formattedResult;
128451
+ } catch (error2) {
128452
+ if (debug) {
128453
+ console.error("[BashTool] Execution error:", error2);
128454
+ }
128455
+ return `Error executing bash command: ${error2.message}`;
128456
+ }
128457
+ }
128458
+ });
128459
+ };
128460
+ }
128461
+ });
128462
+
126531
128463
  // src/tools/langchain.js
126532
128464
  function createSearchTool() {
126533
128465
  return {
@@ -126745,6 +128677,10 @@ __export(tools_exports, {
126745
128677
  DEFAULT_SYSTEM_MESSAGE: () => DEFAULT_SYSTEM_MESSAGE,
126746
128678
  attemptCompletionSchema: () => attemptCompletionSchema,
126747
128679
  attemptCompletionToolDefinition: () => attemptCompletionToolDefinition,
128680
+ bashDescription: () => bashDescription,
128681
+ bashSchema: () => bashSchema,
128682
+ bashTool: () => bashTool,
128683
+ bashToolDefinition: () => bashToolDefinition,
126748
128684
  createExtractTool: () => createExtractTool,
126749
128685
  createQueryTool: () => createQueryTool,
126750
128686
  createSearchTool: () => createSearchTool,
@@ -126765,16 +128701,19 @@ var init_tools = __esm({
126765
128701
  "src/tools/index.js"() {
126766
128702
  "use strict";
126767
128703
  init_vercel();
128704
+ init_bash();
126768
128705
  init_langchain();
126769
128706
  init_common();
126770
128707
  init_system_message();
126771
128708
  init_vercel();
128709
+ init_bash();
126772
128710
  init_system_message();
126773
128711
  tools = {
126774
128712
  searchTool: searchTool(),
126775
128713
  queryTool: queryTool(),
126776
128714
  extractTool: extractTool(),
126777
128715
  delegateTool: delegateTool(),
128716
+ bashTool: bashTool(),
126778
128717
  DEFAULT_SYSTEM_MESSAGE
126779
128718
  };
126780
128719
  }
@@ -126787,10 +128726,10 @@ async function listFilesByLevel(options) {
126787
128726
  maxFiles = 100,
126788
128727
  respectGitignore = true
126789
128728
  } = options;
126790
- if (!import_fs.default.existsSync(directory)) {
128729
+ if (!import_fs2.default.existsSync(directory)) {
126791
128730
  throw new Error(`Directory does not exist: ${directory}`);
126792
128731
  }
126793
- const gitDirExists = import_fs.default.existsSync(import_path4.default.join(directory, ".git"));
128732
+ const gitDirExists = import_fs2.default.existsSync(import_path6.default.join(directory, ".git"));
126794
128733
  if (gitDirExists && respectGitignore) {
126795
128734
  try {
126796
128735
  return await listFilesUsingGit(directory, maxFiles);
@@ -126805,8 +128744,8 @@ async function listFilesUsingGit(directory, maxFiles) {
126805
128744
  const { stdout } = await execAsync4("git ls-files", { cwd: directory });
126806
128745
  const files = stdout.split("\n").filter(Boolean);
126807
128746
  const sortedFiles = files.sort((a3, b3) => {
126808
- const depthA = a3.split(import_path4.default.sep).length;
126809
- const depthB = b3.split(import_path4.default.sep).length;
128747
+ const depthA = a3.split(import_path6.default.sep).length;
128748
+ const depthB = b3.split(import_path6.default.sep).length;
126810
128749
  return depthA - depthB;
126811
128750
  });
126812
128751
  return sortedFiles.slice(0, maxFiles);
@@ -126821,19 +128760,19 @@ async function listFilesByLevelManually(directory, maxFiles, respectGitignore) {
126821
128760
  while (queue.length > 0 && result.length < maxFiles) {
126822
128761
  const { dir, level } = queue.shift();
126823
128762
  try {
126824
- const entries = import_fs.default.readdirSync(dir, { withFileTypes: true });
128763
+ const entries = import_fs2.default.readdirSync(dir, { withFileTypes: true });
126825
128764
  const files = entries.filter((entry) => entry.isFile());
126826
128765
  for (const file of files) {
126827
128766
  if (result.length >= maxFiles) break;
126828
- const filePath = import_path4.default.join(dir, file.name);
126829
- const relativePath = import_path4.default.relative(directory, filePath);
128767
+ const filePath = import_path6.default.join(dir, file.name);
128768
+ const relativePath = import_path6.default.relative(directory, filePath);
126830
128769
  if (shouldIgnore(relativePath, ignorePatterns)) continue;
126831
128770
  result.push(relativePath);
126832
128771
  }
126833
128772
  const dirs = entries.filter((entry) => entry.isDirectory());
126834
128773
  for (const subdir of dirs) {
126835
- const subdirPath = import_path4.default.join(dir, subdir.name);
126836
- const relativeSubdirPath = import_path4.default.relative(directory, subdirPath);
128774
+ const subdirPath = import_path6.default.join(dir, subdir.name);
128775
+ const relativeSubdirPath = import_path6.default.relative(directory, subdirPath);
126837
128776
  if (shouldIgnore(relativeSubdirPath, ignorePatterns)) continue;
126838
128777
  if (subdir.name === "node_modules" || subdir.name === ".git") continue;
126839
128778
  queue.push({ dir: subdirPath, level: level + 1 });
@@ -126845,12 +128784,12 @@ async function listFilesByLevelManually(directory, maxFiles, respectGitignore) {
126845
128784
  return result;
126846
128785
  }
126847
128786
  function loadGitignorePatterns(directory) {
126848
- const gitignorePath = import_path4.default.join(directory, ".gitignore");
126849
- if (!import_fs.default.existsSync(gitignorePath)) {
128787
+ const gitignorePath = import_path6.default.join(directory, ".gitignore");
128788
+ if (!import_fs2.default.existsSync(gitignorePath)) {
126850
128789
  return [];
126851
128790
  }
126852
128791
  try {
126853
- const content = import_fs.default.readFileSync(gitignorePath, "utf8");
128792
+ const content = import_fs2.default.readFileSync(gitignorePath, "utf8");
126854
128793
  return content.split("\n").map((line) => line.trim()).filter((line) => line && !line.startsWith("#"));
126855
128794
  } catch (error2) {
126856
128795
  console.error(`Warning: Could not read .gitignore: ${error2.message}`);
@@ -126868,15 +128807,15 @@ function shouldIgnore(filePath, ignorePatterns) {
126868
128807
  }
126869
128808
  return false;
126870
128809
  }
126871
- var import_fs, import_path4, import_util5, import_child_process6, execAsync4;
128810
+ var import_fs2, import_path6, import_util5, import_child_process7, execAsync4;
126872
128811
  var init_file_lister = __esm({
126873
128812
  "src/utils/file-lister.js"() {
126874
128813
  "use strict";
126875
- import_fs = __toESM(__nccwpck_require__(79896), 1);
126876
- import_path4 = __toESM(__nccwpck_require__(16928), 1);
128814
+ import_fs2 = __toESM(__nccwpck_require__(79896), 1);
128815
+ import_path6 = __toESM(__nccwpck_require__(16928), 1);
126877
128816
  import_util5 = __nccwpck_require__(39023);
126878
- import_child_process6 = __nccwpck_require__(35317);
126879
- execAsync4 = (0, import_util5.promisify)(import_child_process6.exec);
128817
+ import_child_process7 = __nccwpck_require__(35317);
128818
+ execAsync4 = (0, import_util5.promisify)(import_child_process7.exec);
126880
128819
  }
126881
128820
  });
126882
128821
 
@@ -129031,7 +130970,7 @@ var require_headStream = __commonJS({
129031
130970
  if ((0, stream_type_check_1.isReadableStream)(stream)) {
129032
130971
  return (0, headStream_browser_1.headStream)(stream, bytes);
129033
130972
  }
129034
- return new Promise((resolve2, reject) => {
130973
+ return new Promise((resolve4, reject) => {
129035
130974
  const collector = new Collector();
129036
130975
  collector.limit = bytes;
129037
130976
  stream.pipe(collector);
@@ -129042,7 +130981,7 @@ var require_headStream = __commonJS({
129042
130981
  collector.on("error", reject);
129043
130982
  collector.on("finish", function() {
129044
130983
  const bytes2 = new Uint8Array(Buffer.concat(this.buffers));
129045
- resolve2(bytes2);
130984
+ resolve4(bytes2);
129046
130985
  });
129047
130986
  });
129048
130987
  };
@@ -129300,21 +131239,21 @@ var require_dist_cjs15 = __commonJS({
129300
131239
  let sendBody = true;
129301
131240
  if (expect === "100-continue") {
129302
131241
  sendBody = await Promise.race([
129303
- new Promise((resolve2) => {
129304
- timeoutId = Number(timing.setTimeout(() => resolve2(true), Math.max(MIN_WAIT_TIME, maxContinueTimeoutMs)));
131242
+ new Promise((resolve4) => {
131243
+ timeoutId = Number(timing.setTimeout(() => resolve4(true), Math.max(MIN_WAIT_TIME, maxContinueTimeoutMs)));
129305
131244
  }),
129306
- new Promise((resolve2) => {
131245
+ new Promise((resolve4) => {
129307
131246
  httpRequest.on("continue", () => {
129308
131247
  timing.clearTimeout(timeoutId);
129309
- resolve2(true);
131248
+ resolve4(true);
129310
131249
  });
129311
131250
  httpRequest.on("response", () => {
129312
131251
  timing.clearTimeout(timeoutId);
129313
- resolve2(false);
131252
+ resolve4(false);
129314
131253
  });
129315
131254
  httpRequest.on("error", () => {
129316
131255
  timing.clearTimeout(timeoutId);
129317
- resolve2(false);
131256
+ resolve4(false);
129318
131257
  });
129319
131258
  })
129320
131259
  ]);
@@ -129350,13 +131289,13 @@ var require_dist_cjs15 = __commonJS({
129350
131289
  constructor(options) {
129351
131290
  this.socketWarningTimestamp = 0;
129352
131291
  this.metadata = { handlerProtocol: "http/1.1" };
129353
- this.configProvider = new Promise((resolve2, reject) => {
131292
+ this.configProvider = new Promise((resolve4, reject) => {
129354
131293
  if (typeof options === "function") {
129355
131294
  options().then((_options) => {
129356
- resolve2(this.resolveDefaultConfig(_options));
131295
+ resolve4(this.resolveDefaultConfig(_options));
129357
131296
  }).catch(reject);
129358
131297
  } else {
129359
- resolve2(this.resolveDefaultConfig(options));
131298
+ resolve4(this.resolveDefaultConfig(options));
129360
131299
  }
129361
131300
  });
129362
131301
  }
@@ -129440,7 +131379,7 @@ or increase socketAcquisitionWarningTimeout=(millis) in the NodeHttpHandler conf
129440
131379
  return new Promise((_resolve, _reject) => {
129441
131380
  let writeRequestBodyPromise = void 0;
129442
131381
  const timeouts = [];
129443
- const resolve2 = /* @__PURE__ */ __name(async (arg) => {
131382
+ const resolve4 = /* @__PURE__ */ __name(async (arg) => {
129444
131383
  await writeRequestBodyPromise;
129445
131384
  timeouts.forEach(timing.clearTimeout);
129446
131385
  _resolve(arg);
@@ -129510,7 +131449,7 @@ or increase socketAcquisitionWarningTimeout=(millis) in the NodeHttpHandler conf
129510
131449
  headers: getTransformedHeaders(res.headers),
129511
131450
  body: res
129512
131451
  });
129513
- resolve2({ response: httpResponse });
131452
+ resolve4({ response: httpResponse });
129514
131453
  });
129515
131454
  req.on("error", (err) => {
129516
131455
  if (NODEJS_TIMEOUT_ERROR_CODES.includes(err.code)) {
@@ -129699,13 +131638,13 @@ or increase socketAcquisitionWarningTimeout=(millis) in the NodeHttpHandler conf
129699
131638
  constructor(options) {
129700
131639
  this.metadata = { handlerProtocol: "h2" };
129701
131640
  this.connectionManager = new NodeHttp2ConnectionManager({});
129702
- this.configProvider = new Promise((resolve2, reject) => {
131641
+ this.configProvider = new Promise((resolve4, reject) => {
129703
131642
  if (typeof options === "function") {
129704
131643
  options().then((opts) => {
129705
- resolve2(opts || {});
131644
+ resolve4(opts || {});
129706
131645
  }).catch(reject);
129707
131646
  } else {
129708
- resolve2(options || {});
131647
+ resolve4(options || {});
129709
131648
  }
129710
131649
  });
129711
131650
  }
@@ -129738,7 +131677,7 @@ or increase socketAcquisitionWarningTimeout=(millis) in the NodeHttpHandler conf
129738
131677
  return new Promise((_resolve, _reject) => {
129739
131678
  let fulfilled = false;
129740
131679
  let writeRequestBodyPromise = void 0;
129741
- const resolve2 = /* @__PURE__ */ __name(async (arg) => {
131680
+ const resolve4 = /* @__PURE__ */ __name(async (arg) => {
129742
131681
  await writeRequestBodyPromise;
129743
131682
  _resolve(arg);
129744
131683
  }, "resolve");
@@ -129794,7 +131733,7 @@ or increase socketAcquisitionWarningTimeout=(millis) in the NodeHttpHandler conf
129794
131733
  body: req
129795
131734
  });
129796
131735
  fulfilled = true;
129797
- resolve2({ response: httpResponse });
131736
+ resolve4({ response: httpResponse });
129798
131737
  if (disableConcurrentStreams) {
129799
131738
  session.close();
129800
131739
  this.connectionManager.deleteSession(authority, session);
@@ -129883,7 +131822,7 @@ or increase socketAcquisitionWarningTimeout=(millis) in the NodeHttpHandler conf
129883
131822
  if (isReadableStreamInstance(stream)) {
129884
131823
  return collectReadableStream(stream);
129885
131824
  }
129886
- return new Promise((resolve2, reject) => {
131825
+ return new Promise((resolve4, reject) => {
129887
131826
  const collector = new Collector();
129888
131827
  stream.pipe(collector);
129889
131828
  stream.on("error", (err) => {
@@ -129893,7 +131832,7 @@ or increase socketAcquisitionWarningTimeout=(millis) in the NodeHttpHandler conf
129893
131832
  collector.on("error", reject);
129894
131833
  collector.on("finish", function() {
129895
131834
  const bytes = new Uint8Array(Buffer.concat(this.bufferedBytes));
129896
- resolve2(bytes);
131835
+ resolve4(bytes);
129897
131836
  });
129898
131837
  });
129899
131838
  }, "streamCollector");
@@ -129958,7 +131897,7 @@ var require_dist_cjs16 = __commonJS({
129958
131897
  }
129959
131898
  __name(createRequest, "createRequest");
129960
131899
  function requestTimeout(timeoutInMs = 0) {
129961
- return new Promise((resolve2, reject) => {
131900
+ return new Promise((resolve4, reject) => {
129962
131901
  if (timeoutInMs) {
129963
131902
  setTimeout(() => {
129964
131903
  const timeoutError = new Error(`Request did not complete within ${timeoutInMs} ms`);
@@ -130085,7 +132024,7 @@ var require_dist_cjs16 = __commonJS({
130085
132024
  ];
130086
132025
  if (abortSignal) {
130087
132026
  raceOfPromises.push(
130088
- new Promise((resolve2, reject) => {
132027
+ new Promise((resolve4, reject) => {
130089
132028
  const onAbort = /* @__PURE__ */ __name(() => {
130090
132029
  const abortError = new Error("Request aborted");
130091
132030
  abortError.name = "AbortError";
@@ -130153,7 +132092,7 @@ var require_dist_cjs16 = __commonJS({
130153
132092
  }
130154
132093
  __name(collectStream, "collectStream");
130155
132094
  function readToBase64(blob) {
130156
- return new Promise((resolve2, reject) => {
132095
+ return new Promise((resolve4, reject) => {
130157
132096
  const reader = new FileReader();
130158
132097
  reader.onloadend = () => {
130159
132098
  if (reader.readyState !== 2) {
@@ -130162,7 +132101,7 @@ var require_dist_cjs16 = __commonJS({
130162
132101
  const result = reader.result ?? "";
130163
132102
  const commaIndex = result.indexOf(",");
130164
132103
  const dataOffset = commaIndex > -1 ? commaIndex + 1 : result.length;
130165
- resolve2(result.substring(dataOffset));
132104
+ resolve4(result.substring(dataOffset));
130166
132105
  };
130167
132106
  reader.onabort = () => reject(new Error("Read aborted"));
130168
132107
  reader.onerror = () => reject(reader.error);
@@ -130649,9 +132588,10 @@ var TypeRegistry;
130649
132588
  var init_TypeRegistry = __esm({
130650
132589
  "node_modules/@smithy/core/dist-es/submodules/schema/TypeRegistry.js"() {
130651
132590
  TypeRegistry = class _TypeRegistry {
130652
- constructor(namespace, schemas = /* @__PURE__ */ new Map()) {
132591
+ constructor(namespace, schemas = /* @__PURE__ */ new Map(), exceptions = /* @__PURE__ */ new Map()) {
130653
132592
  this.namespace = namespace;
130654
132593
  this.schemas = schemas;
132594
+ this.exceptions = exceptions;
130655
132595
  }
130656
132596
  static for(namespace) {
130657
132597
  if (!_TypeRegistry.registries.has(namespace)) {
@@ -130661,8 +132601,7 @@ var init_TypeRegistry = __esm({
130661
132601
  }
130662
132602
  register(shapeId, schema) {
130663
132603
  const qualifiedName = this.normalizeShapeId(shapeId);
130664
- const registry = _TypeRegistry.for(this.getNamespace(shapeId));
130665
- registry.schemas.set(qualifiedName, schema);
132604
+ this.schemas.set(qualifiedName, schema);
130666
132605
  }
130667
132606
  getSchema(shapeId) {
130668
132607
  const id = this.normalizeShapeId(shapeId);
@@ -130671,6 +132610,12 @@ var init_TypeRegistry = __esm({
130671
132610
  }
130672
132611
  return this.schemas.get(id);
130673
132612
  }
132613
+ registerError(errorSchema, ctor) {
132614
+ this.exceptions.set(errorSchema, ctor);
132615
+ }
132616
+ getErrorCtor(errorSchema) {
132617
+ return this.exceptions.get(errorSchema);
132618
+ }
130674
132619
  getBaseException() {
130675
132620
  for (const [id, schema] of this.schemas.entries()) {
130676
132621
  if (id.startsWith("smithy.ts.sdk.synthetic.") && id.endsWith("ServiceException")) {
@@ -130682,9 +132627,9 @@ var init_TypeRegistry = __esm({
130682
132627
  find(predicate) {
130683
132628
  return [...this.schemas.values()].find(predicate);
130684
132629
  }
130685
- destroy() {
130686
- _TypeRegistry.registries.delete(this.namespace);
132630
+ clear() {
130687
132631
  this.schemas.clear();
132632
+ this.exceptions.clear();
130688
132633
  }
130689
132634
  normalizeShapeId(shapeId) {
130690
132635
  if (shapeId.includes("#")) {
@@ -130832,7 +132777,7 @@ var init_ErrorSchema = __esm({
130832
132777
  traits,
130833
132778
  memberNames,
130834
132779
  memberList,
130835
- ctor
132780
+ ctor: null
130836
132781
  });
130837
132782
  }
130838
132783
  });
@@ -131801,11 +133746,11 @@ function __metadata(metadataKey, metadataValue) {
131801
133746
  }
131802
133747
  function __awaiter(thisArg, _arguments, P, generator) {
131803
133748
  function adopt(value) {
131804
- return value instanceof P ? value : new P(function(resolve2) {
131805
- resolve2(value);
133749
+ return value instanceof P ? value : new P(function(resolve4) {
133750
+ resolve4(value);
131806
133751
  });
131807
133752
  }
131808
- return new (P || (P = Promise))(function(resolve2, reject) {
133753
+ return new (P || (P = Promise))(function(resolve4, reject) {
131809
133754
  function fulfilled(value) {
131810
133755
  try {
131811
133756
  step(generator.next(value));
@@ -131821,7 +133766,7 @@ function __awaiter(thisArg, _arguments, P, generator) {
131821
133766
  }
131822
133767
  }
131823
133768
  function step(result) {
131824
- result.done ? resolve2(result.value) : adopt(result.value).then(fulfilled, rejected);
133769
+ result.done ? resolve4(result.value) : adopt(result.value).then(fulfilled, rejected);
131825
133770
  }
131826
133771
  step((generator = generator.apply(thisArg, _arguments || [])).next());
131827
133772
  });
@@ -132012,14 +133957,14 @@ function __asyncValues(o3) {
132012
133957
  }, i3);
132013
133958
  function verb(n3) {
132014
133959
  i3[n3] = o3[n3] && function(v3) {
132015
- return new Promise(function(resolve2, reject) {
132016
- v3 = o3[n3](v3), settle(resolve2, reject, v3.done, v3.value);
133960
+ return new Promise(function(resolve4, reject) {
133961
+ v3 = o3[n3](v3), settle(resolve4, reject, v3.done, v3.value);
132017
133962
  });
132018
133963
  };
132019
133964
  }
132020
- function settle(resolve2, reject, d3, v3) {
133965
+ function settle(resolve4, reject, d3, v3) {
132021
133966
  Promise.resolve(v3).then(function(v4) {
132022
- resolve2({ value: v4, done: d3 });
133967
+ resolve4({ value: v4, done: d3 });
132023
133968
  }, reject);
132024
133969
  }
132025
133970
  }
@@ -136990,16 +138935,18 @@ var init_SmithyRpcV2CborProtocol = __esm({
136990
138935
  if (dataObject.Message) {
136991
138936
  dataObject.message = dataObject.Message;
136992
138937
  }
136993
- const baseExceptionSchema = TypeRegistry.for("smithy.ts.sdk.synthetic." + namespace).getBaseException();
138938
+ const synthetic = TypeRegistry.for("smithy.ts.sdk.synthetic." + namespace);
138939
+ const baseExceptionSchema = synthetic.getBaseException();
136994
138940
  if (baseExceptionSchema) {
136995
- const ErrorCtor = baseExceptionSchema.ctor;
136996
- throw Object.assign(new ErrorCtor({ name: errorName }), errorMetadata, dataObject);
138941
+ const ErrorCtor2 = synthetic.getErrorCtor(baseExceptionSchema);
138942
+ throw Object.assign(new ErrorCtor2({ name: errorName }), errorMetadata, dataObject);
136997
138943
  }
136998
138944
  throw Object.assign(new Error(errorName), errorMetadata, dataObject);
136999
138945
  }
137000
138946
  const ns = NormalizedSchema.of(errorSchema);
138947
+ const ErrorCtor = registry.getErrorCtor(errorSchema);
137001
138948
  const message = dataObject.message ?? dataObject.Message ?? "Unknown";
137002
- const exception = new errorSchema.ctor(message);
138949
+ const exception = new ErrorCtor(message);
137003
138950
  const output = {};
137004
138951
  for (const [name14, member] of ns.structIterator()) {
137005
138952
  output[name14] = this.deserializer.readValue(member, dataObject[name14]);
@@ -142665,7 +144612,7 @@ var require_dist_cjs37 = __commonJS({
142665
144612
  );
142666
144613
  }
142667
144614
  waitForReady(socket, connectionTimeout) {
142668
- return new Promise((resolve2, reject) => {
144615
+ return new Promise((resolve4, reject) => {
142669
144616
  const timeout = setTimeout(() => {
142670
144617
  this.removeNotUsableSockets(socket.url);
142671
144618
  reject({
@@ -142676,7 +144623,7 @@ var require_dist_cjs37 = __commonJS({
142676
144623
  }, connectionTimeout);
142677
144624
  socket.onopen = () => {
142678
144625
  clearTimeout(timeout);
142679
- resolve2();
144626
+ resolve4();
142680
144627
  };
142681
144628
  });
142682
144629
  }
@@ -142685,10 +144632,10 @@ var require_dist_cjs37 = __commonJS({
142685
144632
  let socketErrorOccurred = false;
142686
144633
  let reject = /* @__PURE__ */ __name(() => {
142687
144634
  }, "reject");
142688
- let resolve2 = /* @__PURE__ */ __name(() => {
144635
+ let resolve4 = /* @__PURE__ */ __name(() => {
142689
144636
  }, "resolve");
142690
144637
  socket.onmessage = (event) => {
142691
- resolve2({
144638
+ resolve4({
142692
144639
  done: false,
142693
144640
  value: new Uint8Array(event.data)
142694
144641
  });
@@ -142704,7 +144651,7 @@ var require_dist_cjs37 = __commonJS({
142704
144651
  if (streamError) {
142705
144652
  reject(streamError);
142706
144653
  } else {
142707
- resolve2({
144654
+ resolve4({
142708
144655
  done: true,
142709
144656
  value: void 0
142710
144657
  // unchecked because done=true.
@@ -142715,7 +144662,7 @@ var require_dist_cjs37 = __commonJS({
142715
144662
  [Symbol.asyncIterator]: () => ({
142716
144663
  next: /* @__PURE__ */ __name(() => {
142717
144664
  return new Promise((_resolve, _reject) => {
142718
- resolve2 = _resolve;
144665
+ resolve4 = _resolve;
142719
144666
  reject = _reject;
142720
144667
  });
142721
144668
  }, "next")
@@ -143238,13 +145185,13 @@ var require_dist_cjs42 = __commonJS({
143238
145185
  ...data2.default && { default: data2.default }
143239
145186
  }
143240
145187
  ), "getConfigData");
143241
- var import_path9 = __nccwpck_require__(16928);
145188
+ var import_path11 = __nccwpck_require__(16928);
143242
145189
  var import_getHomeDir = require_getHomeDir();
143243
145190
  var ENV_CONFIG_PATH = "AWS_CONFIG_FILE";
143244
- var getConfigFilepath = /* @__PURE__ */ __name(() => process.env[ENV_CONFIG_PATH] || (0, import_path9.join)((0, import_getHomeDir.getHomeDir)(), ".aws", "config"), "getConfigFilepath");
145191
+ var getConfigFilepath = /* @__PURE__ */ __name(() => process.env[ENV_CONFIG_PATH] || (0, import_path11.join)((0, import_getHomeDir.getHomeDir)(), ".aws", "config"), "getConfigFilepath");
143245
145192
  var import_getHomeDir2 = require_getHomeDir();
143246
145193
  var ENV_CREDENTIALS_PATH = "AWS_SHARED_CREDENTIALS_FILE";
143247
- var getCredentialsFilepath = /* @__PURE__ */ __name(() => process.env[ENV_CREDENTIALS_PATH] || (0, import_path9.join)((0, import_getHomeDir2.getHomeDir)(), ".aws", "credentials"), "getCredentialsFilepath");
145194
+ var getCredentialsFilepath = /* @__PURE__ */ __name(() => process.env[ENV_CREDENTIALS_PATH] || (0, import_path11.join)((0, import_getHomeDir2.getHomeDir)(), ".aws", "credentials"), "getCredentialsFilepath");
143248
145195
  var import_getHomeDir3 = require_getHomeDir();
143249
145196
  var prefixKeyRegex = /^([\w-]+)\s(["'])?([\w-@\+\.%:/]+)\2$/;
143250
145197
  var profileNameBlockList = ["__proto__", "profile __proto__"];
@@ -143302,11 +145249,11 @@ var require_dist_cjs42 = __commonJS({
143302
145249
  const relativeHomeDirPrefix = "~/";
143303
145250
  let resolvedFilepath = filepath;
143304
145251
  if (filepath.startsWith(relativeHomeDirPrefix)) {
143305
- resolvedFilepath = (0, import_path9.join)(homeDir, filepath.slice(2));
145252
+ resolvedFilepath = (0, import_path11.join)(homeDir, filepath.slice(2));
143306
145253
  }
143307
145254
  let resolvedConfigFilepath = configFilepath;
143308
145255
  if (configFilepath.startsWith(relativeHomeDirPrefix)) {
143309
- resolvedConfigFilepath = (0, import_path9.join)(homeDir, configFilepath.slice(2));
145256
+ resolvedConfigFilepath = (0, import_path11.join)(homeDir, configFilepath.slice(2));
143310
145257
  }
143311
145258
  const parsedFiles = await Promise.all([
143312
145259
  (0, import_slurpFile.slurpFile)(resolvedConfigFilepath, {
@@ -143961,7 +145908,7 @@ var require_dist_cjs46 = __commonJS({
143961
145908
  this.refillTokenBucket();
143962
145909
  if (amount > this.currentCapacity) {
143963
145910
  const delay = (amount - this.currentCapacity) / this.fillRate * 1e3;
143964
- await new Promise((resolve2) => _DefaultRateLimiter.setTimeoutFn(resolve2, delay));
145911
+ await new Promise((resolve4) => _DefaultRateLimiter.setTimeoutFn(resolve4, delay));
143965
145912
  }
143966
145913
  this.currentCapacity = this.currentCapacity - amount;
143967
145914
  }
@@ -144352,7 +146299,7 @@ var require_dist_cjs47 = __commonJS({
144352
146299
  const delayFromResponse = getDelayFromRetryAfterHeader(err.$response);
144353
146300
  const delay = Math.max(delayFromResponse || 0, delayFromDecider);
144354
146301
  totalDelay += delay;
144355
- await new Promise((resolve2) => setTimeout(resolve2, delay));
146302
+ await new Promise((resolve4) => setTimeout(resolve4, delay));
144356
146303
  continue;
144357
146304
  }
144358
146305
  if (!err.$metadata) {
@@ -144512,7 +146459,7 @@ var require_dist_cjs47 = __commonJS({
144512
146459
  attempts = retryToken.getRetryCount();
144513
146460
  const delay = retryToken.getRetryDelay();
144514
146461
  totalRetryDelay += delay;
144515
- await new Promise((resolve2) => setTimeout(resolve2, delay));
146462
+ await new Promise((resolve4) => setTimeout(resolve4, delay));
144516
146463
  }
144517
146464
  }
144518
146465
  } else {
@@ -144855,7 +146802,7 @@ var require_dist_cjs49 = __commonJS({
144855
146802
  var import_buffer = __nccwpck_require__(20181);
144856
146803
  var import_http = __nccwpck_require__(58611);
144857
146804
  function httpRequest(options) {
144858
- return new Promise((resolve2, reject) => {
146805
+ return new Promise((resolve4, reject) => {
144859
146806
  const req = (0, import_http.request)({
144860
146807
  method: "GET",
144861
146808
  ...options,
@@ -144884,7 +146831,7 @@ var require_dist_cjs49 = __commonJS({
144884
146831
  chunks.push(chunk);
144885
146832
  });
144886
146833
  res.on("end", () => {
144887
- resolve2(import_buffer.Buffer.concat(chunks));
146834
+ resolve4(import_buffer.Buffer.concat(chunks));
144888
146835
  req.destroy();
144889
146836
  });
144890
146837
  });
@@ -145319,7 +147266,7 @@ var require_retry_wrapper = __commonJS({
145319
147266
  try {
145320
147267
  return await toRetry();
145321
147268
  } catch (e3) {
145322
- await new Promise((resolve2) => setTimeout(resolve2, delayMs));
147269
+ await new Promise((resolve4) => setTimeout(resolve4, delayMs));
145323
147270
  }
145324
147271
  }
145325
147272
  return await toRetry();
@@ -145763,7 +147710,7 @@ var require_dist_cjs53 = __commonJS({
145763
147710
  calculateBodyLength: () => calculateBodyLength3
145764
147711
  });
145765
147712
  module2.exports = __toCommonJS2(index_exports2);
145766
- var import_fs7 = __nccwpck_require__(79896);
147713
+ var import_fs8 = __nccwpck_require__(79896);
145767
147714
  var calculateBodyLength3 = /* @__PURE__ */ __name((body) => {
145768
147715
  if (!body) {
145769
147716
  return 0;
@@ -145777,9 +147724,9 @@ var require_dist_cjs53 = __commonJS({
145777
147724
  } else if (typeof body.start === "number" && typeof body.end === "number") {
145778
147725
  return body.end + 1 - body.start;
145779
147726
  } else if (typeof body.path === "string" || Buffer.isBuffer(body.path)) {
145780
- return (0, import_fs7.lstatSync)(body.path).size;
147727
+ return (0, import_fs8.lstatSync)(body.path).size;
145781
147728
  } else if (typeof body.fd === "number") {
145782
- return (0, import_fs7.fstatSync)(body.fd).size;
147729
+ return (0, import_fs8.fstatSync)(body.fd).size;
145783
147730
  }
145784
147731
  throw new Error(`Body Length computation failed for ${body}`);
145785
147732
  }, "calculateBodyLength");
@@ -147817,8 +149764,8 @@ var require_dist_cjs57 = __commonJS({
147817
149764
  }
147818
149765
  }, "validateTokenKey");
147819
149766
  var import_shared_ini_file_loader = require_dist_cjs42();
147820
- var import_fs7 = __nccwpck_require__(79896);
147821
- var { writeFile } = import_fs7.promises;
149767
+ var import_fs8 = __nccwpck_require__(79896);
149768
+ var { writeFile } = import_fs8.promises;
147822
149769
  var writeSSOTokenToFile = /* @__PURE__ */ __name((id, ssoToken) => {
147823
149770
  const tokenFilepath = (0, import_shared_ini_file_loader.getSSOTokenFilepath)(id);
147824
149771
  const tokenString = JSON.stringify(ssoToken, null, 2);
@@ -149460,7 +151407,7 @@ var require_dist_cjs59 = __commonJS({
149460
151407
  module2.exports = __toCommonJS2(index_exports2);
149461
151408
  var import_property_provider2 = require_dist_cjs24();
149462
151409
  var import_shared_ini_file_loader = require_dist_cjs42();
149463
- var import_child_process8 = __nccwpck_require__(35317);
151410
+ var import_child_process9 = __nccwpck_require__(35317);
149464
151411
  var import_util7 = __nccwpck_require__(39023);
149465
151412
  var import_client7 = (init_client(), __toCommonJS(client_exports));
149466
151413
  var getValidatedProcessCredentials = /* @__PURE__ */ __name((profileName, data2, profiles) => {
@@ -149497,7 +151444,7 @@ var require_dist_cjs59 = __commonJS({
149497
151444
  if (profiles[profileName]) {
149498
151445
  const credentialProcess = profile["credential_process"];
149499
151446
  if (credentialProcess !== void 0) {
149500
- const execPromise = (0, import_util7.promisify)(import_shared_ini_file_loader.externalDataInterceptor?.getTokenRecord?.().exec ?? import_child_process8.exec);
151447
+ const execPromise = (0, import_util7.promisify)(import_shared_ini_file_loader.externalDataInterceptor?.getTokenRecord?.().exec ?? import_child_process9.exec);
149501
151448
  try {
149502
151449
  const { stdout } = await execPromise(credentialProcess);
149503
151450
  let data2;
@@ -150236,7 +152183,7 @@ var require_dist_cjs64 = __commonJS({
150236
152183
  streamEnded = true;
150237
152184
  });
150238
152185
  while (!generationEnded) {
150239
- const value = await new Promise((resolve2) => setTimeout(() => resolve2(records.shift()), 0));
152186
+ const value = await new Promise((resolve4) => setTimeout(() => resolve4(records.shift()), 0));
150240
152187
  if (value) {
150241
152188
  yield value;
150242
152189
  }
@@ -153613,16 +155560,16 @@ function prepareTools(mode) {
153613
155560
  }
153614
155561
  const toolWarnings = [];
153615
155562
  const bedrockTools = [];
153616
- for (const tool2 of tools2) {
153617
- if (tool2.type === "provider-defined") {
153618
- toolWarnings.push({ type: "unsupported-tool", tool: tool2 });
155563
+ for (const tool3 of tools2) {
155564
+ if (tool3.type === "provider-defined") {
155565
+ toolWarnings.push({ type: "unsupported-tool", tool: tool3 });
153619
155566
  } else {
153620
155567
  bedrockTools.push({
153621
155568
  toolSpec: {
153622
- name: tool2.name,
153623
- description: tool2.description,
155569
+ name: tool3.name,
155570
+ description: tool3.description,
153624
155571
  inputSchema: {
153625
- json: tool2.parameters
155572
+ json: tool3.parameters
153626
155573
  }
153627
155574
  }
153628
155575
  });
@@ -154633,8 +156580,8 @@ function checkAttemptCompleteRecovery(cleanedXmlString, validTools = []) {
154633
156580
  function hasOtherToolTags(xmlString, validTools = []) {
154634
156581
  const defaultTools = ["search", "query", "extract", "listFiles", "searchFiles", "implement", "attempt_completion"];
154635
156582
  const toolsToCheck = validTools.length > 0 ? validTools : defaultTools;
154636
- for (const tool2 of toolsToCheck) {
154637
- if (tool2 !== "attempt_completion" && xmlString.includes(`<${tool2}`)) {
156583
+ for (const tool3 of toolsToCheck) {
156584
+ if (tool3 !== "attempt_completion" && xmlString.includes(`<${tool3}`)) {
154638
156585
  return true;
154639
156586
  }
154640
156587
  }
@@ -154662,12 +156609,16 @@ var init_xmlParsingUtils = __esm({
154662
156609
 
154663
156610
  // src/agent/tools.js
154664
156611
  function createTools(configOptions) {
154665
- return {
156612
+ const tools2 = {
154666
156613
  searchTool: searchTool(configOptions),
154667
156614
  queryTool: queryTool(configOptions),
154668
156615
  extractTool: extractTool(configOptions),
154669
156616
  delegateTool: delegateTool(configOptions)
154670
156617
  };
156618
+ if (configOptions.enableBash) {
156619
+ tools2.bashTool = bashTool(configOptions);
156620
+ }
156621
+ return tools2;
154671
156622
  }
154672
156623
  function parseXmlToolCallWithThinking(xmlString, validTools) {
154673
156624
  const { cleanedXmlString, recoveryResult } = processXmlWithThinkingAndRecovery(xmlString, validTools);
@@ -154811,26 +156762,33 @@ function createWrappedTools(baseTools) {
154811
156762
  baseTools.delegateTool.execute
154812
156763
  );
154813
156764
  }
156765
+ if (baseTools.bashTool) {
156766
+ wrappedTools.bashToolInstance = wrapToolWithEmitter(
156767
+ baseTools.bashTool,
156768
+ "bash",
156769
+ baseTools.bashTool.execute
156770
+ );
156771
+ }
154814
156772
  return wrappedTools;
154815
156773
  }
154816
- 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;
156774
+ 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;
154817
156775
  var init_probeTool = __esm({
154818
156776
  "src/agent/probeTool.js"() {
154819
156777
  "use strict";
154820
156778
  init_index();
154821
- import_child_process7 = __nccwpck_require__(35317);
156779
+ import_child_process8 = __nccwpck_require__(35317);
154822
156780
  import_util6 = __nccwpck_require__(39023);
154823
156781
  import_crypto4 = __nccwpck_require__(76982);
154824
156782
  import_events = __nccwpck_require__(24434);
154825
- import_fs2 = __toESM(__nccwpck_require__(79896), 1);
154826
- import_fs3 = __nccwpck_require__(79896);
154827
- import_path5 = __toESM(__nccwpck_require__(16928), 1);
156783
+ import_fs3 = __toESM(__nccwpck_require__(79896), 1);
156784
+ import_fs4 = __nccwpck_require__(79896);
156785
+ import_path7 = __toESM(__nccwpck_require__(16928), 1);
154828
156786
  import_glob = __nccwpck_require__(21363);
154829
156787
  toolCallEmitter = new import_events.EventEmitter();
154830
156788
  activeToolExecutions = /* @__PURE__ */ new Map();
154831
- wrapToolWithEmitter = (tool2, toolName, baseExecute) => {
156789
+ wrapToolWithEmitter = (tool3, toolName, baseExecute) => {
154832
156790
  return {
154833
- ...tool2,
156791
+ ...tool3,
154834
156792
  // Spread schema, description etc.
154835
156793
  execute: async (params) => {
154836
156794
  const debug = process.env.DEBUG === "1";
@@ -154912,9 +156870,9 @@ var init_probeTool = __esm({
154912
156870
  execute: async (params) => {
154913
156871
  const { directory = ".", workingDirectory } = params;
154914
156872
  const baseCwd = workingDirectory || process.cwd();
154915
- const secureBaseDir = import_path5.default.resolve(baseCwd);
154916
- const targetDir = import_path5.default.resolve(secureBaseDir, directory);
154917
- if (!targetDir.startsWith(secureBaseDir + import_path5.default.sep) && targetDir !== secureBaseDir) {
156873
+ const secureBaseDir = import_path7.default.resolve(baseCwd);
156874
+ const targetDir = import_path7.default.resolve(secureBaseDir, directory);
156875
+ if (!targetDir.startsWith(secureBaseDir + import_path7.default.sep) && targetDir !== secureBaseDir) {
154918
156876
  throw new Error("Path traversal attempt detected. Access denied.");
154919
156877
  }
154920
156878
  try {
@@ -154937,9 +156895,9 @@ var init_probeTool = __esm({
154937
156895
  throw new Error("Pattern is required for file search");
154938
156896
  }
154939
156897
  const baseCwd = workingDirectory || process.cwd();
154940
- const secureBaseDir = import_path5.default.resolve(baseCwd);
154941
- const targetDir = import_path5.default.resolve(secureBaseDir, directory);
154942
- if (!targetDir.startsWith(secureBaseDir + import_path5.default.sep) && targetDir !== secureBaseDir) {
156898
+ const secureBaseDir = import_path7.default.resolve(baseCwd);
156899
+ const targetDir = import_path7.default.resolve(secureBaseDir, directory);
156900
+ if (!targetDir.startsWith(secureBaseDir + import_path7.default.sep) && targetDir !== secureBaseDir) {
154943
156901
  throw new Error("Path traversal attempt detected. Access denied.");
154944
156902
  }
154945
156903
  try {
@@ -154971,7 +156929,7 @@ function createMockProvider() {
154971
156929
  provider: "mock",
154972
156930
  // Mock the doGenerate method used by Vercel AI SDK
154973
156931
  doGenerate: async ({ messages, tools: tools2 }) => {
154974
- await new Promise((resolve2) => setTimeout(resolve2, 10));
156932
+ await new Promise((resolve4) => setTimeout(resolve4, 10));
154975
156933
  return {
154976
156934
  text: "This is a mock response for testing",
154977
156935
  toolCalls: [],
@@ -155546,7 +157504,7 @@ ${decodedContent}
155546
157504
  }
155547
157505
  if (needsQuoting(content)) {
155548
157506
  wasFixed = true;
155549
- const safeContent = content.replace(/"/g, "'");
157507
+ const safeContent = content.replace(/"/g, "&quot;").replace(/'/g, "&#39;");
155550
157508
  return `["${safeContent}"]`;
155551
157509
  }
155552
157510
  return match;
@@ -155559,7 +157517,7 @@ ${decodedContent}
155559
157517
  }
155560
157518
  if (needsQuoting(content)) {
155561
157519
  wasFixed = true;
155562
- const safeContent = content.replace(/"/g, "'");
157520
+ const safeContent = content.replace(/"/g, "&quot;").replace(/'/g, "&#39;");
155563
157521
  return `{"${safeContent}"}`;
155564
157522
  }
155565
157523
  return match;
@@ -155729,7 +157687,7 @@ ${fixedContent}
155729
157687
  }
155730
157688
  if (needsQuoting(content)) {
155731
157689
  wasFixed = true;
155732
- const safeContent = content.replace(/"/g, "'");
157690
+ const safeContent = content.replace(/"/g, "&quot;").replace(/'/g, "&#39;");
155733
157691
  return `["${safeContent}"]`;
155734
157692
  }
155735
157693
  return match;
@@ -155742,7 +157700,7 @@ ${fixedContent}
155742
157700
  }
155743
157701
  if (needsQuoting(content)) {
155744
157702
  wasFixed = true;
155745
- const safeContent = content.replace(/"/g, "'");
157703
+ const safeContent = content.replace(/"/g, "&quot;").replace(/'/g, "&#39;");
155746
157704
  return `{"${safeContent}"}`;
155747
157705
  }
155748
157706
  return match;
@@ -156142,11 +158100,11 @@ function loadMCPConfigurationFromPath(configPath) {
156142
158100
  if (!configPath) {
156143
158101
  throw new Error("Config path is required");
156144
158102
  }
156145
- if (!(0, import_fs4.existsSync)(configPath)) {
158103
+ if (!(0, import_fs5.existsSync)(configPath)) {
156146
158104
  throw new Error(`MCP configuration file not found: ${configPath}`);
156147
158105
  }
156148
158106
  try {
156149
- const content = (0, import_fs4.readFileSync)(configPath, "utf8");
158107
+ const content = (0, import_fs5.readFileSync)(configPath, "utf8");
156150
158108
  const config = JSON.parse(content);
156151
158109
  if (process.env.DEBUG === "1") {
156152
158110
  console.error(`[MCP] Loaded configuration from: ${configPath}`);
@@ -156161,19 +158119,19 @@ function loadMCPConfiguration() {
156161
158119
  // Environment variable path
156162
158120
  process.env.MCP_CONFIG_PATH,
156163
158121
  // Local project paths
156164
- (0, import_path6.join)(process.cwd(), ".mcp", "config.json"),
156165
- (0, import_path6.join)(process.cwd(), "mcp.config.json"),
158122
+ (0, import_path8.join)(process.cwd(), ".mcp", "config.json"),
158123
+ (0, import_path8.join)(process.cwd(), "mcp.config.json"),
156166
158124
  // Home directory paths
156167
- (0, import_path6.join)((0, import_os3.homedir)(), ".config", "probe", "mcp.json"),
156168
- (0, import_path6.join)((0, import_os3.homedir)(), ".mcp", "config.json"),
158125
+ (0, import_path8.join)((0, import_os3.homedir)(), ".config", "probe", "mcp.json"),
158126
+ (0, import_path8.join)((0, import_os3.homedir)(), ".mcp", "config.json"),
156169
158127
  // Claude-style config location
156170
- (0, import_path6.join)((0, import_os3.homedir)(), "Library", "Application Support", "Claude", "mcp_config.json")
158128
+ (0, import_path8.join)((0, import_os3.homedir)(), "Library", "Application Support", "Claude", "mcp_config.json")
156171
158129
  ].filter(Boolean);
156172
158130
  let config = null;
156173
158131
  for (const configPath of configPaths) {
156174
- if ((0, import_fs4.existsSync)(configPath)) {
158132
+ if ((0, import_fs5.existsSync)(configPath)) {
156175
158133
  try {
156176
- const content = (0, import_fs4.readFileSync)(configPath, "utf8");
158134
+ const content = (0, import_fs5.readFileSync)(configPath, "utf8");
156177
158135
  config = JSON.parse(content);
156178
158136
  if (process.env.DEBUG === "1") {
156179
158137
  console.error(`[MCP] Loaded configuration from: ${configPath}`);
@@ -156269,22 +158227,22 @@ function parseEnabledServers(config) {
156269
158227
  }
156270
158228
  return servers;
156271
158229
  }
156272
- var import_fs4, import_path6, import_os3, import_url4, __filename4, __dirname4, DEFAULT_CONFIG;
158230
+ var import_fs5, import_path8, import_os3, import_url4, __filename4, __dirname4, DEFAULT_CONFIG;
156273
158231
  var init_config = __esm({
156274
158232
  "src/agent/mcp/config.js"() {
156275
158233
  "use strict";
156276
- import_fs4 = __nccwpck_require__(79896);
156277
- import_path6 = __nccwpck_require__(16928);
158234
+ import_fs5 = __nccwpck_require__(79896);
158235
+ import_path8 = __nccwpck_require__(16928);
156278
158236
  import_os3 = __nccwpck_require__(70857);
156279
158237
  import_url4 = __nccwpck_require__(87016);
156280
158238
  __filename4 = (0, import_url4.fileURLToPath)("file:///");
156281
- __dirname4 = (0, import_path6.dirname)(__filename4);
158239
+ __dirname4 = (0, import_path8.dirname)(__filename4);
156282
158240
  DEFAULT_CONFIG = {
156283
158241
  mcpServers: {
156284
158242
  // Example probe server configuration
156285
158243
  "probe-local": {
156286
158244
  command: "node",
156287
- args: [(0, import_path6.join)(__dirname4, "../../../examples/chat/mcpServer.js")],
158245
+ args: [(0, import_path8.join)(__dirname4, "../../../examples/chat/mcpServer.js")],
156288
158246
  transport: "stdio",
156289
158247
  enabled: false
156290
158248
  },
@@ -156441,12 +158399,12 @@ var init_client2 = __esm({
156441
158399
  });
156442
158400
  const toolsResponse = await client.listTools();
156443
158401
  if (toolsResponse && toolsResponse.tools) {
156444
- for (const tool2 of toolsResponse.tools) {
156445
- const qualifiedName = `${name14}_${tool2.name}`;
158402
+ for (const tool3 of toolsResponse.tools) {
158403
+ const qualifiedName = `${name14}_${tool3.name}`;
156446
158404
  this.tools.set(qualifiedName, {
156447
- ...tool2,
158405
+ ...tool3,
156448
158406
  serverName: name14,
156449
- originalName: tool2.name
158407
+ originalName: tool3.name
156450
158408
  });
156451
158409
  if (this.debug) {
156452
158410
  console.error(`[MCP] Registered tool: ${qualifiedName}`);
@@ -156468,20 +158426,20 @@ var init_client2 = __esm({
156468
158426
  * @param {Object} args - Tool arguments
156469
158427
  */
156470
158428
  async callTool(toolName, args) {
156471
- const tool2 = this.tools.get(toolName);
156472
- if (!tool2) {
158429
+ const tool3 = this.tools.get(toolName);
158430
+ if (!tool3) {
156473
158431
  throw new Error(`Unknown tool: ${toolName}`);
156474
158432
  }
156475
- const clientInfo = this.clients.get(tool2.serverName);
158433
+ const clientInfo = this.clients.get(tool3.serverName);
156476
158434
  if (!clientInfo) {
156477
- throw new Error(`Server ${tool2.serverName} not connected`);
158435
+ throw new Error(`Server ${tool3.serverName} not connected`);
156478
158436
  }
156479
158437
  try {
156480
158438
  if (this.debug) {
156481
158439
  console.error(`[MCP] Calling ${toolName} with args:`, args);
156482
158440
  }
156483
158441
  const result = await clientInfo.client.callTool({
156484
- name: tool2.originalName,
158442
+ name: tool3.originalName,
156485
158443
  arguments: args
156486
158444
  });
156487
158445
  return result;
@@ -156496,11 +158454,11 @@ var init_client2 = __esm({
156496
158454
  */
156497
158455
  getTools() {
156498
158456
  const tools2 = {};
156499
- for (const [name14, tool2] of this.tools.entries()) {
158457
+ for (const [name14, tool3] of this.tools.entries()) {
156500
158458
  tools2[name14] = {
156501
- description: tool2.description,
156502
- inputSchema: tool2.inputSchema,
156503
- serverName: tool2.serverName
158459
+ description: tool3.description,
158460
+ inputSchema: tool3.inputSchema,
158461
+ serverName: tool3.serverName
156504
158462
  };
156505
158463
  }
156506
158464
  return tools2;
@@ -156511,10 +158469,10 @@ var init_client2 = __esm({
156511
158469
  */
156512
158470
  getVercelTools() {
156513
158471
  const tools2 = {};
156514
- for (const [name14, tool2] of this.tools.entries()) {
158472
+ for (const [name14, tool3] of this.tools.entries()) {
156515
158473
  tools2[name14] = {
156516
- description: tool2.description,
156517
- inputSchema: tool2.inputSchema,
158474
+ description: tool3.description,
158475
+ inputSchema: tool3.inputSchema,
156518
158476
  execute: async (args) => {
156519
158477
  const result = await this.callTool(name14, args);
156520
158478
  if (result.content && result.content[0]) {
@@ -156551,9 +158509,9 @@ var init_client2 = __esm({
156551
158509
  });
156552
158510
 
156553
158511
  // src/agent/mcp/xmlBridge.js
156554
- function mcpToolToXmlDefinition(name14, tool2) {
156555
- const description = tool2.description || "MCP tool";
156556
- const inputSchema = tool2.inputSchema || tool2.parameters || {};
158512
+ function mcpToolToXmlDefinition(name14, tool3) {
158513
+ const description = tool3.description || "MCP tool";
158514
+ const inputSchema = tool3.inputSchema || tool3.parameters || {};
156557
158515
  let paramDocs = "";
156558
158516
  if (inputSchema.properties) {
156559
158517
  paramDocs = "\n\nParameters (provide as JSON object):";
@@ -156713,8 +158671,8 @@ var init_xmlBridge = __esm({
156713
158671
  const result = await this.mcpManager.initialize(mcpConfigs);
156714
158672
  const vercelTools = this.mcpManager.getVercelTools();
156715
158673
  this.mcpTools = vercelTools;
156716
- for (const [name14, tool2] of Object.entries(vercelTools)) {
156717
- this.xmlDefinitions[name14] = mcpToolToXmlDefinition(name14, tool2);
158674
+ for (const [name14, tool3] of Object.entries(vercelTools)) {
158675
+ this.xmlDefinitions[name14] = mcpToolToXmlDefinition(name14, tool3);
156718
158676
  }
156719
158677
  if (this.debug) {
156720
158678
  console.error(`[MCP] Loaded ${Object.keys(vercelTools).length} MCP tools from ${result.connected} server(s)`);
@@ -156751,12 +158709,12 @@ var init_xmlBridge = __esm({
156751
158709
  if (this.debug) {
156752
158710
  console.error(`[MCP] Executing MCP tool: ${toolName} with params:`, params);
156753
158711
  }
156754
- const tool2 = this.mcpTools[toolName];
156755
- if (!tool2) {
158712
+ const tool3 = this.mcpTools[toolName];
158713
+ if (!tool3) {
156756
158714
  throw new Error(`Unknown MCP tool: ${toolName}`);
156757
158715
  }
156758
158716
  try {
156759
- const result = await tool2.execute(params);
158717
+ const result = await tool3.execute(params);
156760
158718
  return {
156761
158719
  success: true,
156762
158720
  toolName,
@@ -156808,7 +158766,7 @@ var ProbeAgent_exports = {};
156808
158766
  __export(ProbeAgent_exports, {
156809
158767
  ProbeAgent: () => ProbeAgent
156810
158768
  });
156811
- 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;
158769
+ 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;
156812
158770
  var init_ProbeAgent = __esm({
156813
158771
  "src/agent/ProbeAgent.js"() {
156814
158772
  "use strict";
@@ -156816,12 +158774,12 @@ var init_ProbeAgent = __esm({
156816
158774
  import_openai = __nccwpck_require__(87635);
156817
158775
  import_google = __nccwpck_require__(30260);
156818
158776
  init_dist3();
156819
- import_ai2 = __nccwpck_require__(86619);
158777
+ import_ai3 = __nccwpck_require__(86619);
156820
158778
  import_crypto5 = __nccwpck_require__(76982);
156821
158779
  import_events2 = __nccwpck_require__(24434);
156822
- import_fs5 = __nccwpck_require__(79896);
158780
+ import_fs6 = __nccwpck_require__(79896);
156823
158781
  import_promises = __nccwpck_require__(91943);
156824
- import_path7 = __nccwpck_require__(16928);
158782
+ import_path9 = __nccwpck_require__(16928);
156825
158783
  init_tokenCounter();
156826
158784
  init_tools2();
156827
158785
  init_common();
@@ -156865,6 +158823,8 @@ var init_ProbeAgent = __esm({
156865
158823
  this.outline = !!options.outline;
156866
158824
  this.maxResponseTokens = options.maxResponseTokens || parseInt(process.env.MAX_RESPONSE_TOKENS || "0", 10) || null;
156867
158825
  this.disableMermaidValidation = !!options.disableMermaidValidation;
158826
+ this.enableBash = !!options.enableBash;
158827
+ this.bashConfig = options.bashConfig || {};
156868
158828
  if (options.allowedFolders && Array.isArray(options.allowedFolders)) {
156869
158829
  this.allowedFolders = options.allowedFolders;
156870
158830
  } else if (options.path) {
@@ -156908,7 +158868,9 @@ var init_ProbeAgent = __esm({
156908
158868
  debug: this.debug,
156909
158869
  defaultPath: this.allowedFolders.length > 0 ? this.allowedFolders[0] : process.cwd(),
156910
158870
  allowedFolders: this.allowedFolders,
156911
- outline: this.outline
158871
+ outline: this.outline,
158872
+ enableBash: this.enableBash,
158873
+ bashConfig: this.bashConfig
156912
158874
  };
156913
158875
  const baseTools = createTools(configOptions);
156914
158876
  const wrappedTools = createWrappedTools(baseTools);
@@ -156920,6 +158882,9 @@ var init_ProbeAgent = __esm({
156920
158882
  listFiles: listFilesToolInstance,
156921
158883
  searchFiles: searchFilesToolInstance
156922
158884
  };
158885
+ if (this.enableBash && wrappedTools.bashToolInstance) {
158886
+ this.toolImplementations.bash = wrappedTools.bashToolInstance;
158887
+ }
156923
158888
  this.wrappedTools = wrappedTools;
156924
158889
  }
156925
158890
  /**
@@ -157106,13 +159071,13 @@ var init_ProbeAgent = __esm({
157106
159071
  const allowedDirs = this.allowedFolders && this.allowedFolders.length > 0 ? this.allowedFolders : [process.cwd()];
157107
159072
  let absolutePath;
157108
159073
  let isPathAllowed = false;
157109
- if ((0, import_path7.isAbsolute)(imagePath)) {
159074
+ if ((0, import_path9.isAbsolute)(imagePath)) {
157110
159075
  absolutePath = imagePath;
157111
- isPathAllowed = allowedDirs.some((dir) => absolutePath.startsWith((0, import_path7.resolve)(dir)));
159076
+ isPathAllowed = allowedDirs.some((dir) => absolutePath.startsWith((0, import_path9.resolve)(dir)));
157112
159077
  } else {
157113
159078
  for (const dir of allowedDirs) {
157114
- const resolvedPath3 = (0, import_path7.resolve)(dir, imagePath);
157115
- if (resolvedPath3.startsWith((0, import_path7.resolve)(dir))) {
159079
+ const resolvedPath3 = (0, import_path9.resolve)(dir, imagePath);
159080
+ if (resolvedPath3.startsWith((0, import_path9.resolve)(dir))) {
157116
159081
  absolutePath = resolvedPath3;
157117
159082
  isPathAllowed = true;
157118
159083
  break;
@@ -157607,7 +159572,7 @@ You are working with a repository located at: ${searchDirectory}
157607
159572
  try {
157608
159573
  const executeAIRequest = async () => {
157609
159574
  const messagesForAI = this.prepareMessagesWithImages(currentMessages);
157610
- const result = await (0, import_ai2.streamText)({
159575
+ const result = await (0, import_ai3.streamText)({
157611
159576
  model: this.provider(this.model),
157612
159577
  messages: messagesForAI,
157613
159578
  maxTokens: maxResponseTokens,
@@ -158284,12 +160249,12 @@ function initializeSimpleTelemetryFromOptions(options) {
158284
160249
  });
158285
160250
  return telemetry;
158286
160251
  }
158287
- var import_fs6, import_path8, SimpleTelemetry, SimpleAppTracer;
160252
+ var import_fs7, import_path10, SimpleTelemetry, SimpleAppTracer;
158288
160253
  var init_simpleTelemetry = __esm({
158289
160254
  "src/agent/simpleTelemetry.js"() {
158290
160255
  "use strict";
158291
- import_fs6 = __nccwpck_require__(79896);
158292
- import_path8 = __nccwpck_require__(16928);
160256
+ import_fs7 = __nccwpck_require__(79896);
160257
+ import_path10 = __nccwpck_require__(16928);
158293
160258
  SimpleTelemetry = class {
158294
160259
  constructor(options = {}) {
158295
160260
  this.serviceName = options.serviceName || "probe-agent";
@@ -158303,11 +160268,11 @@ var init_simpleTelemetry = __esm({
158303
160268
  }
158304
160269
  initializeFileExporter() {
158305
160270
  try {
158306
- const dir = (0, import_path8.dirname)(this.filePath);
158307
- if (!(0, import_fs6.existsSync)(dir)) {
158308
- (0, import_fs6.mkdirSync)(dir, { recursive: true });
160271
+ const dir = (0, import_path10.dirname)(this.filePath);
160272
+ if (!(0, import_fs7.existsSync)(dir)) {
160273
+ (0, import_fs7.mkdirSync)(dir, { recursive: true });
158309
160274
  }
158310
- this.stream = (0, import_fs6.createWriteStream)(this.filePath, { flags: "a" });
160275
+ this.stream = (0, import_fs7.createWriteStream)(this.filePath, { flags: "a" });
158311
160276
  this.stream.on("error", (error2) => {
158312
160277
  console.error(`[SimpleTelemetry] Stream error: ${error2.message}`);
158313
160278
  });
@@ -158368,20 +160333,20 @@ var init_simpleTelemetry = __esm({
158368
160333
  }
158369
160334
  async flush() {
158370
160335
  if (this.stream) {
158371
- return new Promise((resolve2) => {
158372
- this.stream.once("drain", resolve2);
160336
+ return new Promise((resolve4) => {
160337
+ this.stream.once("drain", resolve4);
158373
160338
  if (!this.stream.writableNeedDrain) {
158374
- resolve2();
160339
+ resolve4();
158375
160340
  }
158376
160341
  });
158377
160342
  }
158378
160343
  }
158379
160344
  async shutdown() {
158380
160345
  if (this.stream) {
158381
- return new Promise((resolve2) => {
160346
+ return new Promise((resolve4) => {
158382
160347
  this.stream.end(() => {
158383
160348
  console.log(`[SimpleTelemetry] File stream closed: ${this.filePath}`);
158384
- resolve2();
160349
+ resolve4();
158385
160350
  });
158386
160351
  });
158387
160352
  }
@@ -158508,6 +160473,9 @@ __export(index_exports, {
158508
160473
  SimpleTelemetry: () => SimpleTelemetry,
158509
160474
  attemptCompletionSchema: () => attemptCompletionSchema,
158510
160475
  attemptCompletionToolDefinition: () => attemptCompletionToolDefinition,
160476
+ bashSchema: () => bashSchema,
160477
+ bashTool: () => bashTool,
160478
+ bashToolDefinition: () => bashToolDefinition,
158511
160479
  delegate: () => delegate,
158512
160480
  delegateSchema: () => delegateSchema,
158513
160481
  delegateTool: () => delegateTool,
@@ -158544,6 +160512,7 @@ var init_index = __esm({
158544
160512
  init_system_message();
158545
160513
  init_common();
158546
160514
  init_vercel();
160515
+ init_bash();
158547
160516
  init_ProbeAgent();
158548
160517
  init_simpleTelemetry();
158549
160518
  }