147 lines
5.3 KiB
Python
147 lines
5.3 KiB
Python
import os
|
|
from pathlib import Path
|
|
from typing import Dict, Any, List, Optional
|
|
from pydantic import BaseModel, Field, field_validator
|
|
from pydantic_settings import BaseSettings
|
|
|
|
BASE_DIR = Path(__file__).resolve().parent.parent
|
|
DATA_DIR = Path(os.getenv("HUB_DATA_DIR", BASE_DIR / "data"))
|
|
PERSONAS_DIR = DATA_DIR / "personas"
|
|
CLONES_DIR = DATA_DIR / "clones"
|
|
DB_PATH = DATA_DIR / "hub.db"
|
|
|
|
class UniverseConfig(BaseModel):
|
|
id: str
|
|
name: str
|
|
tagline: str
|
|
description: str
|
|
backend_url: str
|
|
scope: str
|
|
accent_token: str
|
|
icon: str
|
|
persona_file: str
|
|
enabled: bool = True
|
|
supports_files: bool = False
|
|
files_url: Optional[str] = None
|
|
is_external_app: bool = False
|
|
|
|
class Settings(BaseSettings):
|
|
app_name: str = "Hermes Hub"
|
|
host: str = "0.0.0.0"
|
|
port: int = 8080
|
|
debug: bool = False
|
|
|
|
# NAS & VPS Network Configurations
|
|
nas_tailscale_ip: str = os.getenv("NAS_TAILSCALE_IP", "100.86.197.88")
|
|
vps_tailscale_ip: str = os.getenv("VPS_TAILSCALE_IP", "100.94.90.119")
|
|
|
|
# Backends
|
|
hermes_tt_url: str = os.getenv("HERMES_TT_URL", "http://100.86.197.88:3010")
|
|
hermes_nyora_url: str = os.getenv("HERMES_NYORA_URL", "http://100.86.197.88:3020")
|
|
hermes_perso_url: str = os.getenv("HERMES_PERSO_URL", "http://100.86.197.88:3031")
|
|
hermes_nabil_url: str = os.getenv("HERMES_NABIL_URL", "http://hermes-nabil:9119")
|
|
hermes_dsh_url: str = os.getenv("HERMES_DSH_URL", "http://dsh-vps:3080")
|
|
dsh_filebrowser_url: str = os.getenv("DSH_FILEBROWSER_URL", "http://dsh-vps-filebrowser:8080")
|
|
|
|
# Backend Passwords
|
|
hermes_tt_password: str = os.getenv("HERMES_TT_PASSWORD", "XiEdCtyWETbzpQ7dxrRyvAYu")
|
|
hermes_nyora_password: str = os.getenv("HERMES_NYORA_PASSWORD", "juoKPfPGuo39wKCn9WJ0kY0_")
|
|
hermes_perso_password: str = os.getenv("HERMES_PERSO_PASSWORD", "-6Q12oViKsgZgIL82Kspa_dV")
|
|
hermes_nabil_username: str = os.getenv("HERMES_NABIL_USERNAME", "nabil")
|
|
hermes_nabil_password: str = os.getenv("HERMES_NABIL_PASSWORD", "NabilMasterHermes2026!")
|
|
|
|
# Hub Secret — OBLIGATOIRE, aucun fallback codé en dur (Fail-Fast au démarrage)
|
|
hub_secret: str = Field(..., min_length=16, description="Clé secrète maîtresse requise pour Hermes Hub")
|
|
|
|
@field_validator("hub_secret")
|
|
@classmethod
|
|
def validate_secret(cls, v: str) -> str:
|
|
if not v or v.strip() == "" or "change-this" in v or "hermes-hub-master-key-2026" in v:
|
|
raise ValueError("HUB_SECRET doit être défini avec une clé sécurisée valide et ne doit pas utiliser de valeur par défaut.")
|
|
return v
|
|
|
|
class Config:
|
|
env_file = ".env"
|
|
extra = "ignore"
|
|
|
|
try:
|
|
settings = Settings()
|
|
except Exception as e:
|
|
if "HUB_SECRET" in os.environ:
|
|
raise e
|
|
settings = None
|
|
|
|
UNIVERSES: Dict[str, UniverseConfig] = {
|
|
"tt": UniverseConfig(
|
|
id="tt",
|
|
name="Tunisie Telecom",
|
|
tagline="Achats Zone Sud",
|
|
description="Direction Régionale — Marchés, RLA & Appels d'Offres",
|
|
backend_url=os.getenv("HERMES_TT_URL", "http://100.86.197.88:3010"),
|
|
scope="tt",
|
|
accent_token="--accent-tt",
|
|
icon="briefcase",
|
|
persona_file="tt.yaml",
|
|
supports_files=False,
|
|
is_external_app=False
|
|
),
|
|
"nyora": UniverseConfig(
|
|
id="nyora",
|
|
name="Nyora",
|
|
tagline="Venture & Dr Nexum",
|
|
description="Projets entrepreneuriaux, conseil & veille stratégique",
|
|
backend_url=os.getenv("HERMES_NYORA_URL", "http://100.86.197.88:3020"),
|
|
scope="nyora",
|
|
accent_token="--accent-nyora",
|
|
icon="sparkles",
|
|
persona_file="nyora.yaml",
|
|
supports_files=False,
|
|
is_external_app=False
|
|
),
|
|
"perso": UniverseConfig(
|
|
id="perso",
|
|
name="Personnel",
|
|
tagline="Famille & Santé",
|
|
description="Espace privé, santé familiale, gestion du quotidien",
|
|
backend_url=os.getenv("HERMES_PERSO_URL", "http://100.86.197.88:3031"),
|
|
scope="perso",
|
|
accent_token="--accent-perso",
|
|
icon="home",
|
|
persona_file="perso.yaml",
|
|
supports_files=False,
|
|
is_external_app=False
|
|
),
|
|
"nabil": UniverseConfig(
|
|
id="nabil",
|
|
name="Nabil Master",
|
|
tagline="Orchestration & Code",
|
|
description="Master Agent VPS, exécution de code & supervision DSH",
|
|
backend_url=os.getenv("HERMES_NABIL_URL", "http://hermes-nabil:9119"),
|
|
scope="nabil",
|
|
accent_token="--accent-nabil",
|
|
icon="terminal",
|
|
persona_file="nabil.yaml",
|
|
supports_files=True,
|
|
files_url=os.getenv("DSH_FILEBROWSER_URL", "http://dsh-vps-filebrowser:8080"),
|
|
is_external_app=False
|
|
),
|
|
"dsh": UniverseConfig(
|
|
id="dsh",
|
|
name="DeepSeek Harness",
|
|
tagline="DSH Autonomous Agent",
|
|
description="Plateforme DeepSeek Harness : agents autonomes, sous-agents, trajectoires et tâches",
|
|
backend_url=os.getenv("HERMES_DSH_URL", "http://dsh-vps:3080"),
|
|
scope="dsh",
|
|
accent_token="--accent-dsh",
|
|
icon="cpu",
|
|
persona_file="dsh.yaml",
|
|
supports_files=False,
|
|
is_external_app=True
|
|
)
|
|
}
|
|
|
|
def get_universe(universe_id: str) -> UniverseConfig:
|
|
if universe_id not in UNIVERSES:
|
|
raise KeyError(f"Universe '{universe_id}' does not exist.")
|
|
return UNIVERSES[universe_id]
|