fix: pass api_key to AIAgent for non-Anthropic /anthropic providers

When the user's config uses a non-Anthropic provider with an
Anthropic-compatible endpoint (e.g. MiniMax at
https://api.minimax.io/anthropic), chat in the WebUI fails silently
with APIConnectionError on every request, while the hermes CLI and
messaging gateway work fine with the same config.

Root cause: both api/routes.py and api/streaming.py constructed
AIAgent using only (model, provider, base_url) from
resolve_model_provider() and never passed api_key. When the base URL
ends in /anthropic, AIAgent uses the anthropic_messages adapter, but
only falls back to ANTHROPIC_TOKEN when provider == "anthropic" (a
safety check to avoid leaking Anthropic credentials to third parties).
For MiniMax and similar providers the effective key becomes "", and
the auth failure surfaces as a generic "Connection error" after three
retries.

The CLI and gateway resolve the key via
hermes_cli.runtime_provider.resolve_runtime_provider(), which reads
MINIMAX_API_KEY (and similar) from ~/.hermes/.env. This patch does the
same before creating the AIAgent in both chat paths.

Fixes #77
This commit is contained in:
Carly 2.0
2026-04-04 15:03:02 -05:00
parent 33fca2383c
commit cc6709c9d5
2 changed files with 28 additions and 1 deletions

View File

@@ -888,8 +888,21 @@ def _handle_chat_sync(handler, body):
with CHAT_LOCK:
from api.config import resolve_model_provider
_model, _provider, _base_url = resolve_model_provider(s.model)
# Resolve API key via Hermes runtime provider (matches gateway behaviour)
_api_key = None
try:
from hermes_cli.runtime_provider import resolve_runtime_provider
_rt = resolve_runtime_provider()
_api_key = _rt.get("api_key")
# Also use runtime provider/base_url if the webui config didn't resolve them
if not _provider:
_provider = _rt.get("provider")
if not _base_url:
_base_url = _rt.get("base_url")
except Exception as _e:
print(f"[webui] WARNING: resolve_runtime_provider failed: {_e}", flush=True)
agent = AIAgent(model=_model, provider=_provider, base_url=_base_url,
platform='cli', quiet_mode=True,
api_key=_api_key, platform='cli', quiet_mode=True,
enabled_toolsets=CLI_TOOLSETS, session_id=s.session_id)
workspace_ctx = f"[Workspace: {s.workspace}]\n"
workspace_system_msg = (

View File

@@ -113,6 +113,19 @@ def _run_agent_streaming(session_id, msg_text, model, workspace, stream_id, atta
raise ImportError("AIAgent not available -- check that hermes-agent is on sys.path")
resolved_model, resolved_provider, resolved_base_url = resolve_model_provider(model)
# Resolve API key via Hermes runtime provider (matches gateway behaviour)
resolved_api_key = None
try:
from hermes_cli.runtime_provider import resolve_runtime_provider
_rt = resolve_runtime_provider()
resolved_api_key = _rt.get("api_key")
if not resolved_provider:
resolved_provider = _rt.get("provider")
if not resolved_base_url:
resolved_base_url = _rt.get("base_url")
except Exception as _e:
print(f"[webui] WARNING: resolve_runtime_provider failed: {_e}", flush=True)
# Read per-profile config at call time (not module-level snapshot)
from api.config import get_config as _get_config
_cfg = _get_config()
@@ -140,6 +153,7 @@ def _run_agent_streaming(session_id, msg_text, model, workspace, stream_id, atta
model=resolved_model,
provider=resolved_provider,
base_url=resolved_base_url,
api_key=resolved_api_key,
platform='cli',
quiet_mode=True,
enabled_toolsets=_toolsets,