Merge pull request #4733 from nesquena/stage-4730-release
Release v0.51.592 — Release UY (gateway-poll skip + smd re-init, #4730)
This commit is contained in:
commit
9430bda43d
3 changed files with 35 additions and 1 deletions
|
|
@ -3,6 +3,12 @@
|
|||
|
||||
## [Unreleased]
|
||||
|
||||
## [v0.51.592] — 2026-06-22 — Release UY (skip gateway poll when hidden/streaming + smd re-init)
|
||||
|
||||
### Fixed
|
||||
|
||||
- **The sidebar's gateway-poll fallback no longer burns CPU re-rendering while you're streaming or the tab is hidden, and long streamed responses render more efficiently.** The 5s gateway-poll fallback now skips its `renderSessionList` pass when the tab is hidden or a turn is actively streaming (it catches up immediately on tab refocus via a one-time `visibilitychange` listener, so no gateway updates are dropped). Separately, when the streaming markdown parser was torn down by a prior segment but `window.smd` is still available, the live renderer now recreates the parser on the cleared element instead of falling back to repeated full-`innerHTML` rebuilds — avoiding O(n²) DOM churn on long responses. Thanks @akrhin. (#4730)
|
||||
|
||||
## [v0.51.591] — 2026-06-22 — Release UX (stop transcript jumping to first message on completion)
|
||||
|
||||
### Fixed
|
||||
|
|
|
|||
|
|
@ -3352,6 +3352,18 @@ function attachLiveStream(activeSid, streamId, uploaded=[], options={}){
|
|||
: _stripXmlToolCalls(assistantText.slice(segmentStart));
|
||||
if(_smdParser){
|
||||
_smdWrite(displayText);
|
||||
} else if(window.smd){
|
||||
// Parser was nulled out (e.g. by a prior segment end) but smd is
|
||||
// available — recreate it on the existing element. Uses the non-fade
|
||||
// renderer to match standard rendering, avoiding O(n²) innerHTML
|
||||
// churn on long responses (#4704). Clear any content the renderMd()
|
||||
// fallback already wrote first: _smdNewParser resets _smdWrittenText to
|
||||
// '' but does NOT clear the element, so a following _smdWrite(displayText)
|
||||
// would append the full accumulated segment ON TOP of the existing
|
||||
// fallback render and duplicate the live text.
|
||||
assistantBody.innerHTML='';
|
||||
_smdNewParser(assistantBody, false);
|
||||
if(_smdParser) _smdWrite(displayText);
|
||||
} else if(renderMd){
|
||||
assistantBody.innerHTML=renderMd(displayText);
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -4101,7 +4101,23 @@ if(typeof window!=='undefined') window.refreshSessionList = refreshSessionList;
|
|||
function startGatewayPollFallback(ms){
|
||||
const intervalMs = Math.max(5000, Number(ms) || _gatewayFallbackPollMs);
|
||||
if(_gatewayPollTimer) clearInterval(_gatewayPollTimer);
|
||||
_gatewayPollTimer = setInterval(() => { renderSessionList({deferWhileInteracting:true}); }, intervalMs);
|
||||
_gatewayPollTimer = setInterval(() => {
|
||||
// Skip poll when tab is hidden or a stream is active — saves CPU
|
||||
// and avoids redundant DOM renders during active streaming (#4704).
|
||||
if(typeof document !== 'undefined' && document.hidden) return;
|
||||
if(typeof S !== 'undefined' && (S.busy || S.activeStreamId)) return;
|
||||
renderSessionList({deferWhileInteracting:true});
|
||||
}, intervalMs);
|
||||
// Visibility catch-up: refresh immediately when tab re-gains focus,
|
||||
// so no gateway updates are dropped during hidden-skip periods.
|
||||
if(typeof document !== 'undefined' && !document._hermesGatewayPollVisibilityHook){
|
||||
document.addEventListener('visibilitychange', () => {
|
||||
if(!document.hidden && typeof renderSessionList === 'function'){
|
||||
void renderSessionList({deferWhileInteracting:false});
|
||||
}
|
||||
});
|
||||
document._hermesGatewayPollVisibilityHook = true;
|
||||
}
|
||||
}
|
||||
|
||||
function stopGatewayPollFallback(){
|
||||
|
|
|
|||
Loading…
Reference in a new issue