Phase 7: Agent Selector — per-agent soul.md + ChromaDB memory filtering

- Agent dropdown UI (chip button + hidden select) in composer header
- Session.agent field persists agent selection across refresh
- soul.md loaded per-agent via ephemeral_system_prompt injection
- ChromaDB memory filtered by agent topic (lotus/, sunflower/, etc.)
- Fixed streaming.py: agent→_ai_agent variable shadowing (lines 1161, 1163)
- New API endpoints: /api/agents/topology, /api/agents/memory/search
- Agent metadata registry with emoji, name, description per Tier-2 agent
This commit is contained in:
Rose
2026-04-20 17:34:58 +02:00
parent 00045314f8
commit c705fad626
14 changed files with 2578 additions and 320 deletions

View File

@@ -16,7 +16,7 @@ logger = logging.getLogger(__name__)
from api.auth import check_auth
from api.config import HOST, PORT, STATE_DIR, SESSION_DIR, DEFAULT_WORKSPACE
from api.helpers import j
from api.routes import handle_get, handle_post
from api.routes import handle_get, handle_post, handle_put, handle_delete
from api.startup import auto_install_agent_deps, fix_credential_permissions
@@ -84,6 +84,30 @@ class Handler(BaseHTTPRequestHandler):
print(f'[webui] ERROR {self.command} {self.path}\n' + traceback.format_exc(), flush=True)
return j(self, {'error': 'Internal server error'}, status=500)
def do_PUT(self) -> None:
self._req_t0 = time.time()
try:
parsed = urlparse(self.path)
if not check_auth(self, parsed): return
result = handle_put(self, parsed)
if result is False:
return j(self, {'error': 'not found'}, status=404)
except Exception as e:
print(f'[webui] ERROR {self.command} {self.path}\n' + traceback.format_exc(), flush=True)
return j(self, {'error': 'Internal server error'}, status=500)
def do_DELETE(self) -> None:
self._req_t0 = time.time()
try:
parsed = urlparse(self.path)
if not check_auth(self, parsed): return
result = handle_delete(self, parsed)
if result is False:
return j(self, {'error': 'not found'}, status=404)
except Exception as e:
print(f'[webui] ERROR {self.command} {self.path}\n' + traceback.format_exc(), flush=True)
return j(self, {'error': 'Internal server error'}, status=500)
def main() -> None:
# Load ~/.hermes/.env into os.environ so API keys are available