Project-aware assist, link suggestions, project-scoped RAG, semantic search tool, SSE race fix
- Writing assistant: inject project notes as context (definition-tagged first), wikilink suggestions - Link suggestions: server-side endpoint finds unlinked term occurrences, NoteEditorView sidebar panel - Project-scoped RAG: ChatView ProjectSelector filters semantic+keyword search to selected project - Semantic search tool: LLM search_notes upgraded to hybrid semantic (0.40 threshold) + keyword merge - SSE race condition fix: drain remaining events after stream loop exits in chat.py and notes.py - RAG_AUTO_SNIPPET raised 800→4000; sidebar include uses full note body; MAX_BODY_CHARS 8000→24000 - Enter-to-submit on writing assistant instruction textareas (note and task editors) - DiffView: equal-line collapsing with 3-line context around changes Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,18 +1,50 @@
|
||||
MAX_BODY_CHARS = 8000
|
||||
MAX_BODY_CHARS = 24000
|
||||
MAX_CONTEXT_NOTE_CHARS = 1500
|
||||
|
||||
|
||||
def _build_context_block(context_notes: list[dict]) -> str:
|
||||
"""Format project context notes into a prompt block."""
|
||||
lines = [
|
||||
"--- Project Context ---",
|
||||
"The following notes are from the same project. Notes tagged 'definition' are "
|
||||
"canonical term definitions — treat them as authoritative. Use them to maintain "
|
||||
"consistency in terminology, tone, style, and [[wikilinks]] to other documents.",
|
||||
"",
|
||||
]
|
||||
for n in context_notes:
|
||||
tags_str = f" [tags: {', '.join(n['tags'])}]" if n.get("tags") else ""
|
||||
body_preview = (n["body"] or "")[:MAX_CONTEXT_NOTE_CHARS]
|
||||
if len(n["body"] or "") > MAX_CONTEXT_NOTE_CHARS:
|
||||
body_preview += "…"
|
||||
lines.append(f"**{n['title']}**{tags_str}")
|
||||
if body_preview:
|
||||
lines.append(body_preview)
|
||||
lines.append("")
|
||||
lines.append("--- End Project Context ---")
|
||||
return "\n".join(lines)
|
||||
|
||||
|
||||
def build_assist_messages(
|
||||
body: str, target_section: str, instruction: str, whole_doc: bool = False
|
||||
body: str,
|
||||
target_section: str,
|
||||
instruction: str,
|
||||
whole_doc: bool = False,
|
||||
context_notes: list[dict] | None = None,
|
||||
) -> 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.
|
||||
|
||||
context_notes: optional list of {title, tags, body} dicts from the same project,
|
||||
injected so the model can maintain consistency with related documents.
|
||||
"""
|
||||
truncated_body = body[:MAX_BODY_CHARS]
|
||||
if len(body) > MAX_BODY_CHARS:
|
||||
truncated_body += "\n... (truncated)"
|
||||
truncated_body += "\n… (truncated)"
|
||||
|
||||
context_block = (_build_context_block(context_notes) + "\n\n") if context_notes else ""
|
||||
|
||||
if whole_doc:
|
||||
system_content = (
|
||||
@@ -21,9 +53,12 @@ def build_assist_messages(
|
||||
"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."
|
||||
"italic (_text_), and code blocks. Never flatten nested lists into plain text. "
|
||||
"When referencing concepts defined in the Project Context, use [[wikilinks]] "
|
||||
"to link to the relevant note by its exact title."
|
||||
)
|
||||
user_content = (
|
||||
f"{context_block}"
|
||||
f"--- Document ---\n{truncated_body}\n--- End Document ---\n\n"
|
||||
f"Instruction: {instruction}"
|
||||
)
|
||||
@@ -41,9 +76,12 @@ def build_assist_messages(
|
||||
"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."
|
||||
"italic (_text_), and code blocks. Never flatten nested lists into plain text. "
|
||||
"When referencing concepts defined in the Project Context, use [[wikilinks]] "
|
||||
"to link to the relevant note by its exact title."
|
||||
)
|
||||
user_content = (
|
||||
f"{context_block}"
|
||||
f"--- Target Section ---\n{target_section}\n--- End Target Section ---\n\n"
|
||||
f"Instruction: {instruction}"
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user