Spaces:
Paused
Paused
| import {minimatch} from 'minimatch' | |
| import {TokenLimits} from './limits' | |
| const info = console.log | |
| export type SeverityLevel = 'critical' | 'major' | 'minor' | 'info' | |
| export class Options { | |
| debug: boolean | |
| disableReview: boolean | |
| disableReleaseNotes: boolean | |
| maxFiles: number | |
| reviewSimpleChanges: boolean | |
| reviewCommentLGTM: boolean | |
| pathFilters: PathFilter | |
| systemMessage: string | |
| lightModel: string | |
| heavyModel: string | |
| modelTemperature: number | |
| retries: number | |
| timeoutMS: number | |
| concurrencyLimit: number | |
| githubConcurrencyLimit: number | |
| lightTokenLimits: TokenLimits | |
| heavyTokenLimits: TokenLimits | |
| apiBaseUrl: string | |
| language: string | |
| createRemedyPR: boolean | |
| minimumSeverity: SeverityLevel | |
| minConfidence: number | |
| denseMode: boolean | |
| showImpactAnalysis: boolean | |
| enableAutoPR: boolean | |
| static readonly HEAVY_MODELS = [ | |
| 'llama-3.3-70b-versatile', | |
| 'meta-llama/llama-4-scout-17b-16e-instruct', | |
| 'deepseek-r1-distill-llama-70b', | |
| 'openai/gpt-oss-120b', | |
| 'qwen/qwen3-32b' | |
| ] | |
| static readonly LIGHT_MODELS = [ | |
| 'meta-llama/llama-4-scout-17b-16e-instruct', | |
| 'llama-3.1-8b-instant', | |
| 'groq/compound' | |
| ] | |
| static readonly SECURITY_MODELS = [ | |
| 'openai/gpt-oss-safeguard-20b', | |
| 'meta-llama/llama-guard-4-12b', | |
| 'meta-llama/llama-prompt-guard-2-86m', | |
| 'meta-llama/llama-prompt-guard-2-22m' | |
| ] | |
| constructor( | |
| debug: boolean, | |
| disableReview: boolean, | |
| disableReleaseNotes: boolean, | |
| maxFiles = '0', | |
| reviewSimpleChanges = false, | |
| reviewCommentLGTM = false, | |
| pathFilters: string[] | null = null, | |
| systemMessage = '', | |
| lightModel = 'meta-llama/llama-4-scout-17b-16e-instruct', | |
| heavyModel = 'llama-3.3-70b-versatile', | |
| modelTemperature = '0.0', | |
| retries = '3', | |
| timeoutMS = '120000', | |
| concurrencyLimit = '3', | |
| githubConcurrencyLimit = '10', | |
| apiBaseUrl = 'https://api.groq.com/openai/v1', | |
| language = 'en-US', | |
| createRemedyPR = true, | |
| minimumSeverity: SeverityLevel = 'minor', | |
| minConfidence = '0', | |
| denseMode = 'false', | |
| showImpactAnalysis = 'true', | |
| enableAutoPR = false | |
| ) { | |
| this.debug = debug | |
| this.disableReview = disableReview | |
| this.disableReleaseNotes = disableReleaseNotes | |
| this.maxFiles = parseInt(maxFiles) | |
| this.reviewSimpleChanges = reviewSimpleChanges | |
| this.reviewCommentLGTM = reviewCommentLGTM | |
| this.pathFilters = new PathFilter(pathFilters) | |
| this.systemMessage = systemMessage | |
| this.lightModel = lightModel | |
| this.heavyModel = heavyModel | |
| this.modelTemperature = parseFloat(modelTemperature) | |
| this.retries = parseInt(retries) | |
| this.timeoutMS = parseInt(timeoutMS) | |
| this.concurrencyLimit = parseInt(concurrencyLimit) | |
| this.githubConcurrencyLimit = parseInt(githubConcurrencyLimit) | |
| this.apiBaseUrl = apiBaseUrl | |
| this.language = language | |
| this.createRemedyPR = createRemedyPR | |
| this.minimumSeverity = minimumSeverity | |
| this.minConfidence = parseInt(minConfidence) | |
| this.denseMode = denseMode === 'true' | |
| this.showImpactAnalysis = showImpactAnalysis === 'true' | |
| this.enableAutoPR = enableAutoPR | |
| this.lightTokenLimits = new TokenLimits(this.lightModel) | |
| this.heavyTokenLimits = new TokenLimits(this.heavyModel) | |
| } | |
| // print all options using core.info | |
| print(): void { | |
| info(`debug: ${this.debug}`) | |
| info(`disable_review: ${this.disableReview}`) | |
| info(`disable_release_notes: ${this.disableReleaseNotes}`) | |
| info(`max_files: ${this.maxFiles}`) | |
| info(`review_simple_changes: ${this.reviewSimpleChanges}`) | |
| info(`review_comment_lgtm: ${this.reviewCommentLGTM}`) | |
| info(`path_filters: ${this.pathFilters}`) | |
| info(`system_message: ${this.systemMessage}`) | |
| info(`light_model: ${this.lightModel}`) | |
| info(`heavy_model: ${this.heavyModel}`) | |
| info(`model_temperature: ${this.modelTemperature}`) | |
| info(`retries: ${this.retries}`) | |
| info(`timeout_ms: ${this.timeoutMS}`) | |
| info(`concurrency_limit: ${this.concurrencyLimit}`) | |
| info(`github_concurrency_limit: ${this.githubConcurrencyLimit}`) | |
| info(`summary_token_limits: ${this.lightTokenLimits.string()}`) | |
| info(`review_token_limits: ${this.heavyTokenLimits.string()}`) | |
| info(`api_base_url: ${this.apiBaseUrl}`) | |
| info(`language: ${this.language}`) | |
| info(`create_remedy_pr: ${this.createRemedyPR}`) | |
| info(`enable_auto_pr: ${this.enableAutoPR}`) | |
| } | |
| checkPath(path: string): boolean { | |
| const ok = this.pathFilters.check(path) | |
| info(`checking path: ${path} => ${ok}`) | |
| return ok | |
| } | |
| private static readonly SEVERITY_ORDER: SeverityLevel[] = [ | |
| 'critical', | |
| 'major', | |
| 'minor', | |
| 'info' | |
| ] | |
| meetsMinimumSeverity(findingSeverity: SeverityLevel): boolean { | |
| const minIndex = Options.SEVERITY_ORDER.indexOf(this.minimumSeverity) | |
| const findingIndex = Options.SEVERITY_ORDER.indexOf(findingSeverity) | |
| return findingIndex >= minIndex | |
| } | |
| meetsConfidenceThreshold(confidence: number): boolean { | |
| return confidence >= this.minConfidence | |
| } | |
| } | |
| export class PathFilter { | |
| private readonly rules: Array<[string /* rule */, boolean /* exclude */]> | |
| constructor(rules: string[] | null = null) { | |
| this.rules = [] | |
| if (rules != null) { | |
| for (const rule of rules) { | |
| const trimmed = rule?.trim() | |
| if (trimmed) { | |
| if (trimmed.startsWith('!')) { | |
| this.rules.push([trimmed.substring(1).trim(), true]) | |
| } else { | |
| this.rules.push([trimmed, false]) | |
| } | |
| } | |
| } | |
| } | |
| } | |
| check(path: string): boolean { | |
| if (this.rules.length === 0) { | |
| return true | |
| } | |
| let included = false | |
| let excluded = false | |
| let inclusionRuleExists = false | |
| for (const [rule, exclude] of this.rules) { | |
| if (minimatch(path, rule)) { | |
| if (exclude) { | |
| excluded = true | |
| } else { | |
| included = true | |
| } | |
| } | |
| if (!exclude) { | |
| inclusionRuleExists = true | |
| } | |
| } | |
| return (!inclusionRuleExists || included) && !excluded | |
| } | |
| } | |
| export class AIOptions { | |
| model: string | |
| tokenLimits: TokenLimits | |
| temperature: number | |
| constructor( | |
| model = 'meta-llama/llama-4-scout-17b-16e-instruct', | |
| tokenLimits: TokenLimits | null = null, | |
| temperature = 0.0 | |
| ) { | |
| this.model = model | |
| this.temperature = temperature | |
| if (tokenLimits != null) { | |
| this.tokenLimits = tokenLimits | |
| } else { | |
| this.tokenLimits = new TokenLimits(model) | |
| } | |
| } | |
| } | |