@probelabs/visor 0.1.176-ee → 0.1.177-ee
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/frontends/slack-frontend.d.ts.map +1 -1
- package/dist/index.js +126 -23
- package/dist/sdk/a2a-frontend-BPWLYLCG.mjs +1658 -0
- package/dist/sdk/a2a-frontend-BPWLYLCG.mjs.map +1 -0
- package/dist/sdk/{check-provider-registry-X7WH3PXQ.mjs → check-provider-registry-G64PWDCZ.mjs} +5 -5
- package/dist/sdk/{check-provider-registry-VE6LQPLY.mjs → check-provider-registry-HW4QPPSA.mjs} +2 -2
- package/dist/sdk/chunk-GVTWESYN.mjs +516 -0
- package/dist/sdk/chunk-GVTWESYN.mjs.map +1 -0
- package/dist/sdk/{chunk-KQAT6H3S.mjs → chunk-IYXOLUDJ.mjs} +73 -28
- package/dist/sdk/chunk-IYXOLUDJ.mjs.map +1 -0
- package/dist/sdk/chunk-OHOBWVPP.mjs +1502 -0
- package/dist/sdk/chunk-OHOBWVPP.mjs.map +1 -0
- package/dist/sdk/chunk-OPI632LK.mjs +739 -0
- package/dist/sdk/chunk-OPI632LK.mjs.map +1 -0
- package/dist/sdk/{chunk-OK4MLC3R.mjs → chunk-Y6PVSFCS.mjs} +49 -9
- package/dist/sdk/chunk-Y6PVSFCS.mjs.map +1 -0
- package/dist/sdk/failure-condition-evaluator-HL33X7MH.mjs +18 -0
- package/dist/sdk/github-frontend-U2U42CKV.mjs +1386 -0
- package/dist/sdk/github-frontend-U2U42CKV.mjs.map +1 -0
- package/dist/sdk/{host-LRWIKURZ.mjs → host-HFOJQIOF.mjs} +4 -4
- package/dist/sdk/routing-SFP4D6O3.mjs +26 -0
- package/dist/sdk/{schedule-tool-INVLVX3G.mjs → schedule-tool-45NAALKS.mjs} +2 -2
- package/dist/sdk/{schedule-tool-R7NSHTPJ.mjs → schedule-tool-7O7SWSJ4.mjs} +5 -5
- package/dist/sdk/{schedule-tool-handler-4SSRQXFJ.mjs → schedule-tool-handler-6MPP5DXK.mjs} +2 -2
- package/dist/sdk/{schedule-tool-handler-5GTQ6SFI.mjs → schedule-tool-handler-KYDXJ2ZL.mjs} +5 -5
- package/dist/sdk/sdk.js +74 -14
- package/dist/sdk/sdk.js.map +1 -1
- package/dist/sdk/sdk.mjs +4 -4
- package/dist/sdk/slack-frontend-XKSIOUXB.mjs +910 -0
- package/dist/sdk/slack-frontend-XKSIOUXB.mjs.map +1 -0
- package/dist/sdk/trace-helpers-L3EOYW5P.mjs +29 -0
- package/dist/sdk/trace-helpers-L3EOYW5P.mjs.map +1 -0
- package/dist/sdk/{workflow-check-provider-IWZSZQ7N.mjs → workflow-check-provider-JIXZJNV5.mjs} +5 -5
- package/dist/sdk/workflow-check-provider-JIXZJNV5.mjs.map +1 -0
- package/dist/sdk/{workflow-check-provider-EY6VSMNG.mjs → workflow-check-provider-OA33MESM.mjs} +2 -2
- package/dist/sdk/workflow-check-provider-OA33MESM.mjs.map +1 -0
- package/dist/utils/workspace-manager.d.ts +5 -1
- package/dist/utils/workspace-manager.d.ts.map +1 -1
- package/dist/utils/worktree-manager.d.ts +5 -1
- package/dist/utils/worktree-manager.d.ts.map +1 -1
- package/package.json +2 -2
- package/dist/sdk/chunk-KQAT6H3S.mjs.map +0 -1
- package/dist/sdk/chunk-OK4MLC3R.mjs.map +0 -1
- /package/dist/sdk/{check-provider-registry-VE6LQPLY.mjs.map → check-provider-registry-G64PWDCZ.mjs.map} +0 -0
- /package/dist/sdk/{check-provider-registry-X7WH3PXQ.mjs.map → check-provider-registry-HW4QPPSA.mjs.map} +0 -0
- /package/dist/sdk/{schedule-tool-INVLVX3G.mjs.map → failure-condition-evaluator-HL33X7MH.mjs.map} +0 -0
- /package/dist/sdk/{host-LRWIKURZ.mjs.map → host-HFOJQIOF.mjs.map} +0 -0
- /package/dist/sdk/{schedule-tool-R7NSHTPJ.mjs.map → routing-SFP4D6O3.mjs.map} +0 -0
- /package/dist/sdk/{schedule-tool-handler-4SSRQXFJ.mjs.map → schedule-tool-45NAALKS.mjs.map} +0 -0
- /package/dist/sdk/{schedule-tool-handler-5GTQ6SFI.mjs.map → schedule-tool-7O7SWSJ4.mjs.map} +0 -0
- /package/dist/sdk/{workflow-check-provider-EY6VSMNG.mjs.map → schedule-tool-handler-6MPP5DXK.mjs.map} +0 -0
- /package/dist/sdk/{workflow-check-provider-IWZSZQ7N.mjs.map → schedule-tool-handler-KYDXJ2ZL.mjs.map} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/footer.ts","../../src/github-check-service.ts","../../src/github-comments.ts","../../src/frontends/github-frontend.ts"],"sourcesContent":["/**\n * Centralized footer generation for Visor comments and outputs\n */\n\nexport interface FooterOptions {\n /**\n * Include metadata like lastUpdated, triggeredBy, commitSha\n */\n includeMetadata?: {\n lastUpdated: string;\n triggeredBy: string;\n commitSha?: string;\n };\n /**\n * Include horizontal rule separator before footer\n */\n includeSeparator?: boolean;\n}\n\n/**\n * Generate a standard Visor footer with branding and optional tip\n */\nexport function generateFooter(options: FooterOptions = {}): string {\n const { includeMetadata, includeSeparator = true } = options;\n\n const parts: string[] = [];\n\n // Add separator\n if (includeSeparator) {\n parts.push('---');\n parts.push('');\n }\n\n // Add branding\n parts.push(\n '*Powered by [Visor](https://probelabs.com/visor) from [Probelabs](https://probelabs.com)*'\n );\n\n // Add metadata if provided\n if (includeMetadata) {\n const { lastUpdated, triggeredBy, commitSha } = includeMetadata;\n const commitInfo = commitSha ? ` | Commit: ${commitSha.substring(0, 7)}` : '';\n parts.push('');\n parts.push(`*Last updated: ${lastUpdated} | Triggered by: ${triggeredBy}${commitInfo}*`);\n }\n\n // Add tip\n parts.push('');\n parts.push('💡 **TIP:** You can chat with Visor using `/visor ask <your question>`');\n\n return parts.join('\\n');\n}\n\n/**\n * Check if a string contains a Visor footer\n */\nexport function hasVisorFooter(text: string): boolean {\n return (\n text.includes('*Powered by [Visor](https://probelabs.com/visor)') ||\n text.includes('*Powered by [Visor](https://github.com/probelabs/visor)')\n );\n}\n","/**\n * GitHub Check Service for creating and managing check runs based on failure conditions\n */\n\nimport { Octokit } from '@octokit/rest';\nimport { FailureConditionResult } from './types/config';\nimport { ReviewIssue } from './reviewer';\nimport { generateFooter } from './footer';\n\nexport interface CheckRunOptions {\n owner: string;\n repo: string;\n head_sha: string;\n name: string;\n details_url?: string;\n external_id?: string;\n engine_mode?: 'legacy' | 'state-machine'; // M4: Track which engine mode was used\n}\n\nexport interface CheckRunAnnotation {\n path: string;\n start_line: number;\n end_line: number;\n annotation_level: 'notice' | 'warning' | 'failure';\n message: string;\n title?: string;\n raw_details?: string;\n}\n\nexport interface CheckRunSummary {\n title: string;\n summary: string;\n text?: string;\n}\n\nexport type CheckRunStatus = 'queued' | 'in_progress' | 'completed';\nexport type CheckRunConclusion =\n | 'success'\n | 'failure'\n | 'neutral'\n | 'cancelled'\n | 'timed_out'\n | 'action_required';\n\n/**\n * Service for managing GitHub Check Runs based on Visor failure conditions\n */\nexport class GitHubCheckService {\n private octokit: Octokit;\n private maxAnnotations = 50; // GitHub API limit\n\n constructor(octokit: Octokit) {\n this.octokit = octokit;\n }\n\n /**\n * Create a new check run in queued status\n * M4: Includes engine_mode metadata in summary\n */\n async createCheckRun(\n options: CheckRunOptions,\n summary?: CheckRunSummary\n ): Promise<{ id: number; url: string }> {\n try {\n // M4: Add engine mode metadata to summary if provided\n const enhancedSummary =\n summary && options.engine_mode\n ? {\n ...summary,\n summary: `${summary.summary}\\n\\n_Engine: ${options.engine_mode}_`,\n }\n : summary;\n\n const response = await this.octokit.rest.checks.create({\n owner: options.owner,\n repo: options.repo,\n name: options.name,\n head_sha: options.head_sha,\n status: 'queued',\n details_url: options.details_url,\n external_id: options.external_id,\n output: enhancedSummary\n ? {\n title: enhancedSummary.title,\n summary: enhancedSummary.summary,\n text: enhancedSummary.text,\n }\n : undefined,\n });\n\n return {\n id: response.data.id,\n url: response.data.html_url || '',\n };\n } catch (error) {\n throw new Error(\n `Failed to create check run: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n }\n\n /**\n * Update check run to in_progress status\n */\n async updateCheckRunInProgress(\n owner: string,\n repo: string,\n check_run_id: number,\n summary?: CheckRunSummary\n ): Promise<void> {\n try {\n await this.octokit.rest.checks.update({\n owner,\n repo,\n check_run_id,\n status: 'in_progress',\n output: summary\n ? {\n title: summary.title,\n summary: summary.summary,\n text: summary.text,\n }\n : undefined,\n });\n } catch (error) {\n throw new Error(\n `Failed to update check run to in_progress: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n }\n\n /**\n * Complete a check run with results based on failure conditions\n */\n async completeCheckRun(\n owner: string,\n repo: string,\n check_run_id: number,\n checkName: string,\n failureResults: FailureConditionResult[],\n reviewIssues: ReviewIssue[] = [],\n executionError?: string,\n filesChangedInCommit?: string[],\n prNumber?: number,\n currentCommitSha?: string\n ): Promise<void> {\n try {\n // Clear old annotations from ALL previous check runs (including older runs on the same commit)\n // This prevents annotation accumulation when a check runs multiple times\n if (prNumber && currentCommitSha) {\n await this.clearOldAnnotations(\n owner,\n repo,\n prNumber,\n checkName,\n currentCommitSha,\n check_run_id\n );\n }\n\n const { conclusion, summary } = this.determineCheckRunConclusion(\n checkName,\n failureResults,\n reviewIssues,\n executionError\n );\n\n // Filter out system-level issues (fail_if conditions, internal errors)\n // These should not appear as annotations but affect the check conclusion\n let filteredIssues = reviewIssues.filter(\n issue => !(issue.file === 'system' && issue.line === 0)\n );\n\n // Filter annotations to only include files changed in this commit\n // This prevents old annotations from previous commits showing up in the Files tab\n if (filesChangedInCommit && filesChangedInCommit.length > 0) {\n filteredIssues = filteredIssues.filter(issue =>\n filesChangedInCommit.some(changedFile => issue.file === changedFile)\n );\n }\n\n const annotations = this.convertIssuesToAnnotations(filteredIssues);\n\n await this.octokit.rest.checks.update({\n owner,\n repo,\n check_run_id,\n status: 'completed',\n conclusion,\n completed_at: new Date().toISOString(),\n output: {\n title: summary.title,\n summary: summary.summary,\n text: summary.text,\n annotations: annotations.slice(0, this.maxAnnotations), // GitHub limit\n },\n });\n } catch (error) {\n throw new Error(\n `Failed to complete check run: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n }\n\n /**\n * Determine check run conclusion based on failure conditions and issues\n */\n private determineCheckRunConclusion(\n checkName: string,\n failureResults: FailureConditionResult[],\n reviewIssues: ReviewIssue[],\n executionError?: string\n ): { conclusion: CheckRunConclusion; summary: CheckRunSummary } {\n // Handle execution errors first\n if (executionError) {\n return {\n conclusion: 'failure',\n summary: {\n title: '❌ Check Execution Failed',\n summary: `The ${checkName} check failed to execute properly.`,\n text: `**Error:** ${executionError}\\n\\nPlease check your configuration and try again.`,\n },\n };\n }\n\n // Check if any fail_if conditions were met\n const failedConditions = failureResults.filter(result => result.failed);\n\n // Count issues by severity (for informational display only)\n const criticalIssues = reviewIssues.filter(issue => issue.severity === 'critical').length;\n const errorIssues = reviewIssues.filter(issue => issue.severity === 'error').length;\n const warningIssues = reviewIssues.filter(issue => issue.severity === 'warning').length;\n const totalIssues = reviewIssues.length;\n\n // Determine conclusion ONLY based on fail_if evaluation results\n // The presence of issues (critical, error, warning) does NOT affect the conclusion\n // Only the fail_if condition determines pass/fail status\n let conclusion: CheckRunConclusion;\n let title: string;\n let summaryText: string;\n let details: string;\n\n if (failedConditions.length > 0) {\n // Check fails if fail_if condition is met\n conclusion = 'failure';\n title = '🚨 Check Failed';\n summaryText = `${checkName} check failed because fail_if condition was met.`;\n\n details = this.formatCheckDetails(failureResults, reviewIssues, {\n failedConditions: failedConditions.length,\n warningConditions: 0,\n criticalIssues,\n errorIssues,\n warningIssues,\n totalIssues,\n });\n } else {\n // No fail_if conditions met - check passes regardless of issues found\n conclusion = 'success';\n\n // Adjust the title and summary based on issues found, but conclusion remains success\n if (criticalIssues > 0 || errorIssues > 0) {\n title = '✅ Check Passed (Issues Found)';\n summaryText = `${checkName} check passed. Found ${criticalIssues} critical and ${errorIssues} error issues, but fail_if condition was not met.`;\n } else if (warningIssues > 0) {\n title = '✅ Check Passed (Warnings Found)';\n summaryText = `${checkName} check passed. Found ${warningIssues} warning${warningIssues === 1 ? '' : 's'}, but fail_if condition was not met.`;\n } else {\n title = '✅ Check Passed';\n summaryText = `${checkName} check completed successfully with no issues found.`;\n }\n\n details = this.formatCheckDetails(failureResults, reviewIssues, {\n failedConditions: 0,\n warningConditions: 0,\n criticalIssues,\n errorIssues,\n warningIssues,\n totalIssues,\n });\n }\n\n return {\n conclusion,\n summary: {\n title,\n summary: summaryText,\n text: details,\n },\n };\n }\n\n /**\n * Format detailed check results for the check run summary\n */\n private formatCheckDetails(\n failureResults: FailureConditionResult[],\n reviewIssues: ReviewIssue[],\n counts: {\n failedConditions: number;\n warningConditions: number;\n criticalIssues: number;\n errorIssues: number;\n warningIssues: number;\n totalIssues: number;\n }\n ): string {\n const sections: string[] = [];\n\n // Summary section\n sections.push('## 📊 Summary');\n sections.push(`- **Total Issues:** ${counts.totalIssues}`);\n if (counts.criticalIssues > 0) {\n sections.push(`- **Critical Issues:** ${counts.criticalIssues}`);\n }\n if (counts.errorIssues > 0) {\n sections.push(`- **Error Issues:** ${counts.errorIssues}`);\n }\n if (counts.warningIssues > 0) {\n sections.push(`- **Warning Issues:** ${counts.warningIssues}`);\n }\n sections.push('');\n\n // Failure conditions section\n if (failureResults.length > 0) {\n sections.push('## 🔍 Failure Condition Results');\n\n const failedConditions = failureResults.filter(result => result.failed);\n const passedConditions = failureResults.filter(result => !result.failed);\n\n if (failedConditions.length > 0) {\n sections.push('### Failed Conditions');\n failedConditions.forEach(condition => {\n sections.push(\n `- **${condition.conditionName}**: ${condition.message || condition.expression}`\n );\n if (condition.severity) {\n const icon = this.getSeverityEmoji(condition.severity);\n sections.push(` - Severity: ${icon} ${condition.severity}`);\n }\n });\n sections.push('');\n }\n\n if (passedConditions.length > 0) {\n sections.push('### Passed Conditions');\n passedConditions.forEach(condition => {\n sections.push(\n `- **${condition.conditionName}**: ${condition.message || 'Condition passed'}`\n );\n });\n sections.push('');\n }\n }\n\n // Issues by category section\n if (reviewIssues.length > 0) {\n const issuesByCategory = this.groupIssuesByCategory(reviewIssues);\n sections.push('## Issues by Category');\n\n Object.entries(issuesByCategory).forEach(([category, issues]) => {\n if (issues.length > 0) {\n sections.push(\n `### ${category.charAt(0).toUpperCase() + category.slice(1)} (${issues.length})`\n );\n\n // Show only first 5 issues per category to keep the summary concise\n const displayIssues = issues.slice(0, 5);\n displayIssues.forEach(issue => {\n const severityIcon = this.getSeverityEmoji(issue.severity);\n sections.push(`- ${severityIcon} **${issue.file}:${issue.line}** - ${issue.message}`);\n });\n\n if (issues.length > 5) {\n sections.push(`- *...and ${issues.length - 5} more ${category} issues*`);\n }\n sections.push('');\n }\n });\n }\n\n // Footer\n sections.push('');\n sections.push(generateFooter());\n\n return sections.join('\\n');\n }\n\n /**\n * Convert review issues to GitHub check run annotations\n */\n private convertIssuesToAnnotations(reviewIssues: ReviewIssue[]): CheckRunAnnotation[] {\n return reviewIssues\n .slice(0, this.maxAnnotations) // Respect GitHub's annotation limit\n .map(issue => ({\n path: issue.file,\n start_line: issue.line,\n end_line: issue.endLine || issue.line,\n annotation_level: this.mapSeverityToAnnotationLevel(issue.severity),\n message: issue.message,\n title: `${issue.category} Issue`,\n raw_details: issue.suggestion || undefined,\n }));\n }\n\n /**\n * Map Visor issue severity to GitHub annotation level\n */\n private mapSeverityToAnnotationLevel(severity: string): 'notice' | 'warning' | 'failure' {\n switch (severity) {\n case 'critical':\n case 'error':\n return 'failure';\n case 'warning':\n return 'warning';\n case 'info':\n default:\n return 'notice';\n }\n }\n\n /**\n * Group issues by category\n */\n private groupIssuesByCategory(issues: ReviewIssue[]): Record<string, ReviewIssue[]> {\n const grouped: Record<string, ReviewIssue[]> = {};\n\n issues.forEach(issue => {\n const category = issue.category || 'general';\n if (!grouped[category]) {\n grouped[category] = [];\n }\n grouped[category].push(issue);\n });\n\n return grouped;\n }\n\n /**\n * Get emoji for issue severity (allowed; step/category emojis are removed)\n */\n private getSeverityEmoji(severity: string): string {\n const iconMap: Record<string, string> = {\n critical: '🚨',\n error: '❌',\n warning: '⚠️',\n info: 'ℹ️',\n };\n return iconMap[String(severity || '').toLowerCase()] || '';\n }\n\n /**\n * Create multiple check runs for different checks with failure condition support\n */\n async createMultipleCheckRuns(\n options: CheckRunOptions,\n checkResults: Array<{\n checkName: string;\n failureResults: FailureConditionResult[];\n reviewIssues: ReviewIssue[];\n executionError?: string;\n }>\n ): Promise<Array<{ checkName: string; id: number; url: string }>> {\n const results: Array<{ checkName: string; id: number; url: string }> = [];\n\n for (const checkResult of checkResults) {\n try {\n // Create check run\n const checkRun = await this.createCheckRun({\n ...options,\n name: `Visor: ${checkResult.checkName}`,\n external_id: `visor-${checkResult.checkName}-${options.head_sha.substring(0, 7)}`,\n });\n\n // Update to in progress\n await this.updateCheckRunInProgress(options.owner, options.repo, checkRun.id, {\n title: `Running ${checkResult.checkName} check...`,\n summary: `Analyzing code with ${checkResult.checkName} check using AI.`,\n });\n\n // Complete with results\n await this.completeCheckRun(\n options.owner,\n options.repo,\n checkRun.id,\n checkResult.checkName,\n checkResult.failureResults,\n checkResult.reviewIssues,\n checkResult.executionError\n );\n\n results.push({\n checkName: checkResult.checkName,\n id: checkRun.id,\n url: checkRun.url,\n });\n } catch (error) {\n console.error(`Failed to create check run for ${checkResult.checkName}:`, error);\n // Continue with other checks even if one fails\n }\n }\n\n return results;\n }\n\n /**\n * Get check runs for a specific commit\n */\n async getCheckRuns(\n owner: string,\n repo: string,\n ref: string\n ): Promise<Array<{ id: number; name: string; status: string; conclusion: string | null }>> {\n try {\n const response = await this.octokit.rest.checks.listForRef({\n owner,\n repo,\n ref,\n filter: 'all',\n });\n\n return response.data.check_runs\n .filter(check => check.name.startsWith('Visor:'))\n .map(check => ({\n id: check.id,\n name: check.name,\n status: check.status,\n conclusion: check.conclusion,\n }));\n } catch (error) {\n throw new Error(\n `Failed to get check runs: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n }\n\n /**\n * Get check runs for a specific commit SHA\n * Returns all check runs with the given name on this commit\n */\n async getCheckRunsForCommit(\n owner: string,\n repo: string,\n commitSha: string,\n checkName: string\n ): Promise<Array<{ id: number; head_sha: string }>> {\n try {\n const checksResponse = await this.octokit.rest.checks.listForRef({\n owner,\n repo,\n ref: commitSha,\n check_name: `Visor: ${checkName}`,\n });\n\n return checksResponse.data.check_runs.map(check => ({\n id: check.id,\n head_sha: commitSha,\n }));\n } catch (error) {\n throw new Error(\n `Failed to get check runs for commit ${commitSha}: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n }\n\n /**\n * Clear annotations from old check runs on the current commit\n * This prevents annotation accumulation when a check runs multiple times on the same commit\n * (e.g., force push, re-running checks)\n */\n async clearOldAnnotations(\n owner: string,\n repo: string,\n prNumber: number, // Not used, kept for backward compatibility\n checkName: string,\n currentCommitSha: string,\n currentCheckRunId: number\n ): Promise<void> {\n try {\n // Get all check runs for this check name on the current commit\n const allCheckRuns = await this.getCheckRunsForCommit(\n owner,\n repo,\n currentCommitSha,\n checkName\n );\n\n // Filter out the CURRENT check run (by ID)\n // This handles the case where Visor runs multiple times on the same commit\n const oldRuns = allCheckRuns.filter(run => run.id !== currentCheckRunId);\n\n if (oldRuns.length === 0) {\n console.debug(`No old check runs to clear for ${checkName} on commit ${currentCommitSha}`);\n return;\n }\n\n console.debug(\n `Clearing ${oldRuns.length} old check run(s) for ${checkName} on commit ${currentCommitSha.substring(0, 7)} (keeping current run ${currentCheckRunId})`\n );\n\n // Update each old check run to have empty annotations\n for (const run of oldRuns) {\n try {\n await this.octokit.rest.checks.update({\n owner,\n repo,\n check_run_id: run.id,\n output: {\n title: 'Outdated',\n summary: 'This check has been superseded by a newer run.',\n annotations: [], // Clear annotations\n },\n });\n console.debug(`✓ Cleared annotations from check run ${run.id}`);\n } catch (error) {\n console.debug(`Could not clear annotations for check run ${run.id}:`, error);\n }\n }\n } catch (error) {\n // Don't fail the whole check if we can't clear old annotations\n console.warn('Failed to clear old annotations:', error);\n }\n }\n}\n","import { Octokit } from '@octokit/rest';\nimport { generateShortHumanId } from './utils/human-id';\nimport { logger } from './logger';\nimport { generateFooter } from './footer';\n\nexport interface Comment {\n id: number;\n body: string;\n user: {\n login: string;\n };\n created_at: string;\n updated_at: string;\n}\n\nexport interface RetryConfig {\n maxRetries: number;\n baseDelay: number;\n maxDelay: number;\n backoffFactor: number;\n}\n\nexport interface CommentMetadata {\n commentId: string;\n lastUpdated: string;\n triggeredBy: string;\n commitSha?: string;\n}\n\ninterface GitHubApiError {\n status?: number;\n response?: {\n status?: number;\n data?: {\n message?: string;\n };\n };\n}\n\n/**\n * Manages GitHub PR comments with dynamic updating capabilities\n */\nexport class CommentManager {\n private octokit: Octokit;\n private retryConfig: RetryConfig;\n\n constructor(octokit: Octokit, retryConfig?: Partial<RetryConfig>) {\n this.octokit = octokit;\n this.retryConfig = {\n maxRetries: 3,\n baseDelay: 1000,\n maxDelay: 10000,\n backoffFactor: 2,\n ...retryConfig,\n };\n }\n\n /**\n * Find existing Visor comment by comment ID marker\n */\n public async findVisorComment(\n owner: string,\n repo: string,\n prNumber: number,\n commentId?: string\n ): Promise<Comment | null> {\n try {\n const comments = await this.octokit.rest.issues.listComments({\n owner,\n repo,\n issue_number: prNumber,\n per_page: 100, // GitHub default max\n });\n\n for (const comment of comments.data) {\n if (comment.body && this.isVisorComment(comment.body, commentId)) {\n return comment as Comment;\n }\n }\n\n return null;\n } catch (error) {\n if (\n this.isRateLimitError(\n error as { status?: number; response?: { data?: { message?: string } } }\n )\n ) {\n await this.handleRateLimit(error as { response?: { headers?: Record<string, string> } });\n return this.findVisorComment(owner, repo, prNumber, commentId);\n }\n throw error;\n }\n }\n\n /**\n * Update existing comment or create new one with collision detection\n */\n public async updateOrCreateComment(\n owner: string,\n repo: string,\n prNumber: number,\n content: string,\n options: {\n commentId?: string;\n triggeredBy?: string;\n allowConcurrentUpdates?: boolean;\n commitSha?: string;\n /** Cached GitHub comment ID to use for updates when listComments may not return it yet (eventual consistency) */\n cachedGithubCommentId?: number;\n } = {}\n ): Promise<Comment> {\n const {\n commentId = this.generateCommentId(),\n triggeredBy = 'unknown',\n allowConcurrentUpdates = false,\n commitSha,\n cachedGithubCommentId,\n } = options;\n\n return this.withRetry(async () => {\n // First try to find the comment via listComments API\n let existingComment = await this.findVisorComment(owner, repo, prNumber, commentId);\n\n // If not found but we have a cached GitHub ID, try to fetch it directly\n // This handles GitHub API eventual consistency where newly created comments\n // may not appear in listComments immediately\n if (!existingComment && cachedGithubCommentId) {\n try {\n const cachedComment = await this.octokit.rest.issues.getComment({\n owner,\n repo,\n comment_id: cachedGithubCommentId,\n });\n if (cachedComment.data && this.isVisorComment(cachedComment.data.body || '', commentId)) {\n existingComment = cachedComment.data as Comment;\n logger.debug(\n `[github-comments] Found comment via cached ID ${cachedGithubCommentId} (not visible in listComments yet)`\n );\n }\n } catch (_e) {\n // Comment may have been deleted, continue with create flow\n logger.debug(\n `[github-comments] Cached comment ${cachedGithubCommentId} not found, will create new`\n );\n }\n }\n\n const formattedContent = this.formatCommentWithMetadata(content, {\n commentId,\n lastUpdated: new Date().toISOString(),\n triggeredBy,\n commitSha,\n });\n\n if (existingComment) {\n // Check for collision if not allowing concurrent updates\n if (!allowConcurrentUpdates) {\n const currentComment = await this.octokit.rest.issues.getComment({\n owner,\n repo,\n comment_id: existingComment.id,\n });\n\n if (currentComment.data.updated_at !== existingComment.updated_at) {\n throw new Error(\n `Comment collision detected for comment ${commentId}. Another process may have updated it.`\n );\n }\n }\n\n const updatedComment = await this.octokit.rest.issues.updateComment({\n owner,\n repo,\n comment_id: existingComment.id,\n body: formattedContent,\n });\n\n logger.info(\n `✅ Successfully updated comment (ID: ${commentId}, GitHub ID: ${existingComment.id}) on PR #${prNumber} in ${owner}/${repo}`\n );\n\n return updatedComment.data as Comment;\n } else {\n const newComment = await this.octokit.rest.issues.createComment({\n owner,\n repo,\n issue_number: prNumber,\n body: formattedContent,\n });\n\n logger.info(\n `✅ Successfully created comment (ID: ${commentId}, GitHub ID: ${newComment.data.id}) on PR #${prNumber} in ${owner}/${repo}`\n );\n\n return newComment.data as Comment;\n }\n });\n }\n\n /**\n * Format comment content with metadata markers\n */\n public formatCommentWithMetadata(content: string, metadata: CommentMetadata): string {\n const { commentId, lastUpdated, triggeredBy, commitSha } = metadata;\n\n const footer = generateFooter({\n includeMetadata: {\n lastUpdated,\n triggeredBy,\n commitSha,\n },\n });\n\n return `<!-- visor-comment-id:${commentId} -->\n${content}\n\n${footer}\n<!-- /visor-comment-id:${commentId} -->`;\n }\n\n /**\n * Create collapsible sections for comment content\n */\n public createCollapsibleSection(\n title: string,\n content: string,\n isExpanded: boolean = false\n ): string {\n const openAttribute = isExpanded ? ' open' : '';\n return `<details${openAttribute}>\n<summary>${title}</summary>\n\n${content}\n\n</details>`;\n }\n\n /**\n * Group review results by check type with collapsible sections\n */\n public formatGroupedResults(\n results: Array<{ checkType: string; content: string; score?: number; issuesFound?: number }>,\n groupBy: 'check' | 'severity' = 'check'\n ): string {\n const grouped = this.groupResults(results, groupBy);\n const sections: string[] = [];\n\n for (const [groupKey, items] of Object.entries(grouped)) {\n const totalScore = items.reduce((sum, item) => sum + (item.score || 0), 0) / items.length;\n const totalIssues = items.reduce((sum, item) => sum + (item.issuesFound || 0), 0);\n\n const title = this.formatGroupTitle(groupKey, totalScore, totalIssues);\n\n const sectionContent = items.map(item => item.content).join('\\n\\n');\n sections.push(this.createCollapsibleSection(title, sectionContent, totalIssues > 0));\n }\n\n return sections.join('\\n\\n');\n }\n\n /**\n * Generate unique comment ID\n */\n private generateCommentId(): string {\n return generateShortHumanId();\n }\n\n /**\n * Check if comment is a Visor comment\n */\n private isVisorComment(body: string, commentId?: string): boolean {\n if (commentId) {\n // Check for the new format with exact matching - look for the exact ID followed by space or \" -->\"\n if (\n body.includes(`visor-comment-id:${commentId} `) ||\n body.includes(`visor-comment-id:${commentId} -->`)\n ) {\n return true;\n }\n // Check for legacy format (visor-review-* pattern) for backwards compatibility\n if (commentId.startsWith('pr-review-') && body.includes('visor-review-')) {\n return true;\n }\n // If we have a specific commentId but no exact match, return false\n return false;\n }\n // General Visor comment detection (only when no specific commentId provided)\n return (\n (body.includes('visor-comment-id:') && body.includes('<!-- /visor-comment-id:')) ||\n body.includes('visor-review-')\n );\n }\n\n /**\n * Extract comment ID from comment body\n */\n public extractCommentId(body: string): string | null {\n const match = body.match(/visor-comment-id:([a-f0-9-]+)/);\n return match ? match[1] : null;\n }\n\n /**\n * Handle rate limiting with exponential backoff\n */\n private async handleRateLimit(error: {\n response?: { headers?: Record<string, string> };\n }): Promise<void> {\n const resetTime = error.response?.headers?.['x-ratelimit-reset'];\n if (resetTime) {\n const resetDate = new Date(parseInt(resetTime) * 1000);\n const waitTime = Math.max(resetDate.getTime() - Date.now(), this.retryConfig.baseDelay);\n console.log(`Rate limit exceeded. Waiting ${Math.round(waitTime / 1000)}s until reset...`);\n await this.sleep(Math.min(waitTime, this.retryConfig.maxDelay));\n } else {\n await this.sleep(this.retryConfig.baseDelay);\n }\n }\n\n /**\n * Check if error is a rate limit error\n */\n private isRateLimitError(error: GitHubApiError): boolean {\n return error.status === 403 && (error.response?.data?.message?.includes('rate limit') ?? false);\n }\n\n /**\n * Check if error should not be retried (auth errors, not found, etc.)\n */\n private isNonRetryableError(error: GitHubApiError): boolean {\n // Don't retry auth errors, not found, etc., but allow rate limit errors to be handled separately\n const nonRetryableStatuses = [401, 404, 422]; // Unauthorized, Not Found, Unprocessable Entity\n const status = error.status || error.response?.status;\n\n // 403 is non-retryable unless it's a rate limit error\n if (status === 403) {\n return !this.isRateLimitError(error);\n }\n\n return status !== undefined && nonRetryableStatuses.includes(status);\n }\n\n /**\n * Retry wrapper with exponential backoff\n */\n private async withRetry<T>(operation: () => Promise<T>): Promise<T> {\n let lastError: Error = new Error('Unknown error');\n\n for (let attempt = 0; attempt <= this.retryConfig.maxRetries; attempt++) {\n try {\n return await operation();\n } catch (error) {\n lastError = error instanceof Error ? error : new Error(String(error));\n\n if (attempt === this.retryConfig.maxRetries) {\n break;\n }\n\n if (\n this.isRateLimitError(\n error as { status?: number; response?: { data?: { message?: string } } }\n )\n ) {\n await this.handleRateLimit(error as { response?: { headers?: Record<string, string> } });\n } else if (this.isNonRetryableError(error as GitHubApiError)) {\n // Don't retry auth errors, not found errors, etc.\n throw error;\n } else {\n const computed =\n this.retryConfig.baseDelay * Math.pow(this.retryConfig.backoffFactor, attempt);\n const delay =\n computed > this.retryConfig.maxDelay\n ? Math.max(0, this.retryConfig.maxDelay - 1)\n : computed;\n await this.sleep(delay);\n }\n }\n }\n\n throw lastError;\n }\n\n /**\n * Sleep utility\n */\n private sleep(ms: number): Promise<void> {\n return new Promise(resolve => {\n const t = setTimeout(resolve, ms);\n if (typeof (t as any).unref === 'function') {\n try {\n (t as any).unref();\n } catch {}\n }\n });\n }\n\n /**\n * Group results by specified criteria\n */\n private groupResults(\n results: Array<{ checkType: string; content: string; score?: number; issuesFound?: number }>,\n groupBy: 'check' | 'severity'\n ): Record<\n string,\n Array<{ checkType: string; content: string; score?: number; issuesFound?: number }>\n > {\n const grouped: Record<\n string,\n Array<{ checkType: string; content: string; score?: number; issuesFound?: number }>\n > = {};\n\n for (const result of results) {\n const key = groupBy === 'check' ? result.checkType : this.getSeverityGroup(result.score);\n if (!grouped[key]) {\n grouped[key] = [];\n }\n grouped[key].push(result);\n }\n\n return grouped;\n }\n\n /**\n * Get severity group based on score\n */\n private getSeverityGroup(score?: number): string {\n if (!score) return 'Unknown';\n if (score >= 90) return 'Excellent';\n if (score >= 75) return 'Good';\n if (score >= 50) return 'Needs Improvement';\n return 'Critical Issues';\n }\n\n // Emoji helper removed: plain titles are used in group headers\n\n /**\n * Format group title with score and issue count\n */\n private formatGroupTitle(groupKey: string, score: number, issuesFound: number): string {\n const formattedScore = Math.round(score);\n return `${groupKey} Review (Score: ${formattedScore}/100)${issuesFound > 0 ? ` - ${issuesFound} issues found` : ''}`;\n }\n}\n","import type { Frontend, FrontendContext } from './host';\nimport { logger } from '../logger';\nimport { extractTextFromJson } from '../utils/json-text-extractor';\n\n/**\n * Skeleton GitHub frontend.\n * - Subscribes to engine events via EventBus when present\n * - Maps key events to debug logs for now (no side effects)\n * - Real implementation will upsert checks and manage grouped PR comments\n */\ntype SectionState = {\n status: 'queued' | 'in_progress' | 'completed' | 'errored';\n conclusion?: 'success' | 'failure' | 'neutral' | 'skipped';\n issues?: number;\n lastUpdated: string;\n error?: string;\n content?: string;\n};\n\nexport class GitHubFrontend implements Frontend {\n public readonly name = 'github';\n private subs: Array<{ unsubscribe(): void }> = [];\n private checkRunIds: Map<string, number> = new Map();\n private revision = 0;\n private cachedCommentId?: string; // legacy single-thread id (kept for compatibility)\n // Group → (checkId → SectionState)\n private stepStatusByGroup: Map<string, Map<string, SectionState>> = new Map();\n\n // Debounce/coalescing state\n private debounceMs: number = 400;\n private maxWaitMs: number = 2000;\n private _timer: NodeJS.Timeout | null = null;\n private _lastFlush: number = 0;\n private _pendingIds: Set<string> = new Set<string>();\n\n // Mutex for serializing comment updates per group\n private updateLocks: Map<string, Promise<void>> = new Map();\n public minUpdateDelayMs: number = 1000; // Minimum delay between updates (public for testing)\n // Cache of created GitHub comment IDs per group to handle API eventual consistency\n private createdCommentGithubIds: Map<string, number> = new Map();\n private _stopped = false;\n\n start(ctx: FrontendContext): void {\n const log = ctx.logger;\n const bus = ctx.eventBus;\n const octokit = (ctx as any).octokit;\n const repo = ctx.run.repo;\n const pr = ctx.run.pr;\n const headSha = ctx.run.headSha;\n\n // Determine capabilities separately for comments vs check runs\n const canPostComments = !!(octokit && repo && pr);\n const canPostChecks = !!(octokit && repo && pr && headSha);\n\n // Create helpers if possible\n const svc = canPostChecks\n ? new (require('../github-check-service').GitHubCheckService)(octokit)\n : null;\n const CommentManager = require('../github-comments').CommentManager;\n const comments = canPostComments ? new CommentManager(octokit) : null;\n\n const threadKey =\n repo && pr && headSha\n ? `${repo.owner}/${repo.name}#${pr}@${(headSha || '').substring(0, 7)}`\n : ctx.run.runId;\n this.cachedCommentId = `visor-thread-${threadKey}`;\n\n // CheckScheduled → create queued check run\n this.subs.push(\n bus.on('CheckScheduled', async (env: any) => {\n const ev = (env && env.payload) || env;\n try {\n if (!canPostChecks || !svc) return;\n if (this.checkRunIds.has(ev.checkId)) return; // already created\n // Update local model only (no comment yet; wait for content)\n const group = this.getGroupForCheck(ctx, ev.checkId);\n this.upsertSectionState(group, ev.checkId, {\n status: 'queued',\n lastUpdated: new Date().toISOString(),\n });\n // Do not call updateGroupedComment here — avoid \"queued\" placeholder comments\n const res = await svc.createCheckRun(\n {\n owner: repo!.owner,\n repo: repo!.name,\n head_sha: headSha!,\n name: `Visor: ${ev.checkId}`,\n external_id: `visor:${ctx.run.runId}:${ev.checkId}`,\n engine_mode: 'state-machine',\n },\n { title: `${ev.checkId}`, summary: 'Queued' }\n );\n this.checkRunIds.set(ev.checkId, res.id);\n } catch (e) {\n log.warn(\n `[github-frontend] createCheckRun failed for ${ev.checkId}: ${e instanceof Error ? e.message : e}`\n );\n }\n })\n );\n\n // CheckCompleted → complete check run and update grouped comment\n this.subs.push(\n bus.on('CheckCompleted', async (env: any) => {\n const ev = (env && env.payload) || env;\n try {\n // Complete check run (only when we have headSha)\n if (canPostChecks && svc && this.checkRunIds.has(ev.checkId)) {\n const id = this.checkRunIds.get(ev.checkId)!;\n const issues = Array.isArray(ev.result?.issues) ? ev.result.issues : [];\n // Evaluate failure conditions so GitHub conclusion reflects actual pass/fail\n const failureResults = await this.evaluateFailureResults(ctx, ev.checkId, ev.result);\n await svc.completeCheckRun(\n repo!.owner,\n repo!.name,\n id,\n ev.checkId,\n failureResults,\n issues,\n undefined,\n undefined,\n pr!,\n headSha!\n );\n }\n\n // Update grouped summary comment\n if (canPostComments && comments) {\n const count = Array.isArray(ev.result?.issues) ? ev.result.issues.length : 0;\n const failureResults = await this.evaluateFailureResults(ctx, ev.checkId, ev.result);\n const failed = Array.isArray(failureResults)\n ? failureResults.some((r: any) => r && r.failed)\n : false;\n const group = this.getGroupForCheck(ctx, ev.checkId);\n // Extract text from JSON-like content if template didn't unwrap it properly\n const rawContent = (ev?.result as any)?.content;\n const extractedContent = extractTextFromJson(rawContent);\n this.upsertSectionState(group, ev.checkId, {\n status: 'completed',\n conclusion: failed ? 'failure' : 'success',\n issues: count,\n lastUpdated: new Date().toISOString(),\n content: extractedContent,\n });\n await this.updateGroupedComment(ctx, comments, group, ev.checkId);\n }\n } catch (e) {\n log.warn(\n `[github-frontend] handle CheckCompleted failed: ${e instanceof Error ? e.message : e}`\n );\n }\n })\n );\n\n // CheckErrored → mark failure and update comment\n this.subs.push(\n bus.on('CheckErrored', async (env: any) => {\n const ev = (env && env.payload) || env;\n try {\n if (canPostChecks && svc && this.checkRunIds.has(ev.checkId)) {\n const id = this.checkRunIds.get(ev.checkId)!;\n await svc.completeCheckRun(\n repo!.owner,\n repo!.name,\n id,\n ev.checkId,\n [],\n [],\n ev.error?.message || 'Execution error',\n undefined,\n pr!,\n headSha!\n );\n }\n if (canPostComments && comments) {\n const group = this.getGroupForCheck(ctx, ev.checkId);\n this.upsertSectionState(group, ev.checkId, {\n status: 'errored',\n conclusion: 'failure',\n issues: 0,\n lastUpdated: new Date().toISOString(),\n error: ev.error?.message || 'Execution error',\n });\n await this.updateGroupedComment(ctx, comments, group, ev.checkId);\n }\n } catch (e) {\n log.warn(\n `[github-frontend] handle CheckErrored failed: ${e instanceof Error ? e.message : e}`\n );\n }\n })\n );\n\n // StateTransition: update summary on terminal\n this.subs.push(\n bus.on('StateTransition', async (env: any) => {\n const ev = (env && env.payload) || env;\n try {\n if (ev.to === 'Completed' || ev.to === 'Error') {\n if (canPostComments && comments) {\n for (const group of this.stepStatusByGroup.keys()) {\n await this.updateGroupedComment(ctx, comments, group);\n }\n }\n }\n } catch (e) {\n log.warn(\n `[github-frontend] handle StateTransition failed: ${e instanceof Error ? e.message : e}`\n );\n }\n })\n );\n }\n\n async stop(): Promise<void> {\n this._stopped = true;\n for (const s of this.subs) s.unsubscribe();\n this.subs = [];\n if (this._timer) {\n clearTimeout(this._timer);\n this._timer = null;\n }\n this._pendingIds.clear();\n // Drain any in-flight updateGroupedComment operations so callers that\n // await stop() (e.g. FrontendsHost.stopAll) are guaranteed no async\n // work leaks after stop resolves.\n const pending = Array.from(this.updateLocks.values());\n if (pending.length > 0) {\n await Promise.allSettled(pending);\n }\n }\n\n private async buildFullBody(ctx: FrontendContext, group: string): Promise<string> {\n const header = this.renderThreadHeader(ctx, group);\n const sections = this.renderSections(ctx, group);\n return `${header}\n\n${sections}\n\n<!-- visor:thread-end key=\"${this.threadKeyFor(ctx)}\" -->`;\n }\n\n private threadKeyFor(ctx: FrontendContext): string {\n const r = ctx.run;\n return r.repo && r.pr && r.headSha\n ? `${r.repo.owner}/${r.repo.name}#${r.pr}@${(r.headSha || '').substring(0, 7)}`\n : r.runId;\n }\n\n private renderThreadHeader(ctx: FrontendContext, group: string): string {\n const header = {\n key: this.threadKeyFor(ctx),\n runId: ctx.run.runId,\n workflowId: ctx.run.workflowId,\n revision: this.revision,\n group,\n generatedAt: new Date().toISOString(),\n } as any;\n return `<!-- visor:thread=${JSON.stringify(header)} -->`;\n }\n\n private renderSections(ctx: FrontendContext, group: string): string {\n const lines: string[] = [];\n const groupMap = this.stepStatusByGroup.get(group) || new Map<string, SectionState>();\n for (const [checkId, st] of groupMap.entries()) {\n const start = `<!-- visor:section=${JSON.stringify({ id: checkId, revision: this.revision })} -->`;\n const end = `<!-- visor:section-end id=\"${checkId}\" -->`;\n const body =\n st.content && st.content.toString().trim().length > 0 ? st.content.toString().trim() : '';\n lines.push(`${start}\n${body}\n${end}`);\n }\n return lines.join('\\\\n\\\\n');\n }\n\n /**\n * Acquires a mutex lock for the given group and executes the update.\n * This ensures only one comment update happens at a time per group,\n * preventing race conditions where updates overwrite each other.\n *\n * Uses a proper queue-based mutex: each new caller chains onto the previous\n * lock, ensuring strict serialization even when multiple callers wait\n * simultaneously.\n */\n private async updateGroupedComment(\n ctx: FrontendContext,\n comments: any,\n group: string,\n changedIds?: string | string[]\n ) {\n // Get the current lock (if any) - we'll wait for it before proceeding\n const existingLock = this.updateLocks.get(group);\n\n // Create our own lock promise that we'll resolve when done\n // This must be created BEFORE awaiting existingLock to ensure proper chaining\n let resolveLock: () => void;\n const ourLock = new Promise<void>(resolve => {\n resolveLock = resolve;\n });\n\n // Immediately set our lock so subsequent callers will wait for us\n this.updateLocks.set(group, ourLock);\n\n try {\n // Wait for the previous update to complete (if any)\n if (existingLock) {\n logger.info(\n `[github-frontend] Comment update for group \"${group}\" queued, waiting for previous update to finish...`\n );\n const queuedAt = Date.now();\n const reminder = setInterval(() => {\n const waited = Math.round((Date.now() - queuedAt) / 1000);\n logger.info(\n `[github-frontend] Comment update for group \"${group}\" still queued (${waited}s).`\n );\n }, 10000);\n try {\n await existingLock;\n } catch (error) {\n logger.warn(\n `[github-frontend] Previous update for group ${group} failed: ${error instanceof Error ? error.message : error}`\n );\n // Continue with current update despite previous failure\n } finally {\n clearInterval(reminder);\n const waitedMs = Date.now() - queuedAt;\n if (waitedMs > 100) {\n logger.info(\n `[github-frontend] Comment update for group \"${group}\" dequeued after ${Math.round(waitedMs / 1000)}s.`\n );\n }\n }\n }\n\n // Now perform our update\n await this.performGroupedCommentUpdate(ctx, comments, group, changedIds);\n } finally {\n // Clean up the lock from the map if it's still ours (no one else is waiting)\n if (this.updateLocks.get(group) === ourLock) {\n this.updateLocks.delete(group);\n }\n // Always resolve our lock - this allows the next waiter (if any) to proceed.\n // Even if another caller replaced our lock in the map, they're waiting on\n // our lock promise, so we must resolve it.\n resolveLock!();\n }\n }\n\n /**\n * Performs the actual comment update with delay enforcement.\n */\n private async performGroupedCommentUpdate(\n ctx: FrontendContext,\n comments: any,\n group: string,\n changedIds?: string | string[]\n ) {\n try {\n if (this._stopped) return;\n if (!ctx.run.repo || !ctx.run.pr) return;\n\n // Check if PR comments are enabled (default to true if not specified)\n const config = ctx.config as any;\n const prCommentEnabled = config?.output?.pr_comment?.enabled !== false;\n if (!prCommentEnabled) {\n logger.debug(\n `[github-frontend] PR comments disabled in config, skipping comment for group: ${group}`\n );\n return;\n }\n\n // Enforce minimum delay between updates to prevent API rate limiting\n const timeSinceLastFlush = Date.now() - this._lastFlush;\n if (this._lastFlush > 0 && timeSinceLastFlush < this.minUpdateDelayMs) {\n const delay = this.minUpdateDelayMs - timeSinceLastFlush;\n logger.debug(\n `[github-frontend] Waiting ${delay}ms before next update to prevent rate limiting`\n );\n await this.sleep(delay);\n }\n\n this.revision++;\n const commentId = this.commentIdForGroup(ctx, group);\n const mergedBody = await this.mergeIntoExistingBody(ctx, comments, group, changedIds);\n\n // Check if we have a cached GitHub comment ID from a previous creation\n // This handles GitHub API eventual consistency where listComments may not\n // immediately return a newly created comment\n const cachedGithubId = this.createdCommentGithubIds.get(commentId);\n\n const result = await comments.updateOrCreateComment(\n ctx.run.repo.owner,\n ctx.run.repo.name,\n ctx.run.pr,\n mergedBody,\n {\n commentId,\n triggeredBy: this.deriveTriggeredBy(ctx),\n commitSha: ctx.run.headSha,\n // Pass the cached GitHub comment ID if available\n cachedGithubCommentId: cachedGithubId,\n }\n );\n\n // Cache the GitHub comment ID for future updates\n if (result && result.id) {\n this.createdCommentGithubIds.set(commentId, result.id);\n }\n\n this._lastFlush = Date.now();\n } catch (e) {\n logger.debug(\n `[github-frontend] updateGroupedComment failed: ${e instanceof Error ? e.message : e}`\n );\n }\n }\n\n private deriveTriggeredBy(ctx: FrontendContext): string {\n const ev = (ctx.run as any).event || '';\n const actor = (ctx.run as any).actor;\n const commentEvents = new Set([\n 'issue_comment',\n 'issue_comment_created',\n 'pr_comment',\n 'comment',\n 'pull_request_review_comment',\n ]);\n if (commentEvents.has(ev) && actor) return actor;\n if (ev) return ev;\n return actor || 'unknown';\n }\n\n private async mergeIntoExistingBody(\n ctx: FrontendContext,\n comments: any,\n group: string,\n changedIds?: string | string[]\n ): Promise<string> {\n const repo = ctx.run.repo!;\n const pr = ctx.run.pr!;\n const existing = await comments.findVisorComment(\n repo.owner,\n repo.name,\n pr,\n this.commentIdForGroup(ctx, group)\n );\n if (!existing || !existing.body) return this.buildFullBody(ctx, group);\n const body = String(existing.body);\n const doc = this.parseSections(body);\n doc.header = {\n ...(doc.header || {}),\n key: this.threadKeyFor(ctx),\n revision: this.revision,\n group,\n } as any;\n if (changedIds) {\n const ids = Array.isArray(changedIds) ? changedIds : [changedIds];\n const fresh = this.renderSections(ctx, group);\n for (const id of ids) {\n const block = this.extractSectionById(fresh, id);\n if (block) doc.sections.set(id, block);\n }\n } else {\n // Add any missing new sections; leave others untouched to preserve text\n const fresh = this.renderSections(ctx, group);\n const map = this.stepStatusByGroup.get(group) || new Map<string, SectionState>();\n for (const [checkId] of map.entries()) {\n if (!doc.sections.has(checkId)) {\n const block = this.extractSectionById(fresh, checkId);\n if (block) doc.sections.set(checkId, block);\n }\n }\n }\n return this.serializeSections(doc);\n }\n\n private parseSections(body: string): { header?: any; sections: Map<string, string> } {\n const sections = new Map<string, string>();\n const headerRe = /<!--\\s*visor:thread=(\\{[\\s\\S]*?\\})\\s*-->/m;\n const startRe = /<!--\\s*visor:section=(\\{[\\s\\S]*?\\})\\s*-->/g;\n const endRe = /<!--\\s*visor:section-end\\s+id=\\\"([^\\\"]+)\\\"\\s*-->/g;\n\n // Helper: safely parse JSON and pick only allowed keys\n const safePick = (obj: any, allowed: Record<string, 'string' | 'number'>) => {\n if (!obj || typeof obj !== 'object' || Array.isArray(obj)) return undefined;\n const out: Record<string, unknown> = Object.create(null);\n for (const [k, t] of Object.entries(allowed)) {\n if (Object.prototype.hasOwnProperty.call(obj, k)) {\n const v = (obj as any)[k];\n if (t === 'string' && typeof v === 'string') out[k] = v;\n else if (t === 'number' && typeof v === 'number' && Number.isFinite(v)) out[k] = v;\n }\n }\n return out;\n };\n\n const safeParse = (text: string) => {\n try {\n return JSON.parse(text);\n } catch {\n return undefined;\n }\n };\n\n let header: any;\n try {\n const h = headerRe.exec(body);\n if (h) {\n const parsed = safeParse(h[1]);\n const picked = safePick(parsed, {\n key: 'string',\n runId: 'string',\n workflowId: 'string',\n revision: 'number',\n group: 'string',\n generatedAt: 'string',\n });\n header = picked;\n }\n } catch {}\n\n let cursor = 0;\n while (true) {\n const s = startRe.exec(body);\n if (!s) break;\n const metaRaw = safeParse(s[1]);\n const meta = safePick(metaRaw, { id: 'string', revision: 'number' }) || { id: '' };\n const startIdx = startRe.lastIndex;\n endRe.lastIndex = startIdx;\n const e = endRe.exec(body);\n if (!e) break;\n const id =\n typeof (meta as any).id === 'string' && (meta as any).id\n ? String((meta as any).id)\n : String(e[1]);\n const content = body.substring(startIdx, e.index).trim();\n const block = `<!-- visor:section=${JSON.stringify(meta)} -->\\n${content}\\n<!-- visor:section-end id=\"${id}\" -->`;\n sections.set(id, block);\n cursor = endRe.lastIndex;\n startRe.lastIndex = cursor;\n }\n return { header, sections };\n }\n\n private serializeSections(doc: { header?: any; sections: Map<string, string> }): string {\n const header = `<!-- visor:thread=${JSON.stringify({ ...(doc.header || {}), generatedAt: new Date().toISOString() })} -->`;\n const blocks = Array.from(doc.sections.values()).join('\\n\\n');\n const key = (doc.header && (doc.header as any).key) || '';\n return `${header}\\n\\n${blocks}\\n\\n<!-- visor:thread-end key=\"${key}\" -->`;\n }\n\n private extractSectionById(rendered: string, id: string): string | undefined {\n const rx = new RegExp(\n `<!--\\\\s*visor:section=(\\\\{[\\\\s\\\\S]*?\\\\})\\\\s*-->[\\\\s\\\\S]*?<!--\\\\s*visor:section-end\\\\s+id=\\\\\"${this.escapeRegExp(id)}\\\\\"\\\\s*-->`,\n 'm'\n );\n const m = rx.exec(rendered);\n return m ? m[0] : undefined;\n }\n\n private escapeRegExp(s: string): string {\n return s.replace(/[.*+?^${}()|[\\\\]\\\\]/g, '\\\\$&');\n }\n\n private getGroupForCheck(ctx: FrontendContext, checkId: string): string {\n try {\n const cfg: any = ctx.config || {};\n const g = cfg?.checks?.[checkId]?.group || cfg?.steps?.[checkId]?.group;\n if (typeof g === 'string' && g.trim().length > 0) return g;\n } catch {}\n return 'review';\n }\n\n private upsertSectionState(group: string, checkId: string, patch: Partial<SectionState>): void {\n let groupMap = this.stepStatusByGroup.get(group);\n if (!groupMap) {\n groupMap = new Map<string, SectionState>();\n this.stepStatusByGroup.set(group, groupMap);\n }\n const prev =\n groupMap.get(checkId) ||\n ({ status: 'queued', lastUpdated: new Date().toISOString() } as SectionState);\n groupMap.set(checkId, { ...prev, ...patch });\n }\n\n private commentIdForGroup(ctx: FrontendContext, group: string): string {\n // For \"dynamic\" group, each run creates a new comment (not updated across runs)\n // This is used for assistants that respond to issue comments where each\n // response should be a separate comment rather than updating a previous one.\n // Within a single run, the comment ID stays stable so updates work correctly.\n if (group === 'dynamic') {\n return `visor-thread-dynamic-${ctx.run.runId}`;\n }\n // Stable per-PR per-group ID (does not include commit SHA)\n const r = ctx.run;\n const base = r.repo && r.pr ? `${r.repo.owner}/${r.repo.name}#${r.pr}` : r.runId;\n return `visor-thread-${group}-${base}`;\n }\n\n /**\n * Compute failure condition results for a completed check so Check Runs map to the\n * correct GitHub conclusion. This mirrors the engine's evaluation for fail_if.\n */\n private async evaluateFailureResults(\n ctx: FrontendContext,\n checkId: string,\n result: { issues?: any[]; output?: unknown }\n ): Promise<any[]> {\n try {\n const config: any = ctx.config || {};\n const checks = (config && config.checks) || {};\n const checkCfg = checks[checkId] || {};\n const checkSchema = typeof checkCfg.schema === 'string' ? checkCfg.schema : 'code-review';\n const checkGroup = checkCfg.group || 'default';\n\n const { FailureConditionEvaluator } = require('../failure-condition-evaluator');\n const evaluator = new FailureConditionEvaluator();\n const reviewSummary = { issues: Array.isArray(result?.issues) ? result.issues : [] };\n\n const failures: any[] = [];\n\n // Global fail_if\n if (config.fail_if) {\n const failed = await evaluator.evaluateSimpleCondition(\n checkId,\n checkSchema,\n checkGroup,\n reviewSummary,\n config.fail_if\n );\n failures.push({\n conditionName: 'global_fail_if',\n failed,\n expression: config.fail_if,\n severity: 'error',\n haltExecution: false,\n });\n }\n\n // Check-level fail_if\n if (checkCfg.fail_if) {\n const failed = await evaluator.evaluateSimpleCondition(\n checkId,\n checkSchema,\n checkGroup,\n reviewSummary,\n checkCfg.fail_if\n );\n failures.push({\n conditionName: `${checkId}_fail_if`,\n failed,\n expression: checkCfg.fail_if,\n severity: 'error',\n haltExecution: false,\n });\n }\n\n return failures;\n } catch {\n return [];\n }\n }\n\n // Debounce helpers\n private scheduleUpdate(ctx: FrontendContext, comments: any, group: string, id?: string) {\n if (id) this._pendingIds.add(id);\n const now = Date.now();\n const since = now - this._lastFlush;\n const remaining = this.maxWaitMs - since;\n if (this._timer) clearTimeout(this._timer);\n const wait = Math.max(0, Math.min(this.debounceMs, remaining));\n this._timer = setTimeout(async () => {\n const ids = Array.from(this._pendingIds);\n this._pendingIds.clear();\n this._timer = null;\n await this.updateGroupedComment(ctx, comments, group, ids.length > 0 ? ids : undefined);\n this._lastFlush = Date.now();\n }, wait);\n }\n\n private async flushNow(ctx: FrontendContext, comments: any, group: string) {\n if (this._timer) {\n clearTimeout(this._timer);\n this._timer = null;\n }\n const ids = Array.from(this._pendingIds);\n this._pendingIds.clear();\n await this.updateGroupedComment(ctx, comments, group, ids.length > 0 ? ids : undefined);\n this._lastFlush = Date.now();\n }\n\n /**\n * Sleep utility for enforcing delays\n */\n private sleep(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms));\n }\n}\n"],"mappings":"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","names":["CommentManager"]}
|
|
@@ -24,10 +24,10 @@ var init_host = __esm({
|
|
|
24
24
|
const { NdjsonSink } = await import("./ndjson-sink-FD2PSXGD.mjs");
|
|
25
25
|
this.frontends.push(new NdjsonSink(spec.config));
|
|
26
26
|
} else if (spec.name === "github") {
|
|
27
|
-
const { GitHubFrontend } = await import("./github-frontend-
|
|
27
|
+
const { GitHubFrontend } = await import("./github-frontend-U2U42CKV.mjs");
|
|
28
28
|
this.frontends.push(new GitHubFrontend());
|
|
29
29
|
} else if (spec.name === "slack") {
|
|
30
|
-
const { SlackFrontend } = await import("./slack-frontend-
|
|
30
|
+
const { SlackFrontend } = await import("./slack-frontend-XKSIOUXB.mjs");
|
|
31
31
|
this.frontends.push(new SlackFrontend(spec.config));
|
|
32
32
|
} else if (spec.name === "tui") {
|
|
33
33
|
const { TuiFrontend } = await import("./tui-frontend-T56PZB67.mjs");
|
|
@@ -45,7 +45,7 @@ var init_host = __esm({
|
|
|
45
45
|
const { TeamsFrontend } = await import("./teams-frontend-DNW5GZP3.mjs");
|
|
46
46
|
this.frontends.push(new TeamsFrontend(spec.config));
|
|
47
47
|
} else if (spec.name === "a2a") {
|
|
48
|
-
const { A2AFrontend } = await import("./a2a-frontend-
|
|
48
|
+
const { A2AFrontend } = await import("./a2a-frontend-BPWLYLCG.mjs");
|
|
49
49
|
this.frontends.push(new A2AFrontend(spec.config));
|
|
50
50
|
} else {
|
|
51
51
|
this.log.warn(`[FrontendsHost] Unknown frontend '${spec.name}', skipping`);
|
|
@@ -84,4 +84,4 @@ export {
|
|
|
84
84
|
FrontendsHost,
|
|
85
85
|
isActiveFrontend
|
|
86
86
|
};
|
|
87
|
-
//# sourceMappingURL=host-
|
|
87
|
+
//# sourceMappingURL=host-HFOJQIOF.mjs.map
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import {
|
|
2
|
+
checkLoopBudget,
|
|
3
|
+
evaluateGoto,
|
|
4
|
+
evaluateTransitions,
|
|
5
|
+
handleRouting,
|
|
6
|
+
init_routing
|
|
7
|
+
} from "./chunk-OHOBWVPP.mjs";
|
|
8
|
+
import "./chunk-OPI632LK.mjs";
|
|
9
|
+
import "./chunk-GVTWESYN.mjs";
|
|
10
|
+
import "./chunk-6VVXKXTI.mjs";
|
|
11
|
+
import "./chunk-34QX63WK.mjs";
|
|
12
|
+
import "./chunk-PQWZ6NFL.mjs";
|
|
13
|
+
import "./chunk-25IC7KXZ.mjs";
|
|
14
|
+
import "./chunk-LW3INISN.mjs";
|
|
15
|
+
import "./chunk-UFHOIB3R.mjs";
|
|
16
|
+
import "./chunk-FT3I25QV.mjs";
|
|
17
|
+
import "./chunk-UCMJJ3IM.mjs";
|
|
18
|
+
import "./chunk-J7LXIPZS.mjs";
|
|
19
|
+
init_routing();
|
|
20
|
+
export {
|
|
21
|
+
checkLoopBudget,
|
|
22
|
+
evaluateGoto,
|
|
23
|
+
evaluateTransitions,
|
|
24
|
+
handleRouting
|
|
25
|
+
};
|
|
26
|
+
//# sourceMappingURL=routing-SFP4D6O3.mjs.map
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
handleScheduleAction,
|
|
5
5
|
init_schedule_tool,
|
|
6
6
|
isScheduleTool
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-Y6PVSFCS.mjs";
|
|
8
8
|
import "./chunk-YSOIR46P.mjs";
|
|
9
9
|
import "./chunk-PDQTEBOJ.mjs";
|
|
10
10
|
import "./chunk-7VTZDC2X.mjs";
|
|
@@ -33,4 +33,4 @@ export {
|
|
|
33
33
|
handleScheduleAction,
|
|
34
34
|
isScheduleTool
|
|
35
35
|
};
|
|
36
|
-
//# sourceMappingURL=schedule-tool-
|
|
36
|
+
//# sourceMappingURL=schedule-tool-45NAALKS.mjs.map
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
handleScheduleAction,
|
|
5
5
|
init_schedule_tool,
|
|
6
6
|
isScheduleTool
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-IYXOLUDJ.mjs";
|
|
8
8
|
import "./chunk-YSOIR46P.mjs";
|
|
9
9
|
import "./chunk-PDQTEBOJ.mjs";
|
|
10
10
|
import "./chunk-7VTZDC2X.mjs";
|
|
@@ -14,9 +14,9 @@ import "./chunk-RHKPFJLG.mjs";
|
|
|
14
14
|
import "./chunk-UBTZE3FO.mjs";
|
|
15
15
|
import "./chunk-MM3TGVQ4.mjs";
|
|
16
16
|
import "./chunk-KWTCTEFT.mjs";
|
|
17
|
-
import "./chunk-
|
|
18
|
-
import "./chunk-
|
|
19
|
-
import "./chunk-
|
|
17
|
+
import "./chunk-OHOBWVPP.mjs";
|
|
18
|
+
import "./chunk-OPI632LK.mjs";
|
|
19
|
+
import "./chunk-GVTWESYN.mjs";
|
|
20
20
|
import "./chunk-6VVXKXTI.mjs";
|
|
21
21
|
import "./chunk-34QX63WK.mjs";
|
|
22
22
|
import "./chunk-PQWZ6NFL.mjs";
|
|
@@ -33,4 +33,4 @@ export {
|
|
|
33
33
|
handleScheduleAction,
|
|
34
34
|
isScheduleTool
|
|
35
35
|
};
|
|
36
|
-
//# sourceMappingURL=schedule-tool-
|
|
36
|
+
//# sourceMappingURL=schedule-tool-7O7SWSJ4.mjs.map
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
extractSlackContext,
|
|
7
7
|
init_schedule_tool_handler,
|
|
8
8
|
isScheduleToolCall
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-Y6PVSFCS.mjs";
|
|
10
10
|
import "./chunk-YSOIR46P.mjs";
|
|
11
11
|
import "./chunk-PDQTEBOJ.mjs";
|
|
12
12
|
import "./chunk-7VTZDC2X.mjs";
|
|
@@ -37,4 +37,4 @@ export {
|
|
|
37
37
|
extractSlackContext,
|
|
38
38
|
isScheduleToolCall
|
|
39
39
|
};
|
|
40
|
-
//# sourceMappingURL=schedule-tool-handler-
|
|
40
|
+
//# sourceMappingURL=schedule-tool-handler-6MPP5DXK.mjs.map
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
extractSlackContext,
|
|
7
7
|
init_schedule_tool_handler,
|
|
8
8
|
isScheduleToolCall
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-IYXOLUDJ.mjs";
|
|
10
10
|
import "./chunk-YSOIR46P.mjs";
|
|
11
11
|
import "./chunk-PDQTEBOJ.mjs";
|
|
12
12
|
import "./chunk-7VTZDC2X.mjs";
|
|
@@ -16,9 +16,9 @@ import "./chunk-RHKPFJLG.mjs";
|
|
|
16
16
|
import "./chunk-UBTZE3FO.mjs";
|
|
17
17
|
import "./chunk-MM3TGVQ4.mjs";
|
|
18
18
|
import "./chunk-KWTCTEFT.mjs";
|
|
19
|
-
import "./chunk-
|
|
20
|
-
import "./chunk-
|
|
21
|
-
import "./chunk-
|
|
19
|
+
import "./chunk-OHOBWVPP.mjs";
|
|
20
|
+
import "./chunk-OPI632LK.mjs";
|
|
21
|
+
import "./chunk-GVTWESYN.mjs";
|
|
22
22
|
import "./chunk-6VVXKXTI.mjs";
|
|
23
23
|
import "./chunk-34QX63WK.mjs";
|
|
24
24
|
import "./chunk-PQWZ6NFL.mjs";
|
|
@@ -37,4 +37,4 @@ export {
|
|
|
37
37
|
extractSlackContext,
|
|
38
38
|
isScheduleToolCall
|
|
39
39
|
};
|
|
40
|
-
//# sourceMappingURL=schedule-tool-handler-
|
|
40
|
+
//# sourceMappingURL=schedule-tool-handler-KYDXJ2ZL.mjs.map
|
package/dist/sdk/sdk.js
CHANGED
|
@@ -823,7 +823,7 @@ var require_package = __commonJS({
|
|
|
823
823
|
"@opentelemetry/sdk-node": "^0.203.0",
|
|
824
824
|
"@opentelemetry/sdk-trace-base": "^1.30.1",
|
|
825
825
|
"@opentelemetry/semantic-conventions": "^1.30.1",
|
|
826
|
-
"@probelabs/probe": "^0.6.0-
|
|
826
|
+
"@probelabs/probe": "^0.6.0-rc292",
|
|
827
827
|
"@types/commander": "^2.12.0",
|
|
828
828
|
"@types/uuid": "^10.0.0",
|
|
829
829
|
acorn: "^8.16.0",
|
|
@@ -48791,11 +48791,26 @@ var init_worktree_manager = __esm({
|
|
|
48791
48791
|
await this.deleteLocalBranches(worktreePath);
|
|
48792
48792
|
}
|
|
48793
48793
|
/**
|
|
48794
|
-
* Delete
|
|
48794
|
+
* Delete local branches in a worktree that are safe to remove.
|
|
48795
48795
|
* Worktrees are always used in detached HEAD state, so any local branches
|
|
48796
48796
|
* were unintentionally created and should be cleaned up.
|
|
48797
|
+
* IMPORTANT: Git worktrees share the branch namespace with the main repo
|
|
48798
|
+
* and all other worktrees. We must NOT delete branches that are checked out
|
|
48799
|
+
* in the main working tree or any other worktree — doing so would destroy
|
|
48800
|
+
* the user's work.
|
|
48797
48801
|
*/
|
|
48798
48802
|
async deleteLocalBranches(worktreePath) {
|
|
48803
|
+
const worktreeListCmd = `git -C ${this.escapeShellArg(worktreePath)} worktree list --porcelain`;
|
|
48804
|
+
const worktreeListResult = await this.executeGitCommand(worktreeListCmd, { timeout: 1e4 });
|
|
48805
|
+
const protectedBranches = /* @__PURE__ */ new Set();
|
|
48806
|
+
if (worktreeListResult.exitCode === 0) {
|
|
48807
|
+
for (const line of worktreeListResult.stdout.split("\n")) {
|
|
48808
|
+
const match = line.match(/^branch refs\/heads\/(.+)$/);
|
|
48809
|
+
if (match) {
|
|
48810
|
+
protectedBranches.add(match[1]);
|
|
48811
|
+
}
|
|
48812
|
+
}
|
|
48813
|
+
}
|
|
48799
48814
|
const listCmd = `git -C ${this.escapeShellArg(worktreePath)} branch --list --format='%(refname:short)'`;
|
|
48800
48815
|
const listResult = await this.executeGitCommand(listCmd, { timeout: 1e4 });
|
|
48801
48816
|
if (listResult.exitCode !== 0 || !listResult.stdout.trim()) {
|
|
@@ -48803,6 +48818,10 @@ var init_worktree_manager = __esm({
|
|
|
48803
48818
|
}
|
|
48804
48819
|
const branches = listResult.stdout.trim().split("\n").map((b) => b.trim()).filter((b) => b.length > 0);
|
|
48805
48820
|
for (const branch of branches) {
|
|
48821
|
+
if (protectedBranches.has(branch)) {
|
|
48822
|
+
logger.debug(`Skipping branch '${branch}' \u2014 checked out in another worktree`);
|
|
48823
|
+
continue;
|
|
48824
|
+
}
|
|
48806
48825
|
const deleteCmd = `git -C ${this.escapeShellArg(worktreePath)} branch -D ${this.escapeShellArg(branch)}`;
|
|
48807
48826
|
const deleteResult = await this.executeGitCommand(deleteCmd, { timeout: 1e4 });
|
|
48808
48827
|
if (deleteResult.exitCode === 0) {
|
|
@@ -50307,7 +50326,7 @@ async function executeCheckWithForEachItems(checkId, forEachParent, forEachItems
|
|
|
50307
50326
|
workflowInputs,
|
|
50308
50327
|
ai: {
|
|
50309
50328
|
...checkConfig.ai || {},
|
|
50310
|
-
timeout: checkConfig.ai?.timeout || 18e5,
|
|
50329
|
+
timeout: checkConfig.timeout || checkConfig.ai?.timeout || 18e5,
|
|
50311
50330
|
debug: !!context2.debug
|
|
50312
50331
|
}
|
|
50313
50332
|
};
|
|
@@ -50394,7 +50413,7 @@ async function executeCheckWithForEachItems(checkId, forEachParent, forEachItems
|
|
|
50394
50413
|
context2,
|
|
50395
50414
|
prInfo,
|
|
50396
50415
|
dependencyResults,
|
|
50397
|
-
checkConfig.ai?.timeout || 18e5,
|
|
50416
|
+
checkConfig.timeout || checkConfig.ai?.timeout || 18e5,
|
|
50398
50417
|
() => provider.execute(prInfo, providerConfig, dependencyResults, executionContext)
|
|
50399
50418
|
);
|
|
50400
50419
|
try {
|
|
@@ -50810,7 +50829,7 @@ async function executeInvocation(item, context2, scope, prInfo, dependencyResult
|
|
|
50810
50829
|
__outputHistory: outputHistory,
|
|
50811
50830
|
ai: {
|
|
50812
50831
|
...stepConfig.ai || {},
|
|
50813
|
-
timeout: stepConfig.ai?.timeout || 18e5,
|
|
50832
|
+
timeout: stepConfig.timeout || stepConfig.ai?.timeout || 18e5,
|
|
50814
50833
|
debug: !!context2.debug
|
|
50815
50834
|
}
|
|
50816
50835
|
};
|
|
@@ -51334,7 +51353,7 @@ async function executeSingleCheck(checkId, context2, state, emitEvent, transitio
|
|
|
51334
51353
|
workflowInputs,
|
|
51335
51354
|
ai: {
|
|
51336
51355
|
...checkConfig.ai || {},
|
|
51337
|
-
timeout: checkConfig.ai?.timeout || 18e5,
|
|
51356
|
+
timeout: checkConfig.timeout || checkConfig.ai?.timeout || 18e5,
|
|
51338
51357
|
debug: !!context2.debug
|
|
51339
51358
|
}
|
|
51340
51359
|
};
|
|
@@ -51435,7 +51454,7 @@ async function executeSingleCheck(checkId, context2, state, emitEvent, transitio
|
|
|
51435
51454
|
context2,
|
|
51436
51455
|
prInfo,
|
|
51437
51456
|
dependencyResults,
|
|
51438
|
-
checkConfig.ai?.timeout || 18e5,
|
|
51457
|
+
checkConfig.timeout || checkConfig.ai?.timeout || 18e5,
|
|
51439
51458
|
() => provider.execute(prInfo, providerConfig, dependencyResults, executionContext)
|
|
51440
51459
|
);
|
|
51441
51460
|
try {
|
|
@@ -52207,7 +52226,7 @@ async function executeCheckWithForEachItems2(checkId, forEachParent, forEachItem
|
|
|
52207
52226
|
workflowInputs,
|
|
52208
52227
|
ai: {
|
|
52209
52228
|
...checkConfig.ai || {},
|
|
52210
|
-
timeout: checkConfig.ai?.timeout || 18e5,
|
|
52229
|
+
timeout: checkConfig.timeout || checkConfig.ai?.timeout || 18e5,
|
|
52211
52230
|
debug: !!context2.debug
|
|
52212
52231
|
}
|
|
52213
52232
|
};
|
|
@@ -52242,7 +52261,10 @@ async function executeCheckWithForEachItems2(checkId, forEachParent, forEachItem
|
|
|
52242
52261
|
`[LevelDispatch] Conversation extracted (${conv?.transport || "unknown"}): ${messageCount} messages`
|
|
52243
52262
|
);
|
|
52244
52263
|
}
|
|
52245
|
-
const transportCtx = slackConv ? { slack: { event: event || {}, conversation: slackConv } } : {
|
|
52264
|
+
const transportCtx = slackConv ? { slack: { event: event || {}, conversation: slackConv } } : {
|
|
52265
|
+
telegram: { event: event || {}, conversation: telegramConv },
|
|
52266
|
+
webhook: payload
|
|
52267
|
+
};
|
|
52246
52268
|
providerConfig.eventContext = {
|
|
52247
52269
|
...providerConfig.eventContext,
|
|
52248
52270
|
...transportCtx,
|
|
@@ -52406,7 +52428,7 @@ async function executeCheckWithForEachItems2(checkId, forEachParent, forEachItem
|
|
|
52406
52428
|
context2,
|
|
52407
52429
|
prInfo,
|
|
52408
52430
|
dependencyResults,
|
|
52409
|
-
checkConfig.ai?.timeout || 18e5,
|
|
52431
|
+
checkConfig.timeout || checkConfig.ai?.timeout || 18e5,
|
|
52410
52432
|
() => provider.execute(prInfo, providerConfig, dependencyResults, executionContext)
|
|
52411
52433
|
);
|
|
52412
52434
|
try {
|
|
@@ -53335,7 +53357,7 @@ async function executeSingleCheck2(checkId, context2, state, emitEvent, transiti
|
|
|
53335
53357
|
workflowInputs,
|
|
53336
53358
|
ai: {
|
|
53337
53359
|
...checkConfig2.ai || {},
|
|
53338
|
-
timeout: checkConfig2.ai?.timeout || 18e5,
|
|
53360
|
+
timeout: checkConfig2.timeout || checkConfig2.ai?.timeout || 18e5,
|
|
53339
53361
|
debug: !!context2.debug
|
|
53340
53362
|
}
|
|
53341
53363
|
};
|
|
@@ -53366,7 +53388,9 @@ async function executeSingleCheck2(checkId, context2, state, emitEvent, transiti
|
|
|
53366
53388
|
const event = payload?.event;
|
|
53367
53389
|
const messageCount = Array.isArray(conv?.messages) ? conv.messages.length : 0;
|
|
53368
53390
|
if (context2.debug) {
|
|
53369
|
-
logger.info(
|
|
53391
|
+
logger.info(
|
|
53392
|
+
`[LevelDispatch] Conversation extracted (${conv?.transport || "unknown"}): ${messageCount} messages`
|
|
53393
|
+
);
|
|
53370
53394
|
}
|
|
53371
53395
|
const transportCtx = slackConv ? { slack: { event: event || {}, conversation: slackConv } } : { telegram: { event: event || {}, conversation: telegramConv }, webhook: payload };
|
|
53372
53396
|
providerConfig.eventContext = {
|
|
@@ -53504,7 +53528,7 @@ async function executeSingleCheck2(checkId, context2, state, emitEvent, transiti
|
|
|
53504
53528
|
context2,
|
|
53505
53529
|
prInfo,
|
|
53506
53530
|
dependencyResults,
|
|
53507
|
-
checkConfig2.ai?.timeout || 18e5,
|
|
53531
|
+
checkConfig2.timeout || checkConfig2.ai?.timeout || 18e5,
|
|
53508
53532
|
() => provider.execute(prInfo, providerConfig, dependencyResults, executionContext)
|
|
53509
53533
|
);
|
|
53510
53534
|
try {
|
|
@@ -56663,10 +56687,27 @@ var init_workspace_manager = __esm({
|
|
|
56663
56687
|
await this.deleteLocalBranches(worktreePath);
|
|
56664
56688
|
}
|
|
56665
56689
|
/**
|
|
56666
|
-
* Delete
|
|
56690
|
+
* Delete local branches in a worktree that are safe to remove.
|
|
56691
|
+
* IMPORTANT: Git worktrees share the branch namespace with the main repo
|
|
56692
|
+
* and all other worktrees. We must NOT delete branches that are checked out
|
|
56693
|
+
* in the main working tree or any other worktree — doing so would destroy
|
|
56694
|
+
* the user's work.
|
|
56667
56695
|
*/
|
|
56668
56696
|
async deleteLocalBranches(worktreePath) {
|
|
56669
56697
|
const escapedPath = shellEscape(worktreePath);
|
|
56698
|
+
const worktreeListResult = await commandExecutor.execute(
|
|
56699
|
+
`git -C ${escapedPath} worktree list --porcelain`,
|
|
56700
|
+
{ timeout: 1e4 }
|
|
56701
|
+
);
|
|
56702
|
+
const protectedBranches = /* @__PURE__ */ new Set();
|
|
56703
|
+
if (worktreeListResult.exitCode === 0) {
|
|
56704
|
+
for (const line of worktreeListResult.stdout.split("\n")) {
|
|
56705
|
+
const match = line.match(/^branch refs\/heads\/(.+)$/);
|
|
56706
|
+
if (match) {
|
|
56707
|
+
protectedBranches.add(match[1]);
|
|
56708
|
+
}
|
|
56709
|
+
}
|
|
56710
|
+
}
|
|
56670
56711
|
const listResult = await commandExecutor.execute(
|
|
56671
56712
|
`git -C ${escapedPath} branch --list --format='%(refname:short)'`,
|
|
56672
56713
|
{ timeout: 1e4 }
|
|
@@ -56676,6 +56717,10 @@ var init_workspace_manager = __esm({
|
|
|
56676
56717
|
}
|
|
56677
56718
|
const branches = listResult.stdout.trim().split("\n").map((b) => b.trim()).filter((b) => b.length > 0);
|
|
56678
56719
|
for (const branch of branches) {
|
|
56720
|
+
if (protectedBranches.has(branch)) {
|
|
56721
|
+
logger.debug(`[Workspace] Skipping branch '${branch}' \u2014 checked out in another worktree`);
|
|
56722
|
+
continue;
|
|
56723
|
+
}
|
|
56679
56724
|
const deleteResult = await commandExecutor.execute(
|
|
56680
56725
|
`git -C ${escapedPath} branch -D ${shellEscape(branch)}`,
|
|
56681
56726
|
{ timeout: 1e4 }
|
|
@@ -60809,6 +60854,21 @@ ${message}`;
|
|
|
60809
60854
|
if (out && typeof out._rawOutput === "string" && out._rawOutput.trim().length > 0) {
|
|
60810
60855
|
text = (text || "") + "\n\n" + out._rawOutput.trim();
|
|
60811
60856
|
}
|
|
60857
|
+
if (!text) {
|
|
60858
|
+
const issues = result?.issues || [];
|
|
60859
|
+
const errorIssues = issues.filter(
|
|
60860
|
+
(i) => i.severity === "error" && (i.ruleId?.startsWith("system/") || i.ruleId?.endsWith("/error"))
|
|
60861
|
+
);
|
|
60862
|
+
if (errorIssues.length > 0) {
|
|
60863
|
+
const errorMessages = errorIssues.map((i) => i.message).join("\n");
|
|
60864
|
+
text = `:warning: Something went wrong while processing your request:
|
|
60865
|
+
${errorMessages}`;
|
|
60866
|
+
this.errorNotified = true;
|
|
60867
|
+
ctx.logger.warn(
|
|
60868
|
+
`[slack-frontend] posting error fallback for ${checkId}: ${errorIssues.length} system error(s)`
|
|
60869
|
+
);
|
|
60870
|
+
}
|
|
60871
|
+
}
|
|
60812
60872
|
if (!text) {
|
|
60813
60873
|
ctx.logger.info(
|
|
60814
60874
|
`[slack-frontend] skip posting AI reply for ${checkId}: no renderable text in check output`
|