UNPKG

pr-vibe

Version:

AI-powered PR review responder that vibes with CodeRabbit, DeepSource, and other bots to automate repetitive feedback

155 lines (133 loc) 4.72 kB
/** * Utility for handling GitHub comment length limits */ const GITHUB_COMMENT_LIMIT = 65536; const TRUNCATION_BUFFER = 1000; // Leave room for truncation notice const MAX_SAFE_LENGTH = GITHUB_COMMENT_LIMIT - TRUNCATION_BUFFER; export class MessageTruncator { /** * Truncate a message to fit within GitHub's comment limits * @param {string} message - The message to potentially truncate * @param {Object} options - Truncation options * @returns {Object} { message: string, wasTruncated: boolean, originalLength: number } */ static truncate(message, options = {}) { const { preserveCodeBlocks = true, addNotice = true } = options; if (message.length <= MAX_SAFE_LENGTH) { return { message, wasTruncated: false, originalLength: message.length }; } let truncatedMessage = message; if (preserveCodeBlocks) { // Try to truncate at a natural boundary (end of code block, paragraph, etc.) truncatedMessage = this.truncateAtNaturalBoundary(message, MAX_SAFE_LENGTH); } else { truncatedMessage = message.substring(0, MAX_SAFE_LENGTH); } if (addNotice) { const truncatedChars = message.length - truncatedMessage.length; const truncationNotice = `\n\n---\n⚠️ **Message truncated**: ${truncatedChars.toLocaleString()} characters removed to fit GitHub's comment limit.\n`; truncatedMessage += truncationNotice; } return { message: truncatedMessage, wasTruncated: true, originalLength: message.length }; } /** * Try to truncate at a natural boundary to preserve readability */ static truncateAtNaturalBoundary(message, maxLength) { // Look for natural break points in reverse order of preference const boundaries = [ { pattern: /```\n/g, name: 'code block' }, { pattern: /\n\n/g, name: 'paragraph' }, { pattern: /\n/g, name: 'line' }, { pattern: /\. /g, name: 'sentence' } ]; for (const boundary of boundaries) { const matches = Array.from(message.matchAll(boundary.pattern)); // Find the last match before our limit for (let i = matches.length - 1; i >= 0; i--) { const match = matches[i]; if (match.index < maxLength) { // Truncate after this boundary const truncateAt = match.index + match[0].length; // Make sure we're not losing too much content if (truncateAt > maxLength * 0.8) { return message.substring(0, truncateAt); } } } } // If no good boundary found, just truncate at maxLength return message.substring(0, maxLength); } /** * Split a long message into multiple comments * @param {string} message - The message to split * @param {Object} options - Split options * @returns {Array<string>} Array of message parts */ static split(message, options = {}) { const { maxPartLength = MAX_SAFE_LENGTH - 500, // Leave extra room for continuation markers addContinuationMarkers = true } = options; if (message.length <= maxPartLength) { return [message]; } const parts = []; let remaining = message; let partNumber = 1; const totalParts = Math.ceil(message.length / maxPartLength); while (remaining.length > 0) { let rawSlice = remaining.substring(0, maxPartLength); let currentPart = rawSlice; // Try to break at a natural boundary if (remaining.length > maxPartLength) { rawSlice = this.truncateAtNaturalBoundary(remaining, maxPartLength); currentPart = rawSlice; } // Add continuation markers if (addContinuationMarkers) { if (partNumber > 1) { currentPart = `*...continued from previous comment*\n\n${currentPart}`; } if (partNumber < totalParts) { currentPart += `\n\n*...continues in next comment (${partNumber}/${totalParts})*`; } } parts.push(currentPart); remaining = remaining.substring(rawSlice.length); partNumber++; } return parts; } /** * Check if a message exceeds GitHub's limit */ static exceedsLimit(message) { return message.length > GITHUB_COMMENT_LIMIT; } /** * Get a summary of how much a message exceeds the limit */ static getExcessInfo(message) { const excess = message.length - GITHUB_COMMENT_LIMIT; return { exceedsLimit: excess > 0, messageLength: message.length, limit: GITHUB_COMMENT_LIMIT, excessCharacters: Math.max(0, excess), excessPercentage: Math.max(0, (excess / GITHUB_COMMENT_LIMIT) * 100) }; } }