Merge pull request #5813 from nesquena/release/stage-5773
Release: keep live reasoning on one renderer path (#5773)
This commit is contained in:
5 files changed
+49
-5
No files matched your search
@@ -5,6 +5,8 @@
|
||||
|
||||
### Fixed
|
||||
|
||||
- **Live reasoning no longer briefly renders twice while a reply streams.** The streaming path updated the reasoning display through two renderers at once (the anchored reasoning block and the live thinking card), which could momentarily show the reasoning twice. It now routes through a single renderer — the live thinking card only updates when the anchored path didn't handle it. Thanks @rodboev. (#5773, #5720)
|
||||
|
||||
- **A wide or tall code block in the chat no longer thrashes the surrounding layout while a reply streams.** Code blocks now use CSS `contain: content`, so a growing/overflowing `<pre>` is isolated to its own rounded container (with its own horizontal scroll) instead of reflowing the message column during streaming. Thanks @rodboev. (#5770, #5760)
|
||||
|
||||
- **Workspace switcher is now navigable with a screen reader.** The workspace switcher exposes proper roles/labels and announces the "New Chat" workspace state transiently, and the closed workspace dropdown is kept out of screen-reader navigation so it isn't read while collapsed. Visual layout and click/keyboard behavior are unchanged. Thanks @rodboev. (#5721, #5671)
|
||||
|
||||
+4
-2
@@ -5024,8 +5024,10 @@ function attachLiveStream(activeSid, streamId, uploaded=[], options={}){
|
||||
if(d.text&&S.session&&S.session.session_id===activeSid) _completeAutomaticCompressionOnLiveProgress(activeSid);
|
||||
syncInflightAssistantMessage();
|
||||
if(text&&S.session&&S.session.session_id===activeSid){
|
||||
_upsertAnchorReasoning(_liveThinkingText());
|
||||
_updateLiveThinkingCard(_liveThinkingText());
|
||||
const liveThinkingText=_liveThinkingText();
|
||||
if(!_upsertAnchorReasoning(liveThinkingText)){
|
||||
_updateLiveThinkingCard(liveThinkingText);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -931,8 +931,12 @@ def test_messages_js_supports_live_reasoning_and_tool_completion(cleanup_test_se
|
||||
"messages.js must listen for live reasoning SSE events"
|
||||
assert "liveReasoningText += text" in src, \
|
||||
"live reasoning SSE events must update the active Worklog Thinking Card text"
|
||||
assert "_updateLiveThinkingCard(_liveThinkingText())" in src, \
|
||||
"live reasoning SSE events must refresh the current segment's Worklog Thinking Card"
|
||||
assert "const liveThinkingText=_liveThinkingText();" in src, \
|
||||
"live reasoning SSE events must compute the current segment's Worklog Thinking Card text once"
|
||||
assert "if(!_upsertAnchorReasoning(liveThinkingText))" in src, \
|
||||
"live reasoning SSE events must prefer the anchor renderer before falling back"
|
||||
assert "_updateLiveThinkingCard(liveThinkingText)" in src, \
|
||||
"live reasoning SSE events must keep the current segment's Worklog Thinking Card as fallback"
|
||||
assert "source.addEventListener('tool_complete'" in src or 'source.addEventListener("tool_complete"' in src, \
|
||||
"messages.js must listen for live tool completion SSE events"
|
||||
assert "function _parseStreamState()" in src, \
|
||||
|
||||
@@ -1306,7 +1306,9 @@ def test_slice6_live_shadow_feed_wires_anchor_scene_for_visible_order_handoff():
|
||||
assert "_upsertAnchorProcessProse(displayText" in src
|
||||
reasoning_body = _event_listener_body(src, "reasoning")
|
||||
assert "_applyToAnchor" not in reasoning_body
|
||||
assert "_upsertAnchorReasoning(_liveThinkingText())" in reasoning_body
|
||||
assert "const liveThinkingText=_liveThinkingText();" in reasoning_body
|
||||
assert "if(!_upsertAnchorReasoning(liveThinkingText))" in reasoning_body
|
||||
assert "_updateLiveThinkingCard(liveThinkingText)" in reasoning_body
|
||||
assert "function _flushReasoningToAnchor()" in src
|
||||
assert "_upsertAnchorReasoning(reasoningText" in src
|
||||
assert "`live-reasoning:${streamId}:final`" in src
|
||||
|
||||
@@ -670,6 +670,40 @@ class TestToolCallGroupingStatic:
|
||||
"Tool starts must not split consecutive tools into one-tool Activity rows."
|
||||
)
|
||||
|
||||
def test_reasoning_stream_uses_one_live_renderer_path(self):
|
||||
reasoning_match = re.search(
|
||||
r"source\.addEventListener\('reasoning',e=>\{(.*?)\n\s*\}\);",
|
||||
MESSAGES_JS,
|
||||
re.S,
|
||||
)
|
||||
assert reasoning_match, "reasoning listener not found"
|
||||
reasoning_fn = reasoning_match.group(1)
|
||||
render_live_thinking_fn = _function_body(MESSAGES_JS, "_renderLiveThinking")
|
||||
|
||||
assert reasoning_fn.count("_liveThinkingText()") == 1, (
|
||||
"_liveThinkingText() should be computed once inside the active-session branch."
|
||||
)
|
||||
assert "const liveThinkingText=_liveThinkingText();" in reasoning_fn, (
|
||||
"Reasoning SSE updates should cache the live thinking text before routing."
|
||||
)
|
||||
assert "_upsertAnchorReasoning(liveThinkingText)" in reasoning_fn, (
|
||||
"Anchor reasoning must remain the primary renderer path."
|
||||
)
|
||||
assert reasoning_fn.index("_upsertAnchorReasoning(liveThinkingText)") < reasoning_fn.index(
|
||||
"_updateLiveThinkingCard(liveThinkingText)"
|
||||
), (
|
||||
"The legacy thinking card should only run after anchor upsert fails."
|
||||
)
|
||||
assert "if(!_upsertAnchorReasoning(liveThinkingText)){" in reasoning_fn, (
|
||||
"The legacy thinking card should be a falsy-anchor fallback."
|
||||
)
|
||||
assert reasoning_fn.count("_updateLiveThinkingCard(liveThinkingText)") == 1, (
|
||||
"Reasoning SSE updates should call the live thinking card only in fallback."
|
||||
)
|
||||
assert "_updateLiveThinkingCard(" in render_live_thinking_fn, (
|
||||
"Inline parsed thinking still needs the live thinking card renderer."
|
||||
)
|
||||
|
||||
def test_live_thinking_card_is_segment_scoped_not_global_singleton(self):
|
||||
live_thinking_fn = _function_body(UI_JS, "appendThinking")
|
||||
placement_fn = _function_body(MESSAGES_JS, "_liveThinkingPlacement")
|
||||
|
||||
Reference in new issue
Block a user