From 9788abb8ce64257e6053ed13189f5f71af8e9750 Mon Sep 17 00:00:00 2001 From: Shawn Date: Mon, 1 Jun 2026 23:53:39 -0400 Subject: [PATCH] feat: Agent Chat API backend - profiles, send, history - GET /api/agents - list known profiles with online/offline status - POST /api/agents/{profile}/send - send message via Hermes CLI subprocess - GET /api/agents/{profile}/history - retrieve conversation history - SQLite conversation store at ~/.hermes/kanban/boards/hermes-command-center/conversations.db - Response cleanup to strip Hermes CLI wrapper formatting - Auth-gated via existing Basic Auth middleware --- server.py | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/server.py b/server.py index e1d273c..dd9f7f6 100644 --- a/server.py +++ b/server.py @@ -143,6 +143,42 @@ def _get_conversation_history(profile: str, limit: int = 50) -> list[dict]: conn.close() +def _clean_agent_response(text: str) -> str: + """Extract just the agent's reply from Hermes CLI wrapper output.""" + lines = text.splitlines() + result_lines = [] + in_box = False + for line in lines: + stripped = line.strip() + if stripped.startswith("Query:") or stripped.startswith("Initializing"): + continue + if stripped.startswith("╭─"): + in_box = True + continue + if stripped.startswith("╰─"): + in_box = False + continue + if in_box: + result_lines.append(stripped) + if stripped.startswith("Resume this session") \ + or stripped.startswith("Session:") \ + or stripped.startswith("Duration:") \ + or stripped.startswith("Messages:"): + break + cleaned = "\n".join(result_lines).strip() + if cleaned: + return cleaned + if "╰─" in text: + parts = text.split("╰─") + before = parts[0] + if "╭─" in before: + for line in before.split("╭─", 1)[1].splitlines(): + s = line.strip() + if s: + return s + return "" + + _init_conversations_db() app = FastAPI(title="Hermes Command Center") @@ -729,6 +765,11 @@ async def agent_send(profile: str, request: Request): if not response_text: response_text = "(no response)" + # Clean up CLI wrapper text — extract the actual agent response + cleaned = _clean_agent_response(response_text) + if cleaned: + response_text = cleaned + # Save agent response _save_message(profile, "agent", response_text)