fix(ai): contexte applicatif de l'assistant, dossier vide et liens fiables (#88, BUG-041, BUG-042)
- BUG-041 : le contexte d'un dossier vide ne renvoie plus 404 ; il degrade vers le prompt General enrichi d'un bloc « Dossier vide ». - BUG-042 : liens de fichiers deterministes (nom -> presse-papiers, dossier -> arborescence, chemin -> viewer) et resolution du chemin contre l'index du vault (exact -> suffixe -> basename) avant ouverture, fin des 'File not found'. - #88 : app_context (documents ouverts, repertoire/vault courants, recherche + resultats affiches) et fichiers recemment modifies injectes dans le prompt General. Tests : pytest 963 passed / 6 skipped, ruff 0, mypy 0, frontend 52/52 + validate-imports 36 modules.
This commit is contained in:
+73
-2
@@ -499,13 +499,84 @@ Règles :
|
||||
"""
|
||||
|
||||
|
||||
def build_general_system_prompt(vaults: list[str] | None = None) -> str:
|
||||
"""System prompt for the General assistant (app help + actions)."""
|
||||
def _format_app_context(app_context: dict[str, Any] | None, recent_files: list[dict[str, Any]] | None) -> str:
|
||||
"""Render the live application state for the General assistant prompt.
|
||||
|
||||
The General assistant has no document context; without this block it only
|
||||
knows the app exists. Passing what the user currently sees (open documents,
|
||||
current directory, active search, recently modified files) lets it answer
|
||||
"résume ce que je fais / où j'en suis" style questions.
|
||||
"""
|
||||
app_context = app_context or {}
|
||||
lines: list[str] = []
|
||||
|
||||
vault = app_context.get("vault") or app_context.get("current_vault")
|
||||
if vault:
|
||||
lines.append(f"- Vault sélectionné : {vault}")
|
||||
directory = app_context.get("directory")
|
||||
if directory:
|
||||
lines.append(f"- Répertoire courant : {directory}")
|
||||
current_path = app_context.get("current_path")
|
||||
if current_path:
|
||||
lines.append(f"- Document affiché dans le viewer : {current_path}")
|
||||
|
||||
docs = app_context.get("open_documents") or []
|
||||
rendered_docs = []
|
||||
for doc in docs:
|
||||
if not isinstance(doc, dict) or not doc.get("path"):
|
||||
continue
|
||||
rendered_docs.append(f"{doc['path']} (vault {doc['vault']})" if doc.get("vault") else str(doc["path"]))
|
||||
if rendered_docs:
|
||||
lines.append("- Documents ouverts dans les onglets/panneaux : " + ", ".join(rendered_docs))
|
||||
|
||||
query = app_context.get("search_query")
|
||||
if query:
|
||||
total = app_context.get("search_total")
|
||||
suffix = f" ({total} résultat(s))" if isinstance(total, int) else ""
|
||||
lines.append(f"- Recherche en cours : « {query} »{suffix}")
|
||||
|
||||
results = app_context.get("search_results") or []
|
||||
rendered_results = [str(r.get("path")) for r in results[:10] if isinstance(r, dict) and r.get("path")]
|
||||
if rendered_results:
|
||||
lines.append("- Premiers résultats affichés : " + ", ".join(rendered_results))
|
||||
|
||||
if recent_files:
|
||||
rendered_recent = [
|
||||
f"{f.get('vault')}/{f.get('path')}" for f in recent_files[:10] if f.get("path")
|
||||
]
|
||||
if rendered_recent:
|
||||
lines.append("- Fichiers récemment modifiés : " + ", ".join(rendered_recent))
|
||||
|
||||
if not lines:
|
||||
return ""
|
||||
return (
|
||||
"## Contexte applicatif actuel\n"
|
||||
"Voici ce que l'utilisateur voit ou fait en ce moment dans ObsiGate. "
|
||||
"Sers-t'en pour comprendre sa demande ; ne le répète pas inutilement.\n"
|
||||
+ "\n".join(lines)
|
||||
+ "\n"
|
||||
)
|
||||
|
||||
|
||||
def build_general_system_prompt(
|
||||
vaults: list[str] | None = None,
|
||||
app_context: dict[str, Any] | None = None,
|
||||
recent_files: list[dict[str, Any]] | None = None,
|
||||
) -> str:
|
||||
"""System prompt for the General assistant (app help + actions).
|
||||
|
||||
``app_context`` carries the live UI state (open documents, current
|
||||
directory, active search) and ``recent_files`` the last modified files, so
|
||||
the assistant knows what the user is doing rather than answering blind.
|
||||
"""
|
||||
prompt = GENERAL_SYSTEM_PROMPT
|
||||
if vaults:
|
||||
prompt += "\nVaults disponibles : " + ", ".join(sorted(vaults)) + "\n"
|
||||
else:
|
||||
prompt += "\nAucun vault n'est actuellement configuré.\n"
|
||||
block = _format_app_context(app_context, recent_files)
|
||||
if block:
|
||||
prompt += "\n" + block
|
||||
return prompt
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user