feat(ai): phase 0 couche d'outils partagee (backend/tools) + tests
CI / lint (push) Successful in 57s
CI / security (push) Successful in 39s
CI / test (push) Failing after 41s
CI / build (push) Skipped
CI / e2e (push) Skipped
Desktop Build / build-windows (push) Canceled after 0s
Desktop Build / build-linux (push) Canceled after 0s
CI / lint (push) Successful in 57s
CI / security (push) Successful in 39s
CI / test (push) Failing after 41s
CI / build (push) Skipped
CI / e2e (push) Skipped
Desktop Build / build-windows (push) Canceled after 0s
Desktop Build / build-linux (push) Canceled after 0s
- backend/tools/: ToolContext, registry @tool + schemas JSON, audit ai_tool_call - Services lecture/recherche: list_vaults, list_directory, read_file, search_fulltext, list_tags - Permissions check_vault_access + resolve_safe_path, confirmation gating (two-step) - Redaction des secrets, limites de taille, audit JSONL (args sensibles resumes) - tests/test_tools.py: 30 tests (registry, contexte, execution, confirmation, audit) - ROADMAP: item #79 phase A livree (A2 partiel)
This commit is contained in:
+64
-2
@@ -685,6 +685,68 @@
|
||||
|
||||
---
|
||||
|
||||
### 79. Assistant IA — Outils (function calling) & serveur MCP
|
||||
|
||||
- **Effort :** 10-15 jours | **Impact :** 🟡 | **Statut :** 🔵 En cours — Phase 0 livrée (2026-09-11)
|
||||
- **Description :** Transformer l'assistant BooksLM (protocole texte `obsigate-action` limité à `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](./AI_ARCHITECTURE_GUIDE.md) (architecture, catalogue d'outils, sécurité, phases).
|
||||
- **Sous-tâches :**
|
||||
|
||||
##### A. Fondations — couche d'outils partagée (2-3 jours) — ✅ livré (2026-09-11)
|
||||
- [x] **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.py` en fonctions de service réutilisables (les routes deviennent des wrappers) — *partiel : services lecture/recherche livrés (`list_vaults`, `list_directory`, `read_file`, `search_fulltext`, `list_tags`) ; refactor des routes `main.py` à suivre*
|
||||
- [x] **A3.** Contexte de permissions : chaque outil applique `check_vault_access` + `resolve_safe_path`
|
||||
- [x] **A4.** Audit : journalisation JSONL de chaque appel d'outil (qui, quoi, vault, résultat) — action `ai_tool_call`, arguments sensibles résumés
|
||||
- [x] **A5.** Tests unitaires du registry + services (sans IA) — `tests/test_tools.py` (30 tests)
|
||||
|
||||
##### B. Function calling in-app (3-4 jours)
|
||||
- [ ] **B1.** Abstraction tool-calling provider-agnostique : `_call_deepseek_openrouter` (`ai.py:115`) + `_call_gemini` (`ai.py:156`) + Ollama — payload `tools`/`tool_choice`, parsing `tool_calls` / `functionCall`
|
||||
- [ ] **B2.** Agent loop `backend/agent/loop.py` : boucle tool→résultat→tool, limite d'itérations (10) + budget tokens
|
||||
- [ ] **B3.** Fallback protocole texte `obsigate-action` si le modèle ne supporte pas les tools
|
||||
- [ ] **B4.** SSE réellement streaming (corriger `bookslm_routes.py:211`)
|
||||
- [ ] **B5.** Confirmations UI : outils `read` auto, outils `write` via carte Apply (`bookslm.js:515`), aperçu diff pour `edit_file`
|
||||
- [ ] **B6.** Outils de navigation in-app : `open_file`, `reveal_in_tree` (événement `obsigate:open-file`)
|
||||
- [ ] **B7.** Tests : agent loop (LLM mocké), confirmations, permissions
|
||||
|
||||
##### C. Catalogue d'outils — lecture & recherche (1-2 jours)
|
||||
- [ ] **C1.** Vaults/navigation : `list_vaults`, `list_directory`, `list_all_files`
|
||||
- [ ] **C2.** Lecture : `read_file`, `read_file_raw`, `get_backlinks`, `list_backups`, `diff_backup`, `get_graph`
|
||||
- [ ] **C3.** Recherche : `search_fulltext`, `search_advanced`, `search_paths`, `list_tags`, `suggest_tags`, `list_recent`
|
||||
|
||||
##### 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 `/mcp` dans FastAPI, auth `Authorization: Bearer <JWT>` → `get_current_user` (décision 2026-09-11). `stdio` optionnel 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 (adresse le point 4)
|
||||
- [x] **G1.** Persistance `ai_default_provider` + `ai_default_models` dans `data/config.json` (`_DEFAULT_CONFIG`)
|
||||
- [x] **G2.** Lecture + rechargement à chaud dans `backend/ai.py` (`get_default_provider`, `reload_ai_config`)
|
||||
- [x] **G3.** UI : sélecteurs « Fournisseur par défaut » + « Modèle par défaut » dans `#cfg-ai` (`frontend/index.html`, `frontend/js/config.js`)
|
||||
- [x] **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.
|
||||
|
||||
---
|
||||
|
||||
## ⚪ Backlog — Priorité 4 (P4)
|
||||
|
||||
### 67. Notifications web — Push API
|
||||
@@ -916,9 +978,9 @@
|
||||
|---|---|---|
|
||||
| ✅ Complété | #1 → #59, #63-68, #71, #72 (OpenAPI 3.1), #74, #75, #76, #78 (58 E2E, 59 offline, 63 i18n, 64 MFA TOTP+WebAuthn, 65 thèmes, 66 export, 67 push, 68 health, 71 admin, 72 OpenAPI, 74 PDF, 75 split view, 76 BooksLM, 78 Excalidraw) | ~82 jours réalisés |
|
||||
| 🔵 P2 restant | #77 Desktop : signature code (optionnel), wizard 1er lancement (optionnel), 6 tests E2E **manuels** | ~1-2 jours |
|
||||
| ⚪ P3 restant | #62 Collaboration Yjs (5-7j) | ~5-7 jours |
|
||||
| ⚪ P3 restant | #62 Collaboration Yjs (5-7j) · #79 Assistant IA outils + MCP (10-15j, G livré) | ~15-22 jours |
|
||||
| ⚪ P4 restant | #69 Mobile éditeur (2-3j) · #70 Sémantique (4-5j) · #73 Sync (6-8j) | 11-16 jours |
|
||||
| **Total restant** | **5 items + finitions** | **~17-25 jours** |
|
||||
| **Total restant** | **6 items + finitions** | **~27-39 jours** |
|
||||
|
||||
#75 : E2E matriciels 37/37 verts (split-view.spec.js + split-view-matrix.spec.js) — 2026-09-08.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user