Files
vibn-frontend/app
Mark Henderson 3d1a0e00c7 fix(chat): render multi-round assistant turns as separate bubbles
Smoke test surfaced a UX bug: when the model fired multiple tool
rounds with interleaved text, the client concatenated every text
SSE event into one growing assistantContent string and rendered it
as a single chat bubble. Result: 'now.Spinning up...first boot...
The dev container is ready!' — three distinct narrative beats
mashed into one wall of run-on text with no visual breaks.

Server (app/api/chat/route.ts):
- Added assistantTextSegments[] alongside the legacy assistantText.
  Each non-empty resp.text per round pushes one segment.
- assistantText is still produced (joined with blank lines) for
  backward compat — old consumers still get a single-string content.
- finalMsg now persists textSegments[] so reloaded threads can
  reconstruct per-round segmentation.
- Stop-marker / round-cap recovery / loop-break paths all push to
  segments AND content, with the leading '\n\n' stripped from the
  segment form so bubble joins look clean.

Client (components/vibn-chat/chat-panel.tsx):
- TimelineEntry gains a 'text' kind.
- text SSE events push a new TimelineEntry instead of growing a
  single content string. Subsequent tool/thought events land in
  between, so the renderer naturally groups text-tools-text-tools.
- New TimelineText component renders each segment as its own bubble
  inline with thoughts and tool pills.
- MessageBubble's bottom content slot is now skipped for assistant
  messages whose timeline has any text entries, so we don't
  duplicate the prose below the timeline.
- loadThread() rehydrates timeline from persisted textSegments +
  toolCalls so reload preserves bubble segmentation.

Backwards compat: messages without textSegments fall through to the
old single-bubble content rendering — no migration needed for
existing chat history.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-04 10:44:27 -07:00
..
2026-02-15 19:25:52 -08:00