UNPKG

pury

Version:

🛡️ AI-powered security scanner with advanced threat detection, dual reporting system (detailed & summary), and comprehensive code analysis

153 lines 5.77 kB
import { logger } from '../utils/logger.js'; export class ContextManager { maxTokensPerRequest; estimatedTokensPerChar; constructor(maxTokensPerRequest = 2048) { this.maxTokensPerRequest = maxTokensPerRequest; this.estimatedTokensPerChar = 0.25; // Rough estimation: 4 chars ≈ 1 token } createAnalysisRequests(files, analysisTypes) { const requests = []; for (const file of files) { const tokenCount = this.estimateTokenCount(file.content); if (tokenCount > this.maxTokensPerRequest) { // Split large files into chunks const chunks = this.splitLargeFile(file); for (const chunk of chunks) { requests.push({ code: chunk.content, filePath: chunk.path, analysisType: analysisTypes, context: this.generateFileContext(file) }); } } else { requests.push({ code: file.content, filePath: file.path, analysisType: analysisTypes, context: this.generateFileContext(file) }); } } return requests; } createBatchedRequests(files, analysisTypes) { const allRequests = this.createAnalysisRequests(files, analysisTypes); const batches = []; let currentBatch = []; let currentBatchTokens = 0; for (const request of allRequests) { const requestTokens = this.estimateTokenCount(request.code); // If adding this request would exceed the batch limit, start a new batch if (currentBatchTokens + requestTokens > this.maxTokensPerRequest && currentBatch.length > 0) { batches.push(currentBatch); currentBatch = [request]; currentBatchTokens = requestTokens; } else { currentBatch.push(request); currentBatchTokens += requestTokens; } } // Add the final batch if it has requests if (currentBatch.length > 0) { batches.push(currentBatch); } logger.debug(`Created ${batches.length} batches from ${allRequests.length} requests`); return batches; } splitLargeFile(file) { const chunks = []; const lines = file.content.split('\n'); const maxLinesPerChunk = Math.floor(this.maxTokensPerRequest / (this.estimatedTokensPerChar * 50)); // Estimate 50 chars per line for (let i = 0; i < lines.length; i += maxLinesPerChunk) { const chunkLines = lines.slice(i, i + maxLinesPerChunk); const chunkContent = chunkLines.join('\n'); chunks.push({ ...file, path: `${file.path}:${i + 1}-${i + chunkLines.length}`, content: chunkContent, size: chunkContent.length }); } logger.debug(`Split large file ${file.path} into ${chunks.length} chunks`); return chunks; } generateFileContext(file) { const context = []; // Add file type information if (file.extension) { context.push(`File type: ${file.extension}`); } // Add relative path for better understanding context.push(`Relative path: ${file.relativePath}`); // Add file size information context.push(`File size: ${file.size} bytes`); // Determine likely programming language const language = this.detectLanguage(file.extension); if (language) { context.push(`Language: ${language}`); } return context.join(', '); } detectLanguage(extension) { const languageMap = { '.js': 'JavaScript', '.jsx': 'JavaScript React', '.ts': 'TypeScript', '.tsx': 'TypeScript React', '.py': 'Python', '.java': 'Java', '.c': 'C', '.cpp': 'C++', '.cxx': 'C++', '.cc': 'C++', '.h': 'C/C++ Header', '.hpp': 'C++ Header', '.cs': 'C#', '.php': 'PHP', '.rb': 'Ruby', '.go': 'Go', '.rs': 'Rust', '.swift': 'Swift', '.kt': 'Kotlin', '.scala': 'Scala', '.html': 'HTML', '.css': 'CSS', '.scss': 'SCSS', '.sass': 'Sass', '.json': 'JSON', '.xml': 'XML', '.yaml': 'YAML', '.yml': 'YAML', '.sql': 'SQL', '.sh': 'Shell Script', '.bash': 'Bash Script', '.ps1': 'PowerShell', '.bat': 'Batch File', '.dockerfile': 'Dockerfile' }; return languageMap[extension.toLowerCase()] || null; } estimateTokenCount(text) { return Math.ceil(text.length * this.estimatedTokensPerChar); } optimizePromptLength(prompt, maxLength) { if (this.estimateTokenCount(prompt) <= maxLength) { return prompt; } // Simple truncation - in production, you might want more sophisticated truncation const maxChars = Math.floor(maxLength / this.estimatedTokensPerChar); return `${prompt.substring(0, maxChars)}\n[Content truncated due to length]`; } getTokenBudget() { return { max: this.maxTokensPerRequest, estimated: Math.floor(this.maxTokensPerRequest * 0.8) // Leave 20% buffer }; } } //# sourceMappingURL=context-manager.js.map