79 lines
4.9 KiB
Markdown
79 lines
4.9 KiB
Markdown
# Job cron veille Nexum : bascule silencieuse sur DeepSeek/OpenRouter par pin de provider bypassant bifrost-proxy
|
|
|
|
**Instance auteur** : hermes-nyora
|
|
**Date** : 2026-09-10
|
|
**Tags** : [infra, bifrost, opencode-go, cron, hermes-nyora, veille-nexum]
|
|
**Statut** : validé
|
|
|
|
---
|
|
|
|
## Problème
|
|
|
|
Nabil signale que les 3 veilles quotidiennes Dr. Nexum (07h/12h/20h Tunis, job `veille-ia-nexum-4ee61494`) tournent depuis un moment sur DeepSeek V4 Flash via OpenRouter au lieu de MiMo-V2.5 via OpenCode. Aucune erreur visible côté Telegram ou côté site veille.bolbol.tn : le contenu est simplement généré par un modèle différent de celui attendu, sans signal d'échec.
|
|
|
|
---
|
|
|
|
## Contexte et contraintes
|
|
|
|
- `config.yaml` de hermes-agent-nyora route par défaut via `model.default` (`provider: custom`, `base_url: http://bifrost-proxy/v1`) avec un `fallback_providers` (opencode-go/deepseek-v4-flash) puis un `fallback_model` final (openrouter/deepseek-v4-flash) — une chaîne de secours à 3 niveaux, conçue pour ne jamais bloquer un run, pas pour signaler une dégradation.
|
|
- Depuis la règle du 04/09 (`piege-virtual-key-nabil-key-bifrost-hermes-20260904.md`), l'API OpenCode Go exige un header `x-bf-eh-x-opencode-session`, injecté uniquement par `bifrost-proxy`. Un appel direct à `https://opencode.ai/zen/go/v1` sans passer par bifrost-proxy échoue systématiquement.
|
|
- Chaque job cron Hermes peut porter un pin `model`/`provider` au niveau du job, qui prend le pas sur `model.default` de config.yaml.
|
|
|
|
---
|
|
|
|
## Ce qui NE fonctionne PAS
|
|
|
|
| Tentative | Erreur obtenue | Raison de l'échec |
|
|
|-----------|----------------|-------------------|
|
|
| Job cron avec pin `provider=opencode-go` direct | `HTTP 400 MissingSessionID: Request is missing x-opencode-session` | Le pin bypass bifrost-proxy, qui est le seul point d'injection du header de session requis par l'API OpenCode Go |
|
|
| `fallback_providers: opencode-go/deepseek-v4-flash` du job | Même erreur `MissingSessionID` | Même chemin direct que ci-dessus, hérite du même défaut |
|
|
|
|
---
|
|
|
|
## Solution validée
|
|
|
|
Diagnostic (`docker logs hermes-agent-nyora`) :
|
|
```
|
|
WARNING agent.conversation_loop: API call failed (attempt 1/3) provider=opencode-go base_url=https://opencode.ai/zen/go/v1 model=mimo-v2.5 summary=HTTP 400: Error from provider (Console Go): Request is missing x-opencode-session...
|
|
WARNING agent.conversation_loop: API call failed (attempt 1/3) provider=opencode-go base_url=https://opencode.ai/zen/go/v1/ model=deepseek-v4-flash summary=HTTP 400: ...
|
|
🔄 Switched to fallback model: deepseek-v4-flash via opencode-go → deepseek/deepseek-v4-flash via openrouter
|
|
```
|
|
|
|
Comparaison avec `hermes cron list` / lecture directe de `jobs.json` : seul `veille-ia-nexum-4ee61494` portait un pin `model=mimo-v2.5, provider=opencode-go` au niveau du job. Le seul autre job actif (`35d81e5260bb`) avait `model=None, provider=None` et héritait correctement de `config.yaml`.
|
|
|
|
Fix :
|
|
```bash
|
|
docker exec hermes-agent-nyora hermes cron edit veille-ia-nexum-4ee61494 --model "" --provider ""
|
|
```
|
|
Cette commande retire le pin ; le job hérite désormais de `model.default` (custom → bifrost-proxy → mimo-v2.5).
|
|
|
|
---
|
|
|
|
## Vérification
|
|
|
|
```bash
|
|
docker exec hermes-agent-nyora curl -s -X POST http://bifrost-proxy/v1/chat/completions \
|
|
-H "Content-Type: application/json" \
|
|
-H "Authorization: Bearer <vk-hermes-nyora>" \
|
|
-d '{"model":"mimo-v2.5","max_tokens":20,"messages":[{"role":"user","content":"Reponds juste: OK"}]}'
|
|
# Résultat obtenu : HTTP 200, resolved_model_used: mimo-v2.5, provider: opencode (bifrost-proxy sain et actif)
|
|
```
|
|
Job vérifié post-edit : `model=None, provider=None` dans jobs.json, identique au pattern du job sain.
|
|
|
|
---
|
|
|
|
## Pièges spécifiques DSM / NAS
|
|
|
|
- Ce mode de panne est **silencieux par construction** : la chaîne de fallback à 3 niveaux de config.yaml est conçue pour toujours produire une réponse, donc un job cassé au niveau du premier maillon (pin direct opencode-go) continue de délivrer un résultat "normal" en apparence, juste avec un modèle différent et moins cher. Aucune alerte ne se déclenche.
|
|
- Réflexe d'audit : tout job cron / profil Hermes avec un pin `provider=opencode-go` **en direct** (au lieu de `provider=custom` + `base_url=http://bifrost-proxy/v1`) est suspect. Auditer avec `hermes cron list` puis vérifier chaque job avec `model`/`provider` non-null (`jobs.json`, champs `model`/`provider`/`base_url`/`profile`).
|
|
- Un profil Hermes (`/opt/data/profiles/<nom>/config.yaml`) peut porter le même défaut indépendamment des jobs cron — vérifier aussi ce fichier si un job utilise `--profile`.
|
|
- Ticket Baserow : infra-2026-09-037.
|
|
|
|
---
|
|
|
|
## Références
|
|
|
|
- `common/piege-virtual-key-nabil-key-bifrost-hermes-20260904.md` (règle du header x-opencode-session)
|
|
- `common/bifrost-opencode-routing-fix-20260907.md` (fix précédent du routage bifrost-proxy → opencode.ai)
|
|
- `common/migration-vps-bifrost-stub-forwarder-20260904.md` (relocalisation bifrost-proxy VPS)
|