UNPKG

@git.zone/tsdoc

Version:

A comprehensive TypeScript documentation tool that leverages AI to generate and enhance project documentation, including dynamic README creation, API docs via TypeDoc, and smart commit message generation.

284 lines 23.3 kB
/** * Intelligent git diff processor that handles large diffs by sampling and prioritization * instead of blind truncation. */ export class DiffProcessor { constructor(options = {}) { this.options = { maxDiffTokens: options.maxDiffTokens ?? 100000, smallFileLines: options.smallFileLines ?? 50, mediumFileLines: options.mediumFileLines ?? 200, sampleHeadLines: options.sampleHeadLines ?? 20, sampleTailLines: options.sampleTailLines ?? 20, }; } /** * Process an array of git diffs into a structured, token-efficient format */ processDiffs(diffStringArray) { // Parse all diffs into file info objects const fileInfos = diffStringArray .map(diffString => this.parseDiffFile(diffString)) .filter(info => info !== null); // Prioritize files (source files first, build artifacts last) const prioritized = this.prioritizeFiles(fileInfos); const result = { summary: '', fullDiffs: [], summarizedDiffs: [], metadataOnly: [], totalFiles: prioritized.length, totalTokens: 0, }; let tokensUsed = 0; const tokenBudget = this.options.maxDiffTokens; // Categorize and include files based on size and token budget for (const fileInfo of prioritized) { const remainingBudget = tokenBudget - tokensUsed; if (remainingBudget <= 0) { // Budget exhausted - rest are metadata only result.metadataOnly.push(this.formatMetadataOnly(fileInfo)); continue; } if (fileInfo.totalLines <= this.options.smallFileLines) { // Small file - include fully if budget allows if (fileInfo.estimatedTokens <= remainingBudget) { const statusPrefix = this.getFileStatusPrefix(fileInfo); result.fullDiffs.push(`${statusPrefix}${fileInfo.diffContent}`); tokensUsed += fileInfo.estimatedTokens; } else { result.metadataOnly.push(this.formatMetadataOnly(fileInfo)); } } else if (fileInfo.totalLines <= this.options.mediumFileLines) { // Medium file - try to include summary with head/tail const summary = this.extractDiffSample(fileInfo, this.options.sampleHeadLines, this.options.sampleTailLines); const summaryTokens = Math.ceil(summary.length / 4); // Rough estimate if (summaryTokens <= remainingBudget) { result.summarizedDiffs.push(summary); tokensUsed += summaryTokens; } else { result.metadataOnly.push(this.formatMetadataOnly(fileInfo)); } } else { // Large file - metadata only result.metadataOnly.push(this.formatMetadataOnly(fileInfo)); } } result.totalTokens = tokensUsed; result.summary = this.generateSummary(result); return result; } /** * Format the processed diff for inclusion in context */ formatForContext(processed) { const sections = []; // Summary section sections.push('====== GIT DIFF SUMMARY ======'); sections.push(processed.summary); sections.push(''); // Full diffs section if (processed.fullDiffs.length > 0) { sections.push(`====== FULL DIFFS (${processed.fullDiffs.length} files) ======`); sections.push(processed.fullDiffs.join('\n\n')); sections.push(''); } // Summarized diffs section if (processed.summarizedDiffs.length > 0) { sections.push(`====== SUMMARIZED DIFFS (${processed.summarizedDiffs.length} files) ======`); sections.push(processed.summarizedDiffs.join('\n\n')); sections.push(''); } // Metadata only section if (processed.metadataOnly.length > 0) { sections.push(`====== METADATA ONLY (${processed.metadataOnly.length} files) ======`); sections.push(processed.metadataOnly.join('\n')); sections.push(''); } sections.push('====== END OF GIT DIFF ======'); return sections.join('\n'); } /** * Parse a single git diff string into file information */ parseDiffFile(diffString) { if (!diffString || diffString.trim().length === 0) { return null; } const lines = diffString.split('\n'); let filepath = ''; let status = 'modified'; let linesAdded = 0; let linesRemoved = 0; // Parse diff header to extract filepath and status for (const line of lines) { if (line.startsWith('--- a/')) { filepath = line.substring(6); } else if (line.startsWith('+++ b/')) { const newPath = line.substring(6); if (newPath === '/dev/null') { status = 'deleted'; } else if (filepath === '/dev/null') { status = 'added'; filepath = newPath; } else { filepath = newPath; } } else if (line.startsWith('+') && !line.startsWith('+++')) { linesAdded++; } else if (line.startsWith('-') && !line.startsWith('---')) { linesRemoved++; } } const totalLines = linesAdded + linesRemoved; const estimatedTokens = Math.ceil(diffString.length / 4); return { filepath, status, linesAdded, linesRemoved, totalLines, estimatedTokens, diffContent: diffString, }; } /** * Prioritize files by importance (source files before build artifacts) */ prioritizeFiles(files) { return files.sort((a, b) => { const scoreA = this.getFileImportanceScore(a.filepath); const scoreB = this.getFileImportanceScore(b.filepath); return scoreB - scoreA; // Higher score first }); } /** * Calculate importance score for a file path */ getFileImportanceScore(filepath) { // Source files - highest priority if (filepath.match(/^(src|lib|app|components|pages|api)\//)) { return 100; } // Test files - high priority if (filepath.match(/\.(test|spec)\.(ts|js|tsx|jsx)$/) || filepath.startsWith('test/')) { return 80; } // Configuration files - medium-high priority if (filepath.match(/\.(json|yaml|yml|toml|config\.(ts|js))$/)) { return 60; } // Documentation - medium priority if (filepath.match(/\.(md|txt|rst)$/)) { return 40; } // Build artifacts - low priority if (filepath.match(/^(dist|build|out|\.next|public\/dist)\//)) { return 10; } // Start with default priority let score = 50; // Boost interface/type files - they're usually small but critical if (filepath.includes('interfaces/') || filepath.includes('.types.')) { score += 20; } // Boost entry points if (filepath.endsWith('index.ts') || filepath.endsWith('mod.ts')) { score += 15; } return score; } /** * Extract head and tail lines from a diff, omitting the middle */ extractDiffSample(fileInfo, headLines, tailLines) { const lines = fileInfo.diffContent.split('\n'); const totalLines = lines.length; if (totalLines <= headLines + tailLines) { // File is small enough to include fully return fileInfo.diffContent; } // Extract file metadata from diff header const headerLines = []; let bodyStartIndex = 0; for (let i = 0; i < lines.length; i++) { if (lines[i].startsWith('@@')) { headerLines.push(...lines.slice(0, i + 1)); bodyStartIndex = i + 1; break; } } const bodyLines = lines.slice(bodyStartIndex); const head = bodyLines.slice(0, headLines); const tail = bodyLines.slice(-tailLines); const omittedLines = bodyLines.length - headLines - tailLines; const statusEmoji = fileInfo.status === 'added' ? '➕' : fileInfo.status === 'deleted' ? '➖' : '📝'; const parts = []; parts.push(`${statusEmoji} FILE: ${fileInfo.filepath}`); parts.push(`CHANGES: +${fileInfo.linesAdded} lines, -${fileInfo.linesRemoved} lines (${fileInfo.totalLines} total)`); parts.push(''); parts.push(...headerLines); parts.push(...head); parts.push(''); parts.push(`[... ${omittedLines} lines omitted - use Read tool to see full file ...]`); parts.push(''); parts.push(...tail); return parts.join('\n'); } /** * Get file status prefix with emoji */ getFileStatusPrefix(fileInfo) { const statusEmoji = fileInfo.status === 'added' ? '➕' : fileInfo.status === 'deleted' ? '➖' : '📝'; return `${statusEmoji} `; } /** * Extract filepath from diff content */ extractFilepathFromDiff(diffContent) { const lines = diffContent.split('\n'); for (const line of lines) { if (line.startsWith('+++ b/')) { return line.substring(6); } } return 'unknown'; } /** * Format file info as metadata only */ formatMetadataOnly(fileInfo) { const statusEmoji = fileInfo.status === 'added' ? '➕' : fileInfo.status === 'deleted' ? '➖' : '📝'; return `${statusEmoji} ${fileInfo.filepath} (+${fileInfo.linesAdded}, -${fileInfo.linesRemoved})`; } /** * Generate human-readable summary of processed diff */ generateSummary(result) { const parts = []; parts.push(`Files changed: ${result.totalFiles} total`); parts.push(`- ${result.fullDiffs.length} included in full`); parts.push(`- ${result.summarizedDiffs.length} summarized (head/tail shown)`); parts.push(`- ${result.metadataOnly.length} metadata only`); parts.push(`Estimated tokens: ~${result.totalTokens.toLocaleString()}`); if (result.metadataOnly.length > 0) { parts.push(''); parts.push('NOTE: Some files excluded to stay within token budget.'); parts.push('Use Read tool with specific file paths to see full content.'); } return parts.join('\n'); } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5kaWZmcHJvY2Vzc29yLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvY2xhc3Nlcy5kaWZmcHJvY2Vzc29yLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7R0FHRztBQTZCSCxNQUFNLE9BQU8sYUFBYTtJQUd4QixZQUFZLFVBQWlDLEVBQUU7UUFDN0MsSUFBSSxDQUFDLE9BQU8sR0FBRztZQUNiLGFBQWEsRUFBRSxPQUFPLENBQUMsYUFBYSxJQUFJLE1BQU07WUFDOUMsY0FBYyxFQUFFLE9BQU8sQ0FBQyxjQUFjLElBQUksRUFBRTtZQUM1QyxlQUFlLEVBQUUsT0FBTyxDQUFDLGVBQWUsSUFBSSxHQUFHO1lBQy9DLGVBQWUsRUFBRSxPQUFPLENBQUMsZUFBZSxJQUFJLEVBQUU7WUFDOUMsZUFBZSxFQUFFLE9BQU8sQ0FBQyxlQUFlLElBQUksRUFBRTtTQUMvQyxDQUFDO0lBQ0osQ0FBQztJQUVEOztPQUVHO0lBQ0ksWUFBWSxDQUFDLGVBQXlCO1FBQzNDLHlDQUF5QztRQUN6QyxNQUFNLFNBQVMsR0FBb0IsZUFBZTthQUMvQyxHQUFHLENBQUMsVUFBVSxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsYUFBYSxDQUFDLFVBQVUsQ0FBQyxDQUFDO2FBQ2pELE1BQU0sQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLElBQUksS0FBSyxJQUFJLENBQW9CLENBQUM7UUFFcEQsOERBQThEO1FBQzlELE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxlQUFlLENBQUMsU0FBUyxDQUFDLENBQUM7UUFFcEQsTUFBTSxNQUFNLEdBQW1CO1lBQzdCLE9BQU8sRUFBRSxFQUFFO1lBQ1gsU0FBUyxFQUFFLEVBQUU7WUFDYixlQUFlLEVBQUUsRUFBRTtZQUNuQixZQUFZLEVBQUUsRUFBRTtZQUNoQixVQUFVLEVBQUUsV0FBVyxDQUFDLE1BQU07WUFDOUIsV0FBVyxFQUFFLENBQUM7U0FDZixDQUFDO1FBRUYsSUFBSSxVQUFVLEdBQUcsQ0FB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