"""Builds the system prompt that is sent to the AI at the start of each chat session.""" # Prevents very large files from flooding the context window with tokens. MAX_FILE_CHARS = 4000 class SystemPrompter: """Generates system prompts for the chat assistant. When a file is open in the editor it can be embedded in the prompt so the AI has direct context of the code the user is currently working on. """ @staticmethod def generate_prompt( file_context: dict | None = None, search_context: list[dict] | None = None, ) -> str: """Build a system prompt, optionally embedding a file and/or web search results. Args: file_context: dict with keys 'name' (filename) and 'content' (raw text), or None if no file should be included. search_context: list of {"title", "url", "snippet"} dicts from SearchManager, or None if no search results should be included. Returns: A ready-to-use system prompt string. """ base = ( "You are an expert code assistant integrated into a lightweight code editor. " "Help the user with code suggestions, debugging, explanations, and improvements. " "Be concise and precise. Use markdown and fenced code blocks where appropriate." ) prompt = base if file_context: name = file_context.get("name", "unknown") content = file_context.get("content", "") # Truncate large files to avoid exceeding the model's token limit if len(content) > MAX_FILE_CHARS: content = content[:MAX_FILE_CHARS] + "\n... [truncated]" prompt += ( f"\n\nThe user currently has the following file open in the editor:\n" f"\n" f"\n{content}\n\n" f"\n" f"Refer to this file when answering questions about the code." ) if search_context: search_section = "\n\nThe user has performed a web search. Use the results below as additional context if relevant:\n\n" for i, r in enumerate(search_context, 1): search_section += ( f"[{i}] {r.get('title', '')}\n" f"URL: {r.get('url', '')}\n" f"{r.get('snippet', '')}\n\n" ) search_section += "" prompt += search_section return prompt