fix(examples-chat): use get_stream_writer (not adispatch_custom_event)#268
Merged
Conversation
PR #266 fixed the on_llm_new_token signature, after which live diagnostics confirmed the handler ran per token and adispatch_custom_event completed successfully — yet the SSE stream still carried zero a2ui-partial events. Root cause: adispatch_custom_event (langchain_core) and stream_mode= 'custom' (LangGraph) are different layers. langchain_core dispatches visible via stream_mode='events'; LangGraph's 'custom' channel is fed by get_stream_writer() returned from langgraph.config. The transport already requests stream_mode='custom', but the handler was writing to the wrong sink. Fix: replace adispatch_custom_event with get_stream_writer(). The writer is contextvar-scoped to the currently-executing LangGraph node and is inherited by nested callbacks, so the handler can call it from inside the LLM's callback chain. The payload shape is {name, data} so the existing transport-side parser (stream-manager.bridge.ts:509) extracts name + data correctly. Tests updated to mock get_stream_writer (instead of adispatch_custom_event) and assert on writer.call_args. Adds a new test asserting graceful behavior when invoked outside a stream context (writer raises RuntimeError; handler swallows). Live smoke now confirms 758 a2ui-partial events on the wire across a 2.5MB SSE stream for a dashboard prompt. The bridge consumes all events into agent.customEvents() and forwards them to the partial-args bridge. Note: a follow-up frontend issue remains in the partial-args bridge's incremental dispatch logic — early surfaceUpdate envelopes dispatch with incomplete components arrays (no ids yet), preventing beginRendering synthesis, and the dispatchedCount counter then skips re-attempt. Tracking separately.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
3 tasks
blove
added a commit
that referenced
this pull request
May 12, 2026
…rk (#271) Brings the canonical smoke checklist current with 29 PRs that landed between Phase 7 (#239) and today without checklist updates. Specifically: Updated sections: - chat-debug devtools — replaced bottom-drawer model with floating launcher + status pill + switch (PRs #249, #251) - Control palette — palette v2 (status pill, shadcn-styled panel, PR #244) - Generative UI / A2UI surfaces — single-bubble invariant (PR #255), parent-emits-envelopes architecture (PR #259), wrapped-content + tool_calls coexistence (PR #255), envelope reorder - Server-side wire format — tool_calls preserved on the final AI - Replaced 'Multi-thread' section with 'Sidenav (thread management)' reflecting the permanent semantic <nav> + Active/Archived sections (PR #253) and removing the old palette-toggled drawer model Added sections: - Cmd+K history search — palette open/search/select/close, archived result subtitle, keyboard navigation (PR #253) - Per-row thread actions — kebab menu order per state (active, pinned, archived), rename + pin/unpin + archive/unarchive + delete flows (PRs #258, #260, #267) - Thread titles — first-user-message derivation, idempotent writes, manual rename precedence (PR #242) - Progressive A2UI streaming — per-component fallback transition observable during streaming window (PRs #252, #261, #262, #268, #269) - Inline checkpoint markers — render between messages during multi-step runs (PR #243) - Responsive sidenav — viewport breakpoints, auto-collapse behavior (PR #240) Total: ~58 new check items across 6 new sections, plus rewrites to 5 existing sections. Original 333-line checklist → 391 lines / 237 check items.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
PR #266 fixed the `on_llm_new_token` signature, after which live diagnostics confirmed the handler runs per token and `adispatch_custom_event` completes successfully — yet the SSE stream still carried zero `a2ui-partial` events.
Root cause
`adispatch_custom_event` (langchain_core) and `stream_mode='custom'` (LangGraph) are different layers:
The transport already requests `stream_mode='custom'`, but the handler was writing to the wrong sink.
Fix
Replace `adispatch_custom_event` with `get_stream_writer()`. The writer is contextvar-scoped to the currently-executing LangGraph node and inherited by nested callbacks, so the handler can call it from inside the LLM's callback chain. Payload shape `{name, data}` matches what `stream-manager.bridge.ts:509` already expects.
Tests
Live smoke
`a2uiPartialEvents: 758` across a 2.5 MB SSE stream for a dashboard prompt. `agent.customEvents()` now populates with all 758 events.
Known follow-up
A frontend partial-args-bridge bug remains: early surfaceUpdate envelopes dispatch with incomplete `components` arrays (ids not yet streamed), so `pickRoot` returns null and synthesis is skipped. Subsequent pushes then skip the surfaceUpdate envelope because `dispatchedCount` already advanced. Live `liveSurfaceStore` stays empty even though events flow correctly. Tracking separately — out of scope for this PR.
Test plan