@probelabs/visor 0.1.48 → 0.1.50

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.48';
2
+ process.env.VISOR_VERSION = '0.1.50';
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,6 +95601,10 @@ 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
95609
  const { Liquid } = await Promise.resolve().then(() => __importStar(__nccwpck_require__(48694)));
95588
95610
  const fs = await Promise.resolve().then(() => __importStar(__nccwpck_require__(91943)));
@@ -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,19 +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 forEach parent's output with the current item
95847
95871
  const modifiedResult = {
95848
- ...depResult,
95872
+ issues: [],
95849
95873
  output: item,
95850
95874
  };
95851
95875
  forEachDependencyResults.set(depName, modifiedResult);
95876
+ const rawResult = {
95877
+ issues: [],
95878
+ output: forEachItems,
95879
+ };
95880
+ forEachDependencyResults.set(`${depName}-raw`, rawResult);
95852
95881
  }
95853
95882
  else {
95854
95883
  forEachDependencyResults.set(depName, depResult);
@@ -95856,24 +95885,49 @@ class CheckExecutionEngine {
95856
95885
  }
95857
95886
  log(`🔄 Debug: Executing check "${checkName}" for item ${itemIndex + 1}/${forEachItems.length}`);
95858
95887
  const itemResult = await provider.execute(prInfo, providerConfig, forEachDependencyResults, sessionInfo);
95859
- // 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;
95860
95900
  if (itemResult.issues) {
95861
95901
  allIssues.push(...itemResult.issues);
95862
95902
  }
95863
- // Collect outputs from each iteration
95864
- if (itemResult.output) {
95865
- 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());
95866
95910
  }
95867
95911
  }
95912
+ const finalOutput = allOutputs.length > 0 ? allOutputs : undefined;
95868
95913
  finalResult = {
95869
95914
  issues: allIssues,
95870
- output: allOutputs.length > 0 ? allOutputs : undefined,
95915
+ ...(finalOutput !== undefined ? { output: finalOutput } : {}),
95871
95916
  };
95917
+ if (aggregatedContents.length > 0) {
95918
+ finalResult.content =
95919
+ aggregatedContents.join('\n');
95920
+ }
95872
95921
  log(`🔄 Debug: Completed forEach execution for check "${checkName}", total issues: ${allIssues.length}`);
95873
95922
  }
95874
95923
  else {
95875
95924
  // Normal single execution
95876
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
+ }
95877
95931
  log(`🔧 Debug: Completed check: ${checkName}, issues found: ${(finalResult.issues || []).length}`);
95878
95932
  }
95879
95933
  // Add group, schema, template info and timestamp to issues from config
@@ -95915,28 +95969,39 @@ class CheckExecutionEngine {
95915
95969
  if (result.status === 'fulfilled' && result.value.result && !result.value.error) {
95916
95970
  const reviewResult = result.value.result;
95917
95971
  // Handle forEach logic - process array outputs
95918
- if (checkConfig?.forEach && reviewResult.output) {
95919
- let outputArray = reviewResult.output;
95920
- // Ensure output is an array
95921
- if (!Array.isArray(outputArray)) {
95922
- // Try to parse as JSON if it's a string
95923
- if (typeof outputArray === 'string') {
95924
- try {
95925
- const parsed = JSON.parse(outputArray);
95926
- outputArray = Array.isArray(parsed) ? parsed : [parsed];
95927
- }
95928
- catch {
95929
- outputArray = [outputArray];
95930
- }
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];
95931
95988
  }
95932
- else {
95933
- outputArray = [outputArray];
95989
+ catch {
95990
+ normalizedOutput = [rawOutput];
95934
95991
  }
95935
95992
  }
95936
- 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
+ }
95937
96002
  // Store the array for iteration by dependent checks
95938
- reviewResult.forEachItems = outputArray;
95939
- reviewResult.isForEach = true;
96003
+ reviewSummaryWithOutput.forEachItems = normalizedOutput;
96004
+ reviewSummaryWithOutput.isForEach = true;
95940
96005
  }
95941
96006
  results.set(checkName, reviewResult);
95942
96007
  }
@@ -96179,6 +96244,7 @@ class CheckExecutionEngine {
96179
96244
  aggregateDependencyAwareResults(results, dependencyGraph, debug, stoppedEarly) {
96180
96245
  const aggregatedIssues = [];
96181
96246
  const debugInfo = [];
96247
+ const contentMap = {};
96182
96248
  // Add execution plan info
96183
96249
  const stats = dependency_resolver_1.DependencyResolver.getExecutionStats(dependencyGraph);
96184
96250
  const executionInfo = [
@@ -96211,9 +96277,16 @@ class CheckExecutionEngine {
96211
96277
  }
96212
96278
  // Issues are already prefixed and enriched with group/schema info
96213
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
+ }
96214
96285
  }
96215
96286
  }
96216
- 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
+ }
96217
96290
  // Apply issue suppression filtering
96218
96291
  const suppressionEnabled = this.config?.output?.suppressionEnabled !== false;
96219
96292
  const issueFilter = new issue_filter_1.IssueFilter(suppressionEnabled);
@@ -96255,10 +96328,14 @@ class CheckExecutionEngine {
96255
96328
  };
96256
96329
  }
96257
96330
  }
96258
- return {
96331
+ const summary = {
96259
96332
  issues: filteredIssues,
96260
96333
  debug: aggregatedDebug,
96261
96334
  };
96335
+ if (Object.keys(contentMap).length > 0) {
96336
+ summary.__contents = contentMap;
96337
+ }
96338
+ return summary;
96262
96339
  }
96263
96340
  /**
96264
96341
  * Aggregate results from parallel check execution (legacy method)
@@ -96328,7 +96405,9 @@ class CheckExecutionEngine {
96328
96405
  });
96329
96406
  }
96330
96407
  });
96331
- 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
+ }
96332
96411
  // Apply issue suppression filtering
96333
96412
  const suppressionEnabled = this.config?.output?.suppressionEnabled !== false;
96334
96413
  const issueFilter = new issue_filter_1.IssueFilter(suppressionEnabled);
@@ -96548,14 +96627,36 @@ class CheckExecutionEngine {
96548
96627
  /**
96549
96628
  * Check if a task result should trigger fail-fast behavior
96550
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
+ }
96551
96649
  shouldFailFast(result) {
96552
- // If the result has an error property, it's a failed check
96553
- if (result?.error) {
96650
+ if (!this.isFailFastCandidate(result)) {
96651
+ return false;
96652
+ }
96653
+ if (result.error) {
96554
96654
  return true;
96555
96655
  }
96556
96656
  // If the result has a result with critical or error issues, it should fail fast
96557
- if (result?.result?.issues) {
96558
- 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');
96559
96660
  }
96560
96661
  return false;
96561
96662
  }
@@ -96941,6 +97042,9 @@ async function main() {
96941
97042
  const filteredArgv = process.argv.filter(arg => arg !== '--cli');
96942
97043
  // Parse arguments using the CLI class
96943
97044
  const options = cli.parseArgs(filteredArgv);
97045
+ const explicitChecks = options.checks.length > 0
97046
+ ? new Set(options.checks.map(check => check.toString()))
97047
+ : null;
96944
97048
  // Set environment variables early for proper logging in all modules
96945
97049
  process.env.VISOR_OUTPUT_FORMAT = options.output;
96946
97050
  process.env.VISOR_DEBUG = options.debug ? 'true' : 'false';
@@ -96994,7 +97098,7 @@ async function main() {
96994
97098
  .catch(() => configManager.getDefaultConfig());
96995
97099
  }
96996
97100
  // Determine checks to run and validate check types early
96997
- 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 || {});
96998
97102
  // Validate that all requested checks exist in the configuration
96999
97103
  const availableChecks = Object.keys(config.checks || {});
97000
97104
  const invalidChecks = checksToRun.filter(check => !availableChecks.includes(check));
@@ -97002,8 +97106,28 @@ async function main() {
97002
97106
  console.error(`❌ Error: No configuration found for check: ${invalidChecks[0]}`);
97003
97107
  process.exit(1);
97004
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);
97005
97128
  // Use stderr for status messages when outputting formatted results to stdout
97006
- const logFn = console.error;
97129
+ // Suppress all status messages when outputting JSON to avoid breaking parsers
97130
+ const logFn = options.output === 'json' ? () => { } : console.error;
97007
97131
  // Determine if we should include code context (diffs)
97008
97132
  // In CLI mode (local), we do smart detection. PR mode always includes context.
97009
97133
  const isPRContext = false; // This is CLI mode, not GitHub Action
@@ -97049,14 +97173,14 @@ async function main() {
97049
97173
  console.error('❌ Error: Not a git repository. Run "git init" to initialize a repository.');
97050
97174
  process.exit(1);
97051
97175
  }
97176
+ logFn('🔍 Visor - AI-powered code review tool');
97177
+ logFn(`Configuration version: ${config.version}`);
97178
+ logFn(`Configuration source: ${options.configPath || 'default search locations'}`);
97052
97179
  // Check if there are any changes to analyze (only when code context is needed)
97053
97180
  if (includeCodeContext && repositoryInfo.files.length === 0) {
97054
97181
  console.error('❌ Error: No changes to analyze. Make some file changes first.');
97055
97182
  process.exit(1);
97056
97183
  }
97057
- logFn('🔍 Visor - AI-powered code review tool');
97058
- logFn(`Configuration version: ${config.version}`);
97059
- logFn(`Configuration source: ${options.configPath || 'default search locations'}`);
97060
97184
  // Show registered providers if in debug mode
97061
97185
  if (options.debug) {
97062
97186
  const { CheckProviderRegistry } = await Promise.resolve().then(() => __importStar(__nccwpck_require__(57140)));
@@ -97079,26 +97203,52 @@ async function main() {
97079
97203
  // Convert repository info to PRInfo format
97080
97204
  const prInfo = analyzer.toPRInfo(repositoryInfo, includeCodeContext);
97081
97205
  // Store the includeCodeContext flag in prInfo for downstream use
97082
- prInfo.includeCodeContext = includeCodeContext;
97206
+ const prInfoWithContext = prInfo;
97207
+ prInfoWithContext.includeCodeContext = includeCodeContext;
97083
97208
  // Execute checks with proper parameters
97084
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))));
97085
97235
  // Format output based on format type
97086
97236
  let output;
97087
97237
  if (options.output === 'json') {
97088
- output = JSON.stringify(groupedResults, null, 2);
97238
+ output = JSON.stringify(groupedResultsToUse, null, 2);
97089
97239
  }
97090
97240
  else if (options.output === 'sarif') {
97091
97241
  // Build analysis result and format as SARIF
97092
97242
  const analysisResult = {
97093
97243
  repositoryInfo,
97094
97244
  reviewSummary: {
97095
- issues: Object.values(groupedResults)
97245
+ issues: Object.values(groupedResultsToUse)
97096
97246
  .flatMap((r) => r.map((check) => check.issues || []).flat())
97097
97247
  .flat(),
97098
97248
  },
97099
97249
  executionTime: 0,
97100
97250
  timestamp: new Date().toISOString(),
97101
- checksExecuted: checksToRun,
97251
+ checksExecuted: executedCheckNames,
97102
97252
  };
97103
97253
  output = output_formatters_1.OutputFormatters.formatAsSarif(analysisResult);
97104
97254
  }
@@ -97107,13 +97257,13 @@ async function main() {
97107
97257
  const analysisResult = {
97108
97258
  repositoryInfo,
97109
97259
  reviewSummary: {
97110
- issues: Object.values(groupedResults)
97260
+ issues: Object.values(groupedResultsToUse)
97111
97261
  .flatMap((r) => r.map((check) => check.issues || []).flat())
97112
97262
  .flat(),
97113
97263
  },
97114
97264
  executionTime: 0,
97115
97265
  timestamp: new Date().toISOString(),
97116
- checksExecuted: checksToRun,
97266
+ checksExecuted: executedCheckNames,
97117
97267
  };
97118
97268
  output = output_formatters_1.OutputFormatters.formatAsMarkdown(analysisResult);
97119
97269
  }
@@ -97122,19 +97272,19 @@ async function main() {
97122
97272
  const analysisResult = {
97123
97273
  repositoryInfo,
97124
97274
  reviewSummary: {
97125
- issues: Object.values(groupedResults)
97275
+ issues: Object.values(groupedResultsToUse)
97126
97276
  .flatMap((r) => r.map((check) => check.issues || []).flat())
97127
97277
  .flat(),
97128
97278
  },
97129
97279
  executionTime: 0,
97130
97280
  timestamp: new Date().toISOString(),
97131
- checksExecuted: checksToRun,
97281
+ checksExecuted: executedCheckNames,
97132
97282
  };
97133
97283
  output = output_formatters_1.OutputFormatters.formatAsTable(analysisResult, { showDetails: true });
97134
97284
  }
97135
97285
  console.log(output);
97136
97286
  // Check for critical issues
97137
- const allResults = Object.values(groupedResults).flat();
97287
+ const allResults = Object.values(groupedResultsToUse).flat();
97138
97288
  const criticalCount = allResults.reduce((sum, result) => {
97139
97289
  const issues = result.issues || [];
97140
97290
  return (sum + issues.filter((issue) => issue.severity === 'critical').length);
@@ -102245,8 +102395,10 @@ class AICheckProvider extends check_provider_interface_1.CheckProvider {
102245
102395
  }
102246
102396
  }
102247
102397
  // Validate check-level MCP servers if present
102248
- if (cfg.ai_mcp_servers) {
102249
- if (!this.validateMcpServers(cfg.ai_mcp_servers)) {
102398
+ const checkLevelMcpServers = cfg
102399
+ .ai_mcp_servers;
102400
+ if (checkLevelMcpServers) {
102401
+ if (!this.validateMcpServers(checkLevelMcpServers)) {
102250
102402
  return false;
102251
102403
  }
102252
102404
  }
@@ -102264,10 +102416,10 @@ class AICheckProvider extends check_provider_interface_1.CheckProvider {
102264
102416
  return false;
102265
102417
  }
102266
102418
  const config = serverConfig;
102267
- if (!config.command || typeof config.command !== 'string') {
102419
+ if (typeof config.command !== 'string') {
102268
102420
  return false;
102269
102421
  }
102270
- if (config.args && !Array.isArray(config.args)) {
102422
+ if (config.args !== undefined && !Array.isArray(config.args)) {
102271
102423
  return false;
102272
102424
  }
102273
102425
  }
@@ -102506,9 +102658,10 @@ class AICheckProvider extends check_provider_interface_1.CheckProvider {
102506
102658
  outputs: dependencyResults
102507
102659
  ? Object.fromEntries(Array.from(dependencyResults.entries()).map(([checkName, result]) => [
102508
102660
  checkName,
102509
- // If the result has a direct output field, use it directly
102510
- // Otherwise, expose the entire result
102511
- result.output !== undefined ? result.output : result,
102661
+ (() => {
102662
+ const summary = result;
102663
+ return summary.output !== undefined ? summary.output : summary;
102664
+ })(),
102512
102665
  ]))
102513
102666
  : {},
102514
102667
  };
@@ -102534,7 +102687,7 @@ class AICheckProvider extends check_provider_interface_1.CheckProvider {
102534
102687
  return tools;
102535
102688
  }
102536
102689
  const createSdkMcpServer = mcpModule.createSdkMcpServer || mcpModule.default?.createSdkMcpServer;
102537
- if (createSdkMcpServer) {
102690
+ if (typeof createSdkMcpServer === 'function') {
102538
102691
  for (const [serverName, serverConfig] of Object.entries(aiConfig.mcpServers)) {
102539
102692
  try {
102540
102693
  // Create MCP server instance
@@ -102545,8 +102698,8 @@ class AICheckProvider extends check_provider_interface_1.CheckProvider {
102545
102698
  env: { ...process.env, ...serverConfig.env },
102546
102699
  });
102547
102700
  // Add server tools to available tools
102548
- const serverTools = await server.listTools();
102549
- tools.push(...serverTools.map((tool) => ({
102701
+ const serverTools = (await server.listTools());
102702
+ tools.push(...serverTools.map(tool => ({
102550
102703
  name: tool.name,
102551
102704
  server: serverName,
102552
102705
  })));
@@ -102617,7 +102770,7 @@ class AICheckProvider extends check_provider_interface_1.CheckProvider {
102617
102770
  // Setup MCP tools from multiple configuration levels
102618
102771
  const mcpServers = {};
102619
102772
  // 1. Start with global MCP servers (from visor config root)
102620
- const globalConfig = config; // Cast to access potential global config
102773
+ const globalConfig = config;
102621
102774
  if (globalConfig.ai_mcp_servers) {
102622
102775
  Object.assign(mcpServers, globalConfig.ai_mcp_servers);
102623
102776
  }
@@ -102934,6 +103087,9 @@ const liquidjs_1 = __nccwpck_require__(48694);
102934
103087
  const promises_1 = __importDefault(__nccwpck_require__(91943));
102935
103088
  const path_1 = __importDefault(__nccwpck_require__(16928));
102936
103089
  const claude_code_types_1 = __nccwpck_require__(21710);
103090
+ function isClaudeCodeConstructor(value) {
103091
+ return typeof value === 'function';
103092
+ }
102937
103093
  /**
102938
103094
  * Error thrown when Claude Code SDK is not installed
102939
103095
  */
@@ -103028,8 +103184,8 @@ class ClaudeCodeCheckProvider extends check_provider_interface_1.CheckProvider {
103028
103184
  if (!claudeCodeModule) {
103029
103185
  throw new ClaudeCodeSDKNotInstalledError();
103030
103186
  }
103031
- const ClaudeCode = claudeCodeModule.ClaudeCode || claudeCodeModule.default?.ClaudeCode;
103032
- if (!ClaudeCode) {
103187
+ const ClaudeCodeCtor = claudeCodeModule.ClaudeCode || claudeCodeModule.default?.ClaudeCode;
103188
+ if (!isClaudeCodeConstructor(ClaudeCodeCtor)) {
103033
103189
  throw new Error('ClaudeCode class not found in @anthropic/claude-code-sdk');
103034
103190
  }
103035
103191
  // Initialize with API key from environment
@@ -103038,7 +103194,7 @@ class ClaudeCodeCheckProvider extends check_provider_interface_1.CheckProvider {
103038
103194
  throw new ClaudeCodeAPIKeyMissingError();
103039
103195
  }
103040
103196
  try {
103041
- const client = new ClaudeCode({
103197
+ const client = new ClaudeCodeCtor({
103042
103198
  apiKey,
103043
103199
  });
103044
103200
  this.claudeCodeClient = client;
@@ -103069,7 +103225,7 @@ class ClaudeCodeCheckProvider extends check_provider_interface_1.CheckProvider {
103069
103225
  return tools;
103070
103226
  }
103071
103227
  const createSdkMcpServer = mcpModule.createSdkMcpServer || mcpModule.default?.createSdkMcpServer;
103072
- if (createSdkMcpServer) {
103228
+ if (typeof createSdkMcpServer === 'function') {
103073
103229
  for (const [serverName, serverConfig] of Object.entries(config.mcpServers)) {
103074
103230
  try {
103075
103231
  // Create MCP server instance
@@ -103080,8 +103236,8 @@ class ClaudeCodeCheckProvider extends check_provider_interface_1.CheckProvider {
103080
103236
  env: { ...process.env, ...serverConfig.env },
103081
103237
  });
103082
103238
  // Add server tools to available tools
103083
- const serverTools = await server.listTools();
103084
- tools.push(...serverTools.map((tool) => ({
103239
+ const serverTools = (await server.listTools());
103240
+ tools.push(...serverTools.map(tool => ({
103085
103241
  name: tool.name,
103086
103242
  server: serverName,
103087
103243
  })));
@@ -103305,7 +103461,10 @@ class ClaudeCodeCheckProvider extends check_provider_interface_1.CheckProvider {
103305
103461
  checkName,
103306
103462
  // If the result has a direct output field, use it directly
103307
103463
  // Otherwise, expose the entire result
103308
- result.output !== undefined ? result.output : result,
103464
+ (() => {
103465
+ const summary = result;
103466
+ return summary.output !== undefined ? summary.output : summary;
103467
+ })(),
103309
103468
  ]))
103310
103469
  : {},
103311
103470
  };
@@ -103387,7 +103546,6 @@ class ClaudeCodeCheckProvider extends check_provider_interface_1.CheckProvider {
103387
103546
  }
103388
103547
  // Parse the response
103389
103548
  const result = this.parseStructuredResponse(response.content);
103390
- // Add debug information if needed by casting to any
103391
103549
  result.debug = {
103392
103550
  prompt: processedPrompt,
103393
103551
  rawResponse: response.content,
@@ -103401,7 +103559,7 @@ class ClaudeCodeCheckProvider extends check_provider_interface_1.CheckProvider {
103401
103559
  errors: [],
103402
103560
  checksExecuted: [config.checkName || 'claude-code-check'],
103403
103561
  parallelExecution: false,
103404
- timestamp: Date.now(),
103562
+ timestamp: new Date().toISOString(),
103405
103563
  // Claude Code specific debug info
103406
103564
  sessionId: response.session_id,
103407
103565
  turnCount: response.turn_count,
@@ -103654,11 +103812,17 @@ class CommandCheckProvider extends check_provider_interface_1.CheckProvider {
103654
103812
  outputs: this.buildOutputContext(dependencyResults),
103655
103813
  env: this.getSafeEnvironmentVariables(),
103656
103814
  };
103815
+ if (process.env.DEBUG) {
103816
+ console.log('🔧 Debug: Template outputs keys:', Object.keys(templateContext.outputs || {}));
103817
+ }
103657
103818
  try {
103658
103819
  // Render the command with Liquid templates if needed
103659
103820
  let renderedCommand = command;
103660
103821
  if (command.includes('{{') || command.includes('{%')) {
103661
- renderedCommand = await this.liquid.parseAndRender(command, templateContext);
103822
+ renderedCommand = await this.renderCommandTemplate(command, templateContext);
103823
+ }
103824
+ if (process.env.DEBUG) {
103825
+ console.log('🔧 Debug: Rendered command:', renderedCommand);
103662
103826
  }
103663
103827
  // Prepare environment variables - convert all to strings
103664
103828
  const scriptEnv = {};
@@ -103689,16 +103853,18 @@ class CommandCheckProvider extends check_provider_interface_1.CheckProvider {
103689
103853
  if (stderr && process.env.DEBUG) {
103690
103854
  console.error(`Command stderr: ${stderr}`);
103691
103855
  }
103692
- // Try to parse output as JSON
103693
- let output = stdout.trim();
103856
+ // Keep raw output for transforms
103857
+ const rawOutput = stdout.trim();
103858
+ // Try to parse output as JSON for default behavior
103859
+ let output = rawOutput;
103694
103860
  try {
103695
103861
  // Attempt to parse as JSON
103696
- const parsed = JSON.parse(stdout.trim());
103862
+ const parsed = JSON.parse(rawOutput);
103697
103863
  output = parsed;
103698
103864
  }
103699
103865
  catch {
103700
103866
  // If not JSON, keep as string
103701
- output = stdout.trim();
103867
+ output = rawOutput;
103702
103868
  }
103703
103869
  // Apply transform if specified (Liquid or JavaScript)
103704
103870
  let finalOutput = output;
@@ -103707,7 +103873,7 @@ class CommandCheckProvider extends check_provider_interface_1.CheckProvider {
103707
103873
  try {
103708
103874
  const transformContext = {
103709
103875
  ...templateContext,
103710
- output,
103876
+ output: output, // Use parsed output for Liquid (object if JSON, string otherwise)
103711
103877
  };
103712
103878
  const rendered = await this.liquid.parseAndRender(transform, transformContext);
103713
103879
  // Try to parse the transformed result as JSON
@@ -103736,21 +103902,55 @@ class CommandCheckProvider extends check_provider_interface_1.CheckProvider {
103736
103902
  // Then apply JavaScript transform if present
103737
103903
  if (transformJs) {
103738
103904
  try {
103905
+ // For transform_js, always use raw string output so JSON.parse() works as expected
103739
103906
  const jsContext = {
103740
- output: finalOutput,
103907
+ output: rawOutput, // Always use raw string for JavaScript transform
103741
103908
  pr: templateContext.pr,
103742
103909
  files: templateContext.files,
103743
103910
  outputs: templateContext.outputs,
103744
103911
  env: templateContext.env,
103745
- // Helper functions
103746
- JSON: JSON,
103747
103912
  };
103748
103913
  // Compile and execute the JavaScript expression
103749
- const exec = this.sandbox.compile(`
103750
- const { output, pr, files, outputs, env, JSON } = scope;
103751
- return (${transformJs.trim()});
103752
- `);
103914
+ // Use direct property access instead of destructuring to avoid syntax issues
103915
+ const trimmedTransform = transformJs.trim();
103916
+ let transformExpression;
103917
+ if (/return\s+/.test(trimmedTransform)) {
103918
+ transformExpression = `(() => {\n${trimmedTransform}\n})()`;
103919
+ }
103920
+ else {
103921
+ const lines = trimmedTransform.split('\n');
103922
+ if (lines.length > 1) {
103923
+ const lastLine = lines[lines.length - 1].trim();
103924
+ const remaining = lines.slice(0, -1).join('\n');
103925
+ if (lastLine && !lastLine.includes('}') && !lastLine.includes('{')) {
103926
+ const returnTarget = lastLine.replace(/;$/, '');
103927
+ transformExpression = `(() => {\n${remaining}\nreturn ${returnTarget};\n})()`;
103928
+ }
103929
+ else {
103930
+ transformExpression = `(${trimmedTransform})`;
103931
+ }
103932
+ }
103933
+ else {
103934
+ transformExpression = `(${trimmedTransform})`;
103935
+ }
103936
+ }
103937
+ const code = `
103938
+ const output = scope.output;
103939
+ const pr = scope.pr;
103940
+ const files = scope.files;
103941
+ const outputs = scope.outputs;
103942
+ const env = scope.env;
103943
+ return ${transformExpression};
103944
+ `;
103945
+ if (process.env.DEBUG) {
103946
+ console.log('🔧 Debug: JavaScript transform code:', code);
103947
+ console.log('🔧 Debug: JavaScript context:', jsContext);
103948
+ }
103949
+ const exec = this.sandbox.compile(code);
103753
103950
  finalOutput = exec({ scope: jsContext }).run();
103951
+ if (process.env.DEBUG) {
103952
+ console.log('🔧 Debug: transform_js result:', JSON.stringify(finalOutput).slice(0, 200));
103953
+ }
103754
103954
  }
103755
103955
  catch (error) {
103756
103956
  return {
@@ -103767,12 +103967,57 @@ class CommandCheckProvider extends check_provider_interface_1.CheckProvider {
103767
103967
  };
103768
103968
  }
103769
103969
  }
103770
- // Return the output as part of the review summary
103771
- // The output will be available to dependent checks
103772
- return {
103773
- issues: [],
103774
- output: finalOutput,
103970
+ // Extract structured issues when the command returns them (skip for forEach parents)
103971
+ let issues = [];
103972
+ let outputForDependents = finalOutput;
103973
+ let content;
103974
+ let extracted = null;
103975
+ const trimmedRawOutput = typeof rawOutput === 'string' ? rawOutput.trim() : undefined;
103976
+ const commandConfig = config;
103977
+ const isForEachParent = commandConfig.forEach === true;
103978
+ if (!isForEachParent) {
103979
+ extracted = this.extractIssuesFromOutput(finalOutput);
103980
+ if (!extracted && typeof finalOutput === 'string') {
103981
+ // Attempt to parse string output as JSON and extract issues again
103982
+ try {
103983
+ const parsed = JSON.parse(finalOutput);
103984
+ extracted = this.extractIssuesFromOutput(parsed);
103985
+ if (extracted) {
103986
+ issues = extracted.issues;
103987
+ outputForDependents = extracted.remainingOutput;
103988
+ }
103989
+ }
103990
+ catch {
103991
+ // Ignore JSON parse errors – leave output as-is
103992
+ }
103993
+ }
103994
+ else if (extracted) {
103995
+ issues = extracted.issues;
103996
+ outputForDependents = extracted.remainingOutput;
103997
+ }
103998
+ if (!issues.length && this.shouldTreatAsTextOutput(trimmedRawOutput)) {
103999
+ content = trimmedRawOutput;
104000
+ }
104001
+ else if (issues.length && typeof extracted?.remainingOutput === 'string') {
104002
+ const trimmed = extracted.remainingOutput.trim();
104003
+ if (trimmed) {
104004
+ content = trimmed;
104005
+ }
104006
+ }
104007
+ }
104008
+ if (!content && this.shouldTreatAsTextOutput(trimmedRawOutput) && !isForEachParent) {
104009
+ content = trimmedRawOutput;
104010
+ }
104011
+ // Return the output and issues as part of the review summary so dependent checks can use them
104012
+ const result = {
104013
+ issues,
104014
+ output: outputForDependents,
104015
+ ...(content ? { content } : {}),
103775
104016
  };
104017
+ if (process.env.DEBUG && transformJs) {
104018
+ console.log(`🔧 Debug: Command provider returning output:`, JSON.stringify(result.output).slice(0, 200));
104019
+ }
104020
+ return result;
103776
104021
  }
103777
104022
  catch (error) {
103778
104023
  const errorMessage = error instanceof Error ? error.message : 'Unknown error';
@@ -103798,7 +104043,8 @@ class CommandCheckProvider extends check_provider_interface_1.CheckProvider {
103798
104043
  for (const [checkName, result] of dependencyResults) {
103799
104044
  // If the result has a direct output field, use it directly
103800
104045
  // Otherwise, expose the entire result as-is
103801
- outputs[checkName] = result.output !== undefined ? result.output : result;
104046
+ const summary = result;
104047
+ outputs[checkName] = summary.output !== undefined ? summary.output : summary;
103802
104048
  }
103803
104049
  return outputs;
103804
104050
  }
@@ -103840,6 +104086,190 @@ class CommandCheckProvider extends check_provider_interface_1.CheckProvider {
103840
104086
  'Optional: Transform template for processing output',
103841
104087
  ];
103842
104088
  }
104089
+ extractIssuesFromOutput(output) {
104090
+ if (output === null || output === undefined) {
104091
+ return null;
104092
+ }
104093
+ // If output is already a string, do not treat it as issues here (caller may try parsing JSON)
104094
+ if (typeof output === 'string') {
104095
+ return null;
104096
+ }
104097
+ if (Array.isArray(output)) {
104098
+ const issues = this.normalizeIssueArray(output);
104099
+ if (issues) {
104100
+ return { issues, remainingOutput: undefined };
104101
+ }
104102
+ return null;
104103
+ }
104104
+ if (typeof output === 'object') {
104105
+ const record = output;
104106
+ if (Array.isArray(record.issues)) {
104107
+ const issues = this.normalizeIssueArray(record.issues);
104108
+ if (!issues) {
104109
+ return null;
104110
+ }
104111
+ const remaining = { ...record };
104112
+ delete remaining.issues;
104113
+ const remainingKeys = Object.keys(remaining);
104114
+ const remainingOutput = remainingKeys.length > 0 ? remaining : undefined;
104115
+ return {
104116
+ issues,
104117
+ remainingOutput,
104118
+ };
104119
+ }
104120
+ const singleIssue = this.normalizeIssue(record);
104121
+ if (singleIssue) {
104122
+ return { issues: [singleIssue], remainingOutput: undefined };
104123
+ }
104124
+ }
104125
+ return null;
104126
+ }
104127
+ shouldTreatAsTextOutput(value) {
104128
+ if (!value) {
104129
+ return false;
104130
+ }
104131
+ const trimmed = value.trim();
104132
+ if (!trimmed) {
104133
+ return false;
104134
+ }
104135
+ // Heuristic: consider it JSON-like if it starts with { or [ and ends with } or ]
104136
+ const startsJson = (trimmed.startsWith('{') && trimmed.endsWith('}')) ||
104137
+ (trimmed.startsWith('[') && trimmed.endsWith(']'));
104138
+ return !startsJson;
104139
+ }
104140
+ normalizeIssueArray(values) {
104141
+ const normalized = [];
104142
+ for (const value of values) {
104143
+ const issue = this.normalizeIssue(value);
104144
+ if (!issue) {
104145
+ return null;
104146
+ }
104147
+ normalized.push(issue);
104148
+ }
104149
+ return normalized;
104150
+ }
104151
+ normalizeIssue(raw) {
104152
+ if (!raw || typeof raw !== 'object') {
104153
+ return null;
104154
+ }
104155
+ const data = raw;
104156
+ const message = this.toTrimmedString(data.message || data.text || data.description || data.summary);
104157
+ if (!message) {
104158
+ return null;
104159
+ }
104160
+ const allowedSeverities = new Set(['info', 'warning', 'error', 'critical']);
104161
+ const severityRaw = this.toTrimmedString(data.severity || data.level || data.priority);
104162
+ let severity = 'warning';
104163
+ if (severityRaw) {
104164
+ const lower = severityRaw.toLowerCase();
104165
+ if (allowedSeverities.has(lower)) {
104166
+ severity = lower;
104167
+ }
104168
+ else if (['fatal', 'high'].includes(lower)) {
104169
+ severity = 'error';
104170
+ }
104171
+ else if (['medium', 'moderate'].includes(lower)) {
104172
+ severity = 'warning';
104173
+ }
104174
+ else if (['low', 'minor'].includes(lower)) {
104175
+ severity = 'info';
104176
+ }
104177
+ }
104178
+ const allowedCategories = new Set([
104179
+ 'security',
104180
+ 'performance',
104181
+ 'style',
104182
+ 'logic',
104183
+ 'documentation',
104184
+ ]);
104185
+ const categoryRaw = this.toTrimmedString(data.category || data.type || data.group);
104186
+ let category = 'logic';
104187
+ if (categoryRaw && allowedCategories.has(categoryRaw.toLowerCase())) {
104188
+ category = categoryRaw.toLowerCase();
104189
+ }
104190
+ const file = this.toTrimmedString(data.file || data.path || data.filename) || 'system';
104191
+ const line = this.toNumber(data.line || data.startLine || data.lineNumber) ?? 0;
104192
+ const endLine = this.toNumber(data.endLine || data.end_line || data.stopLine);
104193
+ const suggestion = this.toTrimmedString(data.suggestion);
104194
+ const replacement = this.toTrimmedString(data.replacement);
104195
+ const ruleId = this.toTrimmedString(data.ruleId || data.rule || data.id || data.check) || 'command';
104196
+ return {
104197
+ file,
104198
+ line,
104199
+ endLine: endLine ?? undefined,
104200
+ ruleId,
104201
+ message,
104202
+ severity,
104203
+ category,
104204
+ suggestion: suggestion || undefined,
104205
+ replacement: replacement || undefined,
104206
+ };
104207
+ }
104208
+ toTrimmedString(value) {
104209
+ if (typeof value === 'string') {
104210
+ const trimmed = value.trim();
104211
+ return trimmed.length > 0 ? trimmed : null;
104212
+ }
104213
+ if (value !== null && value !== undefined && typeof value.toString === 'function') {
104214
+ const converted = String(value).trim();
104215
+ return converted.length > 0 ? converted : null;
104216
+ }
104217
+ return null;
104218
+ }
104219
+ toNumber(value) {
104220
+ if (value === null || value === undefined) {
104221
+ return null;
104222
+ }
104223
+ const num = Number(value);
104224
+ if (Number.isFinite(num)) {
104225
+ return Math.trunc(num);
104226
+ }
104227
+ return null;
104228
+ }
104229
+ async renderCommandTemplate(template, context) {
104230
+ try {
104231
+ return await this.liquid.parseAndRender(template, context);
104232
+ }
104233
+ catch (error) {
104234
+ if (process.env.DEBUG) {
104235
+ console.warn('🔧 Debug: Liquid rendering failed, falling back to JS evaluation:', error);
104236
+ }
104237
+ return this.renderWithJsExpressions(template, context);
104238
+ }
104239
+ }
104240
+ renderWithJsExpressions(template, context) {
104241
+ const scope = {
104242
+ pr: context.pr,
104243
+ files: context.files,
104244
+ outputs: context.outputs,
104245
+ env: context.env,
104246
+ };
104247
+ const expressionRegex = /\{\{\s*([^{}]+?)\s*\}\}/g;
104248
+ return template.replace(expressionRegex, (_match, expr) => {
104249
+ const expression = String(expr).trim();
104250
+ if (!expression) {
104251
+ return '';
104252
+ }
104253
+ try {
104254
+ const evalCode = `
104255
+ const pr = scope.pr;
104256
+ const files = scope.files;
104257
+ const outputs = scope.outputs;
104258
+ const env = scope.env;
104259
+ return (${expression});
104260
+ `;
104261
+ const evaluator = this.sandbox.compile(evalCode);
104262
+ const result = evaluator({ scope }).run();
104263
+ return result === undefined || result === null ? '' : String(result);
104264
+ }
104265
+ catch (evaluationError) {
104266
+ if (process.env.DEBUG) {
104267
+ console.warn('🔧 Debug: Failed to evaluate expression:', expression, evaluationError);
104268
+ }
104269
+ return '';
104270
+ }
104271
+ });
104272
+ }
103843
104273
  }
103844
104274
  exports.CommandCheckProvider = CommandCheckProvider;
103845
104275
 
@@ -104535,6 +104965,7 @@ class LogCheckProvider extends check_provider_interface_1.CheckProvider {
104535
104965
  }
104536
104966
  if (includeDependencies && dependencyResults) {
104537
104967
  const dependencies = {};
104968
+ const outputs = {};
104538
104969
  context.dependencyCount = dependencyResults.size;
104539
104970
  for (const [checkName, result] of dependencyResults.entries()) {
104540
104971
  dependencies[checkName] = {
@@ -104542,8 +104973,12 @@ class LogCheckProvider extends check_provider_interface_1.CheckProvider {
104542
104973
  suggestionCount: 0,
104543
104974
  issues: result.issues || [],
104544
104975
  };
104976
+ // Add outputs namespace for accessing dependency results directly
104977
+ const summary = result;
104978
+ outputs[checkName] = summary.output !== undefined ? summary.output : summary;
104545
104979
  }
104546
104980
  context.dependencies = dependencies;
104981
+ context.outputs = outputs;
104547
104982
  }
104548
104983
  if (includeMetadata) {
104549
104984
  context.metadata = {
@@ -105246,16 +105681,16 @@ class ConfigLoader {
105246
105681
  const outputFormat = process.env.VISOR_OUTPUT_FORMAT;
105247
105682
  const logFn = outputFormat === 'json' || outputFormat === 'sarif' ? console.error : console.log;
105248
105683
  logFn(`⬇️ Fetching remote configuration from: ${url}`);
105684
+ const controller = new AbortController();
105685
+ const timeoutMs = this.options.timeout ?? 30000;
105686
+ const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
105249
105687
  try {
105250
- const controller = new AbortController();
105251
- const timeoutId = setTimeout(() => controller.abort(), this.options.timeout || 30000);
105252
105688
  const response = await fetch(url, {
105253
105689
  signal: controller.signal,
105254
105690
  headers: {
105255
105691
  'User-Agent': 'Visor/1.0',
105256
105692
  },
105257
105693
  });
105258
- clearTimeout(timeoutId);
105259
105694
  if (!response.ok) {
105260
105695
  throw new Error(`Failed to fetch config: ${response.status} ${response.statusText}`);
105261
105696
  }
@@ -105279,12 +105714,15 @@ class ConfigLoader {
105279
105714
  catch (error) {
105280
105715
  if (error instanceof Error) {
105281
105716
  if (error.name === 'AbortError') {
105282
- throw new Error(`Timeout fetching configuration from ${url} (${this.options.timeout}ms)`);
105717
+ throw new Error(`Timeout fetching configuration from ${url} (${timeoutMs}ms)`);
105283
105718
  }
105284
105719
  throw new Error(`Failed to fetch remote configuration from ${url}: ${error.message}`);
105285
105720
  }
105286
105721
  throw error;
105287
105722
  }
105723
+ finally {
105724
+ clearTimeout(timeoutId);
105725
+ }
105288
105726
  }
105289
105727
  /**
105290
105728
  * Load bundled default configuration
@@ -125873,7 +126311,7 @@ function createMessagePreview(message, charsPerSide = 200) {
125873
126311
  const end = message.substring(message.length - charsPerSide);
125874
126312
  return `${start}...${end}`;
125875
126313
  }
125876
- var import_zod, searchSchema, querySchema, extractSchema, delegateSchema, attemptCompletionSchema, searchToolDefinition, queryToolDefinition, extractToolDefinition, delegateToolDefinition, attemptCompletionToolDefinition, searchDescription, queryDescription, extractDescription, delegateDescription, DEFAULT_VALID_TOOLS;
126314
+ var import_zod, searchSchema, querySchema, extractSchema, delegateSchema, bashSchema, attemptCompletionSchema, searchToolDefinition, queryToolDefinition, extractToolDefinition, delegateToolDefinition, attemptCompletionToolDefinition, bashToolDefinition, searchDescription, queryDescription, extractDescription, delegateDescription, bashDescription, DEFAULT_VALID_TOOLS;
125877
126315
  var init_common = __esm({
125878
126316
  "src/tools/common.js"() {
125879
126317
  "use strict";
@@ -125905,6 +126343,12 @@ var init_common = __esm({
125905
126343
  delegateSchema = import_zod.z.object({
125906
126344
  task: import_zod.z.string().describe("The task to delegate to a subagent. Be specific about what needs to be accomplished.")
125907
126345
  });
126346
+ bashSchema = import_zod.z.object({
126347
+ command: import_zod.z.string().describe("The bash command to execute"),
126348
+ workingDirectory: import_zod.z.string().optional().describe("Directory to execute the command in (optional)"),
126349
+ timeout: import_zod.z.number().optional().describe("Command timeout in milliseconds (optional)"),
126350
+ env: import_zod.z.record(import_zod.z.string()).optional().describe("Additional environment variables (optional)")
126351
+ });
125908
126352
  attemptCompletionSchema = {
125909
126353
  // Custom validation that requires result parameter but allows direct XML response
125910
126354
  safeParse: (params) => {
@@ -126127,11 +126571,67 @@ Usage Example:
126127
126571
  <attempt_completion>
126128
126572
  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.
126129
126573
  </attempt_completion>
126574
+ `;
126575
+ bashToolDefinition = `
126576
+ ## bash
126577
+ 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.
126578
+
126579
+ Parameters:
126580
+ - command: (required) The bash command to execute
126581
+ - workingDirectory: (optional) Directory to execute the command in
126582
+ - timeout: (optional) Command timeout in milliseconds
126583
+ - env: (optional) Additional environment variables as an object
126584
+
126585
+ Security: Commands are filtered through allow/deny lists for safety:
126586
+ - Allowed by default: ls, cat, git status, npm list, find, grep, etc.
126587
+ - Denied by default: rm -rf, sudo, npm install, dangerous system commands
126588
+
126589
+ Usage Examples:
126590
+
126591
+ <examples>
126592
+
126593
+ User: What files are in the src directory?
126594
+ <bash>
126595
+ <command>ls -la src/</command>
126596
+ </bash>
126597
+
126598
+ User: Show me the git status
126599
+ <bash>
126600
+ <command>git status</command>
126601
+ </bash>
126602
+
126603
+ User: Find all TypeScript files
126604
+ <bash>
126605
+ <command>find . -name "*.ts" -type f</command>
126606
+ </bash>
126607
+
126608
+ User: Check installed npm packages
126609
+ <bash>
126610
+ <command>npm list --depth=0</command>
126611
+ </bash>
126612
+
126613
+ User: Search for TODO comments in code
126614
+ <bash>
126615
+ <command>grep -r "TODO" src/</command>
126616
+ </bash>
126617
+
126618
+ User: Show recent git commits
126619
+ <bash>
126620
+ <command>git log --oneline -10</command>
126621
+ </bash>
126622
+
126623
+ User: Check system info
126624
+ <bash>
126625
+ <command>uname -a</command>
126626
+ </bash>
126627
+
126628
+ </examples>
126130
126629
  `;
126131
126630
  searchDescription = "Search code in the repository using Elasticsearch-like query syntax. Use this tool first for any code-related questions.";
126132
126631
  queryDescription = "Search code using ast-grep structural pattern matching. Use this tool to find specific code structures like functions, classes, or methods.";
126133
126632
  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.";
126134
126633
  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.";
126634
+ bashDescription = "Execute bash commands for system exploration and development tasks. Secure by default with built-in allow/deny lists.";
126135
126635
  DEFAULT_VALID_TOOLS = [
126136
126636
  "search",
126137
126637
  "query",
@@ -126185,7 +126685,7 @@ async function delegate({ task, timeout = 300, debug = false, currentIteration =
126185
126685
  console.error(`[DELEGATE] Using binary at: ${binaryPath}`);
126186
126686
  console.error(`[DELEGATE] Command args: ${args.join(" ")}`);
126187
126687
  }
126188
- return new Promise((resolve2, reject) => {
126688
+ return new Promise((resolve4, reject) => {
126189
126689
  const delegationSpan = tracer ? tracer.createDelegationSpan(sessionId, task) : null;
126190
126690
  const process2 = (0, import_child_process5.spawn)(binaryPath, args, {
126191
126691
  stdio: ["pipe", "pipe", "pipe"],
@@ -126250,7 +126750,7 @@ async function delegate({ task, timeout = 300, debug = false, currentIteration =
126250
126750
  delegationSpan.end();
126251
126751
  }
126252
126752
  }
126253
- resolve2(response);
126753
+ resolve4(response);
126254
126754
  } else {
126255
126755
  const errorMessage = stderr.trim() || `Delegate process failed with exit code ${code}`;
126256
126756
  if (debug) {
@@ -126446,10 +126946,10 @@ var init_vercel = __esm({
126446
126946
  let extractOptions = { path: extractPath };
126447
126947
  if (input_content) {
126448
126948
  const { writeFileSync: writeFileSync2, unlinkSync } = await Promise.resolve(/* import() */).then(__nccwpck_require__.t.bind(__nccwpck_require__, 79896, 23));
126449
- const { join: join2 } = await Promise.resolve(/* import() */).then(__nccwpck_require__.t.bind(__nccwpck_require__, 16928, 23));
126949
+ const { join: join3 } = await Promise.resolve(/* import() */).then(__nccwpck_require__.t.bind(__nccwpck_require__, 16928, 23));
126450
126950
  const { tmpdir } = await Promise.resolve(/* import() */).then(__nccwpck_require__.t.bind(__nccwpck_require__, 70857, 23));
126451
126951
  const { randomUUID: randomUUID5 } = await Promise.resolve(/* import() */).then(__nccwpck_require__.t.bind(__nccwpck_require__, 76982, 23));
126452
- tempFilePath = join2(tmpdir(), `probe-extract-${randomUUID5()}.txt`);
126952
+ tempFilePath = join3(tmpdir(), `probe-extract-${randomUUID5()}.txt`);
126453
126953
  writeFileSync2(tempFilePath, input_content);
126454
126954
  if (debug) {
126455
126955
  console.error(`Created temporary file for input content: ${tempFilePath}`);
@@ -126526,6 +127026,1248 @@ var init_vercel = __esm({
126526
127026
  }
126527
127027
  });
126528
127028
 
127029
+ // src/agent/bashDefaults.js
127030
+ var DEFAULT_ALLOW_PATTERNS, DEFAULT_DENY_PATTERNS;
127031
+ var init_bashDefaults = __esm({
127032
+ "src/agent/bashDefaults.js"() {
127033
+ "use strict";
127034
+ DEFAULT_ALLOW_PATTERNS = [
127035
+ // Basic navigation and listing
127036
+ "ls",
127037
+ "dir",
127038
+ "pwd",
127039
+ "cd",
127040
+ "cd:*",
127041
+ // File reading commands
127042
+ "cat",
127043
+ "cat:*",
127044
+ "head",
127045
+ "head:*",
127046
+ "tail",
127047
+ "tail:*",
127048
+ "less",
127049
+ "more",
127050
+ "view",
127051
+ // File information and metadata
127052
+ "file",
127053
+ "file:*",
127054
+ "stat",
127055
+ "stat:*",
127056
+ "wc",
127057
+ "wc:*",
127058
+ "du",
127059
+ "du:*",
127060
+ "df",
127061
+ "df:*",
127062
+ "realpath",
127063
+ "realpath:*",
127064
+ // Search and find commands (read-only) - find restricted to safe operations
127065
+ "find",
127066
+ "find:-name:*",
127067
+ "find:-type:*",
127068
+ "find:-size:*",
127069
+ "find:-mtime:*",
127070
+ "find:-newer:*",
127071
+ "find:-path:*",
127072
+ "find:-iname:*",
127073
+ "find:-maxdepth:*",
127074
+ "find:-mindepth:*",
127075
+ "find:-print",
127076
+ "grep",
127077
+ "grep:*",
127078
+ "egrep",
127079
+ "egrep:*",
127080
+ "fgrep",
127081
+ "fgrep:*",
127082
+ "rg",
127083
+ "rg:*",
127084
+ "ag",
127085
+ "ag:*",
127086
+ "ack",
127087
+ "ack:*",
127088
+ "which",
127089
+ "which:*",
127090
+ "whereis",
127091
+ "whereis:*",
127092
+ "locate",
127093
+ "locate:*",
127094
+ "type",
127095
+ "type:*",
127096
+ "command",
127097
+ "command:*",
127098
+ // Tree and structure visualization
127099
+ "tree",
127100
+ "tree:*",
127101
+ // Git read-only operations
127102
+ "git:status",
127103
+ "git:log",
127104
+ "git:log:*",
127105
+ "git:diff",
127106
+ "git:diff:*",
127107
+ "git:show",
127108
+ "git:show:*",
127109
+ "git:branch",
127110
+ "git:branch:*",
127111
+ "git:tag",
127112
+ "git:tag:*",
127113
+ "git:describe",
127114
+ "git:describe:*",
127115
+ "git:remote",
127116
+ "git:remote:*",
127117
+ "git:config:*",
127118
+ "git:blame",
127119
+ "git:blame:*",
127120
+ "git:shortlog",
127121
+ "git:reflog",
127122
+ "git:ls-files",
127123
+ "git:ls-tree",
127124
+ "git:rev-parse",
127125
+ "git:rev-list",
127126
+ "git:--version",
127127
+ "git:help",
127128
+ "git:help:*",
127129
+ // Package managers (information only)
127130
+ "npm:list",
127131
+ "npm:ls",
127132
+ "npm:view",
127133
+ "npm:info",
127134
+ "npm:show",
127135
+ "npm:outdated",
127136
+ "npm:audit",
127137
+ "npm:--version",
127138
+ "yarn:list",
127139
+ "yarn:info",
127140
+ "yarn:--version",
127141
+ "pnpm:list",
127142
+ "pnpm:--version",
127143
+ "pip:list",
127144
+ "pip:show",
127145
+ "pip:--version",
127146
+ "pip3:list",
127147
+ "pip3:show",
127148
+ "pip3:--version",
127149
+ "gem:list",
127150
+ "gem:--version",
127151
+ "bundle:list",
127152
+ "bundle:show",
127153
+ "bundle:--version",
127154
+ "composer:show",
127155
+ "composer:--version",
127156
+ // Language and runtime versions
127157
+ "node:--version",
127158
+ "node:-v",
127159
+ "python:--version",
127160
+ "python:-V",
127161
+ "python3:--version",
127162
+ "python3:-V",
127163
+ "ruby:--version",
127164
+ "ruby:-v",
127165
+ "go:version",
127166
+ "go:env",
127167
+ "go:list",
127168
+ "go:mod:graph",
127169
+ "rustc:--version",
127170
+ "cargo:--version",
127171
+ "cargo:tree",
127172
+ "cargo:metadata",
127173
+ "java:--version",
127174
+ "java:-version",
127175
+ "javac:--version",
127176
+ "mvn:--version",
127177
+ "gradle:--version",
127178
+ "php:--version",
127179
+ "dotnet:--version",
127180
+ "dotnet:list",
127181
+ // Database client versions (connection info only)
127182
+ "psql:--version",
127183
+ "mysql:--version",
127184
+ "redis-cli:--version",
127185
+ "mongo:--version",
127186
+ "sqlite3:--version",
127187
+ // System information
127188
+ "uname",
127189
+ "uname:*",
127190
+ "hostname",
127191
+ "whoami",
127192
+ "id",
127193
+ "groups",
127194
+ "date",
127195
+ "cal",
127196
+ "uptime",
127197
+ "w",
127198
+ "users",
127199
+ "sleep",
127200
+ "sleep:*",
127201
+ // Environment and shell
127202
+ "env",
127203
+ "printenv",
127204
+ "echo",
127205
+ "echo:*",
127206
+ "printf",
127207
+ "printf:*",
127208
+ "export",
127209
+ "export:*",
127210
+ "set",
127211
+ "unset",
127212
+ // Process information (read-only)
127213
+ "ps",
127214
+ "ps:*",
127215
+ "pgrep",
127216
+ "pgrep:*",
127217
+ "jobs",
127218
+ "top:-n:1",
127219
+ // Network information (read-only)
127220
+ "ifconfig",
127221
+ "ip:addr",
127222
+ "ip:link",
127223
+ "hostname:-I",
127224
+ "ping:-c:*",
127225
+ "traceroute",
127226
+ "nslookup",
127227
+ "dig",
127228
+ // Text processing and utilities (awk removed - too powerful)
127229
+ "sed:-n:*",
127230
+ "cut",
127231
+ "cut:*",
127232
+ "sort",
127233
+ "sort:*",
127234
+ "uniq",
127235
+ "uniq:*",
127236
+ "tr",
127237
+ "tr:*",
127238
+ "column",
127239
+ "column:*",
127240
+ "paste",
127241
+ "paste:*",
127242
+ "join",
127243
+ "join:*",
127244
+ "comm",
127245
+ "comm:*",
127246
+ "diff",
127247
+ "diff:*",
127248
+ "cmp",
127249
+ "cmp:*",
127250
+ "patch:--dry-run:*",
127251
+ // Hashing and encoding (read-only)
127252
+ "md5sum",
127253
+ "md5sum:*",
127254
+ "sha1sum",
127255
+ "sha1sum:*",
127256
+ "sha256sum",
127257
+ "sha256sum:*",
127258
+ "base64",
127259
+ "base64:-d",
127260
+ "od",
127261
+ "od:*",
127262
+ "hexdump",
127263
+ "hexdump:*",
127264
+ // Archive and compression (list/view only)
127265
+ "tar:-tf:*",
127266
+ "tar:-tzf:*",
127267
+ "unzip:-l:*",
127268
+ "zip:-l:*",
127269
+ "gzip:-l:*",
127270
+ "gunzip:-l:*",
127271
+ // Help and documentation
127272
+ "man",
127273
+ "man:*",
127274
+ "--help",
127275
+ "help",
127276
+ "info",
127277
+ "info:*",
127278
+ "whatis",
127279
+ "whatis:*",
127280
+ "apropos",
127281
+ "apropos:*",
127282
+ // Make (dry run and info)
127283
+ "make:-n",
127284
+ "make:--dry-run",
127285
+ "make:-p",
127286
+ "make:--print-data-base",
127287
+ // Docker (read-only operations)
127288
+ "docker:ps",
127289
+ "docker:images",
127290
+ "docker:version",
127291
+ "docker:info",
127292
+ "docker:logs:*",
127293
+ "docker:inspect:*",
127294
+ // Test runners (list/info only)
127295
+ "jest:--listTests",
127296
+ "mocha:--help",
127297
+ "pytest:--collect-only"
127298
+ ];
127299
+ DEFAULT_DENY_PATTERNS = [
127300
+ // Dangerous file operations
127301
+ "rm:-rf",
127302
+ "rm:-f:/",
127303
+ "rm:/",
127304
+ "rm:-rf:*",
127305
+ "rmdir",
127306
+ "chmod:777",
127307
+ "chmod:-R:777",
127308
+ "chown",
127309
+ "chgrp",
127310
+ "dd",
127311
+ "dd:*",
127312
+ "shred",
127313
+ "shred:*",
127314
+ // Dangerous find operations that can execute arbitrary commands
127315
+ "find:-exec:*",
127316
+ "find:*:-exec:*",
127317
+ "find:-execdir:*",
127318
+ "find:*:-execdir:*",
127319
+ "find:-ok:*",
127320
+ "find:*:-ok:*",
127321
+ "find:-okdir:*",
127322
+ "find:*:-okdir:*",
127323
+ // Powerful scripting tools that can execute arbitrary commands
127324
+ "awk",
127325
+ "awk:*",
127326
+ "perl",
127327
+ "perl:*",
127328
+ "python:-c:*",
127329
+ "node:-e:*",
127330
+ // System administration and modification
127331
+ "sudo:*",
127332
+ "su",
127333
+ "su:*",
127334
+ "passwd",
127335
+ "adduser",
127336
+ "useradd",
127337
+ "userdel",
127338
+ "usermod",
127339
+ "groupadd",
127340
+ "groupdel",
127341
+ "visudo",
127342
+ // Package installation and removal
127343
+ "npm:install",
127344
+ "npm:i",
127345
+ "npm:uninstall",
127346
+ "npm:publish",
127347
+ "npm:unpublish",
127348
+ "npm:link",
127349
+ "npm:update",
127350
+ "yarn:install",
127351
+ "yarn:add",
127352
+ "yarn:remove",
127353
+ "yarn:upgrade",
127354
+ "pnpm:install",
127355
+ "pnpm:add",
127356
+ "pnpm:remove",
127357
+ "pip:install",
127358
+ "pip:uninstall",
127359
+ "pip:upgrade",
127360
+ "pip3:install",
127361
+ "pip3:uninstall",
127362
+ "pip3:upgrade",
127363
+ "gem:install",
127364
+ "gem:uninstall",
127365
+ "gem:update",
127366
+ "bundle:install",
127367
+ "bundle:update",
127368
+ "composer:install",
127369
+ "composer:update",
127370
+ "composer:remove",
127371
+ "apt:*",
127372
+ "apt-get:*",
127373
+ "yum:*",
127374
+ "dnf:*",
127375
+ "zypper:*",
127376
+ "brew:install",
127377
+ "brew:uninstall",
127378
+ "brew:upgrade",
127379
+ "conda:install",
127380
+ "conda:remove",
127381
+ "conda:update",
127382
+ // Service and system control
127383
+ "systemctl:*",
127384
+ "service:*",
127385
+ "chkconfig:*",
127386
+ "initctl:*",
127387
+ "upstart:*",
127388
+ // Network operations that could be dangerous
127389
+ "curl:-d:*",
127390
+ "curl:--data:*",
127391
+ "curl:-X:POST:*",
127392
+ "curl:-X:PUT:*",
127393
+ "wget:-O:/",
127394
+ "wget:--post-data:*",
127395
+ "ssh",
127396
+ "ssh:*",
127397
+ "scp",
127398
+ "scp:*",
127399
+ "sftp",
127400
+ "sftp:*",
127401
+ "rsync:*",
127402
+ "nc",
127403
+ "nc:*",
127404
+ "netcat",
127405
+ "netcat:*",
127406
+ "telnet",
127407
+ "telnet:*",
127408
+ "ftp",
127409
+ "ftp:*",
127410
+ // Process control and termination
127411
+ "kill",
127412
+ "kill:*",
127413
+ "killall",
127414
+ "killall:*",
127415
+ "pkill",
127416
+ "pkill:*",
127417
+ "nohup:*",
127418
+ "disown:*",
127419
+ // System control and shutdown
127420
+ "shutdown",
127421
+ "shutdown:*",
127422
+ "reboot",
127423
+ "halt",
127424
+ "poweroff",
127425
+ "init",
127426
+ "telinit",
127427
+ // Kernel and module operations
127428
+ "insmod",
127429
+ "insmod:*",
127430
+ "rmmod",
127431
+ "rmmod:*",
127432
+ "modprobe",
127433
+ "modprobe:*",
127434
+ "sysctl:-w:*",
127435
+ // Dangerous git operations
127436
+ "git:push",
127437
+ "git:push:*",
127438
+ "git:force",
127439
+ "git:reset:--hard:*",
127440
+ "git:clean:-fd",
127441
+ "git:rm:*",
127442
+ "git:commit",
127443
+ "git:merge",
127444
+ "git:rebase",
127445
+ "git:cherry-pick",
127446
+ "git:stash:drop",
127447
+ // File system mounting and partitioning
127448
+ "mount",
127449
+ "mount:*",
127450
+ "umount",
127451
+ "umount:*",
127452
+ "fdisk",
127453
+ "fdisk:*",
127454
+ "parted",
127455
+ "parted:*",
127456
+ "mkfs",
127457
+ "mkfs:*",
127458
+ "fsck",
127459
+ "fsck:*",
127460
+ // Cron and scheduling
127461
+ "crontab",
127462
+ "crontab:*",
127463
+ "at",
127464
+ "at:*",
127465
+ "batch",
127466
+ "batch:*",
127467
+ // Compression with potential overwrite
127468
+ "tar:-xf:*",
127469
+ "unzip",
127470
+ "unzip:*",
127471
+ "gzip:*",
127472
+ "gunzip:*",
127473
+ // Build and compilation that might modify files
127474
+ "make",
127475
+ "make:install",
127476
+ "make:clean",
127477
+ "cargo:build",
127478
+ "cargo:install",
127479
+ "npm:run:build",
127480
+ "yarn:build",
127481
+ "mvn:install",
127482
+ "gradle:build",
127483
+ // Docker operations that could modify state
127484
+ "docker:run",
127485
+ "docker:run:*",
127486
+ "docker:exec",
127487
+ "docker:exec:*",
127488
+ "docker:build",
127489
+ "docker:build:*",
127490
+ "docker:pull",
127491
+ "docker:push",
127492
+ "docker:rm",
127493
+ "docker:rmi",
127494
+ "docker:stop",
127495
+ "docker:start",
127496
+ // Database operations
127497
+ "mysql:-e:DROP",
127498
+ "psql:-c:DROP",
127499
+ "redis-cli:FLUSHALL",
127500
+ "mongo:--eval:*",
127501
+ // Text editors that could modify files
127502
+ "vi",
127503
+ "vi:*",
127504
+ "vim",
127505
+ "vim:*",
127506
+ "nano",
127507
+ "nano:*",
127508
+ "emacs",
127509
+ "emacs:*",
127510
+ "sed:-i:*",
127511
+ "perl:-i:*",
127512
+ // Potentially dangerous utilities
127513
+ "eval",
127514
+ "eval:*",
127515
+ "exec",
127516
+ "exec:*",
127517
+ "source",
127518
+ "source:*",
127519
+ "bash:-c:*",
127520
+ "sh:-c:*",
127521
+ "zsh:-c:*"
127522
+ ];
127523
+ }
127524
+ });
127525
+
127526
+ // src/agent/bashCommandUtils.js
127527
+ function parseSimpleCommand(command) {
127528
+ if (!command || typeof command !== "string") {
127529
+ return {
127530
+ success: false,
127531
+ error: "Command must be a non-empty string",
127532
+ command: null,
127533
+ args: [],
127534
+ isComplex: false
127535
+ };
127536
+ }
127537
+ const trimmed = command.trim();
127538
+ if (!trimmed) {
127539
+ return {
127540
+ success: false,
127541
+ error: "Command cannot be empty",
127542
+ command: null,
127543
+ args: [],
127544
+ isComplex: false
127545
+ };
127546
+ }
127547
+ const complexPatterns = [
127548
+ /\|/,
127549
+ // Pipes
127550
+ /&&/,
127551
+ // Logical AND
127552
+ /\|\|/,
127553
+ // Logical OR
127554
+ /(?<!\\);/,
127555
+ // Command separator (but not escaped \;)
127556
+ /&$/,
127557
+ // Background execution
127558
+ /\$\(/,
127559
+ // Command substitution $()
127560
+ /`/,
127561
+ // Command substitution ``
127562
+ />/,
127563
+ // Redirection >
127564
+ /</,
127565
+ // Redirection <
127566
+ /\*\*/,
127567
+ // Glob patterns (potentially dangerous)
127568
+ /^\s*\{.*,.*\}|\{.*\.\.\.*\}/
127569
+ // Brace expansion like {a,b} or {1..10} (but not find {} placeholders)
127570
+ ];
127571
+ for (const pattern of complexPatterns) {
127572
+ if (pattern.test(trimmed)) {
127573
+ return {
127574
+ success: false,
127575
+ error: "Complex shell commands with pipes, operators, or redirections are not supported for security reasons",
127576
+ command: null,
127577
+ args: [],
127578
+ isComplex: true,
127579
+ detected: pattern.toString()
127580
+ };
127581
+ }
127582
+ }
127583
+ const args = [];
127584
+ let current = "";
127585
+ let inQuotes = false;
127586
+ let quoteChar = "";
127587
+ let escaped = false;
127588
+ for (let i3 = 0; i3 < trimmed.length; i3++) {
127589
+ const char = trimmed[i3];
127590
+ const nextChar = i3 + 1 < trimmed.length ? trimmed[i3 + 1] : "";
127591
+ if (escaped) {
127592
+ current += char;
127593
+ escaped = false;
127594
+ continue;
127595
+ }
127596
+ if (char === "\\" && !inQuotes) {
127597
+ escaped = true;
127598
+ continue;
127599
+ }
127600
+ if (!inQuotes && (char === '"' || char === "'")) {
127601
+ inQuotes = true;
127602
+ quoteChar = char;
127603
+ } else if (inQuotes && char === quoteChar) {
127604
+ inQuotes = false;
127605
+ quoteChar = "";
127606
+ } else if (!inQuotes && char === " ") {
127607
+ if (current.trim()) {
127608
+ args.push(current.trim());
127609
+ current = "";
127610
+ }
127611
+ } else {
127612
+ current += char;
127613
+ }
127614
+ }
127615
+ if (current.trim()) {
127616
+ args.push(current.trim());
127617
+ }
127618
+ if (inQuotes) {
127619
+ return {
127620
+ success: false,
127621
+ error: `Unclosed quote in command: ${quoteChar}`,
127622
+ command: null,
127623
+ args: [],
127624
+ isComplex: false
127625
+ };
127626
+ }
127627
+ if (args.length === 0) {
127628
+ return {
127629
+ success: false,
127630
+ error: "No command found after parsing",
127631
+ command: null,
127632
+ args: [],
127633
+ isComplex: false
127634
+ };
127635
+ }
127636
+ const [baseCommand, ...commandArgs] = args;
127637
+ return {
127638
+ success: true,
127639
+ error: null,
127640
+ command: baseCommand,
127641
+ args: commandArgs,
127642
+ fullArgs: args,
127643
+ isComplex: false,
127644
+ original: command
127645
+ };
127646
+ }
127647
+ function isComplexCommand(command) {
127648
+ const result = parseSimpleCommand(command);
127649
+ return result.isComplex;
127650
+ }
127651
+ function parseCommand(command) {
127652
+ const result = parseSimpleCommand(command);
127653
+ if (!result.success) {
127654
+ return {
127655
+ command: "",
127656
+ args: [],
127657
+ error: result.error,
127658
+ isComplex: result.isComplex
127659
+ };
127660
+ }
127661
+ return {
127662
+ command: result.command,
127663
+ args: result.args,
127664
+ error: null,
127665
+ isComplex: result.isComplex
127666
+ };
127667
+ }
127668
+ function parseCommandForExecution(command) {
127669
+ const result = parseSimpleCommand(command);
127670
+ if (!result.success) {
127671
+ return null;
127672
+ }
127673
+ return result.fullArgs;
127674
+ }
127675
+ var init_bashCommandUtils = __esm({
127676
+ "src/agent/bashCommandUtils.js"() {
127677
+ "use strict";
127678
+ }
127679
+ });
127680
+
127681
+ // src/agent/bashPermissions.js
127682
+ function matchesPattern(parsedCommand, pattern) {
127683
+ if (!parsedCommand || !pattern) return false;
127684
+ const { command, args } = parsedCommand;
127685
+ if (!command) return false;
127686
+ const patternParts = pattern.split(":");
127687
+ const commandName = patternParts[0];
127688
+ if (commandName === "*") {
127689
+ return true;
127690
+ } else if (commandName !== command) {
127691
+ return false;
127692
+ }
127693
+ if (patternParts.length === 1) {
127694
+ return true;
127695
+ }
127696
+ for (let i3 = 1; i3 < patternParts.length; i3++) {
127697
+ const patternArg = patternParts[i3];
127698
+ const argIndex = i3 - 1;
127699
+ if (patternArg === "*") {
127700
+ continue;
127701
+ }
127702
+ if (argIndex >= args.length) {
127703
+ return false;
127704
+ }
127705
+ const actualArg = args[argIndex];
127706
+ if (patternArg !== actualArg) {
127707
+ return false;
127708
+ }
127709
+ }
127710
+ return true;
127711
+ }
127712
+ function matchesAnyPattern(parsedCommand, patterns) {
127713
+ if (!patterns || patterns.length === 0) return false;
127714
+ return patterns.some((pattern) => matchesPattern(parsedCommand, pattern));
127715
+ }
127716
+ var BashPermissionChecker;
127717
+ var init_bashPermissions = __esm({
127718
+ "src/agent/bashPermissions.js"() {
127719
+ "use strict";
127720
+ init_bashDefaults();
127721
+ init_bashCommandUtils();
127722
+ BashPermissionChecker = class {
127723
+ /**
127724
+ * Create a permission checker
127725
+ * @param {Object} config - Configuration options
127726
+ * @param {string[]} [config.allow] - Additional allow patterns
127727
+ * @param {string[]} [config.deny] - Additional deny patterns
127728
+ * @param {boolean} [config.disableDefaultAllow] - Disable default allow list
127729
+ * @param {boolean} [config.disableDefaultDeny] - Disable default deny list
127730
+ * @param {boolean} [config.debug] - Enable debug logging
127731
+ */
127732
+ constructor(config = {}) {
127733
+ this.debug = config.debug || false;
127734
+ this.allowPatterns = [];
127735
+ if (!config.disableDefaultAllow) {
127736
+ this.allowPatterns.push(...DEFAULT_ALLOW_PATTERNS);
127737
+ if (this.debug) {
127738
+ console.log(`[BashPermissions] Added ${DEFAULT_ALLOW_PATTERNS.length} default allow patterns`);
127739
+ }
127740
+ }
127741
+ if (config.allow && Array.isArray(config.allow)) {
127742
+ this.allowPatterns.push(...config.allow);
127743
+ if (this.debug) {
127744
+ console.log(`[BashPermissions] Added ${config.allow.length} custom allow patterns:`, config.allow);
127745
+ }
127746
+ }
127747
+ this.denyPatterns = [];
127748
+ if (!config.disableDefaultDeny) {
127749
+ this.denyPatterns.push(...DEFAULT_DENY_PATTERNS);
127750
+ if (this.debug) {
127751
+ console.log(`[BashPermissions] Added ${DEFAULT_DENY_PATTERNS.length} default deny patterns`);
127752
+ }
127753
+ }
127754
+ if (config.deny && Array.isArray(config.deny)) {
127755
+ this.denyPatterns.push(...config.deny);
127756
+ if (this.debug) {
127757
+ console.log(`[BashPermissions] Added ${config.deny.length} custom deny patterns:`, config.deny);
127758
+ }
127759
+ }
127760
+ if (this.debug) {
127761
+ console.log(`[BashPermissions] Total patterns - Allow: ${this.allowPatterns.length}, Deny: ${this.denyPatterns.length}`);
127762
+ }
127763
+ }
127764
+ /**
127765
+ * Check if a simple command is allowed (rejects complex commands for security)
127766
+ * @param {string} command - Command to check
127767
+ * @returns {Object} Permission result
127768
+ */
127769
+ check(command) {
127770
+ if (!command || typeof command !== "string") {
127771
+ return {
127772
+ allowed: false,
127773
+ reason: "Invalid or empty command",
127774
+ command
127775
+ };
127776
+ }
127777
+ if (isComplexCommand(command)) {
127778
+ return {
127779
+ allowed: false,
127780
+ reason: "Complex shell commands with pipes, operators, or redirections are not supported for security reasons",
127781
+ command,
127782
+ isComplex: true
127783
+ };
127784
+ }
127785
+ const parsed = parseCommand(command);
127786
+ if (parsed.error) {
127787
+ return {
127788
+ allowed: false,
127789
+ reason: parsed.error,
127790
+ command
127791
+ };
127792
+ }
127793
+ if (!parsed.command) {
127794
+ return {
127795
+ allowed: false,
127796
+ reason: "No valid command found",
127797
+ command
127798
+ };
127799
+ }
127800
+ if (this.debug) {
127801
+ console.log(`[BashPermissions] Checking simple command: "${command}"`);
127802
+ console.log(`[BashPermissions] Parsed: ${parsed.command} with args: [${parsed.args.join(", ")}]`);
127803
+ }
127804
+ if (matchesAnyPattern(parsed, this.denyPatterns)) {
127805
+ const matchedPatterns = this.denyPatterns.filter((pattern) => matchesPattern(parsed, pattern));
127806
+ return {
127807
+ allowed: false,
127808
+ reason: `Command matches deny pattern: ${matchedPatterns[0]}`,
127809
+ command,
127810
+ parsed,
127811
+ matchedPatterns
127812
+ };
127813
+ }
127814
+ if (this.allowPatterns.length > 0) {
127815
+ if (!matchesAnyPattern(parsed, this.allowPatterns)) {
127816
+ return {
127817
+ allowed: false,
127818
+ reason: "Command not in allow list",
127819
+ command,
127820
+ parsed
127821
+ };
127822
+ }
127823
+ }
127824
+ const result = {
127825
+ allowed: true,
127826
+ command,
127827
+ parsed,
127828
+ isComplex: false
127829
+ };
127830
+ if (this.debug) {
127831
+ console.log(`[BashPermissions] ALLOWED - command passed all checks`);
127832
+ }
127833
+ return result;
127834
+ }
127835
+ /**
127836
+ * Get configuration summary
127837
+ * @returns {Object} Configuration info
127838
+ */
127839
+ getConfig() {
127840
+ return {
127841
+ allowPatterns: this.allowPatterns.length,
127842
+ denyPatterns: this.denyPatterns.length,
127843
+ totalPatterns: this.allowPatterns.length + this.denyPatterns.length
127844
+ };
127845
+ }
127846
+ };
127847
+ }
127848
+ });
127849
+
127850
+ // src/agent/bashExecutor.js
127851
+ async function executeBashCommand(command, options = {}) {
127852
+ const {
127853
+ workingDirectory = process.cwd(),
127854
+ timeout = 12e4,
127855
+ // 2 minutes default
127856
+ env = {},
127857
+ maxBuffer = 10 * 1024 * 1024,
127858
+ // 10MB
127859
+ debug = false
127860
+ } = options;
127861
+ let cwd = workingDirectory;
127862
+ try {
127863
+ cwd = (0, import_path4.resolve)(cwd);
127864
+ if (!(0, import_fs.existsSync)(cwd)) {
127865
+ throw new Error(`Working directory does not exist: ${cwd}`);
127866
+ }
127867
+ } catch (error2) {
127868
+ return {
127869
+ success: false,
127870
+ error: `Invalid working directory: ${error2.message}`,
127871
+ stdout: "",
127872
+ stderr: "",
127873
+ exitCode: 1,
127874
+ command,
127875
+ workingDirectory: cwd,
127876
+ duration: 0
127877
+ };
127878
+ }
127879
+ const startTime = Date.now();
127880
+ if (debug) {
127881
+ console.log(`[BashExecutor] Executing command: "${command}"`);
127882
+ console.log(`[BashExecutor] Working directory: "${cwd}"`);
127883
+ console.log(`[BashExecutor] Timeout: ${timeout}ms`);
127884
+ }
127885
+ return new Promise((resolve4, reject) => {
127886
+ const processEnv = {
127887
+ ...process.env,
127888
+ ...env
127889
+ };
127890
+ const args = parseCommandForExecution(command);
127891
+ if (!args || args.length === 0) {
127892
+ resolve4({
127893
+ success: false,
127894
+ error: "Failed to parse command",
127895
+ stdout: "",
127896
+ stderr: "",
127897
+ exitCode: 1,
127898
+ command,
127899
+ workingDirectory: cwd,
127900
+ duration: Date.now() - startTime
127901
+ });
127902
+ return;
127903
+ }
127904
+ const [cmd, ...cmdArgs] = args;
127905
+ const child = (0, import_child_process6.spawn)(cmd, cmdArgs, {
127906
+ cwd,
127907
+ env: processEnv,
127908
+ stdio: ["ignore", "pipe", "pipe"],
127909
+ // stdin ignored, capture stdout/stderr
127910
+ shell: false,
127911
+ // For security
127912
+ windowsHide: true
127913
+ });
127914
+ let stdout = "";
127915
+ let stderr = "";
127916
+ let killed = false;
127917
+ let timeoutHandle;
127918
+ if (timeout > 0) {
127919
+ timeoutHandle = setTimeout(() => {
127920
+ if (!killed) {
127921
+ killed = true;
127922
+ child.kill("SIGTERM");
127923
+ setTimeout(() => {
127924
+ if (child.exitCode === null) {
127925
+ child.kill("SIGKILL");
127926
+ }
127927
+ }, 5e3);
127928
+ }
127929
+ }, timeout);
127930
+ }
127931
+ child.stdout.on("data", (data2) => {
127932
+ const chunk = data2.toString();
127933
+ if (stdout.length + chunk.length <= maxBuffer) {
127934
+ stdout += chunk;
127935
+ } else {
127936
+ if (!killed) {
127937
+ killed = true;
127938
+ child.kill("SIGTERM");
127939
+ }
127940
+ }
127941
+ });
127942
+ child.stderr.on("data", (data2) => {
127943
+ const chunk = data2.toString();
127944
+ if (stderr.length + chunk.length <= maxBuffer) {
127945
+ stderr += chunk;
127946
+ } else {
127947
+ if (!killed) {
127948
+ killed = true;
127949
+ child.kill("SIGTERM");
127950
+ }
127951
+ }
127952
+ });
127953
+ child.on("close", (code, signal) => {
127954
+ if (timeoutHandle) {
127955
+ clearTimeout(timeoutHandle);
127956
+ }
127957
+ const duration = Date.now() - startTime;
127958
+ if (debug) {
127959
+ console.log(`[BashExecutor] Command completed - Code: ${code}, Signal: ${signal}, Duration: ${duration}ms`);
127960
+ console.log(`[BashExecutor] Stdout length: ${stdout.length}, Stderr length: ${stderr.length}`);
127961
+ }
127962
+ let success = true;
127963
+ let error2 = "";
127964
+ if (killed) {
127965
+ success = false;
127966
+ if (stdout.length + stderr.length > maxBuffer) {
127967
+ error2 = `Command output exceeded maximum buffer size (${maxBuffer} bytes)`;
127968
+ } else {
127969
+ error2 = `Command timed out after ${timeout}ms`;
127970
+ }
127971
+ } else if (code !== 0) {
127972
+ success = false;
127973
+ error2 = `Command exited with code ${code}`;
127974
+ }
127975
+ resolve4({
127976
+ success,
127977
+ error: error2,
127978
+ stdout: stdout.trim(),
127979
+ stderr: stderr.trim(),
127980
+ exitCode: code,
127981
+ signal,
127982
+ command,
127983
+ workingDirectory: cwd,
127984
+ duration,
127985
+ killed
127986
+ });
127987
+ });
127988
+ child.on("error", (error2) => {
127989
+ if (timeoutHandle) {
127990
+ clearTimeout(timeoutHandle);
127991
+ }
127992
+ if (debug) {
127993
+ console.log(`[BashExecutor] Spawn error:`, error2);
127994
+ }
127995
+ resolve4({
127996
+ success: false,
127997
+ error: `Failed to execute command: ${error2.message}`,
127998
+ stdout: "",
127999
+ stderr: "",
128000
+ exitCode: 1,
128001
+ command,
128002
+ workingDirectory: cwd,
128003
+ duration: Date.now() - startTime
128004
+ });
128005
+ });
128006
+ });
128007
+ }
128008
+ function formatExecutionResult(result, includeMetadata = false) {
128009
+ if (!result) {
128010
+ return "No result available";
128011
+ }
128012
+ let output = "";
128013
+ if (includeMetadata) {
128014
+ output += `Command: ${result.command}
128015
+ `;
128016
+ output += `Working directory: ${result.workingDirectory}
128017
+ `;
128018
+ output += `Duration: ${result.duration}ms
128019
+ `;
128020
+ output += `Exit Code: ${result.exitCode}
128021
+ `;
128022
+ if (result.signal) {
128023
+ output += `Signal: ${result.signal}
128024
+ `;
128025
+ }
128026
+ output += "\n";
128027
+ }
128028
+ if (result.stdout) {
128029
+ if (includeMetadata) {
128030
+ output += "--- STDOUT ---\n";
128031
+ }
128032
+ output += result.stdout;
128033
+ if (includeMetadata && result.stderr) {
128034
+ output += "\n";
128035
+ }
128036
+ }
128037
+ if (result.stderr) {
128038
+ if (includeMetadata) {
128039
+ if (result.stdout) output += "\n";
128040
+ output += "--- STDERR ---\n";
128041
+ } else if (result.stdout) {
128042
+ output += "\n--- STDERR ---\n";
128043
+ }
128044
+ output += result.stderr;
128045
+ }
128046
+ if (!result.success && result.error && !result.stderr) {
128047
+ if (output) output += "\n";
128048
+ output += `Error: ${result.error}`;
128049
+ }
128050
+ if (!result.success && result.exitCode !== void 0 && result.exitCode !== 0) {
128051
+ if (output) output += "\n";
128052
+ output += `Exit code: ${result.exitCode}`;
128053
+ }
128054
+ return output || (result.success ? "Command completed successfully (no output)" : "Command failed (no output)");
128055
+ }
128056
+ function validateExecutionOptions(options = {}) {
128057
+ const errors = [];
128058
+ const warnings = [];
128059
+ if (options.timeout !== void 0) {
128060
+ if (typeof options.timeout !== "number" || options.timeout < 0) {
128061
+ errors.push("timeout must be a non-negative number");
128062
+ } else if (options.timeout > 6e5) {
128063
+ warnings.push("timeout is very high (>10 minutes)");
128064
+ }
128065
+ }
128066
+ if (options.maxBuffer !== void 0) {
128067
+ if (typeof options.maxBuffer !== "number" || options.maxBuffer < 1024) {
128068
+ errors.push("maxBuffer must be at least 1024 bytes");
128069
+ } else if (options.maxBuffer > 100 * 1024 * 1024) {
128070
+ warnings.push("maxBuffer is very high (>100MB)");
128071
+ }
128072
+ }
128073
+ if (options.workingDirectory) {
128074
+ if (typeof options.workingDirectory !== "string") {
128075
+ errors.push("workingDirectory must be a string");
128076
+ } else if (!(0, import_fs.existsSync)(options.workingDirectory)) {
128077
+ errors.push(`workingDirectory does not exist: ${options.workingDirectory}`);
128078
+ }
128079
+ }
128080
+ if (options.env && typeof options.env !== "object") {
128081
+ errors.push("env must be an object");
128082
+ }
128083
+ return {
128084
+ valid: errors.length === 0,
128085
+ errors,
128086
+ warnings
128087
+ };
128088
+ }
128089
+ var import_child_process6, import_path4, import_fs;
128090
+ var init_bashExecutor = __esm({
128091
+ "src/agent/bashExecutor.js"() {
128092
+ "use strict";
128093
+ import_child_process6 = __nccwpck_require__(35317);
128094
+ import_path4 = __nccwpck_require__(16928);
128095
+ import_fs = __nccwpck_require__(79896);
128096
+ init_bashCommandUtils();
128097
+ }
128098
+ });
128099
+
128100
+ // src/tools/bash.js
128101
+ var import_ai2, import_path5, bashTool;
128102
+ var init_bash = __esm({
128103
+ "src/tools/bash.js"() {
128104
+ "use strict";
128105
+ import_ai2 = __nccwpck_require__(86619);
128106
+ import_path5 = __nccwpck_require__(16928);
128107
+ init_bashPermissions();
128108
+ init_bashExecutor();
128109
+ bashTool = (options = {}) => {
128110
+ const {
128111
+ bashConfig = {},
128112
+ debug = false,
128113
+ defaultPath,
128114
+ allowedFolders = []
128115
+ } = options;
128116
+ const permissionChecker = new BashPermissionChecker({
128117
+ allow: bashConfig.allow,
128118
+ deny: bashConfig.deny,
128119
+ disableDefaultAllow: bashConfig.disableDefaultAllow,
128120
+ disableDefaultDeny: bashConfig.disableDefaultDeny,
128121
+ debug
128122
+ });
128123
+ const getDefaultWorkingDirectory = () => {
128124
+ if (bashConfig.workingDirectory) {
128125
+ return bashConfig.workingDirectory;
128126
+ }
128127
+ if (defaultPath) {
128128
+ return defaultPath;
128129
+ }
128130
+ if (allowedFolders && allowedFolders.length > 0) {
128131
+ return allowedFolders[0];
128132
+ }
128133
+ return process.cwd();
128134
+ };
128135
+ return (0, import_ai2.tool)({
128136
+ name: "bash",
128137
+ description: `Execute bash commands for system exploration and development tasks.
128138
+
128139
+ Security: This tool has built-in security with allow/deny lists. By default, only safe read-only commands are allowed for code exploration.
128140
+
128141
+ Parameters:
128142
+ - command: (required) The bash command to execute
128143
+ - workingDirectory: (optional) Directory to execute command in
128144
+ - timeout: (optional) Command timeout in milliseconds
128145
+ - env: (optional) Additional environment variables
128146
+
128147
+ Examples of allowed commands by default:
128148
+ - File exploration: ls, cat, head, tail, find, grep
128149
+ - Git operations: git status, git log, git diff, git show
128150
+ - Package info: npm list, pip list, cargo --version
128151
+ - System info: whoami, pwd, uname, date
128152
+
128153
+ Dangerous commands are blocked by default (rm -rf, sudo, npm install, etc.)`,
128154
+ inputSchema: {
128155
+ type: "object",
128156
+ properties: {
128157
+ command: {
128158
+ type: "string",
128159
+ description: "The bash command to execute"
128160
+ },
128161
+ workingDirectory: {
128162
+ type: "string",
128163
+ description: "Directory to execute the command in (optional)"
128164
+ },
128165
+ timeout: {
128166
+ type: "number",
128167
+ description: "Command timeout in milliseconds (optional)",
128168
+ minimum: 1e3,
128169
+ maximum: 6e5
128170
+ },
128171
+ env: {
128172
+ type: "object",
128173
+ description: "Additional environment variables (optional)",
128174
+ additionalProperties: {
128175
+ type: "string"
128176
+ }
128177
+ }
128178
+ },
128179
+ required: ["command"],
128180
+ additionalProperties: false
128181
+ },
128182
+ execute: async ({ command, workingDirectory, timeout, env }) => {
128183
+ try {
128184
+ if (command === null || command === void 0 || typeof command !== "string") {
128185
+ return "Error: Command is required and must be a string";
128186
+ }
128187
+ if (command.trim().length === 0) {
128188
+ return "Error: Command cannot be empty";
128189
+ }
128190
+ const permissionResult = permissionChecker.check(command.trim());
128191
+ if (!permissionResult.allowed) {
128192
+ if (debug) {
128193
+ console.log(`[BashTool] Permission denied for command: "${command}"`);
128194
+ console.log(`[BashTool] Reason: ${permissionResult.reason}`);
128195
+ }
128196
+ return `Permission denied: ${permissionResult.reason}
128197
+
128198
+ This command is not allowed by the current security policy.
128199
+
128200
+ Common reasons:
128201
+ 1. The command is in the deny list (potentially dangerous)
128202
+ 2. The command is not in the allow list (not a recognized safe command)
128203
+
128204
+ If you believe this command should be allowed, you can:
128205
+ - Use the --bash-allow option to add specific patterns
128206
+ - Use the --no-default-bash-deny flag to remove default restrictions (not recommended)
128207
+
128208
+ For code exploration, try these safe alternatives:
128209
+ - ls, cat, head, tail for file operations
128210
+ - find, grep, rg for searching
128211
+ - git status, git log, git show for git operations
128212
+ - npm list, pip list for package information`;
128213
+ }
128214
+ const workingDir = workingDirectory || getDefaultWorkingDirectory();
128215
+ if (allowedFolders && allowedFolders.length > 0) {
128216
+ const resolvedWorkingDir = (0, import_path5.resolve)(workingDir);
128217
+ const isAllowed = allowedFolders.some((folder) => {
128218
+ const resolvedFolder = (0, import_path5.resolve)(folder);
128219
+ return resolvedWorkingDir.startsWith(resolvedFolder);
128220
+ });
128221
+ if (!isAllowed) {
128222
+ return `Error: Working directory "${workingDir}" is not within allowed folders: ${allowedFolders.join(", ")}`;
128223
+ }
128224
+ }
128225
+ const executionOptions = {
128226
+ workingDirectory: workingDir,
128227
+ timeout: timeout || bashConfig.timeout || 12e4,
128228
+ env: { ...bashConfig.env, ...env },
128229
+ maxBuffer: bashConfig.maxBuffer,
128230
+ debug
128231
+ };
128232
+ const validation = validateExecutionOptions(executionOptions);
128233
+ if (!validation.valid) {
128234
+ return `Error: Invalid execution options: ${validation.errors.join(", ")}`;
128235
+ }
128236
+ if (validation.warnings.length > 0 && debug) {
128237
+ console.log("[BashTool] Warnings:", validation.warnings);
128238
+ }
128239
+ if (debug) {
128240
+ console.log(`[BashTool] Executing command: "${command}"`);
128241
+ console.log(`[BashTool] Working directory: "${workingDir}"`);
128242
+ console.log(`[BashTool] Timeout: ${executionOptions.timeout}ms`);
128243
+ }
128244
+ const result = await executeBashCommand(command.trim(), executionOptions);
128245
+ if (debug) {
128246
+ console.log(`[BashTool] Command completed - Success: ${result.success}, Duration: ${result.duration}ms`);
128247
+ }
128248
+ const formattedResult = formatExecutionResult(result, debug);
128249
+ if (!result.success) {
128250
+ let errorInfo = `
128251
+
128252
+ Command failed with exit code ${result.exitCode}`;
128253
+ if (result.killed) {
128254
+ errorInfo += ` (${result.error})`;
128255
+ }
128256
+ return formattedResult + errorInfo;
128257
+ }
128258
+ return formattedResult;
128259
+ } catch (error2) {
128260
+ if (debug) {
128261
+ console.error("[BashTool] Execution error:", error2);
128262
+ }
128263
+ return `Error executing bash command: ${error2.message}`;
128264
+ }
128265
+ }
128266
+ });
128267
+ };
128268
+ }
128269
+ });
128270
+
126529
128271
  // src/tools/langchain.js
126530
128272
  function createSearchTool() {
126531
128273
  return {
@@ -126743,6 +128485,10 @@ __export(tools_exports, {
126743
128485
  DEFAULT_SYSTEM_MESSAGE: () => DEFAULT_SYSTEM_MESSAGE,
126744
128486
  attemptCompletionSchema: () => attemptCompletionSchema,
126745
128487
  attemptCompletionToolDefinition: () => attemptCompletionToolDefinition,
128488
+ bashDescription: () => bashDescription,
128489
+ bashSchema: () => bashSchema,
128490
+ bashTool: () => bashTool,
128491
+ bashToolDefinition: () => bashToolDefinition,
126746
128492
  createExtractTool: () => createExtractTool,
126747
128493
  createQueryTool: () => createQueryTool,
126748
128494
  createSearchTool: () => createSearchTool,
@@ -126763,16 +128509,19 @@ var init_tools = __esm({
126763
128509
  "src/tools/index.js"() {
126764
128510
  "use strict";
126765
128511
  init_vercel();
128512
+ init_bash();
126766
128513
  init_langchain();
126767
128514
  init_common();
126768
128515
  init_system_message();
126769
128516
  init_vercel();
128517
+ init_bash();
126770
128518
  init_system_message();
126771
128519
  tools = {
126772
128520
  searchTool: searchTool(),
126773
128521
  queryTool: queryTool(),
126774
128522
  extractTool: extractTool(),
126775
128523
  delegateTool: delegateTool(),
128524
+ bashTool: bashTool(),
126776
128525
  DEFAULT_SYSTEM_MESSAGE
126777
128526
  };
126778
128527
  }
@@ -126785,10 +128534,10 @@ async function listFilesByLevel(options) {
126785
128534
  maxFiles = 100,
126786
128535
  respectGitignore = true
126787
128536
  } = options;
126788
- if (!import_fs.default.existsSync(directory)) {
128537
+ if (!import_fs2.default.existsSync(directory)) {
126789
128538
  throw new Error(`Directory does not exist: ${directory}`);
126790
128539
  }
126791
- const gitDirExists = import_fs.default.existsSync(import_path4.default.join(directory, ".git"));
128540
+ const gitDirExists = import_fs2.default.existsSync(import_path6.default.join(directory, ".git"));
126792
128541
  if (gitDirExists && respectGitignore) {
126793
128542
  try {
126794
128543
  return await listFilesUsingGit(directory, maxFiles);
@@ -126803,8 +128552,8 @@ async function listFilesUsingGit(directory, maxFiles) {
126803
128552
  const { stdout } = await execAsync4("git ls-files", { cwd: directory });
126804
128553
  const files = stdout.split("\n").filter(Boolean);
126805
128554
  const sortedFiles = files.sort((a3, b3) => {
126806
- const depthA = a3.split(import_path4.default.sep).length;
126807
- const depthB = b3.split(import_path4.default.sep).length;
128555
+ const depthA = a3.split(import_path6.default.sep).length;
128556
+ const depthB = b3.split(import_path6.default.sep).length;
126808
128557
  return depthA - depthB;
126809
128558
  });
126810
128559
  return sortedFiles.slice(0, maxFiles);
@@ -126819,19 +128568,19 @@ async function listFilesByLevelManually(directory, maxFiles, respectGitignore) {
126819
128568
  while (queue.length > 0 && result.length < maxFiles) {
126820
128569
  const { dir, level } = queue.shift();
126821
128570
  try {
126822
- const entries = import_fs.default.readdirSync(dir, { withFileTypes: true });
128571
+ const entries = import_fs2.default.readdirSync(dir, { withFileTypes: true });
126823
128572
  const files = entries.filter((entry) => entry.isFile());
126824
128573
  for (const file of files) {
126825
128574
  if (result.length >= maxFiles) break;
126826
- const filePath = import_path4.default.join(dir, file.name);
126827
- const relativePath = import_path4.default.relative(directory, filePath);
128575
+ const filePath = import_path6.default.join(dir, file.name);
128576
+ const relativePath = import_path6.default.relative(directory, filePath);
126828
128577
  if (shouldIgnore(relativePath, ignorePatterns)) continue;
126829
128578
  result.push(relativePath);
126830
128579
  }
126831
128580
  const dirs = entries.filter((entry) => entry.isDirectory());
126832
128581
  for (const subdir of dirs) {
126833
- const subdirPath = import_path4.default.join(dir, subdir.name);
126834
- const relativeSubdirPath = import_path4.default.relative(directory, subdirPath);
128582
+ const subdirPath = import_path6.default.join(dir, subdir.name);
128583
+ const relativeSubdirPath = import_path6.default.relative(directory, subdirPath);
126835
128584
  if (shouldIgnore(relativeSubdirPath, ignorePatterns)) continue;
126836
128585
  if (subdir.name === "node_modules" || subdir.name === ".git") continue;
126837
128586
  queue.push({ dir: subdirPath, level: level + 1 });
@@ -126843,12 +128592,12 @@ async function listFilesByLevelManually(directory, maxFiles, respectGitignore) {
126843
128592
  return result;
126844
128593
  }
126845
128594
  function loadGitignorePatterns(directory) {
126846
- const gitignorePath = import_path4.default.join(directory, ".gitignore");
126847
- if (!import_fs.default.existsSync(gitignorePath)) {
128595
+ const gitignorePath = import_path6.default.join(directory, ".gitignore");
128596
+ if (!import_fs2.default.existsSync(gitignorePath)) {
126848
128597
  return [];
126849
128598
  }
126850
128599
  try {
126851
- const content = import_fs.default.readFileSync(gitignorePath, "utf8");
128600
+ const content = import_fs2.default.readFileSync(gitignorePath, "utf8");
126852
128601
  return content.split("\n").map((line) => line.trim()).filter((line) => line && !line.startsWith("#"));
126853
128602
  } catch (error2) {
126854
128603
  console.error(`Warning: Could not read .gitignore: ${error2.message}`);
@@ -126866,15 +128615,15 @@ function shouldIgnore(filePath, ignorePatterns) {
126866
128615
  }
126867
128616
  return false;
126868
128617
  }
126869
- var import_fs, import_path4, import_util5, import_child_process6, execAsync4;
128618
+ var import_fs2, import_path6, import_util5, import_child_process7, execAsync4;
126870
128619
  var init_file_lister = __esm({
126871
128620
  "src/utils/file-lister.js"() {
126872
128621
  "use strict";
126873
- import_fs = __toESM(__nccwpck_require__(79896), 1);
126874
- import_path4 = __toESM(__nccwpck_require__(16928), 1);
128622
+ import_fs2 = __toESM(__nccwpck_require__(79896), 1);
128623
+ import_path6 = __toESM(__nccwpck_require__(16928), 1);
126875
128624
  import_util5 = __nccwpck_require__(39023);
126876
- import_child_process6 = __nccwpck_require__(35317);
126877
- execAsync4 = (0, import_util5.promisify)(import_child_process6.exec);
128625
+ import_child_process7 = __nccwpck_require__(35317);
128626
+ execAsync4 = (0, import_util5.promisify)(import_child_process7.exec);
126878
128627
  }
126879
128628
  });
126880
128629
 
@@ -129029,7 +130778,7 @@ var require_headStream = __commonJS({
129029
130778
  if ((0, stream_type_check_1.isReadableStream)(stream)) {
129030
130779
  return (0, headStream_browser_1.headStream)(stream, bytes);
129031
130780
  }
129032
- return new Promise((resolve2, reject) => {
130781
+ return new Promise((resolve4, reject) => {
129033
130782
  const collector = new Collector();
129034
130783
  collector.limit = bytes;
129035
130784
  stream.pipe(collector);
@@ -129040,7 +130789,7 @@ var require_headStream = __commonJS({
129040
130789
  collector.on("error", reject);
129041
130790
  collector.on("finish", function() {
129042
130791
  const bytes2 = new Uint8Array(Buffer.concat(this.buffers));
129043
- resolve2(bytes2);
130792
+ resolve4(bytes2);
129044
130793
  });
129045
130794
  });
129046
130795
  };
@@ -129298,21 +131047,21 @@ var require_dist_cjs15 = __commonJS({
129298
131047
  let sendBody = true;
129299
131048
  if (expect === "100-continue") {
129300
131049
  sendBody = await Promise.race([
129301
- new Promise((resolve2) => {
129302
- timeoutId = Number(timing.setTimeout(() => resolve2(true), Math.max(MIN_WAIT_TIME, maxContinueTimeoutMs)));
131050
+ new Promise((resolve4) => {
131051
+ timeoutId = Number(timing.setTimeout(() => resolve4(true), Math.max(MIN_WAIT_TIME, maxContinueTimeoutMs)));
129303
131052
  }),
129304
- new Promise((resolve2) => {
131053
+ new Promise((resolve4) => {
129305
131054
  httpRequest.on("continue", () => {
129306
131055
  timing.clearTimeout(timeoutId);
129307
- resolve2(true);
131056
+ resolve4(true);
129308
131057
  });
129309
131058
  httpRequest.on("response", () => {
129310
131059
  timing.clearTimeout(timeoutId);
129311
- resolve2(false);
131060
+ resolve4(false);
129312
131061
  });
129313
131062
  httpRequest.on("error", () => {
129314
131063
  timing.clearTimeout(timeoutId);
129315
- resolve2(false);
131064
+ resolve4(false);
129316
131065
  });
129317
131066
  })
129318
131067
  ]);
@@ -129348,13 +131097,13 @@ var require_dist_cjs15 = __commonJS({
129348
131097
  constructor(options) {
129349
131098
  this.socketWarningTimestamp = 0;
129350
131099
  this.metadata = { handlerProtocol: "http/1.1" };
129351
- this.configProvider = new Promise((resolve2, reject) => {
131100
+ this.configProvider = new Promise((resolve4, reject) => {
129352
131101
  if (typeof options === "function") {
129353
131102
  options().then((_options) => {
129354
- resolve2(this.resolveDefaultConfig(_options));
131103
+ resolve4(this.resolveDefaultConfig(_options));
129355
131104
  }).catch(reject);
129356
131105
  } else {
129357
- resolve2(this.resolveDefaultConfig(options));
131106
+ resolve4(this.resolveDefaultConfig(options));
129358
131107
  }
129359
131108
  });
129360
131109
  }
@@ -129438,7 +131187,7 @@ or increase socketAcquisitionWarningTimeout=(millis) in the NodeHttpHandler conf
129438
131187
  return new Promise((_resolve, _reject) => {
129439
131188
  let writeRequestBodyPromise = void 0;
129440
131189
  const timeouts = [];
129441
- const resolve2 = /* @__PURE__ */ __name(async (arg) => {
131190
+ const resolve4 = /* @__PURE__ */ __name(async (arg) => {
129442
131191
  await writeRequestBodyPromise;
129443
131192
  timeouts.forEach(timing.clearTimeout);
129444
131193
  _resolve(arg);
@@ -129508,7 +131257,7 @@ or increase socketAcquisitionWarningTimeout=(millis) in the NodeHttpHandler conf
129508
131257
  headers: getTransformedHeaders(res.headers),
129509
131258
  body: res
129510
131259
  });
129511
- resolve2({ response: httpResponse });
131260
+ resolve4({ response: httpResponse });
129512
131261
  });
129513
131262
  req.on("error", (err) => {
129514
131263
  if (NODEJS_TIMEOUT_ERROR_CODES.includes(err.code)) {
@@ -129697,13 +131446,13 @@ or increase socketAcquisitionWarningTimeout=(millis) in the NodeHttpHandler conf
129697
131446
  constructor(options) {
129698
131447
  this.metadata = { handlerProtocol: "h2" };
129699
131448
  this.connectionManager = new NodeHttp2ConnectionManager({});
129700
- this.configProvider = new Promise((resolve2, reject) => {
131449
+ this.configProvider = new Promise((resolve4, reject) => {
129701
131450
  if (typeof options === "function") {
129702
131451
  options().then((opts) => {
129703
- resolve2(opts || {});
131452
+ resolve4(opts || {});
129704
131453
  }).catch(reject);
129705
131454
  } else {
129706
- resolve2(options || {});
131455
+ resolve4(options || {});
129707
131456
  }
129708
131457
  });
129709
131458
  }
@@ -129736,7 +131485,7 @@ or increase socketAcquisitionWarningTimeout=(millis) in the NodeHttpHandler conf
129736
131485
  return new Promise((_resolve, _reject) => {
129737
131486
  let fulfilled = false;
129738
131487
  let writeRequestBodyPromise = void 0;
129739
- const resolve2 = /* @__PURE__ */ __name(async (arg) => {
131488
+ const resolve4 = /* @__PURE__ */ __name(async (arg) => {
129740
131489
  await writeRequestBodyPromise;
129741
131490
  _resolve(arg);
129742
131491
  }, "resolve");
@@ -129792,7 +131541,7 @@ or increase socketAcquisitionWarningTimeout=(millis) in the NodeHttpHandler conf
129792
131541
  body: req
129793
131542
  });
129794
131543
  fulfilled = true;
129795
- resolve2({ response: httpResponse });
131544
+ resolve4({ response: httpResponse });
129796
131545
  if (disableConcurrentStreams) {
129797
131546
  session.close();
129798
131547
  this.connectionManager.deleteSession(authority, session);
@@ -129881,7 +131630,7 @@ or increase socketAcquisitionWarningTimeout=(millis) in the NodeHttpHandler conf
129881
131630
  if (isReadableStreamInstance(stream)) {
129882
131631
  return collectReadableStream(stream);
129883
131632
  }
129884
- return new Promise((resolve2, reject) => {
131633
+ return new Promise((resolve4, reject) => {
129885
131634
  const collector = new Collector();
129886
131635
  stream.pipe(collector);
129887
131636
  stream.on("error", (err) => {
@@ -129891,7 +131640,7 @@ or increase socketAcquisitionWarningTimeout=(millis) in the NodeHttpHandler conf
129891
131640
  collector.on("error", reject);
129892
131641
  collector.on("finish", function() {
129893
131642
  const bytes = new Uint8Array(Buffer.concat(this.bufferedBytes));
129894
- resolve2(bytes);
131643
+ resolve4(bytes);
129895
131644
  });
129896
131645
  });
129897
131646
  }, "streamCollector");
@@ -129956,7 +131705,7 @@ var require_dist_cjs16 = __commonJS({
129956
131705
  }
129957
131706
  __name(createRequest, "createRequest");
129958
131707
  function requestTimeout(timeoutInMs = 0) {
129959
- return new Promise((resolve2, reject) => {
131708
+ return new Promise((resolve4, reject) => {
129960
131709
  if (timeoutInMs) {
129961
131710
  setTimeout(() => {
129962
131711
  const timeoutError = new Error(`Request did not complete within ${timeoutInMs} ms`);
@@ -130083,7 +131832,7 @@ var require_dist_cjs16 = __commonJS({
130083
131832
  ];
130084
131833
  if (abortSignal) {
130085
131834
  raceOfPromises.push(
130086
- new Promise((resolve2, reject) => {
131835
+ new Promise((resolve4, reject) => {
130087
131836
  const onAbort = /* @__PURE__ */ __name(() => {
130088
131837
  const abortError = new Error("Request aborted");
130089
131838
  abortError.name = "AbortError";
@@ -130151,7 +131900,7 @@ var require_dist_cjs16 = __commonJS({
130151
131900
  }
130152
131901
  __name(collectStream, "collectStream");
130153
131902
  function readToBase64(blob) {
130154
- return new Promise((resolve2, reject) => {
131903
+ return new Promise((resolve4, reject) => {
130155
131904
  const reader = new FileReader();
130156
131905
  reader.onloadend = () => {
130157
131906
  if (reader.readyState !== 2) {
@@ -130160,7 +131909,7 @@ var require_dist_cjs16 = __commonJS({
130160
131909
  const result = reader.result ?? "";
130161
131910
  const commaIndex = result.indexOf(",");
130162
131911
  const dataOffset = commaIndex > -1 ? commaIndex + 1 : result.length;
130163
- resolve2(result.substring(dataOffset));
131912
+ resolve4(result.substring(dataOffset));
130164
131913
  };
130165
131914
  reader.onabort = () => reject(new Error("Read aborted"));
130166
131915
  reader.onerror = () => reject(reader.error);
@@ -130647,9 +132396,10 @@ var TypeRegistry;
130647
132396
  var init_TypeRegistry = __esm({
130648
132397
  "node_modules/@smithy/core/dist-es/submodules/schema/TypeRegistry.js"() {
130649
132398
  TypeRegistry = class _TypeRegistry {
130650
- constructor(namespace, schemas = /* @__PURE__ */ new Map()) {
132399
+ constructor(namespace, schemas = /* @__PURE__ */ new Map(), exceptions = /* @__PURE__ */ new Map()) {
130651
132400
  this.namespace = namespace;
130652
132401
  this.schemas = schemas;
132402
+ this.exceptions = exceptions;
130653
132403
  }
130654
132404
  static for(namespace) {
130655
132405
  if (!_TypeRegistry.registries.has(namespace)) {
@@ -130659,8 +132409,7 @@ var init_TypeRegistry = __esm({
130659
132409
  }
130660
132410
  register(shapeId, schema) {
130661
132411
  const qualifiedName = this.normalizeShapeId(shapeId);
130662
- const registry = _TypeRegistry.for(this.getNamespace(shapeId));
130663
- registry.schemas.set(qualifiedName, schema);
132412
+ this.schemas.set(qualifiedName, schema);
130664
132413
  }
130665
132414
  getSchema(shapeId) {
130666
132415
  const id = this.normalizeShapeId(shapeId);
@@ -130669,6 +132418,12 @@ var init_TypeRegistry = __esm({
130669
132418
  }
130670
132419
  return this.schemas.get(id);
130671
132420
  }
132421
+ registerError(errorSchema, ctor) {
132422
+ this.exceptions.set(errorSchema, ctor);
132423
+ }
132424
+ getErrorCtor(errorSchema) {
132425
+ return this.exceptions.get(errorSchema);
132426
+ }
130672
132427
  getBaseException() {
130673
132428
  for (const [id, schema] of this.schemas.entries()) {
130674
132429
  if (id.startsWith("smithy.ts.sdk.synthetic.") && id.endsWith("ServiceException")) {
@@ -130680,9 +132435,9 @@ var init_TypeRegistry = __esm({
130680
132435
  find(predicate) {
130681
132436
  return [...this.schemas.values()].find(predicate);
130682
132437
  }
130683
- destroy() {
130684
- _TypeRegistry.registries.delete(this.namespace);
132438
+ clear() {
130685
132439
  this.schemas.clear();
132440
+ this.exceptions.clear();
130686
132441
  }
130687
132442
  normalizeShapeId(shapeId) {
130688
132443
  if (shapeId.includes("#")) {
@@ -130830,7 +132585,7 @@ var init_ErrorSchema = __esm({
130830
132585
  traits,
130831
132586
  memberNames,
130832
132587
  memberList,
130833
- ctor
132588
+ ctor: null
130834
132589
  });
130835
132590
  }
130836
132591
  });
@@ -131799,11 +133554,11 @@ function __metadata(metadataKey, metadataValue) {
131799
133554
  }
131800
133555
  function __awaiter(thisArg, _arguments, P, generator) {
131801
133556
  function adopt(value) {
131802
- return value instanceof P ? value : new P(function(resolve2) {
131803
- resolve2(value);
133557
+ return value instanceof P ? value : new P(function(resolve4) {
133558
+ resolve4(value);
131804
133559
  });
131805
133560
  }
131806
- return new (P || (P = Promise))(function(resolve2, reject) {
133561
+ return new (P || (P = Promise))(function(resolve4, reject) {
131807
133562
  function fulfilled(value) {
131808
133563
  try {
131809
133564
  step(generator.next(value));
@@ -131819,7 +133574,7 @@ function __awaiter(thisArg, _arguments, P, generator) {
131819
133574
  }
131820
133575
  }
131821
133576
  function step(result) {
131822
- result.done ? resolve2(result.value) : adopt(result.value).then(fulfilled, rejected);
133577
+ result.done ? resolve4(result.value) : adopt(result.value).then(fulfilled, rejected);
131823
133578
  }
131824
133579
  step((generator = generator.apply(thisArg, _arguments || [])).next());
131825
133580
  });
@@ -132010,14 +133765,14 @@ function __asyncValues(o3) {
132010
133765
  }, i3);
132011
133766
  function verb(n3) {
132012
133767
  i3[n3] = o3[n3] && function(v3) {
132013
- return new Promise(function(resolve2, reject) {
132014
- v3 = o3[n3](v3), settle(resolve2, reject, v3.done, v3.value);
133768
+ return new Promise(function(resolve4, reject) {
133769
+ v3 = o3[n3](v3), settle(resolve4, reject, v3.done, v3.value);
132015
133770
  });
132016
133771
  };
132017
133772
  }
132018
- function settle(resolve2, reject, d3, v3) {
133773
+ function settle(resolve4, reject, d3, v3) {
132019
133774
  Promise.resolve(v3).then(function(v4) {
132020
- resolve2({ value: v4, done: d3 });
133775
+ resolve4({ value: v4, done: d3 });
132021
133776
  }, reject);
132022
133777
  }
132023
133778
  }
@@ -136988,16 +138743,18 @@ var init_SmithyRpcV2CborProtocol = __esm({
136988
138743
  if (dataObject.Message) {
136989
138744
  dataObject.message = dataObject.Message;
136990
138745
  }
136991
- const baseExceptionSchema = TypeRegistry.for("smithy.ts.sdk.synthetic." + namespace).getBaseException();
138746
+ const synthetic = TypeRegistry.for("smithy.ts.sdk.synthetic." + namespace);
138747
+ const baseExceptionSchema = synthetic.getBaseException();
136992
138748
  if (baseExceptionSchema) {
136993
- const ErrorCtor = baseExceptionSchema.ctor;
136994
- throw Object.assign(new ErrorCtor({ name: errorName }), errorMetadata, dataObject);
138749
+ const ErrorCtor2 = synthetic.getErrorCtor(baseExceptionSchema);
138750
+ throw Object.assign(new ErrorCtor2({ name: errorName }), errorMetadata, dataObject);
136995
138751
  }
136996
138752
  throw Object.assign(new Error(errorName), errorMetadata, dataObject);
136997
138753
  }
136998
138754
  const ns = NormalizedSchema.of(errorSchema);
138755
+ const ErrorCtor = registry.getErrorCtor(errorSchema);
136999
138756
  const message = dataObject.message ?? dataObject.Message ?? "Unknown";
137000
- const exception = new errorSchema.ctor(message);
138757
+ const exception = new ErrorCtor(message);
137001
138758
  const output = {};
137002
138759
  for (const [name14, member] of ns.structIterator()) {
137003
138760
  output[name14] = this.deserializer.readValue(member, dataObject[name14]);
@@ -142663,7 +144420,7 @@ var require_dist_cjs37 = __commonJS({
142663
144420
  );
142664
144421
  }
142665
144422
  waitForReady(socket, connectionTimeout) {
142666
- return new Promise((resolve2, reject) => {
144423
+ return new Promise((resolve4, reject) => {
142667
144424
  const timeout = setTimeout(() => {
142668
144425
  this.removeNotUsableSockets(socket.url);
142669
144426
  reject({
@@ -142674,7 +144431,7 @@ var require_dist_cjs37 = __commonJS({
142674
144431
  }, connectionTimeout);
142675
144432
  socket.onopen = () => {
142676
144433
  clearTimeout(timeout);
142677
- resolve2();
144434
+ resolve4();
142678
144435
  };
142679
144436
  });
142680
144437
  }
@@ -142683,10 +144440,10 @@ var require_dist_cjs37 = __commonJS({
142683
144440
  let socketErrorOccurred = false;
142684
144441
  let reject = /* @__PURE__ */ __name(() => {
142685
144442
  }, "reject");
142686
- let resolve2 = /* @__PURE__ */ __name(() => {
144443
+ let resolve4 = /* @__PURE__ */ __name(() => {
142687
144444
  }, "resolve");
142688
144445
  socket.onmessage = (event) => {
142689
- resolve2({
144446
+ resolve4({
142690
144447
  done: false,
142691
144448
  value: new Uint8Array(event.data)
142692
144449
  });
@@ -142702,7 +144459,7 @@ var require_dist_cjs37 = __commonJS({
142702
144459
  if (streamError) {
142703
144460
  reject(streamError);
142704
144461
  } else {
142705
- resolve2({
144462
+ resolve4({
142706
144463
  done: true,
142707
144464
  value: void 0
142708
144465
  // unchecked because done=true.
@@ -142713,7 +144470,7 @@ var require_dist_cjs37 = __commonJS({
142713
144470
  [Symbol.asyncIterator]: () => ({
142714
144471
  next: /* @__PURE__ */ __name(() => {
142715
144472
  return new Promise((_resolve, _reject) => {
142716
- resolve2 = _resolve;
144473
+ resolve4 = _resolve;
142717
144474
  reject = _reject;
142718
144475
  });
142719
144476
  }, "next")
@@ -143236,13 +144993,13 @@ var require_dist_cjs42 = __commonJS({
143236
144993
  ...data2.default && { default: data2.default }
143237
144994
  }
143238
144995
  ), "getConfigData");
143239
- var import_path9 = __nccwpck_require__(16928);
144996
+ var import_path11 = __nccwpck_require__(16928);
143240
144997
  var import_getHomeDir = require_getHomeDir();
143241
144998
  var ENV_CONFIG_PATH = "AWS_CONFIG_FILE";
143242
- var getConfigFilepath = /* @__PURE__ */ __name(() => process.env[ENV_CONFIG_PATH] || (0, import_path9.join)((0, import_getHomeDir.getHomeDir)(), ".aws", "config"), "getConfigFilepath");
144999
+ var getConfigFilepath = /* @__PURE__ */ __name(() => process.env[ENV_CONFIG_PATH] || (0, import_path11.join)((0, import_getHomeDir.getHomeDir)(), ".aws", "config"), "getConfigFilepath");
143243
145000
  var import_getHomeDir2 = require_getHomeDir();
143244
145001
  var ENV_CREDENTIALS_PATH = "AWS_SHARED_CREDENTIALS_FILE";
143245
- var getCredentialsFilepath = /* @__PURE__ */ __name(() => process.env[ENV_CREDENTIALS_PATH] || (0, import_path9.join)((0, import_getHomeDir2.getHomeDir)(), ".aws", "credentials"), "getCredentialsFilepath");
145002
+ var getCredentialsFilepath = /* @__PURE__ */ __name(() => process.env[ENV_CREDENTIALS_PATH] || (0, import_path11.join)((0, import_getHomeDir2.getHomeDir)(), ".aws", "credentials"), "getCredentialsFilepath");
143246
145003
  var import_getHomeDir3 = require_getHomeDir();
143247
145004
  var prefixKeyRegex = /^([\w-]+)\s(["'])?([\w-@\+\.%:/]+)\2$/;
143248
145005
  var profileNameBlockList = ["__proto__", "profile __proto__"];
@@ -143300,11 +145057,11 @@ var require_dist_cjs42 = __commonJS({
143300
145057
  const relativeHomeDirPrefix = "~/";
143301
145058
  let resolvedFilepath = filepath;
143302
145059
  if (filepath.startsWith(relativeHomeDirPrefix)) {
143303
- resolvedFilepath = (0, import_path9.join)(homeDir, filepath.slice(2));
145060
+ resolvedFilepath = (0, import_path11.join)(homeDir, filepath.slice(2));
143304
145061
  }
143305
145062
  let resolvedConfigFilepath = configFilepath;
143306
145063
  if (configFilepath.startsWith(relativeHomeDirPrefix)) {
143307
- resolvedConfigFilepath = (0, import_path9.join)(homeDir, configFilepath.slice(2));
145064
+ resolvedConfigFilepath = (0, import_path11.join)(homeDir, configFilepath.slice(2));
143308
145065
  }
143309
145066
  const parsedFiles = await Promise.all([
143310
145067
  (0, import_slurpFile.slurpFile)(resolvedConfigFilepath, {
@@ -143959,7 +145716,7 @@ var require_dist_cjs46 = __commonJS({
143959
145716
  this.refillTokenBucket();
143960
145717
  if (amount > this.currentCapacity) {
143961
145718
  const delay = (amount - this.currentCapacity) / this.fillRate * 1e3;
143962
- await new Promise((resolve2) => _DefaultRateLimiter.setTimeoutFn(resolve2, delay));
145719
+ await new Promise((resolve4) => _DefaultRateLimiter.setTimeoutFn(resolve4, delay));
143963
145720
  }
143964
145721
  this.currentCapacity = this.currentCapacity - amount;
143965
145722
  }
@@ -144350,7 +146107,7 @@ var require_dist_cjs47 = __commonJS({
144350
146107
  const delayFromResponse = getDelayFromRetryAfterHeader(err.$response);
144351
146108
  const delay = Math.max(delayFromResponse || 0, delayFromDecider);
144352
146109
  totalDelay += delay;
144353
- await new Promise((resolve2) => setTimeout(resolve2, delay));
146110
+ await new Promise((resolve4) => setTimeout(resolve4, delay));
144354
146111
  continue;
144355
146112
  }
144356
146113
  if (!err.$metadata) {
@@ -144510,7 +146267,7 @@ var require_dist_cjs47 = __commonJS({
144510
146267
  attempts = retryToken.getRetryCount();
144511
146268
  const delay = retryToken.getRetryDelay();
144512
146269
  totalRetryDelay += delay;
144513
- await new Promise((resolve2) => setTimeout(resolve2, delay));
146270
+ await new Promise((resolve4) => setTimeout(resolve4, delay));
144514
146271
  }
144515
146272
  }
144516
146273
  } else {
@@ -144853,7 +146610,7 @@ var require_dist_cjs49 = __commonJS({
144853
146610
  var import_buffer = __nccwpck_require__(20181);
144854
146611
  var import_http = __nccwpck_require__(58611);
144855
146612
  function httpRequest(options) {
144856
- return new Promise((resolve2, reject) => {
146613
+ return new Promise((resolve4, reject) => {
144857
146614
  const req = (0, import_http.request)({
144858
146615
  method: "GET",
144859
146616
  ...options,
@@ -144882,7 +146639,7 @@ var require_dist_cjs49 = __commonJS({
144882
146639
  chunks.push(chunk);
144883
146640
  });
144884
146641
  res.on("end", () => {
144885
- resolve2(import_buffer.Buffer.concat(chunks));
146642
+ resolve4(import_buffer.Buffer.concat(chunks));
144886
146643
  req.destroy();
144887
146644
  });
144888
146645
  });
@@ -145317,7 +147074,7 @@ var require_retry_wrapper = __commonJS({
145317
147074
  try {
145318
147075
  return await toRetry();
145319
147076
  } catch (e3) {
145320
- await new Promise((resolve2) => setTimeout(resolve2, delayMs));
147077
+ await new Promise((resolve4) => setTimeout(resolve4, delayMs));
145321
147078
  }
145322
147079
  }
145323
147080
  return await toRetry();
@@ -145761,7 +147518,7 @@ var require_dist_cjs53 = __commonJS({
145761
147518
  calculateBodyLength: () => calculateBodyLength3
145762
147519
  });
145763
147520
  module2.exports = __toCommonJS2(index_exports2);
145764
- var import_fs7 = __nccwpck_require__(79896);
147521
+ var import_fs8 = __nccwpck_require__(79896);
145765
147522
  var calculateBodyLength3 = /* @__PURE__ */ __name((body) => {
145766
147523
  if (!body) {
145767
147524
  return 0;
@@ -145775,9 +147532,9 @@ var require_dist_cjs53 = __commonJS({
145775
147532
  } else if (typeof body.start === "number" && typeof body.end === "number") {
145776
147533
  return body.end + 1 - body.start;
145777
147534
  } else if (typeof body.path === "string" || Buffer.isBuffer(body.path)) {
145778
- return (0, import_fs7.lstatSync)(body.path).size;
147535
+ return (0, import_fs8.lstatSync)(body.path).size;
145779
147536
  } else if (typeof body.fd === "number") {
145780
- return (0, import_fs7.fstatSync)(body.fd).size;
147537
+ return (0, import_fs8.fstatSync)(body.fd).size;
145781
147538
  }
145782
147539
  throw new Error(`Body Length computation failed for ${body}`);
145783
147540
  }, "calculateBodyLength");
@@ -147815,8 +149572,8 @@ var require_dist_cjs57 = __commonJS({
147815
149572
  }
147816
149573
  }, "validateTokenKey");
147817
149574
  var import_shared_ini_file_loader = require_dist_cjs42();
147818
- var import_fs7 = __nccwpck_require__(79896);
147819
- var { writeFile } = import_fs7.promises;
149575
+ var import_fs8 = __nccwpck_require__(79896);
149576
+ var { writeFile } = import_fs8.promises;
147820
149577
  var writeSSOTokenToFile = /* @__PURE__ */ __name((id, ssoToken) => {
147821
149578
  const tokenFilepath = (0, import_shared_ini_file_loader.getSSOTokenFilepath)(id);
147822
149579
  const tokenString = JSON.stringify(ssoToken, null, 2);
@@ -149458,7 +151215,7 @@ var require_dist_cjs59 = __commonJS({
149458
151215
  module2.exports = __toCommonJS2(index_exports2);
149459
151216
  var import_property_provider2 = require_dist_cjs24();
149460
151217
  var import_shared_ini_file_loader = require_dist_cjs42();
149461
- var import_child_process8 = __nccwpck_require__(35317);
151218
+ var import_child_process9 = __nccwpck_require__(35317);
149462
151219
  var import_util7 = __nccwpck_require__(39023);
149463
151220
  var import_client7 = (init_client(), __toCommonJS(client_exports));
149464
151221
  var getValidatedProcessCredentials = /* @__PURE__ */ __name((profileName, data2, profiles) => {
@@ -149495,7 +151252,7 @@ var require_dist_cjs59 = __commonJS({
149495
151252
  if (profiles[profileName]) {
149496
151253
  const credentialProcess = profile["credential_process"];
149497
151254
  if (credentialProcess !== void 0) {
149498
- const execPromise = (0, import_util7.promisify)(import_shared_ini_file_loader.externalDataInterceptor?.getTokenRecord?.().exec ?? import_child_process8.exec);
151255
+ const execPromise = (0, import_util7.promisify)(import_shared_ini_file_loader.externalDataInterceptor?.getTokenRecord?.().exec ?? import_child_process9.exec);
149499
151256
  try {
149500
151257
  const { stdout } = await execPromise(credentialProcess);
149501
151258
  let data2;
@@ -150234,7 +151991,7 @@ var require_dist_cjs64 = __commonJS({
150234
151991
  streamEnded = true;
150235
151992
  });
150236
151993
  while (!generationEnded) {
150237
- const value = await new Promise((resolve2) => setTimeout(() => resolve2(records.shift()), 0));
151994
+ const value = await new Promise((resolve4) => setTimeout(() => resolve4(records.shift()), 0));
150238
151995
  if (value) {
150239
151996
  yield value;
150240
151997
  }
@@ -153611,16 +155368,16 @@ function prepareTools(mode) {
153611
155368
  }
153612
155369
  const toolWarnings = [];
153613
155370
  const bedrockTools = [];
153614
- for (const tool2 of tools2) {
153615
- if (tool2.type === "provider-defined") {
153616
- toolWarnings.push({ type: "unsupported-tool", tool: tool2 });
155371
+ for (const tool3 of tools2) {
155372
+ if (tool3.type === "provider-defined") {
155373
+ toolWarnings.push({ type: "unsupported-tool", tool: tool3 });
153617
155374
  } else {
153618
155375
  bedrockTools.push({
153619
155376
  toolSpec: {
153620
- name: tool2.name,
153621
- description: tool2.description,
155377
+ name: tool3.name,
155378
+ description: tool3.description,
153622
155379
  inputSchema: {
153623
- json: tool2.parameters
155380
+ json: tool3.parameters
153624
155381
  }
153625
155382
  }
153626
155383
  });
@@ -154631,8 +156388,8 @@ function checkAttemptCompleteRecovery(cleanedXmlString, validTools = []) {
154631
156388
  function hasOtherToolTags(xmlString, validTools = []) {
154632
156389
  const defaultTools = ["search", "query", "extract", "listFiles", "searchFiles", "implement", "attempt_completion"];
154633
156390
  const toolsToCheck = validTools.length > 0 ? validTools : defaultTools;
154634
- for (const tool2 of toolsToCheck) {
154635
- if (tool2 !== "attempt_completion" && xmlString.includes(`<${tool2}`)) {
156391
+ for (const tool3 of toolsToCheck) {
156392
+ if (tool3 !== "attempt_completion" && xmlString.includes(`<${tool3}`)) {
154636
156393
  return true;
154637
156394
  }
154638
156395
  }
@@ -154660,12 +156417,16 @@ var init_xmlParsingUtils = __esm({
154660
156417
 
154661
156418
  // src/agent/tools.js
154662
156419
  function createTools(configOptions) {
154663
- return {
156420
+ const tools2 = {
154664
156421
  searchTool: searchTool(configOptions),
154665
156422
  queryTool: queryTool(configOptions),
154666
156423
  extractTool: extractTool(configOptions),
154667
156424
  delegateTool: delegateTool(configOptions)
154668
156425
  };
156426
+ if (configOptions.enableBash) {
156427
+ tools2.bashTool = bashTool(configOptions);
156428
+ }
156429
+ return tools2;
154669
156430
  }
154670
156431
  function parseXmlToolCallWithThinking(xmlString, validTools) {
154671
156432
  const { cleanedXmlString, recoveryResult } = processXmlWithThinkingAndRecovery(xmlString, validTools);
@@ -154809,26 +156570,33 @@ function createWrappedTools(baseTools) {
154809
156570
  baseTools.delegateTool.execute
154810
156571
  );
154811
156572
  }
156573
+ if (baseTools.bashTool) {
156574
+ wrappedTools.bashToolInstance = wrapToolWithEmitter(
156575
+ baseTools.bashTool,
156576
+ "bash",
156577
+ baseTools.bashTool.execute
156578
+ );
156579
+ }
154812
156580
  return wrappedTools;
154813
156581
  }
154814
- 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;
156582
+ 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;
154815
156583
  var init_probeTool = __esm({
154816
156584
  "src/agent/probeTool.js"() {
154817
156585
  "use strict";
154818
156586
  init_index();
154819
- import_child_process7 = __nccwpck_require__(35317);
156587
+ import_child_process8 = __nccwpck_require__(35317);
154820
156588
  import_util6 = __nccwpck_require__(39023);
154821
156589
  import_crypto4 = __nccwpck_require__(76982);
154822
156590
  import_events = __nccwpck_require__(24434);
154823
- import_fs2 = __toESM(__nccwpck_require__(79896), 1);
154824
- import_fs3 = __nccwpck_require__(79896);
154825
- import_path5 = __toESM(__nccwpck_require__(16928), 1);
156591
+ import_fs3 = __toESM(__nccwpck_require__(79896), 1);
156592
+ import_fs4 = __nccwpck_require__(79896);
156593
+ import_path7 = __toESM(__nccwpck_require__(16928), 1);
154826
156594
  import_glob = __nccwpck_require__(21363);
154827
156595
  toolCallEmitter = new import_events.EventEmitter();
154828
156596
  activeToolExecutions = /* @__PURE__ */ new Map();
154829
- wrapToolWithEmitter = (tool2, toolName, baseExecute) => {
156597
+ wrapToolWithEmitter = (tool3, toolName, baseExecute) => {
154830
156598
  return {
154831
- ...tool2,
156599
+ ...tool3,
154832
156600
  // Spread schema, description etc.
154833
156601
  execute: async (params) => {
154834
156602
  const debug = process.env.DEBUG === "1";
@@ -154910,9 +156678,9 @@ var init_probeTool = __esm({
154910
156678
  execute: async (params) => {
154911
156679
  const { directory = ".", workingDirectory } = params;
154912
156680
  const baseCwd = workingDirectory || process.cwd();
154913
- const secureBaseDir = import_path5.default.resolve(baseCwd);
154914
- const targetDir = import_path5.default.resolve(secureBaseDir, directory);
154915
- if (!targetDir.startsWith(secureBaseDir + import_path5.default.sep) && targetDir !== secureBaseDir) {
156681
+ const secureBaseDir = import_path7.default.resolve(baseCwd);
156682
+ const targetDir = import_path7.default.resolve(secureBaseDir, directory);
156683
+ if (!targetDir.startsWith(secureBaseDir + import_path7.default.sep) && targetDir !== secureBaseDir) {
154916
156684
  throw new Error("Path traversal attempt detected. Access denied.");
154917
156685
  }
154918
156686
  try {
@@ -154935,9 +156703,9 @@ var init_probeTool = __esm({
154935
156703
  throw new Error("Pattern is required for file search");
154936
156704
  }
154937
156705
  const baseCwd = workingDirectory || process.cwd();
154938
- const secureBaseDir = import_path5.default.resolve(baseCwd);
154939
- const targetDir = import_path5.default.resolve(secureBaseDir, directory);
154940
- if (!targetDir.startsWith(secureBaseDir + import_path5.default.sep) && targetDir !== secureBaseDir) {
156706
+ const secureBaseDir = import_path7.default.resolve(baseCwd);
156707
+ const targetDir = import_path7.default.resolve(secureBaseDir, directory);
156708
+ if (!targetDir.startsWith(secureBaseDir + import_path7.default.sep) && targetDir !== secureBaseDir) {
154941
156709
  throw new Error("Path traversal attempt detected. Access denied.");
154942
156710
  }
154943
156711
  try {
@@ -154969,7 +156737,7 @@ function createMockProvider() {
154969
156737
  provider: "mock",
154970
156738
  // Mock the doGenerate method used by Vercel AI SDK
154971
156739
  doGenerate: async ({ messages, tools: tools2 }) => {
154972
- await new Promise((resolve2) => setTimeout(resolve2, 10));
156740
+ await new Promise((resolve4) => setTimeout(resolve4, 10));
154973
156741
  return {
154974
156742
  text: "This is a mock response for testing",
154975
156743
  toolCalls: [],
@@ -155544,7 +157312,7 @@ ${decodedContent}
155544
157312
  }
155545
157313
  if (needsQuoting(content)) {
155546
157314
  wasFixed = true;
155547
- const safeContent = content.replace(/"/g, "'");
157315
+ const safeContent = content.replace(/"/g, "&quot;").replace(/'/g, "&#39;");
155548
157316
  return `["${safeContent}"]`;
155549
157317
  }
155550
157318
  return match;
@@ -155557,7 +157325,7 @@ ${decodedContent}
155557
157325
  }
155558
157326
  if (needsQuoting(content)) {
155559
157327
  wasFixed = true;
155560
- const safeContent = content.replace(/"/g, "'");
157328
+ const safeContent = content.replace(/"/g, "&quot;").replace(/'/g, "&#39;");
155561
157329
  return `{"${safeContent}"}`;
155562
157330
  }
155563
157331
  return match;
@@ -155727,7 +157495,7 @@ ${fixedContent}
155727
157495
  }
155728
157496
  if (needsQuoting(content)) {
155729
157497
  wasFixed = true;
155730
- const safeContent = content.replace(/"/g, "'");
157498
+ const safeContent = content.replace(/"/g, "&quot;").replace(/'/g, "&#39;");
155731
157499
  return `["${safeContent}"]`;
155732
157500
  }
155733
157501
  return match;
@@ -155740,7 +157508,7 @@ ${fixedContent}
155740
157508
  }
155741
157509
  if (needsQuoting(content)) {
155742
157510
  wasFixed = true;
155743
- const safeContent = content.replace(/"/g, "'");
157511
+ const safeContent = content.replace(/"/g, "&quot;").replace(/'/g, "&#39;");
155744
157512
  return `{"${safeContent}"}`;
155745
157513
  }
155746
157514
  return match;
@@ -156140,11 +157908,11 @@ function loadMCPConfigurationFromPath(configPath) {
156140
157908
  if (!configPath) {
156141
157909
  throw new Error("Config path is required");
156142
157910
  }
156143
- if (!(0, import_fs4.existsSync)(configPath)) {
157911
+ if (!(0, import_fs5.existsSync)(configPath)) {
156144
157912
  throw new Error(`MCP configuration file not found: ${configPath}`);
156145
157913
  }
156146
157914
  try {
156147
- const content = (0, import_fs4.readFileSync)(configPath, "utf8");
157915
+ const content = (0, import_fs5.readFileSync)(configPath, "utf8");
156148
157916
  const config = JSON.parse(content);
156149
157917
  if (process.env.DEBUG === "1") {
156150
157918
  console.error(`[MCP] Loaded configuration from: ${configPath}`);
@@ -156159,19 +157927,19 @@ function loadMCPConfiguration() {
156159
157927
  // Environment variable path
156160
157928
  process.env.MCP_CONFIG_PATH,
156161
157929
  // Local project paths
156162
- (0, import_path6.join)(process.cwd(), ".mcp", "config.json"),
156163
- (0, import_path6.join)(process.cwd(), "mcp.config.json"),
157930
+ (0, import_path8.join)(process.cwd(), ".mcp", "config.json"),
157931
+ (0, import_path8.join)(process.cwd(), "mcp.config.json"),
156164
157932
  // Home directory paths
156165
- (0, import_path6.join)((0, import_os3.homedir)(), ".config", "probe", "mcp.json"),
156166
- (0, import_path6.join)((0, import_os3.homedir)(), ".mcp", "config.json"),
157933
+ (0, import_path8.join)((0, import_os3.homedir)(), ".config", "probe", "mcp.json"),
157934
+ (0, import_path8.join)((0, import_os3.homedir)(), ".mcp", "config.json"),
156167
157935
  // Claude-style config location
156168
- (0, import_path6.join)((0, import_os3.homedir)(), "Library", "Application Support", "Claude", "mcp_config.json")
157936
+ (0, import_path8.join)((0, import_os3.homedir)(), "Library", "Application Support", "Claude", "mcp_config.json")
156169
157937
  ].filter(Boolean);
156170
157938
  let config = null;
156171
157939
  for (const configPath of configPaths) {
156172
- if ((0, import_fs4.existsSync)(configPath)) {
157940
+ if ((0, import_fs5.existsSync)(configPath)) {
156173
157941
  try {
156174
- const content = (0, import_fs4.readFileSync)(configPath, "utf8");
157942
+ const content = (0, import_fs5.readFileSync)(configPath, "utf8");
156175
157943
  config = JSON.parse(content);
156176
157944
  if (process.env.DEBUG === "1") {
156177
157945
  console.error(`[MCP] Loaded configuration from: ${configPath}`);
@@ -156267,22 +158035,22 @@ function parseEnabledServers(config) {
156267
158035
  }
156268
158036
  return servers;
156269
158037
  }
156270
- var import_fs4, import_path6, import_os3, import_url4, __filename4, __dirname4, DEFAULT_CONFIG;
158038
+ var import_fs5, import_path8, import_os3, import_url4, __filename4, __dirname4, DEFAULT_CONFIG;
156271
158039
  var init_config = __esm({
156272
158040
  "src/agent/mcp/config.js"() {
156273
158041
  "use strict";
156274
- import_fs4 = __nccwpck_require__(79896);
156275
- import_path6 = __nccwpck_require__(16928);
158042
+ import_fs5 = __nccwpck_require__(79896);
158043
+ import_path8 = __nccwpck_require__(16928);
156276
158044
  import_os3 = __nccwpck_require__(70857);
156277
158045
  import_url4 = __nccwpck_require__(87016);
156278
158046
  __filename4 = (0, import_url4.fileURLToPath)("file:///");
156279
- __dirname4 = (0, import_path6.dirname)(__filename4);
158047
+ __dirname4 = (0, import_path8.dirname)(__filename4);
156280
158048
  DEFAULT_CONFIG = {
156281
158049
  mcpServers: {
156282
158050
  // Example probe server configuration
156283
158051
  "probe-local": {
156284
158052
  command: "node",
156285
- args: [(0, import_path6.join)(__dirname4, "../../../examples/chat/mcpServer.js")],
158053
+ args: [(0, import_path8.join)(__dirname4, "../../../examples/chat/mcpServer.js")],
156286
158054
  transport: "stdio",
156287
158055
  enabled: false
156288
158056
  },
@@ -156439,12 +158207,12 @@ var init_client2 = __esm({
156439
158207
  });
156440
158208
  const toolsResponse = await client.listTools();
156441
158209
  if (toolsResponse && toolsResponse.tools) {
156442
- for (const tool2 of toolsResponse.tools) {
156443
- const qualifiedName = `${name14}_${tool2.name}`;
158210
+ for (const tool3 of toolsResponse.tools) {
158211
+ const qualifiedName = `${name14}_${tool3.name}`;
156444
158212
  this.tools.set(qualifiedName, {
156445
- ...tool2,
158213
+ ...tool3,
156446
158214
  serverName: name14,
156447
- originalName: tool2.name
158215
+ originalName: tool3.name
156448
158216
  });
156449
158217
  if (this.debug) {
156450
158218
  console.error(`[MCP] Registered tool: ${qualifiedName}`);
@@ -156466,20 +158234,20 @@ var init_client2 = __esm({
156466
158234
  * @param {Object} args - Tool arguments
156467
158235
  */
156468
158236
  async callTool(toolName, args) {
156469
- const tool2 = this.tools.get(toolName);
156470
- if (!tool2) {
158237
+ const tool3 = this.tools.get(toolName);
158238
+ if (!tool3) {
156471
158239
  throw new Error(`Unknown tool: ${toolName}`);
156472
158240
  }
156473
- const clientInfo = this.clients.get(tool2.serverName);
158241
+ const clientInfo = this.clients.get(tool3.serverName);
156474
158242
  if (!clientInfo) {
156475
- throw new Error(`Server ${tool2.serverName} not connected`);
158243
+ throw new Error(`Server ${tool3.serverName} not connected`);
156476
158244
  }
156477
158245
  try {
156478
158246
  if (this.debug) {
156479
158247
  console.error(`[MCP] Calling ${toolName} with args:`, args);
156480
158248
  }
156481
158249
  const result = await clientInfo.client.callTool({
156482
- name: tool2.originalName,
158250
+ name: tool3.originalName,
156483
158251
  arguments: args
156484
158252
  });
156485
158253
  return result;
@@ -156494,11 +158262,11 @@ var init_client2 = __esm({
156494
158262
  */
156495
158263
  getTools() {
156496
158264
  const tools2 = {};
156497
- for (const [name14, tool2] of this.tools.entries()) {
158265
+ for (const [name14, tool3] of this.tools.entries()) {
156498
158266
  tools2[name14] = {
156499
- description: tool2.description,
156500
- inputSchema: tool2.inputSchema,
156501
- serverName: tool2.serverName
158267
+ description: tool3.description,
158268
+ inputSchema: tool3.inputSchema,
158269
+ serverName: tool3.serverName
156502
158270
  };
156503
158271
  }
156504
158272
  return tools2;
@@ -156509,10 +158277,10 @@ var init_client2 = __esm({
156509
158277
  */
156510
158278
  getVercelTools() {
156511
158279
  const tools2 = {};
156512
- for (const [name14, tool2] of this.tools.entries()) {
158280
+ for (const [name14, tool3] of this.tools.entries()) {
156513
158281
  tools2[name14] = {
156514
- description: tool2.description,
156515
- inputSchema: tool2.inputSchema,
158282
+ description: tool3.description,
158283
+ inputSchema: tool3.inputSchema,
156516
158284
  execute: async (args) => {
156517
158285
  const result = await this.callTool(name14, args);
156518
158286
  if (result.content && result.content[0]) {
@@ -156549,9 +158317,9 @@ var init_client2 = __esm({
156549
158317
  });
156550
158318
 
156551
158319
  // src/agent/mcp/xmlBridge.js
156552
- function mcpToolToXmlDefinition(name14, tool2) {
156553
- const description = tool2.description || "MCP tool";
156554
- const inputSchema = tool2.inputSchema || tool2.parameters || {};
158320
+ function mcpToolToXmlDefinition(name14, tool3) {
158321
+ const description = tool3.description || "MCP tool";
158322
+ const inputSchema = tool3.inputSchema || tool3.parameters || {};
156555
158323
  let paramDocs = "";
156556
158324
  if (inputSchema.properties) {
156557
158325
  paramDocs = "\n\nParameters (provide as JSON object):";
@@ -156711,8 +158479,8 @@ var init_xmlBridge = __esm({
156711
158479
  const result = await this.mcpManager.initialize(mcpConfigs);
156712
158480
  const vercelTools = this.mcpManager.getVercelTools();
156713
158481
  this.mcpTools = vercelTools;
156714
- for (const [name14, tool2] of Object.entries(vercelTools)) {
156715
- this.xmlDefinitions[name14] = mcpToolToXmlDefinition(name14, tool2);
158482
+ for (const [name14, tool3] of Object.entries(vercelTools)) {
158483
+ this.xmlDefinitions[name14] = mcpToolToXmlDefinition(name14, tool3);
156716
158484
  }
156717
158485
  if (this.debug) {
156718
158486
  console.error(`[MCP] Loaded ${Object.keys(vercelTools).length} MCP tools from ${result.connected} server(s)`);
@@ -156749,12 +158517,12 @@ var init_xmlBridge = __esm({
156749
158517
  if (this.debug) {
156750
158518
  console.error(`[MCP] Executing MCP tool: ${toolName} with params:`, params);
156751
158519
  }
156752
- const tool2 = this.mcpTools[toolName];
156753
- if (!tool2) {
158520
+ const tool3 = this.mcpTools[toolName];
158521
+ if (!tool3) {
156754
158522
  throw new Error(`Unknown MCP tool: ${toolName}`);
156755
158523
  }
156756
158524
  try {
156757
- const result = await tool2.execute(params);
158525
+ const result = await tool3.execute(params);
156758
158526
  return {
156759
158527
  success: true,
156760
158528
  toolName,
@@ -156806,7 +158574,7 @@ var ProbeAgent_exports = {};
156806
158574
  __export(ProbeAgent_exports, {
156807
158575
  ProbeAgent: () => ProbeAgent
156808
158576
  });
156809
- 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;
158577
+ 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;
156810
158578
  var init_ProbeAgent = __esm({
156811
158579
  "src/agent/ProbeAgent.js"() {
156812
158580
  "use strict";
@@ -156814,12 +158582,12 @@ var init_ProbeAgent = __esm({
156814
158582
  import_openai = __nccwpck_require__(87635);
156815
158583
  import_google = __nccwpck_require__(30260);
156816
158584
  init_dist3();
156817
- import_ai2 = __nccwpck_require__(86619);
158585
+ import_ai3 = __nccwpck_require__(86619);
156818
158586
  import_crypto5 = __nccwpck_require__(76982);
156819
158587
  import_events2 = __nccwpck_require__(24434);
156820
- import_fs5 = __nccwpck_require__(79896);
158588
+ import_fs6 = __nccwpck_require__(79896);
156821
158589
  import_promises = __nccwpck_require__(91943);
156822
- import_path7 = __nccwpck_require__(16928);
158590
+ import_path9 = __nccwpck_require__(16928);
156823
158591
  init_tokenCounter();
156824
158592
  init_tools2();
156825
158593
  init_common();
@@ -156863,6 +158631,8 @@ var init_ProbeAgent = __esm({
156863
158631
  this.outline = !!options.outline;
156864
158632
  this.maxResponseTokens = options.maxResponseTokens || parseInt(process.env.MAX_RESPONSE_TOKENS || "0", 10) || null;
156865
158633
  this.disableMermaidValidation = !!options.disableMermaidValidation;
158634
+ this.enableBash = !!options.enableBash;
158635
+ this.bashConfig = options.bashConfig || {};
156866
158636
  if (options.allowedFolders && Array.isArray(options.allowedFolders)) {
156867
158637
  this.allowedFolders = options.allowedFolders;
156868
158638
  } else if (options.path) {
@@ -156906,7 +158676,9 @@ var init_ProbeAgent = __esm({
156906
158676
  debug: this.debug,
156907
158677
  defaultPath: this.allowedFolders.length > 0 ? this.allowedFolders[0] : process.cwd(),
156908
158678
  allowedFolders: this.allowedFolders,
156909
- outline: this.outline
158679
+ outline: this.outline,
158680
+ enableBash: this.enableBash,
158681
+ bashConfig: this.bashConfig
156910
158682
  };
156911
158683
  const baseTools = createTools(configOptions);
156912
158684
  const wrappedTools = createWrappedTools(baseTools);
@@ -156918,6 +158690,9 @@ var init_ProbeAgent = __esm({
156918
158690
  listFiles: listFilesToolInstance,
156919
158691
  searchFiles: searchFilesToolInstance
156920
158692
  };
158693
+ if (this.enableBash && wrappedTools.bashToolInstance) {
158694
+ this.toolImplementations.bash = wrappedTools.bashToolInstance;
158695
+ }
156921
158696
  this.wrappedTools = wrappedTools;
156922
158697
  }
156923
158698
  /**
@@ -157104,13 +158879,13 @@ var init_ProbeAgent = __esm({
157104
158879
  const allowedDirs = this.allowedFolders && this.allowedFolders.length > 0 ? this.allowedFolders : [process.cwd()];
157105
158880
  let absolutePath;
157106
158881
  let isPathAllowed = false;
157107
- if ((0, import_path7.isAbsolute)(imagePath)) {
158882
+ if ((0, import_path9.isAbsolute)(imagePath)) {
157108
158883
  absolutePath = imagePath;
157109
- isPathAllowed = allowedDirs.some((dir) => absolutePath.startsWith((0, import_path7.resolve)(dir)));
158884
+ isPathAllowed = allowedDirs.some((dir) => absolutePath.startsWith((0, import_path9.resolve)(dir)));
157110
158885
  } else {
157111
158886
  for (const dir of allowedDirs) {
157112
- const resolvedPath3 = (0, import_path7.resolve)(dir, imagePath);
157113
- if (resolvedPath3.startsWith((0, import_path7.resolve)(dir))) {
158887
+ const resolvedPath3 = (0, import_path9.resolve)(dir, imagePath);
158888
+ if (resolvedPath3.startsWith((0, import_path9.resolve)(dir))) {
157114
158889
  absolutePath = resolvedPath3;
157115
158890
  isPathAllowed = true;
157116
158891
  break;
@@ -157605,7 +159380,7 @@ You are working with a repository located at: ${searchDirectory}
157605
159380
  try {
157606
159381
  const executeAIRequest = async () => {
157607
159382
  const messagesForAI = this.prepareMessagesWithImages(currentMessages);
157608
- const result = await (0, import_ai2.streamText)({
159383
+ const result = await (0, import_ai3.streamText)({
157609
159384
  model: this.provider(this.model),
157610
159385
  messages: messagesForAI,
157611
159386
  maxTokens: maxResponseTokens,
@@ -158282,12 +160057,12 @@ function initializeSimpleTelemetryFromOptions(options) {
158282
160057
  });
158283
160058
  return telemetry;
158284
160059
  }
158285
- var import_fs6, import_path8, SimpleTelemetry, SimpleAppTracer;
160060
+ var import_fs7, import_path10, SimpleTelemetry, SimpleAppTracer;
158286
160061
  var init_simpleTelemetry = __esm({
158287
160062
  "src/agent/simpleTelemetry.js"() {
158288
160063
  "use strict";
158289
- import_fs6 = __nccwpck_require__(79896);
158290
- import_path8 = __nccwpck_require__(16928);
160064
+ import_fs7 = __nccwpck_require__(79896);
160065
+ import_path10 = __nccwpck_require__(16928);
158291
160066
  SimpleTelemetry = class {
158292
160067
  constructor(options = {}) {
158293
160068
  this.serviceName = options.serviceName || "probe-agent";
@@ -158301,11 +160076,11 @@ var init_simpleTelemetry = __esm({
158301
160076
  }
158302
160077
  initializeFileExporter() {
158303
160078
  try {
158304
- const dir = (0, import_path8.dirname)(this.filePath);
158305
- if (!(0, import_fs6.existsSync)(dir)) {
158306
- (0, import_fs6.mkdirSync)(dir, { recursive: true });
160079
+ const dir = (0, import_path10.dirname)(this.filePath);
160080
+ if (!(0, import_fs7.existsSync)(dir)) {
160081
+ (0, import_fs7.mkdirSync)(dir, { recursive: true });
158307
160082
  }
158308
- this.stream = (0, import_fs6.createWriteStream)(this.filePath, { flags: "a" });
160083
+ this.stream = (0, import_fs7.createWriteStream)(this.filePath, { flags: "a" });
158309
160084
  this.stream.on("error", (error2) => {
158310
160085
  console.error(`[SimpleTelemetry] Stream error: ${error2.message}`);
158311
160086
  });
@@ -158366,20 +160141,20 @@ var init_simpleTelemetry = __esm({
158366
160141
  }
158367
160142
  async flush() {
158368
160143
  if (this.stream) {
158369
- return new Promise((resolve2) => {
158370
- this.stream.once("drain", resolve2);
160144
+ return new Promise((resolve4) => {
160145
+ this.stream.once("drain", resolve4);
158371
160146
  if (!this.stream.writableNeedDrain) {
158372
- resolve2();
160147
+ resolve4();
158373
160148
  }
158374
160149
  });
158375
160150
  }
158376
160151
  }
158377
160152
  async shutdown() {
158378
160153
  if (this.stream) {
158379
- return new Promise((resolve2) => {
160154
+ return new Promise((resolve4) => {
158380
160155
  this.stream.end(() => {
158381
160156
  console.log(`[SimpleTelemetry] File stream closed: ${this.filePath}`);
158382
- resolve2();
160157
+ resolve4();
158383
160158
  });
158384
160159
  });
158385
160160
  }
@@ -158506,6 +160281,9 @@ __export(index_exports, {
158506
160281
  SimpleTelemetry: () => SimpleTelemetry,
158507
160282
  attemptCompletionSchema: () => attemptCompletionSchema,
158508
160283
  attemptCompletionToolDefinition: () => attemptCompletionToolDefinition,
160284
+ bashSchema: () => bashSchema,
160285
+ bashTool: () => bashTool,
160286
+ bashToolDefinition: () => bashToolDefinition,
158509
160287
  delegate: () => delegate,
158510
160288
  delegateSchema: () => delegateSchema,
158511
160289
  delegateTool: () => delegateTool,
@@ -158542,6 +160320,7 @@ var init_index = __esm({
158542
160320
  init_system_message();
158543
160321
  init_common();
158544
160322
  init_vercel();
160323
+ init_bash();
158545
160324
  init_ProbeAgent();
158546
160325
  init_simpleTelemetry();
158547
160326
  }