diff --git a/_INDEX.md b/_INDEX.md index 2a5e2d4..0181194 100644 --- a/_INDEX.md +++ b/_INDEX.md @@ -12,6 +12,7 @@ | [Acces Bifrost (passerelle LLM, vision/OCR)](common/bifrost-access.md) | 2026-06-14 | infra, bifrost, llm, vision, x-bf-vk | | [Generation / edition d'images IA (nano-banana)](common/openrouter-image-gen.md) | 2026-06-14 | infra, openrouter, image, nano-banana | | [Gotenberg HTML->PDF (piege police web)](common/gotenberg-pdf.md) | 2026-06-14 | infra, gotenberg, pdf, fonts | +| [Migration provider OpenCode Go (+ fallback OpenRouter)](common/migration-provider-opencode-go.md) | 2026-06-14 | infra, opencode, hermes, family-help, fallback | ## hermes-perso | Runbook | Date | Tags | diff --git a/common/migration-provider-opencode-go.md b/common/migration-provider-opencode-go.md new file mode 100644 index 0000000..f6112b3 --- /dev/null +++ b/common/migration-provider-opencode-go.md @@ -0,0 +1,106 @@ +# Migration provider IA → OpenCode Go (+ fallback OpenRouter) + +**Instance auteur** : hermes-perso (transverse aux 3) +**Date** : 2026-06-14 +**Tags** : infra, opencode, hermes, family-help, llm, fallback +**Statut** : valide + +--- + +## Probleme + +Basculer le provider IA par defaut de OpenRouter vers OpenCode Go (endpoint +`zen/go/v1`), tout en gardant DeepSeek V4 Flash et un fallback OpenRouter. +Concerne les 3 agents Hermes (gateway) + l'app family-help (module medical). + +--- + +## Contexte et contraintes + +- Image `nousresearch/hermes-agent:latest`, source montee dans `/opt/hermes`. +- Les 3 Hermes sont des **stacks Portainer** : 291=nyora, 292=perso (path-based, + compose sur le FS), 294=TT (compose **inline** dans Portainer). Le + `docker-compose.yml` top-level de `hermes-platform/` est OBSOLETE. +- 1 seul abonnement OpenCode Go, plusieurs cles tirant du meme pool (~60$/mois). +- `/Volumes/docker` (Mac) = mount SMB du NAS `/volume1/docker`. + +--- + +## Ce qui NE fonctionne PAS + +| Tentative | Erreur obtenue | Raison de l'echec | +|-----------|----------------|-------------------| +| `docker compose up` depuis `hermes-platform/` (top-level) | `Conflict. The container name is already in use` | Les containers appartiennent aux stacks per-instance, pas au compose top-level | +| `hermes model` / `hermes fallback add` en SSH | `requires an interactive terminal` | Pickers interactifs → editer le YAML directement | +| Provider custom dans `providers:` | inutile | `opencode-go` est deja BUILT-IN (models.dev) | +| family-help medical `max_tokens: 512` | `finish_reason=length`, `content` VIDE | Modele de raisonnement : reasoning_content mange le budget avant le content | + +--- + +## Solution validee + +Provider built-in `opencode-go` : base_url `https://opencode.ai/zen/go/v1`, +cle via env var **`OPENCODE_API_KEY`**, model `deepseek-v4-flash` (sans prefixe). +OpenRouter (fallback) garde `deepseek/deepseek-v4-flash`. + +```yaml +# data/config.yaml (gateway) — pour chaque instance +model: + default: deepseek-v4-flash + provider: opencode-go +fallback_providers: +- provider: openrouter + model: deepseek/deepseek-v4-flash + key_env: OPENROUTER_API_KEY +``` + +```bash +# perso / nyora (stacks path-based) : ajouter OPENCODE_API_KEY au .env + au compose +# - OPENCODE_API_KEY=${OPENCODE_API_KEY} +cd /volume1/docker/hermes-platform/hermes-perso +docker compose up -d --force-recreate hermes-agent-perso + +# TT (stack 294 inline) : via API Portainer +# GET /api/stacks/294/file → inserer "- OPENCODE_API_KEY=" → PUT /api/stacks/294?endpointId=2 +``` + +family-help : `medical_service.py` → helper `_llm_complete()` (OpenCode primaire, +OpenRouter fallback), **`max_tokens: 2048`**, cle `BIFROST_OPENCODE_KEY`. +`docker compose build --no-cache && docker compose up -d --force-recreate`. + +--- + +## Verification + +```bash +docker exec hermes-agent- hermes fallback ls +# Attendu : Primary deepseek-v4-flash (via opencode-go) + +# Test end-to-end +docker exec hermes-agent- curl -s -H "Authorization: Bearer " \ + -H 'Content-Type: application/json' \ + -d '{"model":"deepseek-v4-flash","messages":[{"role":"user","content":"dis OK"}],"max_tokens":40}' \ + http://localhost:8642/v1/chat/completions +# Attendu : HTTP 200, content non vide + +# Test fallback : pointer OPENCODE_GO_BASE_URL vers un hote injoignable → reponse via OpenRouter (200) +``` + +--- + +## Pieges specifiques DSM / NAS + +- `docker` n'est PAS dans le PATH SSH → utiliser `/usr/local/bin/docker`. +- Ne jamais editer le docker-compose top-level (obsolete) ; identifier la vraie source + via `docker inspect --format '{{index .Config.Labels "com.docker.compose.project.config_files"}}'`. +- TT = stack inline Portainer → API Portainer, pas le FS (sudo requis sinon). +- DeepSeek V4 Flash (OpenCode) = reasoning model → `max_tokens` >= 2048 pour les + apps maison qui parsent du JSON (Hermes gere nativement). + +--- + +## References + +- https://opencode.ai/docs/zen +- https://hermes-agent.nousresearch.com/docs/user-guide/features/fallback-providers +- NyoraNotes : note 416da848 (capitalisation), note 26c38f8c (missions)