Phase 4-6: Message Bus, Memory Search (ChromaDB), Token Tracking, Topology Graph
Phase 4: Message Bus Viewer
- Backend: get_message_bus_status(), send_bus_message() in agents.py
- Route: GET /api/agents/message-bus, POST /api/agents/{id}/bus-message
- Frontend: Message Bus tab in agent detail overlay
Phase 5: Memory Search (ChromaDB)
- Backend: _search_agent_memory(), _search_all_agents_memory() via ChromaDB rose_memory collection
- Route: GET /api/agents/memory/search, GET /api/agents/{id}/memory/search
- Frontend: Search bar added to Memory tab, renders confidence scores + topics
Phase 6: Token Tracking + Topology Graph
- Backend: get_agent_usage() reads ~/.hermes/agents/{id}/usage.json
- Route: GET /api/agents/{id}/usage
- Frontend: Usage tab with today/week/month token counts and cost
- Frontend: Topology tab with SVG radial graph of agent network
This commit is contained in:
@@ -859,6 +859,13 @@ def handle_get(handler, parsed) -> bool:
|
||||
limit = int(parse_qs(parsed.query).get("limit", ["20"])[0])
|
||||
return j(handler, _agents.get_agent_errors(agent_id, limit=limit))
|
||||
|
||||
# GET /api/agents/{id}/usage
|
||||
if parsed.path.startswith("/api/agents/") and "/usage" in parsed.path:
|
||||
parts = parsed.path.split("/")
|
||||
if len(parts) == 5 and parts[4] == "usage":
|
||||
agent_id = parts[3]
|
||||
return j(handler, _agents.get_agent_usage(agent_id))
|
||||
|
||||
# GET /api/agents/{id}/chat-history
|
||||
if parsed.path.startswith("/api/agents/") and "/chat-history" in parsed.path:
|
||||
parts = parsed.path.split("/")
|
||||
@@ -881,6 +888,38 @@ def handle_get(handler, parsed) -> bool:
|
||||
agent_id = parts[3]
|
||||
return j(handler, _agents.get_agent_tasks(agent_id))
|
||||
|
||||
# GET /api/agents/message-bus — all inboxes at once
|
||||
if parsed.path == "/api/agents/message-bus":
|
||||
return j(handler, _agents.get_message_bus_status())
|
||||
|
||||
# POST /api/agents/{id}/bus-message — send message to agent via bus
|
||||
if parsed.path.startswith("/api/agents/") and "/bus-message" in parsed.path:
|
||||
parts = parsed.path.split("/")
|
||||
if len(parts) == 5 and parts[4] == "bus-message":
|
||||
agent_id = parts[3]
|
||||
data = read_body(handler)
|
||||
result = _agents.send_bus_message(
|
||||
to_agent=agent_id,
|
||||
from_agent=data.get("from_agent", "rose"),
|
||||
subject=data.get("subject", ""),
|
||||
content=data.get("content", ""),
|
||||
msg_type=data.get("type", "request"),
|
||||
)
|
||||
return j(handler, result)
|
||||
|
||||
# GET /api/agents/memory/search?q= — search all agents
|
||||
if parsed.path == "/api/agents/memory/search":
|
||||
return _handle_memory_search(handler, parsed, agent_id=None)
|
||||
|
||||
# GET /api/agents/{id}/memory/search?q= — search specific agent
|
||||
_mem_match = None
|
||||
if parsed.path.startswith("/api/agents/") and "/memory/search" in parsed.path:
|
||||
parts = parsed.path.split("/")
|
||||
if len(parts) == 6 and parts[5] == "search":
|
||||
_mem_match = parts[3]
|
||||
if _mem_match:
|
||||
return _handle_memory_search(handler, parsed, agent_id=_mem_match)
|
||||
|
||||
# ── Profile API (GET) ──
|
||||
if parsed.path == "/api/profiles":
|
||||
from api.profiles import list_profiles_api, get_active_profile_name
|
||||
@@ -3350,3 +3389,25 @@ def _handle_logs_read(handler, log_name):
|
||||
"line_count": len(lines),
|
||||
"tail_count": len(tail),
|
||||
})
|
||||
|
||||
|
||||
# ── Memory Search ─────────────────────────────────────────────────────────────
|
||||
|
||||
def _handle_memory_search(handler, parsed, agent_id=None) -> bytes:
|
||||
"""
|
||||
GET /api/agents/memory/search?q=query — all agents
|
||||
GET /api/agents/{id}/memory/search?q=query — specific agent
|
||||
"""
|
||||
try:
|
||||
qs = parse_qs(parsed.query)
|
||||
query = " ".join(qs.get("q", [""])).strip()
|
||||
limit = int(" ".join(qs.get("limit", ["20"])).strip())
|
||||
if not query:
|
||||
return bad(handler, "q parameter required")
|
||||
if agent_id:
|
||||
results = _agents._search_agent_memory(agent_id, query, limit=limit)
|
||||
else:
|
||||
results = _agents._search_all_agents_memory(query, limit=limit)
|
||||
return j(handler, {"query": query, "results": results, "count": len(results)})
|
||||
except Exception as e:
|
||||
return bad(handler, str(e))
|
||||
|
||||
Reference in New Issue
Block a user