chore: versioning initial du systeme Context Continuity
Code du systeme de memoire multi-LLM sur Trilium : - trilium_api.py : wrapper trilium-py (notes, labels, relations) - mcp_server.py : serveur MCP Starlette (19 tools, OAuth + Bearer) - api_context.py : API REST FastAPI - trilium_context.py : workflow CLI - watchdog.sh, start_*.sh : supervision et demarrage - skills, docs et ontologie associes Secrets (.env, oauth_state.json) exclus via .gitignore.
This commit is contained in:
@@ -0,0 +1,180 @@
|
||||
# SKILL — Référence technique : APIs Trilium & serveur MCP
|
||||
|
||||
Référence d'implémentation du système Context Continuity. À sortir pour
|
||||
débugger, étendre ou appeler directement les APIs. Le « quand/pourquoi »
|
||||
comportemental est dans le skill de réflexe de continuité ; ici c'est le
|
||||
« comment » technique.
|
||||
|
||||
Trois voies d'accès à Trilium coexistent : **API REST FastAPI** (distante,
|
||||
HTTPS), **ETAPI via wrapper Python** (locale, sur GrosseBertha), **MCP**
|
||||
(pour agents Mistral).
|
||||
|
||||
---
|
||||
|
||||
## 1. API REST FastAPI — accès distant (recommandé pour un LLM)
|
||||
|
||||
Couche créée pour exposer Trilium en HTTPS (pallie l'absence d'accès direct).
|
||||
|
||||
| Paramètre | Valeur |
|
||||
|---|---|
|
||||
| Base URL | `https://api-trilium.bertha-cloud.fr` |
|
||||
| Auth header | `Authorization: <API_KEY>` (clé brute, **sans** `Bearer`) |
|
||||
| Clés | Clé Claude / clé Le Chat — demander à Bastien ou lire dans `.env` |
|
||||
| Doc Swagger | `https://api-trilium.bertha-cloud.fr/api/docs` |
|
||||
|
||||
**Endpoints essentiels :**
|
||||
| Action | Appel |
|
||||
|---|---|
|
||||
| Lire le contexte projet | `GET /api/contexte/{projet}?llm_cible=NomLLM` |
|
||||
| Voir le backlog | `GET /api/backlog/{projet}` |
|
||||
| Enregistrer une décision | `POST /api/decisions` |
|
||||
| Enregistrer un historique | `POST /api/historique` |
|
||||
| Créer une conversation | `POST /api/conversations` |
|
||||
| Clôturer une session | `PATCH /api/conversations/{id}` |
|
||||
| Marquer un backlog item | `PATCH /api/backlog/{id}` |
|
||||
|
||||
**Exemples curl :**
|
||||
```bash
|
||||
# Lire le briefing de reprise
|
||||
curl -s -H "Authorization: CLE" \
|
||||
"https://api-trilium.bertha-cloud.fr/api/contexte/SlidingAutomation?llm_cible=Le+Chat+Large" \
|
||||
| python3 -c "import sys,json; print(json.load(sys.stdin)['briefing'])"
|
||||
|
||||
# Enregistrer une décision
|
||||
curl -s -X POST -H "Authorization: CLE" -H "Content-Type: application/json" \
|
||||
-d '{"projet":"SlidingAutomation","enonce":"Décision prise","justification":"Raison"}' \
|
||||
https://api-trilium.bertha-cloud.fr/api/decisions
|
||||
|
||||
# Marquer un backlog item comme fait
|
||||
curl -s -X PATCH -H "Authorization: CLE" -H "Content-Type: application/json" \
|
||||
-d '{"statut":"fait"}' \
|
||||
https://api-trilium.bertha-cloud.fr/api/backlog/NOTE_ID
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. ETAPI via wrapper Python — accès local (sur GrosseBertha)
|
||||
|
||||
TriliumNext 0.95+ a restructuré ses routes : `POST /etapi/notes` retourne
|
||||
*Router not found*. **Solution validée : `trilium-py 1.3.9`**, encapsulé dans
|
||||
`~/App/Context_continuity/trilium_api.py`.
|
||||
|
||||
```
|
||||
pip install trilium-py python-dotenv
|
||||
```
|
||||
`.env` :
|
||||
```
|
||||
TRILIUM_URL=http://localhost:4292
|
||||
TRILIUM_TOKEN=<token généré dans Options > ETAPI>
|
||||
```
|
||||
Header d'auth : `Authorization: token` (**sans** `Bearer` ; Bearer accepté
|
||||
depuis 0.93 mais non requis).
|
||||
|
||||
**Fonctions du wrapper `trilium_api.py` :**
|
||||
| Fonction | Note |
|
||||
|---|---|
|
||||
| `check_api()` | Lève SystemExit si Trilium inaccessible |
|
||||
| `create_note(parent_id, title, content=" ", note_type="text")` | `content=" "` obligatoire — jamais vide |
|
||||
| `get_note_id(result)` | Extrait `noteId` du résultat de `create_note` |
|
||||
| `get_note(note_id)` / `get_note_content(note_id)` | Récupère note / contenu HTML |
|
||||
| `update_note_content(note_id, content)` | Met à jour le contenu |
|
||||
| `search_notes(query, limit=50)` | Recherche **sans guillemets** autour du terme |
|
||||
| `search_by_label(label, value="")` | Syntaxe interne `#label=value` |
|
||||
| `find_note_by_title(title, parent_id="")` | Retourne `noteId` ou `None` |
|
||||
| `set_label(note_id, name, value="")` | `isInheritable=False` requis en interne |
|
||||
| `get_label_value(note_id, name)` | Retourne la valeur ou `None` |
|
||||
|
||||
**Erreurs connues et fixes :**
|
||||
| Erreur | Cause | Fix |
|
||||
|---|---|---|
|
||||
| `Router not found POST /etapi/notes` | Routing TriliumNext 0.95 | Utiliser `trilium-py` |
|
||||
| `missing argument isInheritable` | `create_attribute()` trilium-py | Passer `isInheritable=False` |
|
||||
| `Note content must be set` | Contenu vide refusé | Passer `content=" "` |
|
||||
| Recherche avec guillemets → `[]` | Parser 0.95 | Chercher sans guillemets |
|
||||
| `{status,code,message}` sur create | Note existe déjà / contenu vide | `find_note_by_title` avant + `content=" "` |
|
||||
|
||||
IDs des dossiers : `trilium_ids.json` (généré par `trilium_init.py`). Clés :
|
||||
`root, Projets, Conversations, Backlog, Decisions, Historique, Glossaire,
|
||||
ContextesReprise`.
|
||||
|
||||
---
|
||||
|
||||
## 3. Serveur MCP — pour agents Mistral
|
||||
|
||||
`mcp_server.py` — serveur MCP pur Starlette (compatible Python 3.9), transport
|
||||
Streamable HTTP sur `/mcp`, écoute `127.0.0.1:8766`, exposé via
|
||||
`https://mcp-trilium.bertha-cloud.fr`. Protocole `2025-06-18`.
|
||||
|
||||
**Authentification : Bearer token statique** (`API_KEY_CLAUDE` /
|
||||
`API_KEY_LECHAT` depuis `.env`). C'est ce qui le rend **utilisable par Le Chat
|
||||
mais PAS par Claude** : les connecteurs distants de Claude.ai exigent OAuth
|
||||
(endpoints de découverte `/.well-known/oauth-authorization-server`, flux
|
||||
d'autorisation), absents de ce serveur. Pour activer Claude, il faudrait
|
||||
ajouter une couche OAuth devant le serveur.
|
||||
|
||||
**11 tools exposés :** `get_backlog`, `get_decisions`, `get_historique`,
|
||||
`get_glossaire`, `get_contexte`, `add_decision`, `add_history`, `add_backlog`,
|
||||
`update_backlog`, `new_conversation`, `close_session`.
|
||||
|
||||
---
|
||||
|
||||
## 4. Structure des données Trilium
|
||||
|
||||
Note racine **Context Continuity** → 8 sous-dossiers : `Projets`,
|
||||
`Conversations`, `Backlog`, `Decisions`, `Historique`, `Glossaire`,
|
||||
`Contextes Reprise`, `Skills`.
|
||||
|
||||
**Types de notes et labels obligatoires :**
|
||||
|
||||
| Type (`type=`) | Labels obligatoires |
|
||||
|---|---|
|
||||
| `projet` | `projet` (sans espaces), `statut` (actif\|en-pause\|archive) |
|
||||
| `conversation` | `projet`, `llm`, `statut` (en-cours\|clos), `date` (YYYY-MM-DD HH:MM) |
|
||||
| `backlogItem` | `projet`, `statut` (a faire\|en cours\|bloque\|fait\|abandonne), `priorite` (haute\|moyenne\|basse) |
|
||||
| `decision` | `projet`, `statut` (active\|revisee\|annulee) |
|
||||
| `historiqueItem` | `projet`, `typeHistorique`, `encoreValide` (true\|false) |
|
||||
| `termeGlossaire` | `projet`, `definition` |
|
||||
| `contexteReprise` | `projet`, `llmCible`, `version` |
|
||||
|
||||
`typeHistorique` ∈ { `Fait etabli`, `Test effectue`, `Hypothese invalidee`,
|
||||
`Contrainte decouverte` }.
|
||||
|
||||
**Filtres des briefings** (pièges) :
|
||||
- `generate-context` n'inclut que les décisions `statut=active`.
|
||||
- N'inclut que l'historique `encoreValide=true`.
|
||||
- `list-backlog` exclut `statut` ∈ { `fait`, `abandonne` }.
|
||||
- Pour retirer un élément du briefing : passer `statut=annulee` (décision) ou
|
||||
`encoreValide=false` (historique) — ne pas supprimer la note.
|
||||
|
||||
**Pièges d'écriture récurrents :**
|
||||
| Erreur | Conséquence | Fix |
|
||||
|---|---|---|
|
||||
| Statut avec majuscule (`Actif`) | Le filtre rate la note | Toujours minuscules |
|
||||
| Nom projet avec espaces | `search_by_label` échoue | `SlidingAutomation` |
|
||||
| `encoreValide="True"` | Filtre cherche `true` | Minuscules |
|
||||
| `definition` absent sur glossaire | Briefing affiche « (voir note) » | Ajouter le label |
|
||||
|
||||
---
|
||||
|
||||
## 5. Workflow CLI (sur GrosseBertha)
|
||||
|
||||
```bash
|
||||
cd ~/App/Context_continuity && source venv/bin/activate
|
||||
# Début
|
||||
python trilium_context.py new-conversation --projet SlidingAutomation --llm "Claude Sonnet" --titre "..."
|
||||
# Reprise
|
||||
python trilium_context.py generate-context --projet SlidingAutomation --llm-cible "Claude Sonnet" --note-id ID --version N
|
||||
# Au fil de l'eau
|
||||
python trilium_context.py add-decision --projet SlidingAutomation --enonce "..." --justification "..."
|
||||
python trilium_context.py add-history --projet SlidingAutomation --type "Test effectue" --enonce "..." --detail "..."
|
||||
# Clôture
|
||||
python trilium_context.py close-session --note-id ID --summary "..."
|
||||
# État
|
||||
python trilium_context.py list-backlog --projet SlidingAutomation
|
||||
python trilium_context.py list-projects
|
||||
```
|
||||
|
||||
Fichiers du système : `trilium_api.py` (wrapper, ne pas modifier),
|
||||
`trilium_init.py` (init unique), `trilium_context.py` (workflow quotidien),
|
||||
`trilium_logger.py` (intégration pipeline Sliding), `trilium_ids.json`,
|
||||
`mcp_server.py`, `api_context.py` (API FastAPI).
|
||||
Reference in New Issue
Block a user