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.`
}
}