Skip to content

fix(conversations): broadcast new chat to list live (#155)#348

Open
mgoldsborough wants to merge 1 commit into
mainfrom
fix/conversations-list-live-update-155
Open

fix(conversations): broadcast new chat to list live (#155)#348
mgoldsborough wants to merge 1 commit into
mainfrom
fix/conversations-list-live-update-155

Conversation

@mgoldsborough
Copy link
Copy Markdown
Contributor

Root cause

A brand-new conversation didn't appear in the Conversations list until the user refreshed or switched tabs (#155). The runtime emitted the new-conversation data.changed signal onto the per-request chat sink, which never reaches the /v1/events SSE channel that useDataSync consumes. This routes the emit through the runtime's default sink instead (the one api/server.ts wraps for /v1/events).

It fires twice for a new conversation:

  • right after the user message is persisted → conversation surfaces with its first-message-preview label
  • after auto-title generation settles → label flips to the generated title

No broadcast on resume (the pre-turn emit is guarded by if (!request.conversationId), and the title block only runs when conversation.title === null).

Hardening

  • FaultIsolatedSink wraps each sink in the defaultEvents fan-out so a logger throw can't abort the SSE broadcast fan-out.
  • AbortSignal.timeout in generateTitle hard-caps a hung fast-model call so the title block's .finally always fires (the list re-pull happens even if title generation/persist fails).
  • Removed a dead chat-stream data.changed branch in handlers.ts (nothing relays it).

Note

This is a rebased + reduced version of #255. The conversation-index pull-on-demand refactor from that PR is deferred to a separate follow-up — it needs mtime+size staleness handling, an ownership-gating caller audit, and a search/stats limit cap.

Test plan

  • bun run verify green for everything touching the changed files; the only red is a pre-existing 15s-timeout flake in body-limit-routes.test.ts (a multipart-upload HTTP test) that reproduces identically on clean origin/main and is unrelated to this change.
  • test/integration/runtime/chat-start-event.test.ts asserts the new-conversation data.changed reaches the default (SSE-bound) sink and that resume does not broadcast (12 pass, 0 fail in isolation).

Closes #155

A brand-new conversation did not appear in the Conversations list until
the user refreshed or switched tabs (#155). The runtime emitted the
data.changed signal onto the per-request chat sink, which never reaches
the /v1/events SSE channel that useDataSync consumes. Route the emit
through the runtime's default sink (the one api/server.ts wraps for
/v1/events). Fire once right after the user message is persisted so the
conversation surfaces with its first-message preview as the label, and
once more after auto-title generation settles so the label flips to the
generated title.

Two adjacent issues surfaced during investigation and are filed
separately:

  - #253: auto-generated titles often contain assistant response content
          instead of a short summary (pre-existing prompt-shape bug)
  - #254: mid-turn conversation switch bleeds the streaming response
          into the destination chat (pre-existing client-side state
          contamination)

Supporting hardening in this commit, in service of the broadcast both
reaching its destination and surviving along the way:

  - FaultIsolatedSink wraps each sink in the defaultEvents fan-out so
    a logger throw can't abort the SSE-broadcast wrap downstream.
    Engine-time sink chain stays loud.
  - generateTitle uses AbortSignal.timeout to hard-cap a hung fast-model
    call so the title-block .finally always fires.
  - Dead chat-stream data.changed branch removed from handlers.ts
    (nothing relays it now; confirmed via grep).

Closes #155

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

New chats do not appear in Conversations list until refresh or tab switch

2 participants