369 lines
19 KiB
Markdown
369 lines
19 KiB
Markdown
# MEMORY.md — Nox 🌑
|
||
|
||
## 📋 Règle de mémorisation
|
||
|
||
| Critère | MEMORY.md | Qdrant | Les deux |
|
||
|---|---|---|---|
|
||
| Config infra (URL, token, IDs) | ✅ | ❌ | — |
|
||
| Préférences & comportements | ✅ | ❌ | — |
|
||
| Leçon courte / gotcha technique | ✅ | ✅ | ← les deux |
|
||
| Procédure détaillée / code | ❌ | ✅ | — |
|
||
| Événement épisodique (ce qu'on a fait) | ❌ | ✅ | — |
|
||
| Fait important ET recherchable | ✅ | ✅ | ← les deux |
|
||
|
||
**Résumé :**
|
||
- **MEMORY.md** = ce que je dois savoir DÈS le démarrage. Court, dense, stable.
|
||
- **Qdrant** = ce que je dois pouvoir RETROUVER par recherche. Détails, procédures, contexte.
|
||
- **Les deux** = les leçons critiques, les gotchas techniques, tout ce qui est à la fois essentiel ET recharchable.
|
||
|
||
**Toujours ajouter dans Qdrant** après toute session de travail significative.
|
||
**Ne pas surcharger MEMORY.md** — si c'est long ou procédural, Qdrant suffit.
|
||
|
||
|
||
|
||
## Christophe
|
||
- Habite Montlieu-La-Garde, Charente-Maritime (17), axe Bordeaux-Angoulême N10
|
||
- Fuseau horaire : Europe/Paris
|
||
- Langue : français
|
||
|
||
## Home Assistant
|
||
- URL : http://192.168.1.40:8123
|
||
- **Lumières** :
|
||
- `light.dimmer_2` → **Entrée**
|
||
- `light.bar` → **Bar**
|
||
- `light.bibliotheque` → **Bibliothèque**
|
||
- `light.dimmer_salon` → **Salon**
|
||
- `light.nano_dimmer` → **Mezzanine** (Nano Dimmer Z-Wave)
|
||
- `light.mi_light_wifi_ibox1` → **Mi-Light WiFi iBox1** (la "lumière wifi")
|
||
- **Caméras** :
|
||
- `camera.onvif_ptz` → **Caméra Extérieur** (double vue, couleur, parking/cour)
|
||
- `camera.fi9821ep` → **Caméra Salon** (Foscam, intérieur)
|
||
- `camera.camera_ndeg7` → **Caméra n°7** (intérieur, sous-sol/atelier)
|
||
- `camera.camera_jarnac_rdc_7` → **Caméra Jarnac RDC 7** (intérieur)
|
||
- `camera.foscam` → **Foscam** (intérieur, entrée/pièce de vie)
|
||
- `camera.klipper_webcam` → **Ender 3 Webcam** (imprimante 3D)
|
||
- `camera.predator_predator` → **Predator**
|
||
- `camera.nono_none` → **Nono**
|
||
- **Media Players** :
|
||
- `media_player.shield` → **SHIELD CUISINE**
|
||
- `media_player.android_tv_cuisine` → **Android TV Cuisine**
|
||
- `media_player.shield_salon` → **SHIELD SALON**
|
||
- `media_player.android_tv_salon` → **Android TV Salon**
|
||
- `media_player.denon_avr_x3400h` → **Denon AVR-X3400H**
|
||
|
||
|
||
## Proxmox
|
||
- URL : https://192.168.1.250:8006
|
||
- Token : variable d'env `PVE_TOKEN` (format `root@pam!openclaw=<uuid>`) — déjà dans .env + docker-compose override
|
||
- Accès API : `curl -sk -H "Authorization: PVEAPIToken=$PVE_TOKEN" "$PVE_URL/api2/json/nodes"`
|
||
- **Parser JSON avec Node.js** (pas jq — permission denied dans le conteneur)
|
||
- Nodes : mini-pc, ts-651, pve, z820
|
||
|
||
## Proxmox Backup Server (PBS)
|
||
- URL : https://192.168.1.91:8007
|
||
- Token : variables d'env `PBS_TOKEN_ID` + `PBS_TOKEN_SECRET` — déjà dans .env + docker-compose override
|
||
- Accès API : `curl -sk -H "Authorization: PBSAPIToken=$PBS_TOKEN_ID:$PBS_TOKEN_SECRET" "$PBS_URL/api2/json/status/datastore-usage"`
|
||
- Datastore : `backups_on_ts651` (1.26 TB total)
|
||
|
||
## Outils & Préférences
|
||
- **Génération d'images** : utiliser fal.ai (FAL_KEY), PAS OpenAI
|
||
- `fal-ai/flux/schnell` — génération rapide, bon pour photos/art
|
||
- `fal-ai/nano-banana-pro` — Gemini 3 Pro Image, bon pour affiches/texte/édition d'images
|
||
- **Browser OpenClaw (outil `browser`)** : ✅ OPÉRATIONNEL — headless Chromium Playwright, profil `openclaw`
|
||
- Config : `attachOnly: false`, `executablePath: /home/node/.openclaw/workspace/chrome-wrapper.sh`
|
||
- Le `chrome-wrapper.sh` nettoie les lock files résiduels AVANT de lancer Chrome (fix permanent pour le bug SingletonLock après redémarrage)
|
||
- Chrome réel : `/home/node/.cache/ms-playwright/chromium-1208/chrome-linux64/chrome` (appelé par le wrapper)
|
||
- CDP port : 18800, user-data-dir : `/home/node/.openclaw/browser/openclaw/user-data`
|
||
- Utiliser pour : snapshots ARIA, interactions UI, screenshots, sessions persistantes
|
||
- Se lance automatiquement au premier appel `browser action=start profile=openclaw`
|
||
- **Toujours sauvegarder les fichiers dans le workspace** — `/tmp` est bloqué pour l'envoi Telegram
|
||
- ⚠️ Si le browser ne répond plus : vérifier que Chrome tourne (`curl -sf http://127.0.0.1:18800/json/version`) — relancer via `bash /home/node/.openclaw/workspace/start-chrome-cdp.sh`
|
||
- **Playwright direct (Node.js)** : pour interception réseau, scripts sur mesure, scraping avancé
|
||
- Installé dans `/home/node/.openclaw/workspace/node_modules/playwright`
|
||
- `executablePath` → `/home/node/.cache/ms-playwright/chromium-1208/chrome-linux64/chrome`
|
||
- Les erreurs `dbus` en conteneur sont normales et sans impact
|
||
- **TTS** : Edge, voix fr-FR-VivienneMultilingualNeural — **TOUJOURS parler en français**, même si la conversation contient de l'anglais
|
||
- **Transcription audio** : Groq Whisper
|
||
|
||
## Anytype
|
||
- Instance self-hosted : http://192.168.1.150:31009
|
||
- Espace principal : **OpenClaw** (id: `bafyreigt3wmpnm2qduzijfubftw5ixrhqfrjrc2yi6hq2e4cpw6yer7hqq.25d1im923toai`)
|
||
- Skill custom dans `/home/node/.openclaw/workspace/skills/anytype/`
|
||
- Utiliser cet espace pour tout ce qui concerne Christophe et moi
|
||
- **Images** : ✅ ÇA MARCHE ! Anytype télécharge et internalise les images depuis une URL externe
|
||
- Méthode : inclure `` dans le `body` markdown lors d'un **POST** (création d'objet)
|
||
- Anytype récupère l'image, lui donne un ID interne (`bafyrei...`) et la sert via `http://127.0.0.1:47800/image/<id>`
|
||
- L'image doit être accessible depuis le serveur Anytype (même réseau local)
|
||
- **PATCH** : utiliser le champ `"markdown"` (PAS `"body"`) pour modifier le contenu existant !
|
||
- Le format icon doit être `{"format":"emoji","name":"🧪"}` et non une string simple
|
||
- **POST** (création) : utiliser `"body"` pour le contenu
|
||
- **PATCH** (modification) : utiliser `"markdown"` pour le contenu
|
||
|
||
## CopyParty (stockage fichiers)
|
||
- URL : http://192.168.1.150:3923
|
||
- Upload simple via `curl -X PUT "http://192.168.1.150:3923/<chemin>" --data-binary @fichier`
|
||
- Pas d'authentification requise
|
||
- Dossier `/anytype/` créé pour les fichiers liés à Anytype
|
||
- Utilisable pour héberger images, schémas, etc. avec lien direct
|
||
- **Utile pour Penpot** : uploader une image sur CopyParty → l'injecter dans Penpot via `upload_file_media_from_url`
|
||
|
||
## Penpot MCP — Workflow & Gotchas
|
||
|
||
### Stack
|
||
- Penpot UI : http://192.168.1.150:9001
|
||
- MCP HTTP endpoint : http://192.168.1.150:9002/mcp (health: /health)
|
||
- MCP = zcube/penpot-mcp-server, image node:22-alpine + npm @zcubekr/penpot-mcp-server
|
||
- Token Penpot déjà configuré dans la stack Portainer (stack id=90)
|
||
|
||
### ⚠️ Règles critiques MCP zcube
|
||
|
||
**1. Tous les paramètres sont en camelCase** (PAS snake_case) :
|
||
- `projectId`, `fileId`, `pageId`, `parentId`
|
||
- `fillColor`, `fontSize`, `fontWeight`
|
||
- `isShared`, `gradientType`, `borderRadius`, `cornerRadius` → `r1/r2/r3/r4`
|
||
|
||
**2. Session unique — toujours redémarrer le container avant** :
|
||
- Le serveur n'autorise QU'UNE session à la fois
|
||
- `initialize` échoue avec "already initialized" si session existante
|
||
- Solution : inclure le restart Portainer dans le script (container `penpot-penpot-mcp-1`)
|
||
|
||
**3. Récupérer IDs depuis `get_profile`** (plus fiable que `list_teams`) :
|
||
- `profile.defaultProjectId` → projet par défaut (Drafts)
|
||
- `profile.defaultTeamId` → team
|
||
|
||
**4. `export_shape` NON IMPLÉMENTÉ** dans zcube — ne pas l'appeler
|
||
|
||
**5. `list_teams` retourne du texte** ("Found 1 teams"), pas du JSON
|
||
|
||
**6. `create_text` — paramètres corrects** :
|
||
- `text` (PAS `content`) → le contenu du texte
|
||
- `textAlign` (PAS `align`) → "left", "center", "right", "justify"
|
||
- `fontWeight` → string "100"–"900" ou "bold"
|
||
- `fillColor` → couleur HEX
|
||
- ⚠️ `parentId` **NON SUPPORTÉ** pour create_text — les textes vont toujours au root frame
|
||
- Width/height auto-calculés (text.length × fontSize × 0.6) — ne pas les spécifier
|
||
|
||
**7. Workflow création fichier** :
|
||
```
|
||
get_profile → defaultProjectId
|
||
create_file { projectId, name } → fileId
|
||
list_pages { fileId } → pageId (array[0].id)
|
||
create_frame { fileId, pageId, name, x, y, width, height, fillColor } → frameId
|
||
create_rectangle { fileId, pageId, parentId: frameId, ... } ← parentId OK pour rect
|
||
create_text { fileId, pageId, text, x, y, textAlign, ... } ← PAS de parentId
|
||
```
|
||
|
||
**8. Coordonnées** : absolues sur la page. Les textes se placent dans le root frame automatiquement. Pour un poster : mettre frame à (0,0) et textes aux bonnes coords absolues.
|
||
|
||
### Pour générer une image finale
|
||
- `export_shape` non dispo → utiliser **HTML/CSS → Playwright screenshot**
|
||
- Script template : `/home/node/.openclaw/workspace/screenshot-poster.mjs`
|
||
- Playwright : `node_modules/playwright`, chrome : `/home/node/.cache/ms-playwright/chromium-1208/chrome-linux64/chrome`
|
||
- Sauvegarder dans workspace (pas /tmp) pour envoi Telegram
|
||
|
||
### Pour injecter une image dans Penpot
|
||
- Uploader sur CopyParty : `curl -X PUT http://192.168.1.150:3923/anytype/image.png --data-binary @image.png`
|
||
- Puis : `upload_file_media_from_url { fileId, url: "http://192.168.1.150:3923/anytype/image.png" }`
|
||
|
||
## Penpot API Directe — Pixel-perfect (⭐ À UTILISER EN PRIORITÉ)
|
||
|
||
### Pourquoi directe > MCP
|
||
- MCP : auto-calcule les dims texte, pas de `parentId` pour les textes → pas de contrôle pixel-perfect
|
||
- API directe : contrôle total (x, y, width, height, parentId, contenu riche)
|
||
|
||
### Accès
|
||
- **URL backend** : `http://192.168.1.150:9003/api/rpc/command/<cmd>` (port 9003 exposé = penpot-backend:6060)
|
||
- **Auth** : `Authorization: Token <access_token>` (dans l'en-tête HTTP)
|
||
- **Token** : récupérable dans Penpot UI → Profile → Access Tokens
|
||
- **Format corps** : JSON **kebab-case** (ex: `page-id`, `frame-id`, `fill-color`)
|
||
- **Réponse** : kebab-case aussi (`default-team-id`, `default-project-id`)
|
||
- ⚠️ L'accès via nginx port 9001 retourne un user vide même avec le bon token — **toujours utiliser le port 9003**
|
||
|
||
### Workflow création poster (Node.js)
|
||
```js
|
||
// 1. Auth + IDs
|
||
const prof = await rpc('get-profile');
|
||
const teamId = prof['default-team-id'];
|
||
const projectId = prof['default-project-id'];
|
||
|
||
// 2. Créer fichier
|
||
const file = await rpc('create-file', { 'project-id': projectId, name: 'Mon affiche', 'is-shared': false });
|
||
const FILE_ID = file.id;
|
||
const PAGE_ID = Object.keys(file.data?.['pages-index'] || {})[0] || file.data?.pages?.[0];
|
||
|
||
// 3. Ajouter shapes une par une (revn incrémental !)
|
||
for (const change of changes) {
|
||
const result = await rpc('update-file', {
|
||
id: FILE_ID, 'session-id': randomUUID(), revn: currentRevn, vern: 0,
|
||
changes: [change]
|
||
});
|
||
currentRevn = result.revn;
|
||
}
|
||
```
|
||
|
||
### Format d'une change `add-obj`
|
||
```js
|
||
{
|
||
type: 'add-obj',
|
||
id: '<uuid>',
|
||
'page-id': PAGE_ID,
|
||
'frame-id': ROOT, // '00000000-0000-0000-0000-000000000000' = root
|
||
'parent-id': ROOT,
|
||
obj: {
|
||
id, type: 'rect'|'text'|'frame', name,
|
||
x, y, width, height,
|
||
'parent-id': ROOT, 'frame-id': ROOT,
|
||
fills: [{ 'fill-color': '#C0392B', 'fill-opacity': 1 }],
|
||
selrect: { x, y, width, height, x1, y1, x2, y2 },
|
||
points: [{x,y},{x:x+w,y},{x:x+w,y:y+h},{x,y:y+h}],
|
||
transform: {a:1,b:0,c:0,d:1,e:0,f:0},
|
||
'transform-inverse': {a:1,b:0,c:0,d:1,e:0,f:0},
|
||
// Pour un text :
|
||
content: { type:'root', children:[{ type:'paragraph-set', children:[{
|
||
type:'paragraph', 'text-align':'center', children:[{
|
||
text: 'Mon texte',
|
||
'font-id':'gfont-work-sans', 'font-family':'Work Sans',
|
||
'font-size':'48', 'font-weight':'700', 'font-style':'normal',
|
||
'letter-spacing':'2', 'line-height': 1.2, 'text-decoration':'none',
|
||
fills:[{'fill-color':'#FFFFFF', 'fill-opacity':1}],
|
||
}]
|
||
}]}]}
|
||
}
|
||
}
|
||
```
|
||
|
||
### ⚠️ Gotchas critiques
|
||
- **Envoyer 1 change à la fois** (pas toutes en même temps) + incrémenter `revn`
|
||
- **`type: 'frame'`** échoue avec erreur `:shapes nil` → utiliser `type: 'rect'` comme fond
|
||
- **toKebab()** : tous les paramètres JS en camelCase → convertir en kebab-case avant envoi
|
||
- **`text` content** : bien mettre le champ `text:` dans le nœud enfant (sinon validation error)
|
||
- **Texte centré** : mettre `x:0, width:W` (toute la largeur) + `text-align: 'center'` dans le paragraphe
|
||
|
||
### Script de référence
|
||
`/home/node/.openclaw/workspace/penpot-api-direct.mjs` — poster 600×900 complet, 16 shapes
|
||
|
||
## Podcasts & Vidéos — Transcription
|
||
- Je peux **récupérer et transcrire** des podcasts/vidéos en ligne
|
||
- **Méthode :**
|
||
1. Utiliser **Playwright** pour intercepter les requêtes réseau et trouver l'URL du fichier audio (.mp3)
|
||
2. Télécharger le MP3 avec `curl -sL -A "Mozilla/5.0..." -H "Referer: <site>" <url> -o fichier.mp3`
|
||
3. Transcrire avec **Groq Whisper** : `curl -X POST https://api.groq.com/openai/v1/audio/transcriptions -H "Authorization: Bearer $GROQ_API_KEY" -F "file=@fichier.mp3" -F "model=whisper-large-v3-turbo" -F "language=fr" -F "response_format=text"`
|
||
- Testé avec succès sur BFM Business / Simplecast (podcasts hébergés sur simplecastaudio.com)
|
||
- Sauvegarder les fichiers dans le workspace, pas dans /tmp
|
||
- **YouTube** : utiliser **yt-dlp** (binaire dans `/home/node/.openclaw/workspace/yt-dlp`)
|
||
- Transcript via API YouTube (sous-titres auto) : `yt-dlp --write-auto-sub --skip-download --sub-lang fr -o workspace/transcript <url>`
|
||
- Audio pour Whisper : `yt-dlp -x --audio-format mp3 -o workspace/audio.mp3 <url>`
|
||
|
||
## Mémoire Vectorielle (Qdrant)
|
||
- **Collection** : `nox-memory` sur Qdrant (`http://192.168.1.150:6333`)
|
||
- **Stack Portainer** : `qdrant` (anciennement `kilocode-qdrant`, renommé 2026-02-22)
|
||
- **Script** : `/home/node/.openclaw/workspace/nox-memory.js`
|
||
- **Modèle** : `text-embedding-3-small` (OpenAI, 1536 dims, Cosine)
|
||
- **Accès** : `node fetch` natif (Node 22) — curl bloqué par sandbox OpenClaw, mais node fetch fonctionne ✅
|
||
- **Réseau Docker** : le stack doit avoir un réseau `bridge` en plus de `swag_lan` pour être accessible depuis le LXC
|
||
- **Usage** :
|
||
```bash
|
||
node nox-memory.js add "texte" --type fact|semantic|preference|episodic --tags "t1,t2" --importance 1-5
|
||
node nox-memory.js search "question naturelle" [--limit 5] [--type fact]
|
||
node nox-memory.js list [--type fact] [--limit 20]
|
||
node nox-memory.js stats
|
||
node nox-memory.js import-md MEMORY.md
|
||
```
|
||
- MEMORY.md importé (9 chunks, 2026-02-22)
|
||
- **Utiliser en priorité** pour les recherches contextuelles (memory_search reste utile pour le démarrage de session)
|
||
- ⚠️ Qdrant charge ~34 collections KiloCode au démarrage → ~30s avant d'être prêt
|
||
|
||
## Home Assistant — Lovelace / Dashboards
|
||
|
||
### Dashboards disponibles
|
||
- `lovelace` → "Aperçu" (dashboard principal, 15+ vues)
|
||
- `vue-par-pieces` → "Vue par pièces"
|
||
- `mushroom-strategy` → "Mushroom-strategy"
|
||
- `map` → Map
|
||
|
||
### Modifier/créer des vues Lovelace via WebSocket API
|
||
L'API REST `/api/lovelace/config` retourne 404 même si HA est en mode storage → **utiliser l'API WebSocket** à la place.
|
||
|
||
**Méthode (Node.js, WebSocket natif Node 22) :**
|
||
```js
|
||
const ws = new WebSocket(`${HA_URL.replace('http://','ws://')}/api/websocket`);
|
||
// Auth
|
||
ws.send(JSON.stringify({ type: 'auth', access_token: TOKEN }));
|
||
// Lire config
|
||
send({ type: 'lovelace/config' }) // → result.views[]
|
||
// Sauvegarder config modifiée
|
||
send({ type: 'lovelace/config/save', config: modifiedConfig })
|
||
// Lister les dashboards
|
||
send({ type: 'lovelace/dashboards/list' })
|
||
// Pour un dashboard spécifique (url_path)
|
||
send({ type: 'lovelace/config', url_path: 'vue-par-pieces' })
|
||
```
|
||
|
||
**Script template :** `/home/node/.openclaw/workspace/ha_ws_add_lights.mjs`
|
||
- Lire config → modifier le tableau `views` → sauvegarder
|
||
- Utiliser le WebSocket natif Node 22 (pas besoin du package `ws`)
|
||
- Timeout de sécurité à 15s
|
||
- Le code de sortie 1 (timeout) est normal si `ws.close()` ne coupe pas avant le timeout — le succès est dans le log
|
||
|
||
**Astuce :** Pour ajouter une vue sans écraser les existantes, lire d'abord la config, push la nouvelle vue, puis sauvegarder le tout.
|
||
|
||
## Portainer
|
||
- URL : https://192.168.1.150:9443
|
||
- Token : variable d'env `PORTAINER_API_KEY`
|
||
- Endpoint local : id=2 (socket Docker)
|
||
- ~38 stacks dont ~25 actives
|
||
- Pas de `jq` dans le conteneur → utiliser curl + Node.js directement
|
||
|
||
## Proxmox — Inventaire VMs/LXC clés
|
||
- **VM 138** (`mini-pc`) → **Home Assistant** (192.168.1.40) — pas d'agent QEMU
|
||
- **LXC 145** (`mini-pc`) → **OpenClaw** (ce conteneur)
|
||
- **LXC 139** (`mini-pc`) → **Frigate** (NVR)
|
||
- **VM 109** (`z820`) → **PBS** (Proxmox Backup Server, 192.168.1.91)
|
||
|
||
## Docker — Règles de mise à jour
|
||
- **Toujours exécuter `docker-backup.js` avant toute mise à jour d'un conteneur Docker**
|
||
- Script : `node /home/node/.openclaw/workspace/docker-backup.js <nom_conteneur>`
|
||
- Exemple : `node docker-backup.js vaultwarden` avant de puller une nouvelle image
|
||
- Services configurés : vaultwarden, vikunja, nocodb, freshrss
|
||
- Le cron hebdo a été créé mais **désactivé** à la demande de Christophe (2026-02-23)
|
||
- Réactiver si besoin : `node /app/dist/index.js cron add ...`
|
||
|
||
## Santé — Christophe
|
||
- **Profil :** Homme, né 12/06/1981 (44 ans), 1m81, ~90 kg, IMC ~27,5
|
||
- **Appareil tension :** Sanitas (poignet, profil 1)
|
||
- **Suivi tension** dans `memory/YYYY-MM-DD.md` — tableau SYS/DIA/Pouls
|
||
- **Première mesure :** 2026-02-25 12:08 → 145/94 mmHg, pouls 77 bpm (HTA stade 1)
|
||
|
||
## VidBee — Téléchargement vidéo
|
||
|
||
- UI : http://192.168.1.150:3800 | API : http://192.168.1.150:3801
|
||
- Stack Portainer : `vidbee` (id=101)
|
||
- Fichiers dans : `/share/ZFS24_DATA/docker/vidbee/downloads/`
|
||
- **Toutes les routes API sont en POST sous `/rpc/<route>`** (pas `/openapi/`, pas sans préfixe)
|
||
- **Format oRPC** : body `{"json": {...}}`, réponse `{"json": {...}}`
|
||
- Routes clés :
|
||
- `POST /rpc/videoInfo {"json":{"url":"..."}}` → infos + liste des formats
|
||
- `POST /rpc/downloads/create {"json":{"url":"...","type":"video","title":"...","selectedFormat":{...}}}` → lance le DL
|
||
- `POST /rpc/downloads/list {"json":{}}` → téléchargements en cours
|
||
- `POST /rpc/history/list {"json":{}}` → historique (completed, etc.)
|
||
- Format pour `selectedFormat` : `{"formatId":"299","ext":"mp4","height":1080,"vcodec":"...","acodec":"none"}`
|
||
- Qualités dispo typiquement : 2160p, 1440p, 1080p, 720p… → choisir 1080p mp4 par défaut
|
||
|
||
## Sites & Flux RSS
|
||
- **Korben.info** : utiliser le flux RSS `https://korben.info/feed` pour récupérer les articles (plus propre que scraper la homepage)
|
||
|
||
## Veilles actives
|
||
|
||
### 📡 XGS-PON CMTD — Montlieu-la-Garde
|
||
- Christophe est sur le réseau **CMTD** (RIP, géré par Orange) actuellement en GPON → plafond ~1 Gbps
|
||
- Migration XGS-PON en cours, prévue fin 2026
|
||
- **Quand XGS-PON dispo** → recommander passage **Freebox Ultra grand public** (moins cher que FreePro, mêmes features + 8 Gbps sym)
|
||
- Vérifier 1x/mois via heartbeat
|
||
|
||
## Leçons apprises
|
||
- **Toujours prendre un snapshot du LXC 145** (`mini-pc`) avant toute modification de config ou installation qui pourrait casser OpenClaw
|
||
- Commande : `curl -sk -X POST -H "Authorization: PVEAPIToken=$PVE_TOKEN" -H "Content-Type: application/json" -d '{"snapname":"<nom>","description":"<desc>"}' "$PVE_URL/api2/json/nodes/mini-pc/lxc/145/snapshot"`
|
||
- Toujours vérifier les `friendly_name` dans HA pour trouver les entités
|
||
- Les skills custom sont dans `/home/node/.openclaw/workspace/skills/`
|
||
- **curl est bloqué** dans le sandbox OpenClaw pour certaines destinations réseau, mais **node fetch (Node 22)** fonctionne — utiliser node pour les requêtes HTTP internes quand curl échoue
|