refactor(hermes): API server OpenAI-compatible unifié, retrait du gateway discord-bridge dédié
Un seul listener par hôte (profil default) sert tous les profils sous /p/<profil>/... au lieu d'un gateway séparé par profil. Le pont Discord existant (services/discord-bot) appelle maintenant http://127.0.0.1:8642/p/discord-bridge/v1/chat/completions et expose une surface de test locale (HERMES_BRIDGE_ASK_PORT). services/discord-hermes-bridge (gateway dédié, 71 lignes) est retiré ; la clé est réutilisée depuis secrets/discord-hermes-bridge.yml (clé renommée hermes_api_server_env).
This commit is contained in:
@@ -1,17 +1,17 @@
|
||||
hermes_discord_bridge_env: ENC[AES256_GCM,data:SJ2zitdGqLLt9seXzmxu3o8uVmJFG6k5pGaMACpZ2aWzqbgP6D8LwTPKlJZiSZ8lwNUnurJrQ3J9RBSJaIOkoKrRtwX0AMs6crxRJe+E6CU=,iv:czq1KzUHEQs2fdDObhA0WmGgQwNwjczVcctQimttFxQ=,tag:LLcMUdPc4gQWhnZdWYD7XQ==,type:str]
|
||||
discord_bot_hermes_bridge_env: ENC[AES256_GCM,data:VHIQgLh0azzLBEB9vemDrSPjqqSvirlp4d1fL+1vXwAmAYWN4UPMpYlUAjWrar23JY+QZ7FkFjbGV18GoPta6UYSIK/2ICVmsPHhHo1G3hEw+BUYYF+X,iv:8lis93YMqPz8mJR7J/ifm/SyYi1k/5s5XZVjglqR8G4=,tag:8i4Ju5C78CD3hfL+KmJXYg==,type:str]
|
||||
hermes_discord_bridge_env: ENC[AES256_GCM,data:N14TYsne5p5a7PJvMZzJELORa7xV5Njy2ThiYN4fe0xP+Lt+f5XYcY1dkVi6Azp5VD2ILz+PT9Bg3deitSGsO9sduO6FGD9SFveUZZ7MOA==,iv:VYDRuQKbZFp4vgCG8ZKTaBQNuIdlF6KNLsNfoZi5xOY=,tag:x/sxdzlDghT9Hd8IaVWBHw==,type:str]
|
||||
discord_bot_hermes_bridge_env: ENC[AES256_GCM,data:aG1k7e5o8AEGugKnuozvyy/pNzv8j+WJoVNmqnG3lDRBqhnzsNQoRr8BN8CimoRDncKHfRHMc/UalFbw+87RODw+MXfyo6YhvouQqh6xrnpN5/xfbpo=,iv:ISVsE+hvJBYdkGqjTqXlDzghRPzMZqq4F70hVxGd1EU=,tag:0Agx+x9/dPsyN0gY+VUiNw==,type:str]
|
||||
sops:
|
||||
age:
|
||||
- enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBqendZNnBBdW9FQ0lYOXJT
|
||||
WmN1b1ZoL2htbG1XRndlM2hlU1BjZTNZemprCktteUkvREtZYlFCTCtIdVh5WkFR
|
||||
L1MxblNxKy9pVnRCYU9ScjZZdGhkelEKLS0tIDBmdk0xeGVzY3MwbmZncnFya2Fv
|
||||
Nm4wRFY2UFQ0eFNuYXlGUWFjdytaZDQKjhK7ZpoqiWjdMFEXZ3Fzsas1EdKbTKNq
|
||||
/2rL0KJAmQu/7pn9qKAXdrO7W7qf6XEwiVSmoZ0Z4BATcI6xiX+UPQ==
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBRL2lLM3pKanU3cm5HRFI5
|
||||
SmFHKzdMbXNtNmE1cXdTeEJYaGZ3b2RjbWlNCjBaZ1k4enVMM1RiMUdDU1hTdzBO
|
||||
RGw1ay93R0JseEhPODVkNTc2bzFkMHMKLS0tIGZUVElIRk81enIyVTFJSlB0UE1J
|
||||
ejBIcnd1ZW1Fb2hKcDdQellxcm5rM0EKFiwGlSEkY6zmb97CdZdtvuCXrbZaIrFB
|
||||
emRzpaYoiPFFZor3WSrVtsXSaL1ujKddtUAEULKem1V4OFBsKL72HQ==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
recipient: age1usm3v0ugducrzcwud60dda7xfnj49fdhecj7kcsfm7dzwzrzeyqq2jc2hm
|
||||
lastmodified: "2026-09-27T06:54:21Z"
|
||||
mac: ENC[AES256_GCM,data:+tNIeBz2vsvMPNGFIYm/VNaBm/jzDc2XtvhiRZVxYC+3IGM5On+2F8qKEmFEDEejdLo9SkKU2+XI0OBuD3fcBo5Gb9hevQMxS48W7EIzjsQ8KxHsvuRPor8krw8Q0vNyvpxtLOf9SEhcFWoYiFJt5HQ9q6lhvV93ZgQdXiZk4uI=,iv:66NsoDMKqsJHBjD1OO7B5o6B7tbmQIKnHYCyfiz9bKg=,tag:D9Db4M6lLeiWGENN1nMXRA==,type:str]
|
||||
lastmodified: "2026-09-27T20:35:36Z"
|
||||
mac: ENC[AES256_GCM,data:tU15GvpxbBefkdaBFRPel7yRreS62E10FltgvwT66oCBuE3I9RR9fbAdF4Xf0dMfG6ANRBVw0QGqlihjfBI84Ghaf57YKNhDuTvYcdP6fI3uQ0cZCEscY7H52o6VbOekawkWRP33Xnq4x3L+4fI0GkWmzK60Xm5zjPuNGcAsaF8=,iv:9nZfRiUj2SZ0f9Tw9+SFAOmJt9KzX92VZ2hrDDsopcQ=,tag:Dmk4zq0E3AvQ3LDbs2831Q==,type:str]
|
||||
unencrypted_suffix: _unencrypted
|
||||
version: 3.13.3
|
||||
|
||||
@@ -18,7 +18,8 @@
|
||||
port = 8050;
|
||||
};
|
||||
|
||||
# Pont vers le gateway Hermes dédié (services/discord-hermes-bridge).
|
||||
# Pont vers l'API server Hermes. Un seul listener par hôte (le profil default,
|
||||
# cf. services/hermes) : un profil secondaire est servi sous /p/<profil>/.
|
||||
# HERMES_BRIDGE_URL n'est pas secret (loopback local), seule la clé l'est.
|
||||
systemd.services.discord-bot.serviceConfig.EnvironmentFile = lib.mkAfter [
|
||||
config.sops.secrets."discord_bot_hermes_bridge_env".path
|
||||
@@ -26,6 +27,9 @@
|
||||
systemd.services.discord-bot.environment = {
|
||||
HERMES_BRIDGE_URL = "http://127.0.0.1:8643/v1/chat/completions";
|
||||
HERMES_BRIDGE_ROLE_NAME = "hermes";
|
||||
# Surface de test locale du cog (loopback, PAS ouverte au firewall) :
|
||||
# POST /hermes/ask {"message": "..."} -> {"answer": "..."}.
|
||||
HERMES_BRIDGE_ASK_PORT = "8052";
|
||||
};
|
||||
|
||||
sops.secrets."discord_bot_env" = {};
|
||||
|
||||
@@ -39,7 +39,8 @@
|
||||
environmentFiles =
|
||||
[ config.sops.secrets."hermes_env".path ]
|
||||
++ lib.optional config.services.hermes.enableMatrixToken config.sops.secrets."hermes_matrix_env".path
|
||||
++ lib.optional config.services.hermes.enableDiscordToken config.sops.secrets."hermes_discord_env".path;
|
||||
++ lib.optional config.services.hermes.enableDiscordToken config.sops.secrets."hermes_discord_env".path
|
||||
++ [ config.sops.secrets."hermes_api_server_env".path ];
|
||||
addToSystemPackages = true;
|
||||
|
||||
# venv nix scellé -> deps mem0 (mem0ai) installées au runtime dans une cible durable
|
||||
@@ -67,6 +68,19 @@
|
||||
# (l'env du process se pose sur l'unité systemd, pas via `environment`, qui
|
||||
# n'écrit que $HERMES_HOME/.env) ---
|
||||
|
||||
# --- API Server (OpenAI-compatible) : UN SEUL listener pour l'hôte ---
|
||||
# La topologie de Hermes est "un gateway par hôte qui sert tous les profils"
|
||||
# (multiplex). Un profil secondaire qui demande son API server n'obtient PAS
|
||||
# son propre port : le listener du profil default le sert sous
|
||||
# /p/<profil>/... (log gateway : "api_server is served by the default
|
||||
# profile's listener at /p/<profil>/ — not starting a second listener").
|
||||
# C'est ce que consomme le pont Discord : services/discord-bot appelle
|
||||
# http://127.0.0.1:8642/p/discord-bridge/v1/chat/completions.
|
||||
# Bind loopback uniquement, clé obligatoire (sops), jamais ouvert au
|
||||
# firewall, jamais routé par Pangolin.
|
||||
environment.API_SERVER_ENABLED = "true";
|
||||
environment.API_SERVER_PORT = "8642";
|
||||
|
||||
# psycopg2 buildé par nix (évite le wheel manylinux psycopg2-binary)
|
||||
# numpy N'EST PLUS LISTÉ ICI : depuis l'ajout de "stt-whisper" (onnxruntime ->
|
||||
# numpy 2.4.3) le venv scellé le fournit lui-même, et le build du paquet hermes
|
||||
@@ -360,6 +374,15 @@
|
||||
|
||||
sops.secrets."hermes_env" = {};
|
||||
|
||||
# Clé du listener API Server du profil default (clé "hermes_api_server_env"
|
||||
# du fichier sops, valeur = contenu dotenv "API_SERVER_KEY=..."). Même valeur
|
||||
# que HERMES_BRIDGE_API_KEY côté services/discord-bot, qui l'envoie en Bearer :
|
||||
# le pont Discord et l'API server partagent donc LA MÊME clé, chiffrée une
|
||||
# seule fois dans secrets/discord-hermes-bridge.yml.
|
||||
sops.secrets."hermes_api_server_env" = {
|
||||
sopsFile = ../../secrets/discord-hermes-bridge.yml;
|
||||
};
|
||||
|
||||
# Token Matrix du bot (@hermes) — clé "hermes_matrix_env" du fichier sops,
|
||||
# valeur = contenu dotenv (MATRIX_ACCESS_TOKEN=...) fusionné dans .env.
|
||||
# Déclaré uniquement là où l'option est active : les destinataires du fichier
|
||||
|
||||
Reference in New Issue
Block a user