// src/utils/fileManifest.ts // // Utility for building a lightweight [Conversation Files] context block // from a file manifest. Injected into the compaction windowed view so the // LLM retains awareness of ALL conversation files, even when old messages // (with full file content) are behind the summary. import type { FileManifestEntry } from '@/types/graph'; /** * Prefix marker for the file manifest block. * Used to detect and deduplicate manifest messages across turns. */ export const FILE_MANIFEST_PREFIX = '[Conversation Files]'; /** * Builds a compact text block listing all files in the conversation. * Each entry costs ~10-15 tokens, so 10 files ≈ 100-150 tokens total. * * The block includes retrieval hints so the LLM knows how to fetch * full content on demand (via file_search or content_tool). * * @param manifest - Array of file metadata entries * @returns Formatted text block, or empty string if manifest is empty/undefined */ export function buildFileManifestBlock( manifest: FileManifestEntry[] | undefined ): string { if (!manifest || manifest.length === 0) { return ''; } const lines = manifest.map((entry) => { const parts: string[] = [`- ${entry.filename}`]; if (entry.contentId) { parts.push(`(content_id: ${entry.contentId})`); } if (entry.source) { parts.push(`[${entry.source}]`); } return parts.join(' '); }); return [ FILE_MANIFEST_PREFIX, 'The following files have been shared in this conversation.', 'Use file_search or content_tool read (with content_id) to retrieve full content when needed.', '', ...lines, ].join('\n'); }