molecule-core/workspace-template/adapters/hermes/adapter.py
Dev Lead Agent 08fe37aee1 feat: implement Hermes adapter create_executor() with OpenRouter fallback
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-13 16:47:29 -07:00

65 lines
2.1 KiB
Python

"""Hermes adapter — Nous Research Hermes models via Nous Portal or OpenRouter.
Uses the OpenAI-compatible client (openai>=1.0.0) to communicate with
either the Nous Portal directly (HERMES_API_KEY) or OpenRouter as a
fallback (OPENROUTER_API_KEY).
"""
import os
from adapters.base import BaseAdapter, AdapterConfig
class HermesAdapter(BaseAdapter):
@staticmethod
def name() -> str:
return "hermes"
@staticmethod
def display_name() -> str:
return "Hermes (Nous Research)"
@staticmethod
def description() -> str:
return "Hermes models via Nous Portal or OpenRouter — openai>=1.0.0 compatible client"
@staticmethod
def get_config_schema() -> dict:
return {
"model": {
"type": "string",
"description": (
"Hermes model ID (e.g. nousresearch/hermes-3-llama-3.1-405b for OpenRouter "
"or hermes-3-llama-3.1-405b for Nous Portal)"
),
},
}
async def setup(self, config: AdapterConfig) -> None: # pragma: no cover
try:
import openai # noqa: F401
except ImportError as e:
raise RuntimeError(
"Hermes adapter requires openai>=1.0.0 — "
"install with: pip install 'openai>=1.0.0'"
) from e
async def create_executor(self, config: AdapterConfig): # pragma: no cover
"""Create and return a HermesA2AExecutor using key resolution from env/config."""
from .executor import create_executor, HermesA2AExecutor
# Resolve API key: prefer workspace secrets (runtime_config), then env vars
hermes_api_key = config.runtime_config.get("hermes_api_key") or None
executor = create_executor(hermes_api_key=hermes_api_key)
# Override model from config if provided
model = config.model
if ":" in model:
_, model = model.split(":", 1)
if model:
executor.model = model
executor._heartbeat = config.heartbeat
return executor