UNPKG

@probelabs/visor

Version:

AI-powered code review tool for GitHub Pull Requests - CLI and GitHub Action

375 lines (374 loc) 11.6 kB
import { ReviewSummary, GroupedCheckResults } from './reviewer'; import { AnalysisResult } from './output-formatters'; import { PRInfo } from './pr-analyzer'; import { FailureConditionResult } from './types/config'; /** * Statistics for a single check execution */ export interface CheckExecutionStats { checkName: string; totalRuns: number; successfulRuns: number; failedRuns: number; skipped: boolean; skipReason?: 'if_condition' | 'fail_fast' | 'dependency_failed'; skipCondition?: string; totalDuration: number; perIterationDuration?: number[]; issuesFound: number; issuesBySeverity: { critical: number; error: number; warning: number; info: number; }; outputsProduced?: number; errorMessage?: string; forEachPreview?: string[]; } /** * Overall execution statistics for all checks */ export interface ExecutionStatistics { totalChecksConfigured: number; totalExecutions: number; successfulExecutions: number; failedExecutions: number; skippedChecks: number; totalDuration: number; checks: CheckExecutionStats[]; } /** * Result of executing checks, including both the grouped results and execution statistics */ export interface ExecutionResult { results: GroupedCheckResults; statistics: ExecutionStatistics; } export interface MockOctokit { rest: { pulls: { get: () => Promise<{ data: Record<string, unknown>; }>; listFiles: () => Promise<{ data: Record<string, unknown>[]; }>; }; issues: { listComments: () => Promise<{ data: Record<string, unknown>[]; }>; createComment: () => Promise<{ data: Record<string, unknown>; }>; }; }; request: () => Promise<{ data: Record<string, unknown>; }>; graphql: () => Promise<Record<string, unknown>>; log: { debug: (...args: unknown[]) => void; info: (...args: unknown[]) => void; warn: (...args: unknown[]) => void; error: (...args: unknown[]) => void; }; hook: { before: (...args: unknown[]) => void; after: (...args: unknown[]) => void; error: (...args: unknown[]) => void; wrap: (...args: unknown[]) => void; }; auth: () => Promise<{ token: string; }>; } export interface CheckExecutionOptions { checks: string[]; workingDirectory?: string; showDetails?: boolean; timeout?: number; maxParallelism?: number; failFast?: boolean; outputFormat?: string; config?: import('./types/config').VisorConfig; debug?: boolean; tagFilter?: import('./types/config').TagFilter; webhookContext?: { webhookData: Map<string, unknown>; }; githubChecks?: { enabled: boolean; octokit?: import('@octokit/rest').Octokit; owner?: string; repo?: string; headSha?: string; prNumber?: number; }; } export declare class CheckExecutionEngine { private gitAnalyzer; private mockOctokit; private reviewer; private providerRegistry; private failureEvaluator; private githubCheckService?; private checkRunMap?; private githubContext?; private workingDirectory; private config?; private webhookContext?; private routingSandbox?; private executionStats; private outputHistory; private routingEventOverride?; private executionContext?; private actionContext?; constructor(workingDirectory?: string, octokit?: import('@octokit/rest').Octokit); /** * Enrich event context with authenticated octokit instance * @param eventContext - The event context to enrich * @returns Enriched event context with octokit if available */ private enrichEventContext; /** * Set execution context for providers (CLI message, hooks, etc.) * This allows passing state without using static properties */ setExecutionContext(context: import('./providers/check-provider.interface').ExecutionContext): void; /** * Lazily create a secure sandbox for routing JS (goto_js, run_js) */ private getRoutingSandbox; private redact; private sleep; private deterministicJitter; private computeBackoffDelay; /** * Execute a check with retry/backoff and routing semantics (on_fail/on_success) */ private executeWithRouting; /** * Set webhook context on a provider if it supports it */ private setProviderWebhookContext; /** * Filter checks based on tag filter configuration */ private filterChecksByTags; /** * Execute checks on the local repository */ executeChecks(options: CheckExecutionOptions): Promise<AnalysisResult>; /** * Execute tasks with controlled parallelism using a pool pattern */ private executeWithLimitedParallelism; /** * Execute review checks using parallel execution for multiple AI checks */ private executeReviewChecks; /** * Execute review checks and return grouped results with statistics for new architecture */ executeGroupedChecks(prInfo: PRInfo, checks: string[], timeout?: number, config?: import('./types/config').VisorConfig, outputFormat?: string, debug?: boolean, maxParallelism?: number, failFast?: boolean, tagFilter?: import('./types/config').TagFilter, _pauseGate?: () => Promise<void>): Promise<ExecutionResult>; /** * Execute single check and return grouped result */ private executeSingleGroupedCheck; /** * Validate and normalize forEach output * Returns normalized array or throws validation error result */ private validateAndNormalizeForEachOutput; /** * Execute multiple checks with dependency awareness - return grouped results with statistics */ private executeGroupedDependencyAwareChecks; /** * Convert ReviewSummary to GroupedCheckResults */ private convertReviewSummaryToGroupedResults; /** * Validates that a file path is safe and within the project directory * Prevents path traversal attacks by: * - Blocking absolute paths * - Blocking paths with ".." segments * - Ensuring resolved path is within project directory * - Blocking special characters and null bytes * - Enforcing .liquid file extension */ private validateTemplatePath; /** * Evaluate `if` condition for a check * @param checkName Name of the check * @param condition The condition string to evaluate * @param prInfo PR information * @param results Current check results * @param debug Whether debug mode is enabled * @returns true if the check should run, false if it should be skipped */ private evaluateCheckCondition; /** * Render check content using the appropriate template */ private renderCheckContent; /** * Attempt to elevate an issue/issue_comment context to full PR context when routing via goto_event. * Returns a new PRInfo with files/diff when possible; otherwise returns null. */ private elevateContextToPullRequest; /** * Execute multiple checks with dependency awareness - intelligently parallel and sequential */ private executeDependencyAwareChecks; /** * Execute multiple checks in parallel using controlled parallelism (legacy method) */ private executeParallelChecks; /** * Execute a single configured check */ private executeSingleConfiguredCheck; /** * Map check name to focus for AI provider * This is a fallback when focus is not explicitly configured */ private mapCheckNameToFocus; /** * Aggregate results from dependency-aware check execution */ private aggregateDependencyAwareResults; /** * Aggregate results from parallel check execution (legacy method) */ private aggregateParallelResults; /** * Get available check types */ static getAvailableCheckTypes(): string[]; /** * Validate check types */ static validateCheckTypes(checks: string[]): { valid: string[]; invalid: string[]; }; /** * List available providers with their status */ listProviders(): Promise<Array<{ name: string; description: string; available: boolean; requirements: string[]; }>>; /** * Create a mock Octokit instance for local analysis */ private createMockOctokit; /** * Create an error result */ private createErrorResult; /** * Check if a task result should trigger fail-fast behavior */ private isFailFastCandidate; private shouldFailFast; /** * Check if the working directory is a valid git repository */ isGitRepository(): Promise<boolean>; /** * Evaluate failure conditions for a check result */ evaluateFailureConditions(checkName: string, reviewSummary: ReviewSummary, config?: import('./types/config').VisorConfig, prInfo?: PRInfo, previousOutputs?: Record<string, ReviewSummary> | Map<string, ReviewSummary>): Promise<FailureConditionResult[]>; /** * Get repository status summary */ getRepositoryStatus(): Promise<{ isGitRepository: boolean; hasChanges: boolean; branch: string; filesChanged: number; }>; /** * Initialize GitHub check runs for each configured check */ private initializeGitHubChecks; /** * Update GitHub check runs to in-progress status */ private updateGitHubChecksInProgress; /** * Complete GitHub check runs with results */ private completeGitHubChecksWithResults; /** * Complete GitHub check runs with error status */ private completeGitHubChecksWithError; /** * Filter checks based on their event triggers to prevent execution of checks * that shouldn't run for the current event type */ private filterChecksByEvent; /** * Determine the current event type from PR info */ private getCurrentEventType; /** * Initialize execution statistics for a check */ private initializeCheckStats; /** * Record the start of a check iteration * Returns the start timestamp for duration tracking */ private recordIterationStart; /** * Record completion of a check iteration */ private recordIterationComplete; /** * Track output in history for loop/goto scenarios */ private trackOutputHistory; /** * Record that a check was skipped */ private recordSkip; /** * Record forEach preview items */ private recordForEachPreview; /** * Record an error for a check */ private recordError; /** * Build the final execution statistics object */ private buildExecutionStatistics; private isFatalRule; private hasFatal; private failIfTriggered; /** * Truncate a string to max length with ellipsis */ private truncate; /** * Format the Status column for execution summary table */ private formatStatusColumn; /** * Format the Details column for execution summary table */ private formatDetailsColumn; /** * Log the execution summary table */ private logExecutionSummary; }