1780eed406
- Model override: qwen3.7-plus (4.5x meer requests/uur dan max) - Toolsets disabled bij model override (DeepSeek compat fix) - NoneType crash fix voor error paths - Originele qwen3.7-max blijft actief voor andere chats
148 lines
4.8 KiB
Python
148 lines
4.8 KiB
Python
"""
|
|
Hermes Client — directe Python import (geen subprocess overhead).
|
|
|
|
Warme agent: eenmalig initialiseren, daarna hergebruiken voor elke query.
|
|
Dit bespaart de subprocess + Python startup overhead van 2-5 seconden per query.
|
|
"""
|
|
import io
|
|
import os
|
|
import sys
|
|
import time
|
|
import logging
|
|
from contextlib import redirect_stdout, redirect_stderr
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
# ── Eenmalige Hermes imports (bij module laden) ──────────────────────
|
|
_HERMES_LOADED = False
|
|
_cli = None
|
|
|
|
# Model override voor relay (leeg = default uit config)
|
|
MODEL_OVERRIDE = "qwen3.7-plus"
|
|
|
|
|
|
def _ensure_hermes_loaded():
|
|
"""Laad Hermes eenmalig bij eerste gebruik — dit is het zware werk."""
|
|
global _HERMES_LOADED, _cli
|
|
if _HERMES_LOADED:
|
|
return
|
|
|
|
start = time.time()
|
|
|
|
# Zorg dat Hermes in de Python path zit
|
|
hermes_path = '/usr/local/lib/hermes-agent/venv/lib/python3.11/site-packages'
|
|
if hermes_path not in sys.path:
|
|
sys.path.insert(0, hermes_path)
|
|
|
|
# Force UTF-8
|
|
os.environ.setdefault('PYTHONIOENCODING', 'utf-8')
|
|
|
|
# Laad .env via Hermes' eigen loader
|
|
from hermes_cli.env_loader import load_hermes_dotenv
|
|
from hermes_constants import get_hermes_home
|
|
_hermes_home = get_hermes_home()
|
|
_project_env = os.path.join(os.path.dirname(hermes_path), '.env')
|
|
load_hermes_dotenv(hermes_home=_hermes_home, project_env=_project_env)
|
|
|
|
# Load config
|
|
from hermes_cli.config import load_config
|
|
config = load_config()
|
|
|
|
# Resolve toolsets (geen tools voor snelle relay)
|
|
from hermes_cli.tools_config import _get_platform_tools
|
|
if MODEL_OVERRIDE:
|
|
# Geen tools laden bij model override (DeepSeek heeft incompatible tool schema)
|
|
toolsets = []
|
|
else:
|
|
toolsets = sorted(_get_platform_tools(config, 'cli'))
|
|
|
|
# YOLO mode + interactive mode
|
|
os.environ['HERMES_YOLO_MODE'] = '1'
|
|
os.environ['HERMES_INTERACTIVE'] = '1'
|
|
os.environ['HERMES_SESSION_SOURCE'] = 'relay'
|
|
|
|
# Import HermesCLI
|
|
from cli import HermesCLI
|
|
|
|
# Maak CLI instantie (nog géén agent init — dat gebeurt pas bij eerste query)
|
|
_cli = HermesCLI(
|
|
model=config.get('model', {}).get('default', ''),
|
|
toolsets=toolsets,
|
|
)
|
|
# Onderdruk banner/status output
|
|
_cli.tool_progress_mode = 'off'
|
|
|
|
elapsed = time.time() - start
|
|
logger.info(
|
|
"Hermes loaded in %.2fs (toolsets: %s)",
|
|
elapsed, toolsets
|
|
)
|
|
_HERMES_LOADED = True
|
|
|
|
|
|
def call_hermes(prompt):
|
|
"""
|
|
Roep Hermes aan — hergebruikt een warme agent.
|
|
|
|
De agent wordt één keer geïnitialiseerd (bij eerste query) en daarna
|
|
hergebruikt. Na elke query wordt de conversation history gereset,
|
|
zodat elke query een frisse start krijgt.
|
|
"""
|
|
_ensure_hermes_loaded()
|
|
|
|
# Prefix (zoals /fast)
|
|
prefix = os.environ.get('HERMES_RELAY_PREFIX', '/fast')
|
|
full_prompt = (prefix + " " + prompt).strip() if prefix else prompt
|
|
|
|
start = time.time()
|
|
|
|
# ── Agent initialiseren met model override ──
|
|
turn_route = _cli._resolve_turn_agent_config(full_prompt)
|
|
|
|
# Override model als MODEL_OVERRIDE is ingesteld
|
|
model_override = MODEL_OVERRIDE if MODEL_OVERRIDE else turn_route['model']
|
|
|
|
if turn_route['signature'] != _cli._active_agent_route_signature:
|
|
_cli.agent = None
|
|
init_ok = _cli._init_agent(
|
|
model_override=model_override,
|
|
runtime_override=turn_route['runtime'],
|
|
request_overrides=turn_route.get('request_overrides'),
|
|
)
|
|
if not init_ok:
|
|
return "⚠️ Kon Hermes agent niet initialiseren."
|
|
|
|
# Stil modus
|
|
_cli.agent.quiet_mode = True
|
|
_cli.agent.suppress_status_output = True
|
|
_cli.agent.stream_delta_callback = None
|
|
_cli.agent.tool_gen_callback = None
|
|
|
|
# ── Query uitvoeren ──
|
|
# Capture alles wat naar stdout/stderr gaat (session_id, banner, etc.)
|
|
stdout_capture = io.StringIO()
|
|
stderr_capture = io.StringIO()
|
|
|
|
try:
|
|
with redirect_stdout(stdout_capture), redirect_stderr(stderr_capture):
|
|
# conversation_history wissen voor frisse start
|
|
_cli.agent.messages = []
|
|
result = _cli.agent.chat(full_prompt)
|
|
except SystemExit:
|
|
# Hermes roept sys.exit() aan in sommige error paths
|
|
logger.warning("Hermes riep sys.exit() aan tijdens query")
|
|
result = stdout_capture.getvalue().strip()
|
|
except Exception as e:
|
|
logger.error("Hermes error: %s", e, exc_info=True)
|
|
return "⚠️ Hermes error: " + str(e)
|
|
|
|
elapsed = time.time() - start
|
|
|
|
# Fallback als Hermes None teruggeeft (error path)
|
|
if result is None:
|
|
logger.warning("Hermes returned None — possible error during query")
|
|
return "⚠️ Geen antwoord van Hermes. Probeer opnieuw."
|
|
|
|
logger.info("Hermes responded in %.1fs (%d chars)", elapsed, len(result))
|
|
return result
|