fix(gateway): accept delta-only assistant events for live chat projection#83038
fix(gateway): accept delta-only assistant events for live chat projection#83038jackjin1997 wants to merge 1 commit into
Conversation
…tion Both gateway/server-chat and tui/embedded-backend gated chat projection on a cumulative data.text string, dropping canonical assistant events that only carry an incremental data.delta. Live UIs lost working/streaming state between run start and final response. Add hasLiveAssistantContent helper so the gate accepts either text or delta. emitChatDelta already handles delta-only inputs via resolveMergedAssistantText. Fixes openclaw#82988
|
Codex review: needs maintainer review before merge. Summary Reproducibility: yes. source-level reproduction is high confidence: current main requires Real behavior proof Next step before merge Security Review detailsBest possible solution: Land the focused gate normalization with regression coverage once the normal CI and maintainer merge checks pass, preserving the existing SDK contract for delta-only assistant chunks. Do we have a high-confidence way to reproduce the issue? Yes, source-level reproduction is high confidence: current main requires Is this the best way to solve the issue? Yes, the proposed approach is the narrowest maintainable fix I found: admit text-or-delta assistant content at the two gates and reuse the existing normalization and merge helpers. A broader provider or SDK change is not needed for this bug. Acceptance criteria:
What I checked:
Likely related people:
Remaining risk / open question:
Codex review notes: model gpt-5.5, reasoning high; reviewed against 8dd91b14d3c0. |
|
Updated the PR body with a Real behavior proof section: ran an inline |
|
Closing this as stale — 17 days with 0 maintainer activity, well past the typical review window for this repo. The delta-only event projection fix in |
Summary
src/gateway/server-chat.tsandsrc/tui/embedded-backend.tsboth gated live chat projection on a cumulativedata.textstring, dropping canonical assistant events that only carry an incrementaldata.delta. Live UIs lost working/streaming state between run start and final response.Add a small
hasLiveAssistantContenthelper insrc/gateway/live-chat-projector.tsso the gate accepts eithertextordelta.emitChatDeltaandresolveMergedAssistantTextalready merge delta-only inputs correctly, so the change is limited to the two gates plus their import.Fixes #82988
Real behavior proof
Behavior addressed: Gateway and embedded TUI live chat projection drop assistant events that only carry
data.delta. After this patch, both gates accept eitherdata.textordata.delta, and the existingresolveMergedAssistantTextbuffer keeps streaming deltas appended into the live chat surface.Real environment tested: Local macOS checkout of
openclaw/openclawin a git worktree based onorigin/main2c9f68f42b, Nodev25.5.0,tsxloader from the repo'snode_modules.Exact steps or command run after this patch:
The probe imports the patched
src/gateway/live-chat-projector.tsdirectly and exercises (a) the newhasLiveAssistantContentpredicate that both gates now consult, and (b) the existingresolveMergedAssistantTextbuffer with a delta-only stream that simulates the exact event shape from the issue.Evidence after fix: Live stdout from the probe (real
noderuntime, no test framework):Pre-patch, the delta-only event would have failed the
typeof evt.data?.text === "string"gate in bothserver-chat.tsandembedded-backend.ts, so the chat projection layer would never reachemitChatDeltaand the bufferedfirstChunk/secondChunkwould stay empty.Observed result after fix: Assistant events that only carry
data.deltanow pass the live chat gate and are appended to the per-run buffer through the existingresolveMergedAssistantTextmerge path. A delta-only stream of\"hello\"followed by\" world\"accumulates to\"hello world\"in the live chat surface instead of being dropped.What was not tested: End-to-end live run through a real provider that emits delta-only assistant events; the unaffected throttle/coalesce path (
isAgentTextThrottleEvent) intentionally still requiresdata.textbecause the issue is scoped to live chat projection.Verification
node scripts/run-vitest.mjs src/gateway/live-chat-projector.test.ts src/tui/embedded-backend.test.ts-> 4 files, 38/38 pass (covers the newhasLiveAssistantContentcases, theresolveMergedAssistantTextdelta-only path, and a new TUI testemits a chat delta for assistant events that only carry delta with no text).node --import tsx .artifacts/probe-82988.mjs-> 5/5 pass (output above).The probe script lives at
.artifacts/probe-82988.mjsin the contributor environment only; it is not part of the committed diff.