diff --git a/src/agentkit/server/routes/portal.py b/src/agentkit/server/routes/portal.py index f146d8c..dd3378d 100644 --- a/src/agentkit/server/routes/portal.py +++ b/src/agentkit/server/routes/portal.py @@ -14,6 +14,11 @@ from pydantic import BaseModel from agentkit.core.protocol import TaskMessage from agentkit.core.react import ReActEngine from agentkit.router.intent import IntentRouter +from agentkit.server.routes.evolution_dashboard import ( + _experiences as _dashboard_experiences, + DashboardExperience, + _broadcast_event as _broadcast_dashboard_event, +) logger = logging.getLogger(__name__) @@ -520,6 +525,29 @@ async def portal_websocket(websocket: WebSocket): # Add user message to conversation _conversation_store.add_message(conv.id, "user", message_text) + start_time = datetime.now(timezone.utc) + + async def _record_experience( + task_type: str, goal: str, outcome: str, duration_seconds: float + ) -> None: + """Record experience to dashboard after chat completion.""" + try: + exp = DashboardExperience( + id=str(uuid.uuid4()), + task_type=task_type, + goal=goal[:200], + outcome=outcome, + duration_seconds=duration_seconds, + created_at=datetime.now(timezone.utc), + ) + _dashboard_experiences.append(exp) + await _broadcast_dashboard_event("experience_added", { + "id": exp.id, "task_type": exp.task_type, + "goal": exp.goal, "outcome": exp.outcome, + }) + await _broadcast_dashboard_event("metrics_updated", {"period": "7d"}) + except Exception as e: + logger.warning(f"Failed to record experience: {e}") # Unified routing via CostAwareRouter (handles Layer 0/1/2) pool = websocket.app.state.agent_pool @@ -588,6 +616,7 @@ async def portal_websocket(websocket: WebSocket): "type": "result", "data": {"status": "completed", "content": response.content}, }) + await _record_experience("chat", message_text, "success", (datetime.now(timezone.utc) - start_time).total_seconds()) continue # General path: agent execution @@ -614,6 +643,7 @@ async def portal_websocket(websocket: WebSocket): "type": "result", "data": {"status": "completed", "content": response.content}, }) + await _record_experience("chat", message_text, "success", (datetime.now(timezone.utc) - start_time).total_seconds()) continue agent = await pool.create_agent_from_skill(agent_name) @@ -675,9 +705,14 @@ async def portal_websocket(websocket: WebSocket): if response_text: _conversation_store.add_message(conv.id, "assistant", response_text) + outcome = "success" if response_text else "failure" await websocket.send_json( {"type": "result", "data": {"message": response_text}} ) + await _record_experience( + routing_result.skill_name or "agent", message_text, + outcome, (datetime.now(timezone.utc) - start_time).total_seconds(), + ) except WebSocketDisconnect: logger.debug(f"Portal WebSocket disconnected for conversation {conv.id if conv else 'N/A'}")