replica-omnisciente/experiments/hermes-launch/scripts/setup_hermes.py
AI Agent 060a325bdc feat(experiments): add Aurelio × Hermes hackathon launch workspace
- Hermes agent configuration, skills and MCP client wrappers
- Hardware Lab Node SSE server with ESP32, PPK2, Xgecu adapters
- Olhos-de-Orpheu launcher and sci-bot wrapper scripts
- Demo scenario, integration test and orchestrator task definitions
- Add local .gitignore for venvs, build outputs and runtime logs
2026-06-22 13:50:47 +01:00

145 lines
4.5 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env python3
"""Configure Hermes Agent to use Olhos-de-Orpheu as its single MCP gateway."""
import os
import subprocess
import sys
import urllib.request
from pathlib import Path
HERMES_HOME = Path.home() / ".hermes"
CONFIG_PATH = HERMES_HOME / "config.yaml"
ENV_PATH = HERMES_HOME / ".env"
REPO_ROOT = Path(__file__).resolve().parent.parent
VENV_PYTHON = REPO_ROOT / ".venv" / "bin" / "python"
HERMES_BIN = REPO_ROOT / ".venv" / "bin" / "hermes"
OLHOS_DE_ORPHEU_STDIO = REPO_ROOT / "scripts" / "olhos_de_orpheu_mcp.py"
OLLAMA_HOST = os.getenv("OLLAMA_HOST", "192.168.0.104")
OLLAMA_PORT = os.getenv("OLLAMA_PORT", "11434")
OLLAMA_MODEL = os.getenv("OLLAMA_MODEL", "llama3.2")
OLHOS_SSE_URL = os.getenv("MCP_OLHOS_DE_ORPHEU_URL", "http://192.168.0.16:8001/sse")
def ensure_hermes_home():
HERMES_HOME.mkdir(parents=True, exist_ok=True)
def _url_reachable(url: str, timeout: float = 3.0) -> bool:
try:
with urllib.request.urlopen(url, timeout=timeout) as resp:
return resp.status < 500
except Exception:
return False
def write_env(nvidia_key: str | None, stripe_key: str | None):
lines = []
if nvidia_key:
lines.append(f'NVIDIA_API_KEY="{nvidia_key}"')
else:
lines.append('# NVIDIA_API_KEY="nvapi-..." # get from https://build.nvidia.com')
if stripe_key:
lines.append(f'STRIPE_SECRET_KEY="{stripe_key}"')
else:
lines.append('# STRIPE_SECRET_KEY="sk_test_..." # get from https://dashboard.stripe.com/test/apikeys')
lines.append(f'OLLAMA_HOST="{OLLAMA_HOST}"')
lines.append(f'OLLAMA_PORT="{OLLAMA_PORT}"')
lines.append(f'OLLAMA_MODEL="{OLLAMA_MODEL}"')
lines.append('DEEPSEEK_API_KEY="ollama"')
lines.append(f'MCP_OLHOS_DE_ORPHEU_URL="{OLHOS_SSE_URL}"')
ENV_PATH.write_text("\n".join(lines) + "\n", encoding="utf-8")
print(f"Wrote {ENV_PATH}")
def write_config(nvidia_key: str | None, use_olhos_sse: bool):
if nvidia_key:
model_block = """model:
default: nvidia/nemotron-3-ultra-550b-a55b
provider: custom
base_url: https://integrate.api.nvidia.com/v1"""
else:
model_block = f"""model:
default: {OLLAMA_MODEL}
provider: custom
base_url: http://{OLLAMA_HOST}:{OLLAMA_PORT}/v1"""
if use_olhos_sse:
olhos_block = f""" olhos-de-orpheu:
url: "{OLHOS_SSE_URL}"
transport: "sse"
timeout: 120
connect_timeout: 10"""
else:
olhos_block = f""" olhos-de-orpheu:
command: "{VENV_PYTHON}"
args:
- "{OLHOS_DE_ORPHEU_STDIO}"
transport: "stdio"
timeout: 120
connect_timeout: 30"""
config = f"""# Hermes configuration for Portugal Futurista Aurelio × Hermes hackathon
# Single MCP gateway: Olhos-de-Orpheu (Proxmox CT 206)
{model_block}
providers: {{}}
fallback_providers: []
toolsets:
- hermes-cli
max_iterations: 90
quiet_mode: true
mcp_servers:
{olhos_block}
"""
CONFIG_PATH.write_text(config, encoding="utf-8")
print(f"Wrote {CONFIG_PATH}")
def verify_hermes():
result = subprocess.run(
[str(HERMES_BIN), "doctor"],
capture_output=True,
text=True,
)
print(result.stdout)
if result.returncode != 0:
print(result.stderr, file=sys.stderr)
sys.exit(1)
def main():
nvidia_key = os.getenv("NVIDIA_NIM_API_KEY") or os.getenv("NVIDIA_API_KEY")
stripe_key = os.getenv("STRIPE_SECRET_KEY")
if not nvidia_key:
print("WARNING: NVIDIA_NIM_API_KEY not set; Hermes will fall back to local Ollama.")
print("Get a free key at https://build.nvidia.com and re-run with NVIDIA_NIM_API_KEY set.")
print(f"Checking Olhos-de-Orpheu gateway at {OLHOS_SSE_URL}...")
use_olhos_sse = _url_reachable(OLHOS_SSE_URL)
if use_olhos_sse:
print("Gateway reachable — using SSE transport.")
else:
print("Gateway unreachable — falling back to local stdio wrapper.")
if not OLHOS_DE_ORPHEU_STDIO.exists():
print(f"ERROR: stdio wrapper not found at {OLHOS_DE_ORPHEU_STDIO}", file=sys.stderr)
sys.exit(1)
ensure_hermes_home()
write_env(nvidia_key, stripe_key)
write_config(nvidia_key, use_olhos_sse)
# Let Hermes migrate/expand the config with its current defaults
subprocess.run([str(HERMES_BIN), "doctor", "--fix"], check=False)
print("\nHermes configuration complete.")
print("Run: hermes doctor")
print("Then: hermes mcp list")
print("Then: hermes chat -q 'Aurelio, help the Alentejo cooperative recover the watermill and deploy a soil sensor.'")
if __name__ == "__main__":
main()