fix(ai): mode agent utilise les outils natifs au lieu du bloc obsigate-action (BUG-053)
CI / lint (push) Successful in 1m33s
CI / security (push) Successful in 1m0s
CI / test (push) Successful in 2m57s
CI / build (push) Successful in 56s
CI / e2e (push) Successful in 10m48s

This commit is contained in:
2026-09-17 07:30:31 -04:00
parent e3434d19ea
commit f02174af57
14 changed files with 122 additions and 19 deletions
+32 -2
View File
@@ -486,12 +486,17 @@ def build_system_prompt(context: dict[str, Any], scope: str = "directory", vault
return prompt
GENERAL_SYSTEM_PROMPT = """Tu es l'assistant intégré d'ObsiGate, une application web auto-hébergée pour consulter, rechercher et éditer des vaults Obsidian (Markdown).
GENERAL_SYSTEM_HEADER = """Tu es l'assistant intégré d'ObsiGate, une application web auto-hébergée pour consulter, rechercher et éditer des vaults Obsidian (Markdown).
Tes deux rôles :
1. **Aider sur l'application** : expliquer la navigation, la recherche (full-text, filtres `tag:`, `created:`, `path:`), l'éditeur (CodeMirror, autosave, raccourcis), les onglets et le split view, les sauvegardes et la restauration, le partage public, l'export (HTML/Markdown/ePub/PDF), Mermaid, Excalidraw, les plugins, les thèmes, le mode hors-ligne, le MFA, etc.
2. **Proposer des actions concrètes** : créer un fichier ou un dossier dans un vault.
"""
# Text action protocol — used by the classic (non-agent) chat endpoint, where
# the model has no native tool calling; the frontend turns each block into a
# clickable “Apply” card.
GENERAL_ACTION_TEXT_PROTOCOL = """
Quand l'utilisateur demande explicitement de créer un fichier, inclus un bloc de ce type dans ta réponse (un bloc par fichier, et rien d'autre à l'intérieur du bloc) :
```obsigate-action
@@ -513,6 +518,25 @@ Règles :
- Réponds dans la langue de l'utilisateur, de façon concise et structurée (Markdown).
"""
# Agent mode: the model has native tools, so it must call them (function
# calling) instead of emitting the text `obsigate-action` blocks — otherwise
# the requested file is never created (BUG-053).
GENERAL_ACTION_TOOL_PROTOCOL = """
Tu disposes d'outils natifs (function calling) pour lire, chercher et modifier les vaults : `create_file`, `create_directory`, `append_to_file`, `edit_file`, `read_file`, `search_fulltext`, etc.
Quand l'utilisateur demande explicitement de créer un fichier, **appelle directement l'outil `create_file`** avec `{"vault": "<nom du vault>", "path": "<chemin/relatif.md>", "content": "<contenu markdown>"}`. Pour créer un dossier, appelle `create_directory`.
Règles :
- N'écris **jamais** de bloc ```obsigate-action``` : en mode agent, toutes les actions passent par les outils natifs.
- Écris le contenu **complet** demandé dans l'argument `content` (ne le tronque pas, pas de « … » ni de ligne omise).
- Pour créer un fichier dans un nouveau dossier, un seul appel `create_file` avec le chemin complet suffit (les dossiers parents sont créés automatiquement).
- N'invente jamais un nom de vault : utilise l'un des vaults disponibles listés ci-dessous.
- Réponds dans la langue de l'utilisateur, de façon concise et structurée (Markdown).
"""
# Backwards-compatible alias (classic chat prompt).
GENERAL_SYSTEM_PROMPT = GENERAL_SYSTEM_HEADER + GENERAL_ACTION_TEXT_PROTOCOL
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.
@@ -588,14 +612,20 @@ 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,
agent: bool = False,
) -> 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.
``agent`` selects the action protocol: the classic chat endpoint (no native
tools) uses the text ``obsigate-action`` blocks, while the tool-calling
agent endpoint must invoke the native tools instead (BUG-053).
"""
prompt = GENERAL_SYSTEM_PROMPT
protocol = GENERAL_ACTION_TOOL_PROTOCOL if agent else GENERAL_ACTION_TEXT_PROTOCOL
prompt = GENERAL_SYSTEM_HEADER + protocol
if vaults:
prompt += "\nVaults disponibles : " + ", ".join(sorted(vaults)) + "\n"
else: