mirror of
https://github.com/nesquena/hermes-webui.git
synced 2026-05-25 11:10:18 +00:00
fix(streaming): finish auto-compression card after rotation
This commit is contained in:
+6
-3
@@ -1829,12 +1829,15 @@ function attachLiveStream(activeSid, streamId, uploaded=[], options={}){
|
||||
// Context was auto-compressed during this turn. Render it through the
|
||||
// same transient compression-card path as manual /compress, without
|
||||
// inserting a fake assistant message into history or model context.
|
||||
if(!S.session||S.session.session_id!==activeSid) return;
|
||||
if(!S.session) return;
|
||||
const currentSid=S.session.session_id;
|
||||
let d={};
|
||||
try{ d=JSON.parse(e.data||'{}')||{}; }catch(_){ d={}; }
|
||||
const eventSid=d.old_session_id||d.session_id||activeSid;
|
||||
if(eventSid!==activeSid && d.new_session_id!==activeSid && d.continuation_session_id!==activeSid) return;
|
||||
const continuationSid=d.new_session_id||d.continuation_session_id||'';
|
||||
const eventMatchesCurrent=!!(currentSid&&(eventSid===currentSid||d.new_session_id===currentSid||d.continuation_session_id===currentSid));
|
||||
if(!eventMatchesCurrent) return;
|
||||
const displaySid=currentSid;
|
||||
const message=String(d.message||'Context auto-compressed to continue the conversation').trim();
|
||||
if(d.usage&&typeof _syncCtxIndicator==='function'){
|
||||
S.lastUsage={...(S.lastUsage||{}),...d.usage};
|
||||
@@ -1842,7 +1845,7 @@ function attachLiveStream(activeSid, streamId, uploaded=[], options={}){
|
||||
}
|
||||
if(typeof setCompressionUi==='function'){
|
||||
const state={
|
||||
sessionId:activeSid,
|
||||
sessionId:displaySid,
|
||||
phase:'done',
|
||||
automatic:true,
|
||||
message,
|
||||
|
||||
@@ -217,16 +217,15 @@ def test_auto_compression_sse_uses_transient_card_not_fake_message():
|
||||
def test_auto_compression_sse_keeps_inactive_and_malformed_paths_safe():
|
||||
block = _compressed_listener_block()
|
||||
|
||||
guard = "if(!S.session||S.session.session_id!==activeSid) return;"
|
||||
guard = "if(!S.session) return;"
|
||||
assert guard in block
|
||||
assert block.index(guard) < block.index("setCompressionUi")
|
||||
assert "try{ d=JSON.parse(e.data||'{}')||{}; }catch(_){ d={}; }" in block
|
||||
assert "const eventSid=d.old_session_id||d.session_id||activeSid;" in block
|
||||
# The listener also accepts a rotated continuation session id so journal-
|
||||
# replay reconnects after compression rotate land the done card.
|
||||
# See Opus advisor followup on stage-385 (v0.51.92).
|
||||
event_guard = "if(eventSid!==activeSid && d.new_session_id!==activeSid && d.continuation_session_id!==activeSid) return;"
|
||||
assert "const eventMatchesCurrent=" in block
|
||||
event_guard = "if(!eventMatchesCurrent) return;"
|
||||
assert event_guard in block
|
||||
assert block.index("const eventMatchesCurrent=") < block.index(event_guard)
|
||||
|
||||
|
||||
def test_auto_compression_done_accepts_rotated_continuation_session_event():
|
||||
@@ -238,12 +237,29 @@ def test_auto_compression_done_accepts_rotated_continuation_session_event():
|
||||
# continuation id as display metadata instead of dropping the event.
|
||||
assert "const eventSid=d.old_session_id||d.session_id||activeSid;" in block
|
||||
assert "const continuationSid=d.new_session_id||d.continuation_session_id||'';" in block
|
||||
event_guard = "if(eventSid!==activeSid && d.new_session_id!==activeSid && d.continuation_session_id!==activeSid) return;"
|
||||
event_guard = "if(!eventMatchesCurrent) return;"
|
||||
assert event_guard in block
|
||||
assert block.index("const eventSid=") < block.index(event_guard)
|
||||
assert block.index("const eventSid=") < block.index("const eventMatchesCurrent=")
|
||||
assert "continuationSessionId:continuationSid" in block
|
||||
|
||||
|
||||
def test_auto_compression_done_accepts_event_after_current_session_rotates():
|
||||
block = _compressed_listener_block()
|
||||
|
||||
# The final compressed event can arrive/replay after another event has already
|
||||
# updated S.session to the continuation session id. Do not drop it just
|
||||
# because the active browser session no longer equals the original activeSid.
|
||||
strict_active_guard = "if(!S.session||S.session.session_id!==activeSid) return;"
|
||||
assert strict_active_guard not in block
|
||||
assert "if(!S.session) return;" in block
|
||||
assert "const currentSid=S.session.session_id;" in block
|
||||
assert "const eventMatchesCurrent=" in block
|
||||
assert "const displaySid=currentSid;" in block
|
||||
assert "sessionId:displaySid" in block
|
||||
assert block.index("const eventSid=") < block.index("const eventMatchesCurrent=")
|
||||
assert block.index("const displaySid=") < block.index("setCompressionUi(state)")
|
||||
|
||||
|
||||
def test_auto_compression_done_sse_refreshes_context_indicator_usage():
|
||||
block = _compressed_listener_block()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user