Add one-shot scripts (plan maison, généalogie, OAuth, etc.)

This commit is contained in:
2026-08-05 12:31:35 +02:00
parent 1936ded08f
commit 6b0f52b577
9 changed files with 2683 additions and 3 deletions
+550
View File
@@ -0,0 +1,550 @@
#!/usr/bin/env python3
"""Génère un PDF expliquant l'architecture Honcho + Hermes"""
from reportlab.lib.pagesizes import A4
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.units import mm, cm
from reportlab.lib.colors import HexColor, black, white
from reportlab.lib.enums import TA_LEFT, TA_CENTER
from reportlab.platypus import (
SimpleDocTemplate, Paragraph, Spacer, PageBreak,
Table, TableStyle, ListFlowable, ListItem, KeepTogether
)
from reportlab.platypus.flowables import HRFlowable
from reportlab.lib import colors
import os
OUTPUT = "/root/workspace/honcho-hermes-architecture.pdf"
# Couleurs
DARK = HexColor("#0f172a")
ACCENT = HexColor("#3b82f6")
GREEN = HexColor("#22c55e")
GRAY = HexColor("#64748b")
LIGHT = HexColor("#f1f5f9")
ORANGE = HexColor("#f59e0b")
doc = SimpleDocTemplate(
OUTPUT,
pagesize=A4,
topMargin=2*cm,
bottomMargin=2*cm,
leftMargin=2.5*cm,
rightMargin=2.5*cm,
)
styles = getSampleStyleSheet()
# Styles personnalisés
styles.add(ParagraphStyle(
"CoverTitle", parent=styles["Title"],
fontSize=28, leading=34, textColor=DARK,
spaceAfter=6*mm, alignment=TA_CENTER,
fontName="Helvetica-Bold"
))
styles.add(ParagraphStyle(
"CoverSub", parent=styles["Normal"],
fontSize=14, leading=18, textColor=GRAY,
spaceAfter=4*mm, alignment=TA_CENTER,
fontName="Helvetica"
))
styles.add(ParagraphStyle(
"SectionTitle", parent=styles["Heading1"],
fontSize=18, leading=22, textColor=DARK,
spaceBefore=10*mm, spaceAfter=4*mm,
fontName="Helvetica-Bold"
))
styles.add(ParagraphStyle(
"SubTitle", parent=styles["Heading2"],
fontSize=14, leading=18, textColor=ACCENT,
spaceBefore=6*mm, spaceAfter=3*mm,
fontName="Helvetica-Bold"
))
styles.add(ParagraphStyle(
"Body", parent=styles["Normal"],
fontSize=10, leading=14, textColor=HexColor("#334155"),
spaceAfter=3*mm,
fontName="Helvetica"
))
# "Code" style already exists in default stylesheet
styles.add(ParagraphStyle(
"MyBullet", parent=styles["Normal"],
fontSize=10, leading=14, textColor=HexColor("#334155"),
leftIndent=8*mm, spaceAfter=2*mm,
fontName="Helvetica"
))
styles.add(ParagraphStyle(
"MySmallNote", parent=styles["Normal"],
fontSize=8, leading=10, textColor=GRAY,
spaceAfter=2*mm, fontName="Helvetica-Oblique"
))
story = []
# ===== PAGE DE COUVERTURE =====
story.append(Spacer(1, 4*cm))
story.append(Paragraph("Honcho + Hermes", styles["CoverTitle"]))
story.append(Paragraph("Architecture & Déploiement", styles["CoverSub"]))
story.append(Spacer(1, 3*mm))
story.append(HRFlowable(width="60%", thickness=1, color=ACCENT))
story.append(Spacer(1, 5*mm))
story.append(Paragraph("Mémoire persistante cross-session pour Hermes Agent", styles["CoverSub"]))
story.append(Spacer(1, 2*cm))
story.append(Paragraph("Laurent Keller — Homelab 2026", styles["MySmallNote"]))
story.append(PageBreak())
# ===== TABLE DES MATIÈRES =====
story.append(Paragraph("Table des matières", styles["SectionTitle"]))
story.append(Spacer(1, 3*mm))
toc_items = [
"1. Qu'est-ce que Honcho ?",
"2. Architecture globale",
"3. Composants déployés",
"4. Flux de fonctionnement",
"5. Configuration Hermes",
"6. Commandes utiles",
"7. Schéma réseau",
"8. Dépannage",
]
for item in toc_items:
story.append(Paragraph(item, styles["MyBullet"]))
story.append(PageBreak())
# ===== 1. QU'EST-CE QUE HONCHO =====
story.append(Paragraph("1. Qu'est-ce que Honcho ?", styles["SectionTitle"]))
story.append(HRFlowable(width="100%", thickness=0.5, color=ACCENT))
story.append(Spacer(1, 3*mm))
story.append(Paragraph(
"Honcho est une infrastructure mémoire open-source (AGPL-3.0) développée par Plastic Labs. "
"Elle permet aux agents AI de construire une représentation persistante de l'utilisateur "
"à travers les sessions — contrairement à une mémoire fichier classique qui ne fait que "
"stocker du texte brut.",
styles["Body"]
))
story.append(Paragraph("Ce que Honcho apporte à Hermes :", styles["SubTitle"]))
bullets = [
"<b>Mémoire cross-session</b> — l'agent se souvient de qui vous êtes entre deux conversations",
"<b>Représentation utilisateur</b> — Honcho analyse les conversations et extrait des conclusions (préférences, patterns, style de communication)",
"<b>Dialectic engine</b> — un moteur de raisonnement en arrière-plan qui synthétise la mémoire",
"<b>Recherche sémantique</b> — retrouver des informations par similarité de sens, pas par mot-clé",
"<b>Multi-peers</b> — chaque profil Hermes a sa propre identité AI tout en partageant la vue utilisateur",
]
for b in bullets:
story.append(Paragraph(b, styles["MyBullet"]))
story.append(Spacer(1, 3*mm))
story.append(Paragraph("Le cœur du système :", styles["SubTitle"]))
story.append(Paragraph(
"1. <b>Store</b> — les conversations sont stockées dans PostgreSQL avec embeddings vectoriels<br/>"
"2. <b>Reason</b> — le Deriver (worker background) analyse les messages et met à jour la représentation<br/>"
"3. <b>Query</b> — Hermes interroge Honcho via 5 outils pour récupérer le contexte<br/>"
"4. <b>Inject</b> — le contexte est injecté dans le system prompt à chaque tour",
styles["Body"]
))
story.append(PageBreak())
# ===== 2. ARCHITECTURE GLOBALE =====
story.append(Paragraph("2. Architecture globale", styles["SectionTitle"]))
story.append(HRFlowable(width="100%", thickness=0.5, color=ACCENT))
story.append(Spacer(1, 3*mm))
story.append(Paragraph(
"Le déploiement s'appuie sur 3 VMs du homelab, interconnectées via le réseau 192.168.30.0/24 :",
styles["Body"]
))
# Tableau des VMs
vm_data = [
["VM", "IP", "Rôle", "Services"],
["Kellerflix\n(VM 101)", "192.168.30.10", "LLM & Embeddings", "Ollama\nnemotron-mini:4b\nnomic-embed-text"],
["postgres\n(LXC/VM)", "192.168.30.35", "Honcho Server", "Honcho API (:8000)\nHoncho Deriver\nPostgreSQL pgvector (:5434)"],
["redis\n(LXC/VM)", "192.168.30.36", "Cache", "Redis (:6379)"],
]
vm_table = Table(vm_data, colWidths=[3.5*cm, 3*cm, 3*cm, 5.5*cm])
vm_table.setStyle(TableStyle([
("BACKGROUND", (0, 0), (-1, 0), DARK),
("TEXTCOLOR", (0, 0), (-1, 0), white),
("FONTNAME", (0, 0), (-1, 0), "Helvetica-Bold"),
("FONTSIZE", (0, 0), (-1, -1), 9),
("ALIGN", (0, 0), (-1, -1), "CENTER"),
("VALIGN", (0, 0), (-1, -1), "MIDDLE"),
("GRID", (0, 0), (-1, -1), 0.5, GRAY),
("BACKGROUND", (0, 1), (-1, -1), LIGHT),
("TOPPADDING", (0, 0), (-1, -1), 6),
("BOTTOMPADDING", (0, 0), (-1, -1), 6),
]))
story.append(vm_table)
story.append(Spacer(1, 5*mm))
story.append(Paragraph("Flux des données :", styles["SubTitle"]))
story.append(Paragraph(
"Hermes (LXC 112) → Honcho API (192.168.30.35:8000) → PostgreSQL pgvector<br/>"
"Honcho Deriver → Ollama (192.168.30.10:11434) pour LLM + embeddings<br/>"
"Honcho API → Redis (192.168.30.36:6379) pour cache",
styles["Body"]
))
story.append(PageBreak())
# ===== 3. COMPOSANTS DÉPLOYÉS =====
story.append(Paragraph("3. Composants déployés", styles["SectionTitle"]))
story.append(HRFlowable(width="100%", thickness=0.5, color=ACCENT))
story.append(Spacer(1, 3*mm))
# 3.1 Honcho API
story.append(Paragraph("3.1 Honcho API (FastAPI)", styles["SubTitle"]))
story.append(Paragraph(
"Serveur HTTP qui expose l'API REST de Honcho. Point d'entrée pour Hermes et le SDK Python. "
"Gère les sessions, peers, messages, et la recherche contextuelle.",
styles["Body"]
))
story.append(Paragraph(
"Port : 8000<br/>"
"Healthcheck : GET /health → {\"status\":\"ok\"}<br/>"
"Docker : honcho-api (build local depuis le Dockerfile du repo plastic-labs/honcho)",
styles["Body"]
))
# 3.2 Honcho Deriver
story.append(Paragraph("3.2 Honcho Deriver (Worker background)", styles["SubTitle"]))
story.append(Paragraph(
"Processus qui tourne en arrière-plan et analyse les messages stockés. "
"Il utilise le LLM configuré (nemotron-mini:4b) pour :",
styles["Body"]
))
bullets = [
"Extraire des conclusions sur l'utilisateur (préférences, habitudes)",
"Générer des résumés de sessions",
"Mettre à jour la représentation du peer",
"Alimenter le moteur dialectic pour honcho_reasoning",
]
for b in bullets:
story.append(Paragraph(b, styles["MyBullet"]))
# 3.3 PostgreSQL pgvector
story.append(Paragraph("3.3 PostgreSQL + pgvector", styles["SubTitle"]))
story.append(Paragraph(
"Base de données vectorielle. Stocke les messages, sessions, peers, et les embeddings "
"(vecteurs à 768 dimensions pour nomic-embed-text). L'extension pgvector permet la "
"recherche par similarité sémantique.",
styles["Body"]
))
story.append(Paragraph(
"Image : pgvector/pgvector:pg15<br/>"
"Port interne : 5434 (évite conflit avec le PostgreSQL existant sur 5432)<br/>"
"Volume : honcho-pgdata (persistant)",
styles["Body"]
))
# 3.4 Redis
story.append(Paragraph("3.4 Redis (Cache)", styles["SubTitle"]))
story.append(Paragraph(
"Cache pour accélérer les requêtes répétées. Redis existant sur le homelab, "
"réutilisé sans conteneur dédié dans le stack Honcho.",
styles["Body"]
))
story.append(Paragraph(
"Hôte : 192.168.30.36:6379<br/>"
"Pas de mot de passe (réseau interne)",
styles["Body"]
))
# 3.5 Ollama
story.append(Paragraph("3.5 Ollama (LLM & Embeddings)", styles["SubTitle"]))
story.append(Paragraph(
"Serveur de modèles LLM locaux sur Kellerflix (GTX 1070, 8GB VRAM). "
"Deux modèles utilisés :",
styles["Body"]
))
bullets = [
"<b>nemotron-mini:4b</b> (Q4_K_M, 2.7GB) — LLM pour le dialectic engine et le deriver. Supporte le tool calling.",
"<b>nomic-embed-text</b> (274MB) — modèle d'embeddings pour la recherche vectorielle (768 dimensions).",
]
for b in bullets:
story.append(Paragraph(b, styles["MyBullet"]))
story.append(PageBreak())
# ===== 4. FLUX DE FONCTIONNEMENT =====
story.append(Paragraph("4. Flux de fonctionnement", styles["SectionTitle"]))
story.append(HRFlowable(width="100%", thickness=0.5, color=ACCENT))
story.append(Spacer(1, 3*mm))
story.append(Paragraph("4.1 À chaque message utilisateur", styles["SubTitle"]))
steps = [
"<b>1.</b> Hermes reçoit le message de l'utilisateur",
"<b>2.</b> Honcho injecte automatiquement le contexte dans le system prompt (représentation utilisateur + résumé de session + carte AI peer)",
"<b>3.</b> Hermes traite la requête avec ce contexte",
"<b>4.</b> La réponse est envoyée à l'utilisateur",
"<b>5.</b> Le message est stocké dans Honcho (via l'API)",
"<b>6.</b> Le Deriver analyse le message en arrière-plan et met à jour la représentation",
]
for s in steps:
story.append(Paragraph(s, styles["MyBullet"]))
story.append(Paragraph("4.2 Modes de rappel (Recall Modes)", styles["SubTitle"]))
recall_data = [
["Mode", "Auto-injection", "Outils mémoire", "Usage"],
["hybrid\n(default)", "Oui", "Oui (5 outils)", "L'agent décide quand utiliser les outils vs le contexte auto-injecté"],
["context", "Oui", "Non (cachés)", "Économique en tokens, pas d'appels outils"],
["tools", "Non", "Oui", "L'agent contrôle tout explicitement"],
]
recall_table = Table(recall_data, colWidths=[3*cm, 2.5*cm, 2.5*cm, 6*cm])
recall_table.setStyle(TableStyle([
("BACKGROUND", (0, 0), (-1, 0), DARK),
("TEXTCOLOR", (0, 0), (-1, 0), white),
("FONTNAME", (0, 0), (-1, 0), "Helvetica-Bold"),
("FONTSIZE", (0, 0), (-1, -1), 9),
("ALIGN", (0, 0), (-1, -1), "CENTER"),
("VALIGN", (0, 0), (-1, -1), "MIDDLE"),
("GRID", (0, 0), (-1, -1), 0.5, GRAY),
("BACKGROUND", (0, 1), (-1, -1), LIGHT),
("TOPPADDING", (0, 0), (-1, -1), 6),
("BOTTOMPADDING", (0, 0), (-1, -1), 6),
]))
story.append(recall_table)
story.append(Spacer(1, 3*mm))
story.append(Paragraph("4.3 Les 5 outils mémoire", styles["SubTitle"]))
tools_data = [
["Outil", "Appel LLM ?", "Coût", "Usage"],
["honcho_profile", "Non", "minimal", "Lire/mettre à jour la carte du peer (nom, rôle, préférences)"],
["honcho_search", "Non", "faible", "Recherche sémantique dans l'historique"],
["honcho_context", "Non", "faible", "Snapshot complet : résumé + représentation + messages récents"],
["honcho_reasoning", "Oui", "moyen-élevé", "Question synthétisée par le dialectic engine"],
["honcho_conclude", "Non", "minimal", "Écrire/supprimer une conclusion persistante"],
]
tools_table = Table(tools_data, colWidths=[3*cm, 2*cm, 2*cm, 7*cm])
tools_table.setStyle(TableStyle([
("BACKGROUND", (0, 0), (-1, 0), DARK),
("TEXTCOLOR", (0, 0), (-1, 0), white),
("FONTNAME", (0, 0), (-1, 0), "Helvetica-Bold"),
("FONTSIZE", (0, 0), (-1, -1), 9),
("ALIGN", (0, 0), (-1, -1), "CENTER"),
("VALIGN", (0, 0), (-1, -1), "MIDDLE"),
("GRID", (0, 0), (-1, -1), 0.5, GRAY),
("BACKGROUND", (0, 1), (-1, -1), LIGHT),
("TOPPADDING", (0, 0), (-1, -1), 6),
("BOTTOMPADDING", (0, 0), (-1, -1), 6),
]))
story.append(tools_table)
story.append(PageBreak())
# ===== 5. CONFIGURATION HERMES =====
story.append(Paragraph("5. Configuration Hermes", styles["SectionTitle"]))
story.append(HRFlowable(width="100%", thickness=0.5, color=ACCENT))
story.append(Spacer(1, 3*mm))
story.append(Paragraph("5.1 Fichier honcho.json", styles["SubTitle"]))
story.append(Paragraph(
"Chemin : /root/.hermes/honcho.json",
styles["Body"]
))
story.append(Paragraph(
"{<br/>"
" \"baseUrl\": \"http://192.168.30.35:8000\",<br/>"
" \"peerName\": \"laurent\",<br/>"
" \"aiPeer\": \"hermes\",<br/>"
" \"workspace\": \"default\",<br/>"
" \"recallMode\": \"hybrid\",<br/>"
" \"writeFrequency\": \"async\",<br/>"
" \"sessionStrategy\": \"per-directory\",<br/>"
" \"observation\": {<br/>"
" \"user\": { \"observeMe\": true, \"observeOthers\": true },<br/>"
" \"ai\": { \"observeMe\": true, \"observeOthers\": true }<br/>"
" },<br/>"
" \"dialecticReasoningLevel\": \"low\",<br/>"
" \"dialecticDepth\": 1,<br/>"
" \"contextCadence\": 1,<br/>"
" \"dialecticCadence\": 2<br/>"
"}",
styles["Code"]
))
story.append(Paragraph("5.2 Config Hermes", styles["SubTitle"]))
story.append(Paragraph(
"Dans /root/.hermes/config.yaml :",
styles["Body"]
))
story.append(Paragraph(
"memory:<br/>"
" provider: honcho",
styles["Code"]
))
story.append(Paragraph("5.3 Fichier .env Honcho", styles["SubTitle"]))
story.append(Paragraph(
"Chemin sur la VM postgres : /root/docker/honcho/.env",
styles["Body"]
))
story.append(Paragraph(
"LOG_LEVEL=INFO<br/>"
"AUTH_USE_AUTH=false<br/>"
"VECTOR_STORE_TYPE=pgvector<br/>"
"LLM_OPENAI_API_KEY=ollama<br/>"
"DERIVER_MODEL_CONFIG__TRANSPORT=openai<br/>"
"DERIVER_MODEL_CONFIG__MODEL=nemotron-mini:4b<br/>"
"DERIVER_MODEL_CONFIG__OVERRIDES__BASE_URL=http://192.168.30.10:11434/v1<br/>"
"DERIVER_MODEL_CONFIG__OVERRIDES__API_KEY_ENV=ollama<br/>"
"EMBEDDING_MODEL_CONFIG__TRANSPORT=openai<br/>"
"EMBEDDING_MODEL_CONFIG__MODEL=nomic-embed-text<br/>"
"EMBEDDING_MODEL_CONFIG__OVERRIDES__BASE_URL=http://192.168.30.10:11434/v1<br/>"
"EMBEDDING_MODEL_CONFIG__OVERRIDES__API_KEY_ENV=ollama<br/>"
"EMBED_MESSAGES=true<br/>"
"EMBEDDING_VECTOR_DIMENSIONS=768",
styles["Code"]
))
story.append(PageBreak())
# ===== 6. COMMANDES UTILES =====
story.append(Paragraph("6. Commandes utiles", styles["SectionTitle"]))
story.append(HRFlowable(width="100%", thickness=0.5, color=ACCENT))
story.append(Spacer(1, 3*mm))
story.append(Paragraph("6.1 Sur Hermes (LXC 112)", styles["SubTitle"]))
cmds = [
("hermes honcho status", "Voir l'état de la connexion Honcho"),
("hermes honcho setup", "Lancer le wizard de configuration"),
("hermes honcho enable/disable", "Activer/désactiver Honcho"),
("hermes honcho peer --user <nom>", "Définir le nom du peer utilisateur"),
("hermes honcho mode hybrid|context|tools", "Changer le mode de rappel"),
("hermes honcho sessions", "Lister les sessions connues"),
("hermes honcho map <nom>", "Mapper le répertoire courant à une session"),
("hermes honcho sync", "Créer les host blocks pour tous les profils"),
("hermes memory status", "Voir le provider mémoire actif"),
("hermes memory off", "Désactiver la mémoire externe"),
]
for cmd, desc in cmds:
story.append(Paragraph(f"<b>{cmd}</b> — {desc}", styles["MyBullet"]))
story.append(Paragraph("6.2 Sur la VM postgres (192.168.30.35)", styles["SubTitle"]))
cmds2 = [
("docker compose ps", "Voir l'état des conteneurs"),
("docker compose logs api --tail 30", "Logs de l'API Honcho"),
("docker compose logs deriver --tail 30", "Logs du Deriver"),
("docker compose down && docker compose up -d", "Redémarrer le stack"),
("docker compose down -v && docker compose up -d --build", "Reset complet + rebuild"),
("curl http://localhost:8000/health", "Healthcheck"),
]
for cmd, desc in cmds2:
story.append(Paragraph(f"<b>{cmd}</b> — {desc}", styles["MyBullet"]))
story.append(Paragraph("6.3 Sur Kellerflix (192.168.30.10)", styles["SubTitle"]))
cmds3 = [
("ollama list", "Lister les modèles disponibles"),
("ollama pull <modele>", "Télécharger un modèle"),
("ollama run <modele>", "Tester un modèle en interactif"),
("curl http://localhost:11434/api/tags", "Lister les modèles via API"),
]
for cmd, desc in cmds3:
story.append(Paragraph(f"<b>{cmd}</b> — {desc}", styles["MyBullet"]))
story.append(PageBreak())
# ===== 7. SCHÉMA RÉSEAU =====
story.append(Paragraph("7. Schéma réseau", styles["SectionTitle"]))
story.append(HRFlowable(width="100%", thickness=0.5, color=ACCENT))
story.append(Spacer(1, 3*mm))
story.append(Paragraph(
"Le schéma ci-dessous représente les flux entre les composants :",
styles["Body"]
))
story.append(Spacer(1, 3*mm))
# Schéma ASCII
schema = """<font face="Courier" size="8">
┌─────────────────────────────────────────────────────────────┐
│ RÉSEAU 192.168.30.0/24 │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────────┐ ┌──────────────────────────────┐ │
│ │ Hermes Agent │ │ VM postgres (30.35) │ │
│ │ (LXC 112) │ │ │ │
│ │ │ │ ┌──────────────────────┐ │ │
│ │ honcho-ai SDK │────▶│ │ Honcho API (:8000) │ │ │
│ │ hermes honcho │ │ │ (FastAPI) │ │ │
│ │ │ │ └──────┬───────────────┘ │ │
│ └──────────────────┘ │ │ │ │
│ │ ▼ │ │
│ │ ┌──────────────────────┐ │ │
│ │ │ PostgreSQL pgvector │ │ │
│ │ │ (:5434) │ │ │
│ │ └──────────────────────┘ │ │
│ │ ▲ │ │
│ │ ┌──────┴───────────────┐ │ │
│ │ │ Honcho Deriver │ │ │
│ │ │ (worker background) │ │ │
│ │ └──────┬───────────────┘ │ │
│ └─────────┼────────────────────┘ │
│ │ │
│ ┌─────────┼────────────┐ │
│ │ ▼ │ │
│ │ ┌──────────────┐ │ │
│ │ │ Redis │ │ │
│ │ │ (30.36:6379) │ │ │
│ │ └──────────────┘ │ │
│ └──────────────────────┘ │
│ │ │
│ ┌─────────┼────────────┐ │
│ │ ▼ │ │
│ │ ┌──────────────────┐ │ │
│ │ │ Kellerflix │ │ │
│ │ │ (30.10:11434) │ │ │
│ │ │ Ollama │ │ │
│ │ │ ├─ nemotron-mini│ │ │
│ │ │ └─ nomic-embed │ │ │
│ │ └──────────────────┘ │ │
│ └────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘
</font>"""
story.append(Paragraph(schema, styles["Body"]))
story.append(PageBreak())
# ===== 8. DÉPANNAGE =====
story.append(Paragraph("8. Dépannage", styles["SectionTitle"]))
story.append(HRFlowable(width="100%", thickness=0.5, color=ACCENT))
story.append(Spacer(1, 3*mm))
issues = [
("Problème", "Cause probable", "Solution"),
("Honcho not configured", "memory.provider pas défini", "hermes config set memory.provider honcho"),
("API Honcho injoignable", "Conteneur down", "docker compose ps && docker compose logs api"),
("OpenAI API key required", "LLM_OPENAI_API_KEY manquant", "Ajouter LLM_OPENAI_API_KEY=ollama dans .env"),
("Embedding dim mismatch", "Dimensions changées après init", "docker compose down -v && docker compose up -d --build"),
("Deriver ne tourne pas", "Dépendance api pas healthy", "Vérifier les logs : docker compose logs deriver"),
("Peer conflict", "Peer déjà créé", "Utiliser un nom différent ou supprimer l'ancien"),
("Ollama inaccessible", "OLLAMA_HOST=127.0.0.1", "Vérifier ss -tlnp | grep 11434"),
("Mémoire non persistante", "writeFrequency = session", "Passer à async dans honcho.json"),
]
issues_table = Table(issues, colWidths=[3.5*cm, 4*cm, 6.5*cm])
issues_table.setStyle(TableStyle([
("BACKGROUND", (0, 0), (-1, 0), DARK),
("TEXTCOLOR", (0, 0), (-1, 0), white),
("FONTNAME", (0, 0), (-1, 0), "Helvetica-Bold"),
("FONTSIZE", (0, 0), (-1, -1), 8),
("ALIGN", (0, 0), (-1, -1), "LEFT"),
("VALIGN", (0, 0), (-1, -1), "MIDDLE"),
("GRID", (0, 0), (-1, -1), 0.5, GRAY),
("BACKGROUND", (0, 1), (-1, -1), LIGHT),
("TOPPADDING", (0, 0), (-1, -1), 5),
("BOTTOMPADDING", (0, 0), (-1, -1), 5),
("LEFTPADDING", (0, 0), (-1, -1), 4),
]))
story.append(issues_table)
story.append(Spacer(1, 5*mm))
story.append(Paragraph("Liens utiles :", styles["SubTitle"]))
story.append(Paragraph(
"Documentation Honcho : https://docs.honcho.dev<br/>"
"Repo Honcho : https://github.com/plastic-labs/honcho<br/>"
"Intégration Hermes : https://docs.honcho.dev/v3/guides/integrations/hermes<br/>"
"App Honcho Cloud : https://app.honcho.dev<br/>"
"Ollama : https://ollama.com",
styles["Body"]
))
# Build
doc.build(story)
print(f"PDF généré : {OUTPUT}")
print(f"Taille : {os.path.getsize(OUTPUT)} bytes")