CI / lint (push) Successful in 59s
CI / security (push) Successful in 49s
CI / test (push) Successful in 1m24s
CI / build (push) Successful in 37s
CI / e2e (push) Successful in 10m24s
Desktop Build / build-windows (push) Canceled after 0s
Desktop Build / build-linux (push) Canceled after 0s
6.9 KiB
6.9 KiB
#79 — Assistant IA — Outils (function calling) & serveur MCP
Statut : 🔵 En cours — Phase 0 + A2 + B1/B2/B3/B4/B5/B6/B7 + C + G livrés (2026-09-11) Effort : 10-15 jours | Impact : 🟡 Références : Roadmap · Guide d'architecture IA
- Description : Transformer l'assistant BooksLM (protocole texte
obsigate-actionlimité àcreate_file/create_directory) en un agent capable de lire, chercher, lister, ouvrir et modifier, via function calling natif, puis exposer ObsiGate à des clients MCP externes (Claude Desktop, Cursor…). Les deux fronts consomment une couche d'outils partagée — source unique de vérité. - Documentation : AI_ARCHITECTURE_GUIDE.md (architecture, catalogue d'outils, sécurité, phases).
A. Fondations — couche d'outils partagée (2-3 jours) — ✅ livré (2026-09-11)
- A1. Créer
backend/tools/:context.py(ToolContext: user, allowed_vaults, mode, confirmed),registry.py(décorateur@tool+ schéma JSON),schemas.py,service.py,audit.py - A2. Extraire la logique métier des routes de
backend/main.pyen fonctions de service réutilisables (les routes deviennent des wrappers) —backend/services/(errors.py,paths.py,vaults.py,files.py,search.py) ; routes/api/vaults,/api/browse,/api/file/{vault}/raw,/api/search,/api/tagset outilslist_vaults/list_directory/read_file/search_fulltext/list_tagsdélèguent à la même couche. LesServiceErrorsont mappées versHTTPException(routes) etToolError(outils). - A3. Contexte de permissions : chaque outil applique
check_vault_access+resolve_safe_path - A4. Audit : journalisation JSONL de chaque appel d'outil (qui, quoi, vault, résultat) — action
ai_tool_call, arguments sensibles résumés - A5. Tests unitaires du registry + services (sans IA) —
tests/test_tools.py(30 tests)
B. Function calling in-app (3-4 jours) — ✅ livré (2026-09-11)
- B1. Abstraction tool-calling provider-agnostique :
backend/ai_chat.py(chat_completion,ToolCall,LLMResponse) — OpenAI-compat (tools/tool_choice, parsingtool_calls) + Gemini (functionDeclarations/functionCall) - B2. Agent loop
backend/agent/loop.py: boucle tool→résultat→tool, limite d'itérations (10), truncation des résultats ; endpoint opt-inPOST /api/ai/bookslm/agent(events SSEtool/message/confirmation) - B3. Fallback : retry sans
toolssi le provider rejette les tools (400/404/422) → chat simple ; protocole texteobsigate-actionconservé côté frontend - B4. SSE réellement streaming —
ai_chat.stream_completion(_openai_stream+_gemini_stream) alimente/api/ai/bookslm/chattoken par token ; le middleware GZip laisse passer les endpoints SSE BooksLM. - B5. Confirmations UI : toggle « mode agent » (front →
/agent), événementstool/confirmation, carte Apply + aperçu diff (LCS) pour les mutations, repriseconfirm/confirm_messagescôté backend. S'active dès que la phase D enregistre des outilswrite. - B6. Outils de navigation in-app :
open_file,reveal_in_tree(événementobsigate:open-file) — livré via les liens cliquables de l'assistant (#80, ai-assistant-ux.md) - B7. Tests : agent loop LLM mocké (
tests/test_agent_loop.py), providers (tests/test_ai_chat.py), endpoint (tests/test_bookslm.py)
C. Catalogue d'outils — lecture & recherche (1-2 jours) — ✅ livré (2026-09-11)
- C1. Vaults/navigation :
list_vaults,list_directory,list_all_files—list_all_filesajouté viabackend/services/vaults.py - C2. Lecture :
read_file,read_file_raw,get_backlinks,list_backups,diff_backup,get_graph— servicesbackend/services/backups.py(backups/diff) etgraph.py;read_file_rawredacte les secrets - C3. Recherche :
search_fulltext,search_advanced,search_paths,list_tags,suggest_tags,list_recent— extensionsbackend/services/search.py(advanced_search_vaults,search_paths) etrecent.py; filtrage systématique par permissions vault - Routes
/api/recent,/api/vault/{vault}/files,/api/file/{vault}/backups,/api/file/{vault}/diff,/api/graph/{vault},/api/tree-search,/api/search/advancedrefactorées en wrappers des services ; teststests/test_tools.py(+17)
D. Catalogue d'outils — mutations (2 jours)
- D1.
create_file,create_directory(migration du protocole texte existant) - D2.
edit_file,append_to_file,rename_file,rename_directory,move_path - D3.
replace_in_files(⚠️ confirmation two-step + backup auto) - D4.
delete_file,delete_directory,restore_backup(⚠️ confirmation two-step + backup auto, toggle par vault)
E. Serveur MCP (2-3 jours)
- E1.
backend/mcp/server.py(SDK MCP Python) enregistrant les outils depuis le registry - E2. Mapping des primitives : Tools (mutations + recherche), Resources (vaults/fichiers en lecture
vault://), Prompts (templates) - E3. Transport Streamable HTTP : endpoint
/mcpdans FastAPI, authAuthorization: Bearer <JWT>→get_current_user(décision 2026-09-11).stdiooptionnel plus tard - E4. Confirmations : two-step
propose_*/apply_*avec token signé (usage unique, TTL) ; élicitation optionnelle si le client l'annonce (décision 2026-09-11) - E5. Toggle par vault pour désactiver les outils destructifs (défaut : activés)
- E6. Tests : handshake MCP, permissions par vault, mapping des ressources, anti-rejeu du token
F. Durcissement & documentation (1 jour)
- F1. Rate limiting par token/outil + quotas (
BOOKSLM_MAX_*) - F2. Redaction des secrets avant retour au LLM
- F3. Documentation OpenAPI (
backend/openapi_docs.py) + guide MCP - F4. Tests E2E de bout en bout
G. Sélection fournisseur/modèle par défaut — ✅ livré
- G1. Persistance
ai_default_provider+ai_default_modelsdansdata/config.json(_DEFAULT_CONFIG) - G2. Lecture + rechargement à chaud dans
backend/ai.py(get_default_provider,reload_ai_config) - G3. UI : sélecteurs « Fournisseur par défaut » + « Modèle par défaut » dans
#cfg-ai(frontend/index.html,frontend/js/config.js) - G4. i18n FR/EN
Décisions
- ✅ Transport MCP : Streamable HTTP (2026-09-11)
- ✅ Confirmation MCP : two-step
propose/apply(2026-09-11) - ✅ Périmètre des mutations externes : toutes autorisées (create/edit/rename/move/delete) — encadrées par confirmation + backup auto + audit + toggle par vault (2026-09-11)
- Détail et justification dans le guide §8.