@probelabs/visor 0.1.40 → 0.1.41

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.
@@ -1 +1 @@
1
- {"version":3,"file":"","sourceRoot":"","sources":["file:///home/runner/work/visor/visor/src/ai-review-service.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"","sourceRoot":"","sources":["file:///home/runner/work/visor/visor/src/ai-review-service.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"","sourceRoot":"","sources":["file:///home/runner/work/visor/visor/src/cli-main.ts"],"names":[],"mappings":"AAQA;;GAEG;AACH,wBAAsB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CA2M1C"}
1
+ {"version":3,"file":"","sourceRoot":"","sources":["file:///home/runner/work/visor/visor/src/cli-main.ts"],"names":[],"mappings":"AAOA;;GAEG;AACH,wBAAsB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CA2P1C"}
package/dist/cli.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"","sourceRoot":"","sources":["file:///home/runner/work/visor/visor/src/cli.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAA2B,MAAM,aAAa,CAAC;AAIlE;;GAEG;AACH,qBAAa,GAAG;IACd,OAAO,CAAC,OAAO,CAAU;IACzB,OAAO,CAAC,WAAW,CAA4E;IAC/F,OAAO,CAAC,YAAY,CAA0D;;IAO9E;;OAEG;IACH,OAAO,CAAC,YAAY;IAsCpB;;OAEG;IACH,OAAO,CAAC,aAAa,CAEnB;IAEF;;OAEG;IACI,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,UAAU;IAuH5C;;OAEG;IACH,OAAO,CAAC,eAAe;IAkCvB;;OAEG;IACI,WAAW,IAAI,MAAM;IAkC5B;;OAEG;IACI,UAAU,IAAI,MAAM;IAa3B;;OAEG;IACI,eAAe,IAAI,MAAM;IAiBhC;;OAEG;IACI,QAAQ,IAAI,IAAI;IAIvB;;OAEG;IACI,WAAW,IAAI,IAAI;CAG3B"}
1
+ {"version":3,"file":"","sourceRoot":"","sources":["file:///home/runner/work/visor/visor/src/cli.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAA2B,MAAM,aAAa,CAAC;AAIlE;;GAEG;AACH,qBAAa,GAAG;IACd,OAAO,CAAC,OAAO,CAAU;IACzB,OAAO,CAAC,WAAW,CAA4E;IAC/F,OAAO,CAAC,YAAY,CAA0D;;IAO9E;;OAEG;IACH,OAAO,CAAC,YAAY;IAwCpB;;OAEG;IACH,OAAO,CAAC,aAAa,CAEnB;IAEF;;OAEG;IACI,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,UAAU;IAkI5C;;OAEG;IACH,OAAO,CAAC,eAAe;IAkCvB;;OAEG;IACI,WAAW,IAAI,MAAM;IAsC5B;;OAEG;IACI,UAAU,IAAI,MAAM;IAa3B;;OAEG;IACI,eAAe,IAAI,MAAM;IAiBhC;;OAEG;IACI,QAAQ,IAAI,IAAI;IAIvB;;OAEG;IACI,WAAW,IAAI,IAAI;CAG3B"}
@@ -27,11 +27,11 @@ export declare class GitRepositoryAnalyzer {
27
27
  /**
28
28
  * Analyze the current git repository state and return data compatible with PRInfo interface
29
29
  */
30
- analyzeRepository(): Promise<GitRepositoryInfo>;
30
+ analyzeRepository(includeContext?: boolean): Promise<GitRepositoryInfo>;
31
31
  /**
32
32
  * Convert GitRepositoryInfo to PRInfo format for compatibility with existing PRReviewer
33
33
  */
34
- toPRInfo(repositoryInfo: GitRepositoryInfo): PRInfo;
34
+ toPRInfo(repositoryInfo: GitRepositoryInfo, includeContext?: boolean): PRInfo;
35
35
  private isGitRepository;
36
36
  private getCurrentBranch;
37
37
  private getBaseBranch;
@@ -1 +1 @@
1
- {"version":3,"file":"","sourceRoot":"","sources":["file:///home/runner/work/visor/visor/src/git-repository-analyzer.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,MAAM,EAAU,MAAM,eAAe,CAAC;AAE/C,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,OAAO,GAAG,SAAS,GAAG,UAAU,GAAG,SAAS,CAAC;IACrD,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,aAAa,EAAE,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;IACvB,eAAe,EAAE,OAAO,CAAC;IACzB,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAED,qBAAa,qBAAqB;IAChC,OAAO,CAAC,GAAG,CAAY;IACvB,OAAO,CAAC,GAAG,CAAS;gBAER,gBAAgB,GAAE,MAAsB;IAKpD;;OAEG;IACG,iBAAiB,IAAI,OAAO,CAAC,iBAAiB,CAAC;IA0CrD;;OAEG;IACH,QAAQ,CAAC,cAAc,EAAE,iBAAiB,GAAG,MAAM;YAuBrC,eAAe;YASf,gBAAgB;YAShB,aAAa;YAmBb,aAAa;YAYb,qBAAqB;YA6BrB,iBAAiB;IAyD/B,OAAO,CAAC,aAAa;IAcrB,OAAO,CAAC,mBAAmB;IA4B3B,OAAO,CAAC,yBAAyB;CAclC"}
1
+ {"version":3,"file":"","sourceRoot":"","sources":["file:///home/runner/work/visor/visor/src/git-repository-analyzer.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,MAAM,EAAU,MAAM,eAAe,CAAC;AAE/C,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,OAAO,GAAG,SAAS,GAAG,UAAU,GAAG,SAAS,CAAC;IACrD,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,aAAa,EAAE,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;IACvB,eAAe,EAAE,OAAO,CAAC;IACzB,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAED,qBAAa,qBAAqB;IAChC,OAAO,CAAC,GAAG,CAAY;IACvB,OAAO,CAAC,GAAG,CAAS;gBAER,gBAAgB,GAAE,MAAsB;IAKpD;;OAEG;IACG,iBAAiB,CAAC,cAAc,GAAE,OAAc,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAgEnF;;OAEG;IACH,QAAQ,CAAC,cAAc,EAAE,iBAAiB,EAAE,cAAc,GAAE,OAAc,GAAG,MAAM;YAmCrE,eAAe;YASf,gBAAgB;YAShB,aAAa;YAmBb,aAAa;YAYb,qBAAqB;YA6BrB,iBAAiB;IAsE/B,OAAO,CAAC,aAAa;IAcrB,OAAO,CAAC,mBAAmB;IA4B3B,OAAO,CAAC,yBAAyB;CAclC"}
package/dist/index.js CHANGED
@@ -94115,6 +94115,21 @@ ${prContext}
94115
94115
  formatPRContext(prInfo) {
94116
94116
  // Check if this is an issue (not a PR)
94117
94117
  const isIssue = prInfo.isIssue === true;
94118
+ // Check if we should include code context (diffs)
94119
+ const isPRContext = prInfo.isPRContext === true;
94120
+ // In PR context, always include diffs. Otherwise check the flag.
94121
+ const includeCodeContext = isPRContext || prInfo.includeCodeContext !== false;
94122
+ // Log the decision for transparency
94123
+ const log = this.config.debug ? console.error : () => { };
94124
+ if (isPRContext) {
94125
+ log('🔍 Including full code diffs in AI context (PR mode)');
94126
+ }
94127
+ else if (!includeCodeContext) {
94128
+ log('📊 Including only file summary in AI context (no diffs)');
94129
+ }
94130
+ else {
94131
+ log('🔍 Including code diffs in AI context');
94132
+ }
94118
94133
  if (isIssue) {
94119
94134
  // Format as issue context
94120
94135
  let context = `<issue>
@@ -94236,31 +94251,39 @@ ${this.escapeXml(prInfo.body)}
94236
94251
  ${this.escapeXml(prInfo.body)}
94237
94252
  </description>`;
94238
94253
  }
94239
- // Add full diff if available (for complete PR review)
94240
- if (prInfo.fullDiff) {
94241
- context += `
94254
+ // Add diffs only if includeCodeContext is true (or in PR mode)
94255
+ if (includeCodeContext) {
94256
+ // Add full diff if available (for complete PR review)
94257
+ if (prInfo.fullDiff) {
94258
+ context += `
94242
94259
  <!-- Complete unified diff showing all changes in the pull request -->
94243
94260
  <full_diff>
94244
94261
  ${this.escapeXml(prInfo.fullDiff)}
94245
94262
  </full_diff>`;
94246
- }
94247
- // Add incremental commit diff if available (for new commit analysis)
94248
- if (prInfo.isIncremental) {
94249
- if (prInfo.commitDiff && prInfo.commitDiff.length > 0) {
94250
- context += `
94263
+ }
94264
+ // Add incremental commit diff if available (for new commit analysis)
94265
+ if (prInfo.isIncremental) {
94266
+ if (prInfo.commitDiff && prInfo.commitDiff.length > 0) {
94267
+ context += `
94251
94268
  <!-- Diff of only the latest commit for incremental analysis -->
94252
94269
  <commit_diff>
94253
94270
  ${this.escapeXml(prInfo.commitDiff)}
94254
94271
  </commit_diff>`;
94255
- }
94256
- else {
94257
- context += `
94272
+ }
94273
+ else {
94274
+ context += `
94258
94275
  <!-- Commit diff could not be retrieved - falling back to full diff analysis -->
94259
94276
  <commit_diff>
94260
94277
  ${prInfo.fullDiff ? this.escapeXml(prInfo.fullDiff) : ''}
94261
94278
  </commit_diff>`;
94279
+ }
94262
94280
  }
94263
94281
  }
94282
+ else {
94283
+ // When not including diffs, add a note about it
94284
+ context += `
94285
+ <!-- Code diffs excluded to reduce token usage (no code-review schema detected or disabled by flag) -->`;
94286
+ }
94264
94287
  // Add file summary for context
94265
94288
  if (prInfo.files.length > 0) {
94266
94289
  context += `
@@ -96869,10 +96892,6 @@ async function main() {
96869
96892
  .findAndLoadConfig()
96870
96893
  .catch(() => configManager.getDefaultConfig());
96871
96894
  }
96872
- // Get repository info using GitRepositoryAnalyzer
96873
- const { GitRepositoryAnalyzer } = await Promise.resolve().then(() => __importStar(__nccwpck_require__(71259)));
96874
- const analyzer = new GitRepositoryAnalyzer(process.cwd());
96875
- const repositoryInfo = await analyzer.analyzeRepository();
96876
96895
  // Determine checks to run and validate check types early
96877
96896
  const checksToRun = options.checks.length > 0 ? options.checks : Object.keys(config.checks || {});
96878
96897
  // Validate that all requested checks exist in the configuration
@@ -96882,13 +96901,58 @@ async function main() {
96882
96901
  console.error(`❌ Error: No configuration found for check: ${invalidChecks[0]}`);
96883
96902
  process.exit(1);
96884
96903
  }
96885
- // Check if we're in a git repository and handle error early
96904
+ // Use stderr for status messages when outputting formatted results to stdout
96905
+ const logFn = console.error;
96906
+ // Determine if we should include code context (diffs)
96907
+ // In CLI mode (local), we do smart detection. PR mode always includes context.
96908
+ const isPRContext = false; // This is CLI mode, not GitHub Action
96909
+ let includeCodeContext = false;
96910
+ if (isPRContext) {
96911
+ // ALWAYS include full context in PR/GitHub Action mode
96912
+ includeCodeContext = true;
96913
+ logFn('📝 Code context: ENABLED (PR context - always included)');
96914
+ }
96915
+ else if (options.codeContext === 'enabled') {
96916
+ includeCodeContext = true;
96917
+ logFn('📝 Code context: ENABLED (forced by --enable-code-context)');
96918
+ }
96919
+ else if (options.codeContext === 'disabled') {
96920
+ includeCodeContext = false;
96921
+ logFn('📝 Code context: DISABLED (forced by --disable-code-context)');
96922
+ }
96923
+ else {
96924
+ // Auto-detect based on schemas (CLI mode only)
96925
+ const hasCodeReviewSchema = checksToRun.some(check => config.checks?.[check]?.schema === 'code-review');
96926
+ includeCodeContext = hasCodeReviewSchema;
96927
+ if (hasCodeReviewSchema) {
96928
+ logFn('📝 Code context: ENABLED (code-review schema detected in local mode)');
96929
+ }
96930
+ else {
96931
+ logFn('📝 Code context: DISABLED (no code-review schema found in local mode)');
96932
+ }
96933
+ }
96934
+ // Get repository info using GitRepositoryAnalyzer
96935
+ const { GitRepositoryAnalyzer } = await Promise.resolve().then(() => __importStar(__nccwpck_require__(71259)));
96936
+ const analyzer = new GitRepositoryAnalyzer(process.cwd());
96937
+ let repositoryInfo;
96938
+ try {
96939
+ repositoryInfo = await analyzer.analyzeRepository(includeCodeContext);
96940
+ }
96941
+ catch (error) {
96942
+ console.error('❌ Error analyzing git repository:', error);
96943
+ console.error('💡 Make sure you are in a git repository or initialize one with "git init"');
96944
+ process.exit(1);
96945
+ }
96946
+ // Check if we're in a git repository
96886
96947
  if (!repositoryInfo.isGitRepository) {
96887
- console.error('❌ Error: Not a git repository or no changes found');
96948
+ console.error('❌ Error: Not a git repository. Run "git init" to initialize a repository.');
96949
+ process.exit(1);
96950
+ }
96951
+ // Check if there are any changes to analyze
96952
+ if (repositoryInfo.files.length === 0) {
96953
+ console.error('❌ Error: No changes to analyze. Make some file changes first.');
96888
96954
  process.exit(1);
96889
96955
  }
96890
- // Use stderr for status messages when outputting formatted results to stdout
96891
- const logFn = console.error;
96892
96956
  logFn('🔍 Visor - AI-powered code review tool');
96893
96957
  logFn(`Configuration version: ${config.version}`);
96894
96958
  logFn(`Configuration source: ${options.configPath || 'default search locations'}`);
@@ -96911,8 +96975,12 @@ async function main() {
96911
96975
  exclude: options.excludeTags,
96912
96976
  }
96913
96977
  : undefined;
96914
- // Execute checks with proper parameters (cast to PRInfo)
96915
- const groupedResults = await engine.executeGroupedChecks(repositoryInfo, checksToRun, options.timeout, config, options.output, options.debug || false, options.maxParallelism, options.failFast, tagFilter);
96978
+ // Convert repository info to PRInfo format
96979
+ const prInfo = analyzer.toPRInfo(repositoryInfo, includeCodeContext);
96980
+ // Store the includeCodeContext flag in prInfo for downstream use
96981
+ prInfo.includeCodeContext = includeCodeContext;
96982
+ // Execute checks with proper parameters
96983
+ const groupedResults = await engine.executeGroupedChecks(prInfo, checksToRun, options.timeout, config, options.output, options.debug || false, options.maxParallelism, options.failFast, tagFilter);
96916
96984
  // Format output based on format type
96917
96985
  let output;
96918
96986
  if (options.output === 'json') {
@@ -97081,6 +97149,8 @@ class CLI {
97081
97149
  .option('--tags <tags>', 'Include checks with these tags (comma-separated)')
97082
97150
  .option('--exclude-tags <tags>', 'Exclude checks with these tags (comma-separated)')
97083
97151
  .option('--no-remote-extends', 'Disable loading configurations from remote URLs')
97152
+ .option('--enable-code-context', 'Force include code diffs in analysis (CLI mode)')
97153
+ .option('--disable-code-context', 'Force exclude code diffs from analysis (CLI mode)')
97084
97154
  .addHelpText('after', this.getExamplesText())
97085
97155
  .exitOverride(); // Prevent automatic process.exit for better error handling
97086
97156
  // Add validation for options
@@ -97118,6 +97188,8 @@ class CLI {
97118
97188
  .option('--tags <tags>', 'Include checks with these tags (comma-separated)')
97119
97189
  .option('--exclude-tags <tags>', 'Exclude checks with these tags (comma-separated)')
97120
97190
  .option('--allowed-remote-patterns <patterns>', 'Comma-separated list of allowed URL prefixes for remote config extends (e.g., "https://github.com/,https://raw.githubusercontent.com/")')
97191
+ .option('--enable-code-context', 'Force include code diffs in analysis (CLI mode)')
97192
+ .option('--disable-code-context', 'Force exclude code diffs from analysis (CLI mode)')
97121
97193
  .allowUnknownOption(false)
97122
97194
  .allowExcessArguments(false) // Don't allow positional arguments
97123
97195
  .addHelpText('after', this.getExamplesText())
@@ -97148,6 +97220,14 @@ class CLI {
97148
97220
  if (options.excludeTags) {
97149
97221
  excludeTags = options.excludeTags.split(',').map((t) => t.trim());
97150
97222
  }
97223
+ // Determine code context mode
97224
+ let codeContext = 'auto';
97225
+ if (options.enableCodeContext) {
97226
+ codeContext = 'enabled';
97227
+ }
97228
+ else if (options.disableCodeContext) {
97229
+ codeContext = 'disabled';
97230
+ }
97151
97231
  return {
97152
97232
  checks: uniqueChecks,
97153
97233
  output: options.output,
@@ -97161,6 +97241,7 @@ class CLI {
97161
97241
  allowedRemotePatterns,
97162
97242
  help: options.help,
97163
97243
  version: options.version,
97244
+ codeContext,
97164
97245
  };
97165
97246
  }
97166
97247
  catch (error) {
@@ -97229,6 +97310,10 @@ class CLI {
97229
97310
  .option('--max-parallelism <count>', 'Maximum number of checks to run in parallel (default: 3)', value => parseInt(value, 10))
97230
97311
  .option('--debug', 'Enable debug mode for detailed output')
97231
97312
  .option('--fail-fast', 'Stop execution on first failure condition')
97313
+ .option('--tags <tags>', 'Include checks with these tags (comma-separated)')
97314
+ .option('--exclude-tags <tags>', 'Exclude checks with these tags (comma-separated)')
97315
+ .option('--enable-code-context', 'Force include code diffs in analysis (CLI mode)')
97316
+ .option('--disable-code-context', 'Force exclude code diffs from analysis (CLI mode)')
97232
97317
  .addHelpText('after', this.getExamplesText());
97233
97318
  // Get the basic help and append examples manually if addHelpText doesn't work
97234
97319
  const basicHelp = tempProgram.helpInformation();
@@ -98780,7 +98865,7 @@ class GitRepositoryAnalyzer {
98780
98865
  /**
98781
98866
  * Analyze the current git repository state and return data compatible with PRInfo interface
98782
98867
  */
98783
- async analyzeRepository() {
98868
+ async analyzeRepository(includeContext = true) {
98784
98869
  // Check if we're in a git repository
98785
98870
  const isRepo = await this.isGitRepository();
98786
98871
  if (!isRepo) {
@@ -98793,15 +98878,36 @@ class GitRepositoryAnalyzer {
98793
98878
  this.getCurrentBranch(),
98794
98879
  ]);
98795
98880
  // Get uncommitted changes
98796
- const uncommittedFiles = await this.getUncommittedChanges();
98797
- // Get recent commit info
98798
- const recentCommits = await this.git.log({ maxCount: 1 });
98799
- const lastCommit = recentCommits.latest;
98881
+ const uncommittedFiles = await this.getUncommittedChanges(includeContext);
98882
+ // Get recent commit info (handle repos with no commits)
98883
+ let lastCommit = null;
98884
+ try {
98885
+ const recentCommits = await this.git.log({ maxCount: 1 });
98886
+ lastCommit = recentCommits.latest;
98887
+ }
98888
+ catch {
98889
+ // Repository has no commits yet - this is OK
98890
+ console.log('📝 Repository has no commits yet, analyzing uncommitted changes');
98891
+ }
98892
+ // Get author from git config if no commits exist
98893
+ let author = lastCommit?.author_name;
98894
+ if (!author) {
98895
+ try {
98896
+ const [userName, userEmail] = await Promise.all([
98897
+ this.git.raw(['config', 'user.name']).catch(() => null),
98898
+ this.git.raw(['config', 'user.email']).catch(() => null),
98899
+ ]);
98900
+ author = userName?.trim() || userEmail?.trim() || 'unknown';
98901
+ }
98902
+ catch {
98903
+ author = 'unknown';
98904
+ }
98905
+ }
98800
98906
  // Create repository info
98801
98907
  const repositoryInfo = {
98802
98908
  title: this.generateTitle(status, currentBranch),
98803
98909
  body: this.generateDescription(status, lastCommit),
98804
- author: lastCommit?.author_name || 'unknown',
98910
+ author,
98805
98911
  base: await this.getBaseBranch(),
98806
98912
  head: currentBranch,
98807
98913
  files: uncommittedFiles,
@@ -98813,14 +98919,32 @@ class GitRepositoryAnalyzer {
98813
98919
  return repositoryInfo;
98814
98920
  }
98815
98921
  catch (error) {
98816
- console.error('Error analyzing git repository:', error);
98922
+ // Don't log the full error object to avoid confusing stack traces
98923
+ const errorMessage = error instanceof Error ? error.message : 'Unknown error';
98924
+ console.error('Error analyzing git repository:', errorMessage);
98817
98925
  return this.createEmptyRepositoryInfo('Error analyzing git repository');
98818
98926
  }
98819
98927
  }
98820
98928
  /**
98821
98929
  * Convert GitRepositoryInfo to PRInfo format for compatibility with existing PRReviewer
98822
98930
  */
98823
- toPRInfo(repositoryInfo) {
98931
+ toPRInfo(repositoryInfo, includeContext = true) {
98932
+ const files = repositoryInfo.files.map((file) => ({
98933
+ filename: file.filename,
98934
+ additions: file.additions,
98935
+ deletions: file.deletions,
98936
+ changes: file.changes,
98937
+ patch: includeContext ? file.patch : undefined,
98938
+ status: file.status,
98939
+ }));
98940
+ // Generate fullDiff from patches if includeContext is true
98941
+ let fullDiff;
98942
+ if (includeContext) {
98943
+ fullDiff = files
98944
+ .filter(file => file.patch)
98945
+ .map(file => `--- ${file.filename}\n${file.patch}`)
98946
+ .join('\n\n');
98947
+ }
98824
98948
  return {
98825
98949
  number: 0, // Local analysis doesn't have PR number
98826
98950
  title: repositoryInfo.title,
@@ -98828,16 +98952,10 @@ class GitRepositoryAnalyzer {
98828
98952
  author: repositoryInfo.author,
98829
98953
  base: repositoryInfo.base,
98830
98954
  head: repositoryInfo.head,
98831
- files: repositoryInfo.files.map((file) => ({
98832
- filename: file.filename,
98833
- additions: file.additions,
98834
- deletions: file.deletions,
98835
- changes: file.changes,
98836
- patch: file.patch,
98837
- status: file.status,
98838
- })),
98955
+ files,
98839
98956
  totalAdditions: repositoryInfo.totalAdditions,
98840
98957
  totalDeletions: repositoryInfo.totalDeletions,
98958
+ fullDiff,
98841
98959
  };
98842
98960
  }
98843
98961
  async isGitRepository() {
@@ -98887,7 +99005,7 @@ class GitRepositoryAnalyzer {
98887
99005
  return null;
98888
99006
  }
98889
99007
  }
98890
- async getUncommittedChanges() {
99008
+ async getUncommittedChanges(includeContext = true) {
98891
99009
  try {
98892
99010
  const status = await this.git.status();
98893
99011
  const changes = [];
@@ -98903,7 +99021,7 @@ class GitRepositoryAnalyzer {
98903
99021
  ];
98904
99022
  for (const { file, status } of fileChanges) {
98905
99023
  const filePath = path.join(this.cwd, file);
98906
- const fileChange = await this.analyzeFileChange(file, status, filePath);
99024
+ const fileChange = await this.analyzeFileChange(file, status, filePath, includeContext);
98907
99025
  changes.push(fileChange);
98908
99026
  }
98909
99027
  return changes;
@@ -98913,14 +99031,14 @@ class GitRepositoryAnalyzer {
98913
99031
  return [];
98914
99032
  }
98915
99033
  }
98916
- async analyzeFileChange(filename, status, filePath) {
99034
+ async analyzeFileChange(filename, status, filePath, includeContext = true) {
98917
99035
  let additions = 0;
98918
99036
  let deletions = 0;
98919
99037
  let patch;
98920
99038
  let content;
98921
99039
  try {
98922
99040
  // Get diff for the file if it exists and is not binary
98923
- if (status !== 'added' && fs.existsSync(filePath)) {
99041
+ if (includeContext && status !== 'added' && fs.existsSync(filePath)) {
98924
99042
  const diff = await this.git.diff(['--', filename]).catch(() => '');
98925
99043
  if (diff) {
98926
99044
  patch = diff;
@@ -98930,15 +99048,28 @@ class GitRepositoryAnalyzer {
98930
99048
  deletions = lines.filter(line => line.startsWith('-')).length;
98931
99049
  }
98932
99050
  }
98933
- // For added files, count lines as additions
99051
+ else if (status !== 'added' && fs.existsSync(filePath)) {
99052
+ // If not including context, still count changes for statistics
99053
+ const diff = await this.git.diff(['--', filename]).catch(() => '');
99054
+ if (diff) {
99055
+ const lines = diff.split('\n');
99056
+ additions = lines.filter(line => line.startsWith('+')).length;
99057
+ deletions = lines.filter(line => line.startsWith('-')).length;
99058
+ }
99059
+ }
99060
+ // For added files
98934
99061
  if (status === 'added' && fs.existsSync(filePath)) {
98935
99062
  try {
98936
99063
  const stats = fs.statSync(filePath);
98937
99064
  if (stats.isFile() && stats.size < 1024 * 1024) {
98938
99065
  // Skip files larger than 1MB
98939
- content = fs.readFileSync(filePath, 'utf8');
98940
- additions = content.split('\n').length;
98941
- patch = content; // For new files, the entire content is the "patch"
99066
+ if (includeContext) {
99067
+ content = fs.readFileSync(filePath, 'utf8');
99068
+ patch = content; // For new files, the entire content is the "patch"
99069
+ }
99070
+ // Always count additions for statistics
99071
+ const fileContent = includeContext ? content : fs.readFileSync(filePath, 'utf8');
99072
+ additions = fileContent.split('\n').length;
98942
99073
  }
98943
99074
  }
98944
99075
  catch {
@@ -100320,6 +100451,9 @@ async function handleIssueComment(octokit, owner, repo, context, inputs, actionC
100320
100451
  prInfo = await analyzer.fetchPRDiff(owner, repo, prNumber, undefined, 'issue_comment');
100321
100452
  // Add event context for templates and XML generation
100322
100453
  prInfo.eventContext = context.event;
100454
+ // PR context always includes code diffs
100455
+ prInfo.includeCodeContext = true;
100456
+ prInfo.isPRContext = true;
100323
100457
  }
100324
100458
  else {
100325
100459
  // It's an issue comment - create a minimal PRInfo structure for issue assistant
@@ -100425,11 +100559,16 @@ async function handlePullRequestWithConfig(octokit, owner, repo, inputs, config,
100425
100559
  // Map the action to event type
100426
100560
  const eventType = mapGitHubEventToTrigger('pull_request', action);
100427
100561
  // Fetch PR diff (handle test scenarios gracefully)
100562
+ // In PR context, ALWAYS include full diffs for proper code review
100563
+ console.log('📝 Code context: ENABLED (PR context - always included)');
100428
100564
  let prInfo;
100429
100565
  try {
100430
100566
  prInfo = await analyzer.fetchPRDiff(owner, repo, prNumber, undefined, eventType);
100431
100567
  // Add event context for templates and XML generation
100432
100568
  prInfo.eventContext = context.event;
100569
+ // Mark that we're in PR context and should always include diffs
100570
+ prInfo.includeCodeContext = true;
100571
+ prInfo.isPRContext = true;
100433
100572
  }
100434
100573
  catch (error) {
100435
100574
  // Handle test scenarios with mock repos
@@ -125847,7 +125986,7 @@ async function delegate({ task, timeout = 300, debug = false, currentIteration =
125847
125986
  console.error(`[DELEGATE] Using binary at: ${binaryPath}`);
125848
125987
  console.error(`[DELEGATE] Command args: ${args.join(" ")}`);
125849
125988
  }
125850
- return new Promise((resolve, reject) => {
125989
+ return new Promise((resolve2, reject) => {
125851
125990
  const delegationSpan = tracer ? tracer.createDelegationSpan(sessionId, task) : null;
125852
125991
  const process2 = (0, import_child_process5.spawn)(binaryPath, args, {
125853
125992
  stdio: ["pipe", "pipe", "pipe"],
@@ -125912,7 +126051,7 @@ async function delegate({ task, timeout = 300, debug = false, currentIteration =
125912
126051
  delegationSpan.end();
125913
126052
  }
125914
126053
  }
125915
- resolve(response);
126054
+ resolve2(response);
125916
126055
  } else {
125917
126056
  const errorMessage = stderr.trim() || `Delegate process failed with exit code ${code}`;
125918
126057
  if (debug) {
@@ -127172,7 +127311,7 @@ function createMockProvider() {
127172
127311
  provider: "mock",
127173
127312
  // Mock the doGenerate method used by Vercel AI SDK
127174
127313
  doGenerate: async ({ messages, tools: tools2 }) => {
127175
- await new Promise((resolve) => setTimeout(resolve, 10));
127314
+ await new Promise((resolve2) => setTimeout(resolve2, 10));
127176
127315
  return {
127177
127316
  text: "This is a mock response for testing",
127178
127317
  toolCalls: [],
@@ -128997,7 +129136,7 @@ var ProbeAgent_exports = {};
128997
129136
  __export(ProbeAgent_exports, {
128998
129137
  ProbeAgent: () => ProbeAgent
128999
129138
  });
129000
- var import_anthropic, import_openai, import_google, import_ai2, import_crypto5, import_events2, MAX_TOOL_ITERATIONS, MAX_HISTORY_MESSAGES, ProbeAgent;
129139
+ 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;
129001
129140
  var init_ProbeAgent = __esm({
129002
129141
  "src/agent/ProbeAgent.js"() {
129003
129142
  "use strict";
@@ -129007,6 +129146,9 @@ var init_ProbeAgent = __esm({
129007
129146
  import_ai2 = __nccwpck_require__(86619);
129008
129147
  import_crypto5 = __nccwpck_require__(76982);
129009
129148
  import_events2 = __nccwpck_require__(24434);
129149
+ import_fs5 = __nccwpck_require__(79896);
129150
+ import_promises = __nccwpck_require__(91943);
129151
+ import_path7 = __nccwpck_require__(16928);
129010
129152
  init_tokenCounter();
129011
129153
  init_tools2();
129012
129154
  init_common();
@@ -129017,6 +129159,8 @@ var init_ProbeAgent = __esm({
129017
129159
  init_mcp();
129018
129160
  MAX_TOOL_ITERATIONS = parseInt(process.env.MAX_TOOL_ITERATIONS || "30", 10);
129019
129161
  MAX_HISTORY_MESSAGES = 100;
129162
+ SUPPORTED_IMAGE_EXTENSIONS = ["png", "jpg", "jpeg", "webp", "gif", "bmp", "svg"];
129163
+ MAX_IMAGE_FILE_SIZE = 20 * 1024 * 1024;
129020
129164
  ProbeAgent = class {
129021
129165
  /**
129022
129166
  * Create a new ProbeAgent instance
@@ -129060,6 +129204,8 @@ var init_ProbeAgent = __esm({
129060
129204
  }
129061
129205
  this.initializeTools();
129062
129206
  this.history = [];
129207
+ this.pendingImages = /* @__PURE__ */ new Map();
129208
+ this.currentImages = [];
129063
129209
  this.events = new import_events2.EventEmitter();
129064
129210
  this.enableMcp = !!options.enableMcp || process.env.ENABLE_MCP === "1";
129065
129211
  this.mcpConfigPath = options.mcpConfigPath || null;
@@ -129185,6 +129331,175 @@ var init_ProbeAgent = __esm({
129185
129331
  console.log(`Using Google API with model: ${this.model}${apiUrl ? ` (URL: ${apiUrl})` : ""}`);
129186
129332
  }
129187
129333
  }
129334
+ /**
129335
+ * Process assistant response content and detect/load image references
129336
+ * @param {string} content - The assistant's response content
129337
+ * @returns {Promise<void>}
129338
+ */
129339
+ async processImageReferences(content) {
129340
+ if (!content) return;
129341
+ const extensionsPattern = `(?:${SUPPORTED_IMAGE_EXTENSIONS.join("|")})`;
129342
+ const imagePatterns = [
129343
+ // Direct file path mentions: "./screenshot.png", "/path/to/image.jpg", etc.
129344
+ new RegExp(`(?:\\.?\\.\\/)?[^\\s"'<>\\[\\]]+\\.${extensionsPattern}(?!\\w)`, "gi"),
129345
+ // Contextual mentions: "look at image.png", "the file screenshot.jpg shows"
129346
+ new RegExp(`(?:image|file|screenshot|diagram|photo|picture|graphic)\\s*:?\\s*([^\\s"'<>\\[\\]]+\\.${extensionsPattern})(?!\\w)`, "gi"),
129347
+ // Tool result mentions: often contain file paths
129348
+ new RegExp(`(?:found|saved|created|generated).*?([^\\s"'<>\\[\\]]+\\.${extensionsPattern})(?!\\w)`, "gi")
129349
+ ];
129350
+ const foundPaths = /* @__PURE__ */ new Set();
129351
+ for (const pattern of imagePatterns) {
129352
+ let match;
129353
+ while ((match = pattern.exec(content)) !== null) {
129354
+ const imagePath = match[1] || match[0];
129355
+ if (imagePath && imagePath.length > 0) {
129356
+ foundPaths.add(imagePath.trim());
129357
+ }
129358
+ }
129359
+ }
129360
+ if (foundPaths.size === 0) return;
129361
+ if (this.debug) {
129362
+ console.log(`[DEBUG] Found ${foundPaths.size} potential image references:`, Array.from(foundPaths));
129363
+ }
129364
+ for (const imagePath of foundPaths) {
129365
+ await this.loadImageIfValid(imagePath);
129366
+ }
129367
+ }
129368
+ /**
129369
+ * Load and cache an image if it's valid and accessible
129370
+ * @param {string} imagePath - Path to the image file
129371
+ * @returns {Promise<boolean>} - True if image was loaded successfully
129372
+ */
129373
+ async loadImageIfValid(imagePath) {
129374
+ try {
129375
+ if (this.pendingImages.has(imagePath)) {
129376
+ if (this.debug) {
129377
+ console.log(`[DEBUG] Image already loaded: ${imagePath}`);
129378
+ }
129379
+ return true;
129380
+ }
129381
+ const allowedDirs = this.allowedFolders && this.allowedFolders.length > 0 ? this.allowedFolders : [process.cwd()];
129382
+ let absolutePath;
129383
+ let isPathAllowed = false;
129384
+ if ((0, import_path7.isAbsolute)(imagePath)) {
129385
+ absolutePath = imagePath;
129386
+ isPathAllowed = allowedDirs.some((dir) => absolutePath.startsWith((0, import_path7.resolve)(dir)));
129387
+ } else {
129388
+ for (const dir of allowedDirs) {
129389
+ const resolvedPath = (0, import_path7.resolve)(dir, imagePath);
129390
+ if (resolvedPath.startsWith((0, import_path7.resolve)(dir))) {
129391
+ absolutePath = resolvedPath;
129392
+ isPathAllowed = true;
129393
+ break;
129394
+ }
129395
+ }
129396
+ }
129397
+ if (!isPathAllowed) {
129398
+ if (this.debug) {
129399
+ console.log(`[DEBUG] Image path outside allowed directories: ${imagePath}`);
129400
+ }
129401
+ return false;
129402
+ }
129403
+ let fileStats;
129404
+ try {
129405
+ fileStats = await (0, import_promises.stat)(absolutePath);
129406
+ } catch (error) {
129407
+ if (this.debug) {
129408
+ console.log(`[DEBUG] Image file not found: ${absolutePath}`);
129409
+ }
129410
+ return false;
129411
+ }
129412
+ if (fileStats.size > MAX_IMAGE_FILE_SIZE) {
129413
+ if (this.debug) {
129414
+ console.log(`[DEBUG] Image file too large: ${absolutePath} (${fileStats.size} bytes, max: ${MAX_IMAGE_FILE_SIZE})`);
129415
+ }
129416
+ return false;
129417
+ }
129418
+ const extension = absolutePath.toLowerCase().split(".").pop();
129419
+ if (!SUPPORTED_IMAGE_EXTENSIONS.includes(extension)) {
129420
+ if (this.debug) {
129421
+ console.log(`[DEBUG] Unsupported image format: ${extension}`);
129422
+ }
129423
+ return false;
129424
+ }
129425
+ const mimeTypes = {
129426
+ "png": "image/png",
129427
+ "jpg": "image/jpeg",
129428
+ "jpeg": "image/jpeg",
129429
+ "webp": "image/webp",
129430
+ "gif": "image/gif",
129431
+ "bmp": "image/bmp",
129432
+ "svg": "image/svg+xml"
129433
+ };
129434
+ const mimeType = mimeTypes[extension];
129435
+ const fileBuffer = await (0, import_promises.readFile)(absolutePath);
129436
+ const base64Data = fileBuffer.toString("base64");
129437
+ const dataUrl = `data:${mimeType};base64,${base64Data}`;
129438
+ this.pendingImages.set(imagePath, dataUrl);
129439
+ if (this.debug) {
129440
+ console.log(`[DEBUG] Successfully loaded image: ${imagePath} (${fileBuffer.length} bytes)`);
129441
+ }
129442
+ return true;
129443
+ } catch (error) {
129444
+ if (this.debug) {
129445
+ console.log(`[DEBUG] Failed to load image ${imagePath}: ${error.message}`);
129446
+ }
129447
+ return false;
129448
+ }
129449
+ }
129450
+ /**
129451
+ * Get all currently loaded images as an array for AI model consumption
129452
+ * @returns {Array<string>} - Array of base64 data URLs
129453
+ */
129454
+ getCurrentImages() {
129455
+ return Array.from(this.pendingImages.values());
129456
+ }
129457
+ /**
129458
+ * Clear loaded images (useful for new conversations)
129459
+ */
129460
+ clearLoadedImages() {
129461
+ this.pendingImages.clear();
129462
+ this.currentImages = [];
129463
+ if (this.debug) {
129464
+ console.log("[DEBUG] Cleared all loaded images");
129465
+ }
129466
+ }
129467
+ /**
129468
+ * Prepare messages for AI consumption, adding images to the latest user message if available
129469
+ * @param {Array} messages - Current conversation messages
129470
+ * @returns {Array} - Messages formatted for AI SDK with potential image content
129471
+ */
129472
+ prepareMessagesWithImages(messages) {
129473
+ const loadedImages = this.getCurrentImages();
129474
+ if (loadedImages.length === 0) {
129475
+ return messages;
129476
+ }
129477
+ const messagesWithImages = [...messages];
129478
+ const lastUserMessageIndex = messagesWithImages.map((m) => m.role).lastIndexOf("user");
129479
+ if (lastUserMessageIndex === -1) {
129480
+ if (this.debug) {
129481
+ console.log("[DEBUG] No user messages found to attach images to");
129482
+ }
129483
+ return messages;
129484
+ }
129485
+ const lastUserMessage = messagesWithImages[lastUserMessageIndex];
129486
+ if (typeof lastUserMessage.content === "string") {
129487
+ messagesWithImages[lastUserMessageIndex] = {
129488
+ ...lastUserMessage,
129489
+ content: [
129490
+ { type: "text", text: lastUserMessage.content },
129491
+ ...loadedImages.map((imageData) => ({
129492
+ type: "image",
129493
+ image: imageData
129494
+ }))
129495
+ ]
129496
+ };
129497
+ if (this.debug) {
129498
+ console.log(`[DEBUG] Added ${loadedImages.length} images to the latest user message`);
129499
+ }
129500
+ }
129501
+ return messagesWithImages;
129502
+ }
129188
129503
  /**
129189
129504
  * Initialize mock model for testing
129190
129505
  */
@@ -129566,9 +129881,10 @@ You are working with a repository located at: ${searchDirectory}
129566
129881
  let assistantResponseContent = "";
129567
129882
  try {
129568
129883
  const executeAIRequest = async () => {
129884
+ const messagesForAI = this.prepareMessagesWithImages(currentMessages);
129569
129885
  const result = await (0, import_ai2.streamText)({
129570
129886
  model: this.provider(this.model),
129571
- messages: currentMessages,
129887
+ messages: messagesForAI,
129572
129888
  maxTokens: maxResponseTokens,
129573
129889
  temperature: 0.3
129574
129890
  });
@@ -129602,6 +129918,9 @@ You are working with a repository located at: ${searchDirectory}
129602
129918
  const assistantPreview = createMessagePreview(assistantResponseContent);
129603
129919
  console.log(`[DEBUG] Assistant response (${assistantResponseContent.length} chars): ${assistantPreview}`);
129604
129920
  }
129921
+ if (assistantResponseContent) {
129922
+ await this.processImageReferences(assistantResponseContent);
129923
+ }
129605
129924
  const validTools = [
129606
129925
  "search",
129607
129926
  "query",
@@ -129726,12 +130045,17 @@ ${toolResultContent}
129726
130045
  throw toolError;
129727
130046
  }
129728
130047
  currentMessages.push({ role: "assistant", content: assistantResponseContent });
130048
+ const toolResultContent = typeof toolResult === "string" ? toolResult : JSON.stringify(toolResult, null, 2);
130049
+ const toolResultMessage = `<tool_result>
130050
+ ${toolResultContent}
130051
+ </tool_result>`;
129729
130052
  currentMessages.push({
129730
130053
  role: "user",
129731
- content: `<tool_result>
129732
- ${typeof toolResult === "string" ? toolResult : JSON.stringify(toolResult, null, 2)}
129733
- </tool_result>`
130054
+ content: toolResultMessage
129734
130055
  });
130056
+ if (toolResultContent) {
130057
+ await this.processImageReferences(toolResultContent);
130058
+ }
129735
130059
  if (this.debug) {
129736
130060
  console.log(`[DEBUG] Tool ${toolName} executed successfully. Result length: ${typeof toolResult === "string" ? toolResult.length : JSON.stringify(toolResult).length}`);
129737
130061
  }
@@ -130229,12 +130553,12 @@ function initializeSimpleTelemetryFromOptions(options) {
130229
130553
  });
130230
130554
  return telemetry;
130231
130555
  }
130232
- var import_fs5, import_path7, SimpleTelemetry, SimpleAppTracer;
130556
+ var import_fs6, import_path8, SimpleTelemetry, SimpleAppTracer;
130233
130557
  var init_simpleTelemetry = __esm({
130234
130558
  "src/agent/simpleTelemetry.js"() {
130235
130559
  "use strict";
130236
- import_fs5 = __nccwpck_require__(79896);
130237
- import_path7 = __nccwpck_require__(16928);
130560
+ import_fs6 = __nccwpck_require__(79896);
130561
+ import_path8 = __nccwpck_require__(16928);
130238
130562
  SimpleTelemetry = class {
130239
130563
  constructor(options = {}) {
130240
130564
  this.serviceName = options.serviceName || "probe-agent";
@@ -130248,11 +130572,11 @@ var init_simpleTelemetry = __esm({
130248
130572
  }
130249
130573
  initializeFileExporter() {
130250
130574
  try {
130251
- const dir = (0, import_path7.dirname)(this.filePath);
130252
- if (!(0, import_fs5.existsSync)(dir)) {
130253
- (0, import_fs5.mkdirSync)(dir, { recursive: true });
130575
+ const dir = (0, import_path8.dirname)(this.filePath);
130576
+ if (!(0, import_fs6.existsSync)(dir)) {
130577
+ (0, import_fs6.mkdirSync)(dir, { recursive: true });
130254
130578
  }
130255
- this.stream = (0, import_fs5.createWriteStream)(this.filePath, { flags: "a" });
130579
+ this.stream = (0, import_fs6.createWriteStream)(this.filePath, { flags: "a" });
130256
130580
  this.stream.on("error", (error) => {
130257
130581
  console.error(`[SimpleTelemetry] Stream error: ${error.message}`);
130258
130582
  });
@@ -130313,20 +130637,20 @@ var init_simpleTelemetry = __esm({
130313
130637
  }
130314
130638
  async flush() {
130315
130639
  if (this.stream) {
130316
- return new Promise((resolve) => {
130317
- this.stream.once("drain", resolve);
130640
+ return new Promise((resolve2) => {
130641
+ this.stream.once("drain", resolve2);
130318
130642
  if (!this.stream.writableNeedDrain) {
130319
- resolve();
130643
+ resolve2();
130320
130644
  }
130321
130645
  });
130322
130646
  }
130323
130647
  }
130324
130648
  async shutdown() {
130325
130649
  if (this.stream) {
130326
- return new Promise((resolve) => {
130650
+ return new Promise((resolve2) => {
130327
130651
  this.stream.end(() => {
130328
130652
  console.log(`[SimpleTelemetry] File stream closed: ${this.filePath}`);
130329
- resolve();
130653
+ resolve2();
130330
130654
  });
130331
130655
  });
130332
130656
  }
@@ -34,6 +34,8 @@ export interface CliOptions {
34
34
  help?: boolean;
35
35
  /** Show version */
36
36
  version?: boolean;
37
+ /** Code context mode: auto (default), enabled (force include), disabled (force exclude) */
38
+ codeContext?: 'auto' | 'enabled' | 'disabled';
37
39
  }
38
40
  /**
39
41
  * CLI command configuration
@@ -1 +1 @@
1
- {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["file:///home/runner/work/visor/visor/src/types/cli.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,MAAM,SAAS,GAAG,aAAa,GAAG,cAAc,GAAG,UAAU,GAAG,OAAO,GAAG,KAAK,CAAC;AAEtF;;GAEG;AACH,MAAM,MAAM,YAAY,GAAG,OAAO,GAAG,MAAM,GAAG,UAAU,GAAG,OAAO,CAAC;AAEnE;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,sCAAsC;IACtC,MAAM,EAAE,SAAS,EAAE,CAAC;IACpB,gCAAgC;IAChC,MAAM,EAAE,YAAY,CAAC;IACrB,iCAAiC;IACjC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,oFAAoF;IACpF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,+DAA+D;IAC/D,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,4CAA4C;IAC5C,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,gDAAgD;IAChD,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,oEAAoE;IACpE,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,sEAAsE;IACtE,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,qDAAqD;IACrD,qBAAqB,CAAC,EAAE,MAAM,EAAE,CAAC;IACjC,qBAAqB;IACrB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,mBAAmB;IACnB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,mBAAmB;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,0BAA0B;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,sBAAsB;IACtB,OAAO,EAAE,UAAU,CAAC;CACrB"}
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["file:///home/runner/work/visor/visor/src/types/cli.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,MAAM,SAAS,GAAG,aAAa,GAAG,cAAc,GAAG,UAAU,GAAG,OAAO,GAAG,KAAK,CAAC;AAEtF;;GAEG;AACH,MAAM,MAAM,YAAY,GAAG,OAAO,GAAG,MAAM,GAAG,UAAU,GAAG,OAAO,CAAC;AAEnE;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,sCAAsC;IACtC,MAAM,EAAE,SAAS,EAAE,CAAC;IACpB,gCAAgC;IAChC,MAAM,EAAE,YAAY,CAAC;IACrB,iCAAiC;IACjC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,oFAAoF;IACpF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,+DAA+D;IAC/D,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,4CAA4C;IAC5C,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,gDAAgD;IAChD,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,oEAAoE;IACpE,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,sEAAsE;IACtE,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,qDAAqD;IACrD,qBAAqB,CAAC,EAAE,MAAM,EAAE,CAAC;IACjC,qBAAqB;IACrB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,mBAAmB;IACnB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,2FAA2F;IAC3F,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,GAAG,UAAU,CAAC;CAC/C;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,mBAAmB;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,0BAA0B;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,sBAAsB;IACtB,OAAO,EAAE,UAAU,CAAC;CACrB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@probelabs/visor",
3
- "version": "0.1.40",
3
+ "version": "0.1.41",
4
4
  "main": "dist/index.js",
5
5
  "bin": {
6
6
  "visor": "./dist/index.js"
@@ -66,7 +66,7 @@
66
66
  "@octokit/auth-app": "^8.1.0",
67
67
  "@octokit/core": "^7.0.3",
68
68
  "@octokit/rest": "^22.0.0",
69
- "@probelabs/probe": "^0.6.0-rc102",
69
+ "@probelabs/probe": "^0.6.0-rc103",
70
70
  "@types/commander": "^2.12.0",
71
71
  "@types/uuid": "^10.0.0",
72
72
  "cli-table3": "^0.6.5",