72 lines
2.1 KiB
TypeScript
72 lines
2.1 KiB
TypeScript
import { readTextContent } from './file'
|
|
import { fileFreshnessService } from '../services/fileFreshness'
|
|
|
|
/**
|
|
* File recovery configuration for auto-compact feature
|
|
* These limits ensure recovered files don't overwhelm the compressed context
|
|
*/
|
|
const MAX_FILES_TO_RECOVER = 5
|
|
const MAX_TOKENS_PER_FILE = 10_000
|
|
const MAX_TOTAL_FILE_TOKENS = 50_000
|
|
|
|
/**
|
|
* Selects and reads recently accessed files for context recovery
|
|
*
|
|
* During auto-compact, this function preserves development context by:
|
|
* - Selecting files based on recent access patterns
|
|
* - Enforcing token budgets to prevent context bloat
|
|
* - Truncating large files while preserving essential content
|
|
*
|
|
* @returns Array of file data with content, token counts, and truncation flags
|
|
*/
|
|
export async function selectAndReadFiles(): Promise<
|
|
Array<{
|
|
path: string
|
|
content: string
|
|
tokens: number
|
|
truncated: boolean
|
|
}>
|
|
> {
|
|
const importantFiles =
|
|
fileFreshnessService.getImportantFiles(MAX_FILES_TO_RECOVER)
|
|
const results = []
|
|
let totalTokens = 0
|
|
|
|
for (const fileInfo of importantFiles) {
|
|
try {
|
|
const { content } = readTextContent(fileInfo.path)
|
|
const estimatedTokens = Math.ceil(content.length * 0.25)
|
|
|
|
// Apply per-file token limit to prevent any single file from dominating context
|
|
let finalContent = content
|
|
let truncated = false
|
|
|
|
if (estimatedTokens > MAX_TOKENS_PER_FILE) {
|
|
const maxChars = Math.floor(MAX_TOKENS_PER_FILE / 0.25)
|
|
finalContent = content.substring(0, maxChars)
|
|
truncated = true
|
|
}
|
|
|
|
const finalTokens = Math.min(estimatedTokens, MAX_TOKENS_PER_FILE)
|
|
|
|
// Enforce total token budget to maintain auto-compact effectiveness
|
|
if (totalTokens + finalTokens > MAX_TOTAL_FILE_TOKENS) {
|
|
break
|
|
}
|
|
|
|
totalTokens += finalTokens
|
|
results.push({
|
|
path: fileInfo.path,
|
|
content: finalContent,
|
|
tokens: finalTokens,
|
|
truncated,
|
|
})
|
|
} catch (error) {
|
|
// Skip files that cannot be read, don't let one failure stop the process
|
|
console.error(`Failed to read file for recovery: ${fileInfo.path}`, error)
|
|
}
|
|
}
|
|
|
|
return results
|
|
}
|