MAX_BODY_CHARS = 8000 def build_assist_messages( body: str, target_section: str, instruction: str, whole_doc: bool = False ) -> list[dict]: """Build Ollama messages for writing assist. When whole_doc=True, the model revises the entire document. When whole_doc=False (section mode), the full body is provided as read-only context and the model outputs only the replacement for the target section. """ truncated_body = body[:MAX_BODY_CHARS] if len(body) > MAX_BODY_CHARS: truncated_body += "\n... (truncated)" if whole_doc: system_content = ( "You are a writing assistant. Revise the document per the instruction. " "Output ONLY the complete revised document. Preserve all structure and " "content not addressed by the instruction. " "Preserve all markdown formatting exactly — including bullet lists (- item), " "numbered lists (1. item), nested/indented sub-items ( - sub), bold (**text**), " "italic (_text_), and code blocks. Never flatten nested lists into plain text." ) user_content = ( f"--- Document ---\n{truncated_body}\n--- End Document ---\n\n" f"Instruction: {instruction}" ) else: system_content = ( "You are an AI writing assistant integrated into a note-taking app. " "The user is editing a document. The full document is shown below for context.\n\n" f"--- Full Document ---\n{truncated_body}\n--- End Document ---\n\n" "The user will give you a specific section of the document and an instruction. " "Output ONLY the replacement text for that section. " "If the target section starts with a markdown heading (e.g. ## Heading), " "your output MUST also start with a heading at the same level. " "You may revise the heading text but do not remove it. " "Do not include other sections, explanatory text, or markdown code fences around the output. " "Match the document's existing tone and style. " "IMPORTANT: Preserve all markdown formatting exactly — including bullet lists (- item), " "numbered lists (1. item), nested/indented sub-items ( - sub), bold (**text**), " "italic (_text_), and code blocks. Never flatten nested lists into plain text." ) user_content = ( f"--- Target Section ---\n{target_section}\n--- End Target Section ---\n\n" f"Instruction: {instruction}" ) return [ {"role": "system", "content": system_content}, {"role": "user", "content": user_content}, ]