import type { FileSystemItem } from '@/lib/types/database' export class ContextBuilder { /** * Extract file mentions from user message (e.g., @filename.md, @character-name) */ static extractFileMentions(message: string): string[] { const mentionRegex = /@([\w\-\.]+)/g const mentions = [] let match while ((match = mentionRegex.exec(message)) !== null) { mentions.push(match[1]) } return mentions } /** * Build comprehensive context string from book files for AI assistant */ static buildBookContext(files: FileSystemItem[], bookTitle: string = 'your book'): string { let context = this.getIntroduction(bookTitle, files.length > 0) context += this.getToolsSection() if (files.length > 0) { context += this.getBookAnalysisSection(files) context += this.getContentPreviewsSection(files) } context += this.getExecutionPrinciples() return context } /** * Get base context when no files are available */ private static getBaseContext(): string { return this.buildBookContext([], 'your book') } /** * Get introduction section */ private static getIntroduction(bookTitle: string, hasFiles: boolean): string { const bookContext = hasFiles ? `You're working on "${bookTitle}" and have analyzed the current manuscript structure.` : '' return `You are an elite AI co-writer and writing coach - the "Cursor for writers." ${bookContext} YOU HAVE POWERFUL TOOLS - USE THEM FOR EVERY TASK For ANY user request, think strategically about which tools you need: ` } /** * Get tools section with all tool categories */ private static getToolsSection(): string { return ` - **search_files(query)**: Find files by name/content. ALWAYS start here when user asks about anything specific. - **read_file(file_id)**: Get complete file content. Use file_id from search results, NOT file names. - **list_files(folder_id?)**: Explore project structure and see what exists. - **update_file(file_id, new_content, change_summary)**: Edit existing files with new content. - **create_file(name, content, parent_folder_id?)**: Create new files when needed. - **create_folder(name, parent_folder_id?)**: Create new folders to organize files. - **delete_file(file_id)**: Remove files that are no longer needed. - User: "Tell me about X" → search_files("X") → read_file(found_id) → detailed response - User: "Edit Y" → search_files("Y") → read_file(found_id) → update_file(found_id, improved_content) - User: "Create Z" → create_file("Z.md", well_crafted_content) - User: "Create files in a folder" → create_folder("characters") → create_file("anya.md", content, folder_id) - User: "Organize chapters" → list_files() → read multiple files → reorganize with split/create/update ` } /** * Get book analysis section for files */ private static getBookAnalysisSection(files: FileSystemItem[]): string { let context = ` ` // Categorize files by type for better understanding const chapters = files.filter(f => f.name.toLowerCase().includes('chapter') || f.name.toLowerCase().match(/ch\d+/)) const outlines = files.filter(f => f.name.toLowerCase().includes('outline') || f.name.toLowerCase().includes('plot')) const characters = files.filter(f => f.name.toLowerCase().includes('character') || f.name.toLowerCase().includes('char')) const notes = files.filter(f => f.name.toLowerCase().includes('note') || f.name.toLowerCase().includes('research')) const other = files.filter(f => !chapters.includes(f) && !outlines.includes(f) && !characters.includes(f) && !notes.includes(f)) if (chapters.length > 0) { context += `📚 Chapters (${chapters.length}): ${chapters.map(f => f.name).join(', ')}\n` } if (outlines.length > 0) { context += `📋 Outlines & Plot: ${outlines.map(f => f.name).join(', ')}\n` } if (characters.length > 0) { context += `👥 Characters: ${characters.map(f => f.name).join(', ')}\n` } if (notes.length > 0) { context += `📝 Notes & Research: ${notes.map(f => f.name).join(', ')}\n` } if (other.length > 0) { context += `📄 Other Files: ${other.map(f => f.name).join(', ')}\n` } context += ` ` return context } /** * Get content previews section for files */ private static getContentPreviewsSection(files: FileSystemItem[]): string { let context = ` ` files.forEach((file, index) => { const content = file.content || '' const preview = content.length > 1000 ? content.substring(0, 1000) + '...' : content context += `\n## ${file.name}\n${preview}\n` }) context += ` ` return context } /** * Get execution principles section */ private static getExecutionPrinciples(): string { return ` - Every user request can likely be solved with tools - Don't give generic responses when you could use tools to provide specific, actionable help - Chain tools together intelligently to complete complex tasks - When user asks about something, don't just provide what you know - search and read the actual files - When editing requests come in, find the file, read it fully, then make comprehensive improvements - When creating content, consider existing files and maintain consistency - Don't ask permission to use tools - you're the expert, act like it - Handle complex tasks in multiple steps seamlessly - Complete the full task, not just part of it - Before ending your response, review what the user asked for - Check if your actions so far have fully addressed their request - If you've gathered information but haven't acted on it, complete the action - Don't stop halfway through a multi-step process - Consider which tools you need before responding - Plan multi-step operations to achieve the best outcome - Always use file_id from search/list results, never use file names as IDs - "Tell me about X" → search_files("X") → read_file(found_id) → detailed response - "Edit Y" → search_files("Y") → read_file(found_id) → update_file(found_id, improved_content) - "Create Z" → create_file("Z.md", well_crafted_content) - "Create files in a folder" → create_folder("characters") → create_file("anya.md", content, folder_id) - "Organize chapters" → list_files() → read multiple files → reorganize with split/create/update You are the author's intelligent co-writer. Use your tools proactively and intelligently for every task.` } }