Add connectivity tests and fix Hermes handle + venv setup
- test_connectivity.py: connectivity tests for all four endpoint types (anthropic, openai, lm_studio, hermes, agent0) — treats no-credits as success - test_hermes.py: raw WebSocket frame logger used to reverse-engineer protocol - Fix handle_hermes: skip prompt.submit ack frame, read full text from message.complete payload.text, always raise on status==error - Fix requirements.txt: use >= pins (fastapi/uvicorn versions didn't exist) - Fix dev.sh: prefer python3.12 for venv (mcp>=1.9.0 requires 3.10+) - Remove ANTHROPIC_KEY env var dependency from server.py (keys come from DB) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -451,21 +451,43 @@ async def handle_hermes(
|
||||
log.info(f"[{agent.name}] created Hermes session {hermes_session_id}")
|
||||
|
||||
# ── 2. Submit prompt ──────────────────────────────────────────
|
||||
await rpc("prompt.submit", {"session_id": hermes_session_id, "text": req.message})
|
||||
# Send prompt.submit but do NOT wait for its ack via rpc() —
|
||||
# the ack arrives interleaved with events (after message.start).
|
||||
# We drain all frames below until message.complete arrives.
|
||||
submit_id = f"h{req_id + 1}"
|
||||
req_id += 1
|
||||
await ws.send(json.dumps({
|
||||
"jsonrpc": "2.0", "id": submit_id,
|
||||
"method": "prompt.submit",
|
||||
"params": {"session_id": hermes_session_id, "text": req.message},
|
||||
}))
|
||||
|
||||
# ── 3. Stream events until message.complete ───────────────────
|
||||
full_text = ""
|
||||
while True:
|
||||
raw = await asyncio.wait_for(ws.recv(), timeout=120.0)
|
||||
msg = json.loads(raw)
|
||||
|
||||
# RPC ack for prompt.submit — ignore, keep reading
|
||||
if msg.get("id") == submit_id:
|
||||
continue
|
||||
|
||||
if msg.get("method") != "event":
|
||||
continue
|
||||
|
||||
params = msg.get("params") or {}
|
||||
etype = params.get("type", "")
|
||||
payload = params.get("payload") or {}
|
||||
|
||||
if etype == "message.delta":
|
||||
full_text += payload.get("text", "")
|
||||
elif etype == "message.complete":
|
||||
# payload.text holds the full assembled response
|
||||
complete_text = payload.get("text", "")
|
||||
if complete_text:
|
||||
full_text = complete_text
|
||||
if payload.get("status") == "error":
|
||||
raise RuntimeError(full_text or "Hermes returned an error response")
|
||||
break
|
||||
elif etype == "error":
|
||||
raise RuntimeError(payload.get("message", "Hermes error"))
|
||||
|
||||
Reference in New Issue
Block a user