From 2e92838033c96b6dd125deb2ef64f6d504cc76f4 Mon Sep 17 00:00:00 2001 From: Alexander Whitestone <8633216+AlexanderWhitestone@users.noreply.github.com> Date: Sat, 28 Feb 2026 20:22:47 -0500 Subject: [PATCH] fix: restore real-time chat responses via WebSocket (#98) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The chat WebSocket return path was broken by two bugs that prevented Timmy's responses from appearing in the live chat feed: 1. Frontend checked msg.type instead of msg.event for 'timmy_response' events — the WSEvent dataclass uses 'event' as the field name. 2. Frontend accessed msg.response instead of msg.data.response — the response payload is nested in the data field. Additional fixes: - Queue acknowledgment ("Message queued...") no longer logged as an agent message in chat history; the real response is logged by the task processor when it completes, eliminating duplicate messages. - Chat message template now carries data-task-id so the WS handler can find and replace the placeholder with the actual response. - appendMessage() uses DOM APIs (textContent) instead of innerHTML for safer content insertion before markdown rendering. - Fixed chat_message.html script targeting when queue-status div is present between the agent message and the inline script. https://claude.ai/code/session_011cJfexqBBuGhSRQU8qwKcR Co-authored-by: Claude --- src/dashboard/app.py | 9 ++++ src/dashboard/routes/agents.py | 11 ++-- .../templates/partials/chat_message.html | 8 ++- .../templates/partials/timmy_panel.html | 50 ++++++++++++++++--- tests/dashboard/test_dashboard.py | 9 ++-- 5 files changed, 68 insertions(+), 19 deletions(-) diff --git a/src/dashboard/app.py b/src/dashboard/app.py index b007ef64..0eb083c9 100644 --- a/src/dashboard/app.py +++ b/src/dashboard/app.py @@ -176,6 +176,15 @@ async def _task_processor_loop() -> None: context = f"[System: Current date/time is {now.strftime('%A, %B %d, %Y at %I:%M %p')}]\n\n" response = timmy_chat(context + task.description) + # Log the real agent response to chat history + try: + from dashboard.store import message_log + timestamp = now.strftime("%H:%M:%S") + message_log.append(role="agent", content=response, timestamp=timestamp) + except Exception as e: + logger.debug("Failed to log response to message_log: %s", e) + + # Push response to chat UI via WebSocket try: from infrastructure.ws_manager.handler import ws_manager asyncio.create_task( diff --git a/src/dashboard/routes/agents.py b/src/dashboard/routes/agents.py index fad0a7d4..7988bd23 100644 --- a/src/dashboard/routes/agents.py +++ b/src/dashboard/routes/agents.py @@ -316,13 +316,16 @@ async def chat_timmy(request: Request, message: str = Form(...)): logger.error("Failed to queue chat message: %s", exc) error_text = f"Failed to queue message: {exc}" - # Log to message history (for context, even though async) + # Log user message to history. For chat_response tasks the real agent + # reply is logged by the task processor when it completes, so we only + # log the queue acknowledgment for explicit task_request commands. message_log.append(role="user", content=message, timestamp=timestamp) - if response_text is not None: + if task_info and response_text is not None: + # Explicit task queue command — the acknowledgment IS the response message_log.append(role="agent", content=response_text, timestamp=timestamp) - else: + elif error_text: message_log.append( - role="error", content=error_text or "Unknown error", timestamp=timestamp + role="error", content=error_text, timestamp=timestamp ) return templates.TemplateResponse( diff --git a/src/dashboard/templates/partials/chat_message.html b/src/dashboard/templates/partials/chat_message.html index 54a8a0eb..b52f5e5d 100644 --- a/src/dashboard/templates/partials/chat_message.html +++ b/src/dashboard/templates/partials/chat_message.html @@ -3,7 +3,7 @@
{{ user_message | e }}
{% if response %} -
+
TIMMY // {{ timestamp }}
{{ response | e }}
@@ -14,7 +14,11 @@ {% endif %}