feat(web): wire WebSocket chat with streaming and conversation switching (#120) #136

Merged
jason.woltje merged 2 commits from feat/p7-009-web-chat-ws into main 2026-03-15 18:09:15 +00:00
Owner

Summary

  • Fix socket singleton lifecycle: add and auto-reset on disconnect so page remounts always get a fresh authenticated connection
  • Add explicit WebSocket transport preference () to avoid polling fallback
  • Filter socket events by to prevent cross-conversation event bleed when switching conversations mid-stream
  • Use pattern so event handlers see current without stale closures or listener re-registration on every render
  • On , append accumulated streaming text as assistant message to local state (matching TUI approach; Pi session is in-memory so DB reload would miss the assistant response)
  • Preserve REST persist of user messages for conversation history on page reload
  • Clear streaming state on conversation switch
  • Fix : show animated typing indicator before first token arrives (previously returned when text was empty)
  • Fix : exclude worktree auto-generated docs from format check (pre-push hook blocker)

Test plan

  • Login to web UI and navigate to /chat
  • Create a new conversation via '+ New' or the Start button
  • Send a message — verify user message appears immediately, streaming indicator shows, assistant response streams in and is appended on completion
  • Switch between conversations — verify streaming state clears, messages load correctly for each conversation
  • Send message without selecting a conversation — verify auto-creation works
  • Verify no duplicate messages or stale events from previous conversations

Closes #120

🤖 Generated with Claude Code

## Summary - Fix socket singleton lifecycle: add and auto-reset on disconnect so page remounts always get a fresh authenticated connection - Add explicit WebSocket transport preference () to avoid polling fallback - Filter socket events by to prevent cross-conversation event bleed when switching conversations mid-stream - Use pattern so event handlers see current without stale closures or listener re-registration on every render - On , append accumulated streaming text as assistant message to local state (matching TUI approach; Pi session is in-memory so DB reload would miss the assistant response) - Preserve REST persist of user messages for conversation history on page reload - Clear streaming state on conversation switch - Fix : show animated typing indicator before first token arrives (previously returned when text was empty) - Fix : exclude worktree auto-generated docs from format check (pre-push hook blocker) ## Test plan - [ ] Login to web UI and navigate to /chat - [ ] Create a new conversation via '+ New' or the Start button - [ ] Send a message — verify user message appears immediately, streaming indicator shows, assistant response streams in and is appended on completion - [ ] Switch between conversations — verify streaming state clears, messages load correctly for each conversation - [ ] Send message without selecting a conversation — verify auto-creation works - [ ] Verify no duplicate messages or stale events from previous conversations Closes #120 🤖 Generated with Claude Code
jason.woltje added 2 commits 2026-03-15 17:57:39 +00:00
- Fix socket singleton lifecycle: add destroySocket() and auto-reset on disconnect
  so page remounts always get a fresh authenticated connection
- Add explicit WebSocket transport preference to avoid polling fallback
- Filter socket events by conversationId to prevent cross-conversation bleed
  when switching between conversations mid-stream
- Use activeIdRef pattern so event handlers see current activeId without
  stale closures or listener re-registration on every render
- On agent:end, append accumulated text as assistant message to local state
  (matching TUI pattern; Pi session is in-memory so DB reload would miss it)
- Preserve REST persist of user messages for conversation history on reload
- Clear streaming state on conversation switch
- StreamingMessage: show animated typing indicator before first token arrives

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
chore: exclude .claude/ worktree docs from Prettier formatting check
All checks were successful
ci/woodpecker/push/ci Pipeline was successful
d468e248c2
The .claude/worktrees/ directory contains auto-generated markdown reports
from the QA automation system that are not authored code and should not
be subject to Prettier style enforcement.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
jason.woltje merged commit d0999a8e37 into main 2026-03-15 18:09:15 +00:00
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: mosaicstack/stack#136