tighten session refresh invalidation

This commit is contained in:
dobby-d-elf committed 2026-05-20 14:40:13 -06:00
1 parent 14dd5aa00d
commit 6278222596
5 files changed
+25 -5

No files matched your search

+15 -1
View File
@@ -4640,7 +4640,8 @@ def handle_post(handler, parsed) -> bool:
project_id=body.get("project_id") or None,
worktree_info=worktree_info,
)
publish_session_list_changed("session_new")
if worktree_info:
publish_session_list_changed("session_new")
return j(handler, {"session": s.compact() | {"messages": s.messages}})
if parsed.path == "/api/session/duplicate":
@@ -8028,6 +8029,16 @@ def _prepare_chat_start_session_for_stream(
s.save()
def _is_hidden_empty_session(s) -> bool:
return (
getattr(s, "title", "Untitled") == "Untitled"
and not getattr(s, "messages", None)
and not getattr(s, "active_stream_id", None)
and not getattr(s, "pending_user_message", None)
and not getattr(s, "worktree_path", None)
)
def _start_chat_stream_for_session(
s,
*,
@@ -8074,6 +8085,7 @@ def _start_chat_stream_for_session(
diag.stage("session_lock_wait") if diag else None
with session_lock:
diag.stage("save_pending_state") if diag else None
was_hidden_empty_session = _is_hidden_empty_session(s)
_prepare_chat_start_session_for_stream(
s,
msg=msg,
@@ -8083,6 +8095,8 @@ def _start_chat_stream_for_session(
model_provider=model_provider,
stream_id=stream_id,
)
if was_hidden_empty_session:
publish_session_list_changed("session_new")
diag.stage("turn_journal_submitted") if diag else None
journal_event = {}
try:
+2 -1
View File
@@ -2138,6 +2138,7 @@ function ensureActiveSessionExternalRefreshPoll(){
async function refreshSessionList(reason='manual', opts={}){
const force = !!(opts && opts.force);
const refreshActive = !!(opts && opts.refreshActive);
if(!force && typeof document !== 'undefined' && document.hidden) return;
if(_sessionListRefreshInFlight){
_sessionListRefreshPendingReason = reason || 'session-list';
@@ -2146,7 +2147,7 @@ async function refreshSessionList(reason='manual', opts={}){
_sessionListRefreshInFlight = true;
try{
await renderSessionList({deferWhileInteracting:!force});
await refreshActiveSessionIfExternallyUpdated(reason||'session-list');
if(refreshActive) await refreshActiveSessionIfExternallyUpdated(reason||'session-list');
}finally{
_sessionListRefreshInFlight = false;
const pendingReason = _sessionListRefreshPendingReason;
+1 -1
View File
@@ -2013,7 +2013,7 @@ if(typeof window!=='undefined') window._resetScrollDirectionTracker=_resetScroll
el.addEventListener('touchend',function(){
if(_ptrState===2){
if(typeof window.refreshSessionList==='function'){
Promise.resolve(window.refreshSessionList('pull', {force:true})).catch(()=>{}).finally(_ptrReset);
Promise.resolve(window.refreshSessionList('pull', {force:true, refreshActive:true})).catch(()=>{}).finally(_ptrReset);
}else{
window.location.reload();
}
+3
View File
@@ -28,6 +28,9 @@ def test_session_events_publish_for_minimal_sidebar_mutations():
):
assert f'publish_session_list_changed("{reason}")' in ROUTES
assert 'if worktree_info:\n publish_session_list_changed("session_new")' in ROUTES
assert "was_hidden_empty_session = _is_hidden_empty_session(s)" in ROUTES
assert 'if was_hidden_empty_session:\n publish_session_list_changed("session_new")' in ROUTES
assert 'publish_session_list_changed("chat_start")' not in ROUTES
assert 'publish_session_list_changed("cron_complete")' in ROUTES
assert 'publish_session_list_changed("cron_complete")' in PROFILES
@@ -38,6 +38,8 @@ def test_session_list_external_refresh_uses_sse_invalidation_not_polling():
assert "_sessionEventsNeedsRefreshOnOpen = true" in SESSIONS_JS
assert "void refreshSessionList('reconnect')" in SESSIONS_JS
assert "renderSessionList({deferWhileInteracting:!force})" in SESSIONS_JS
assert "const refreshActive = !!(opts && opts.refreshActive)" in SESSIONS_JS
assert "if(refreshActive) await refreshActiveSessionIfExternallyUpdated(reason||'session-list')" in SESSIONS_JS
assert "_sessionListRefreshPendingReason = reason || 'session-list'" in SESSIONS_JS
assert "if(pendingReason) _scheduleSessionEventsRefresh(pendingReason)" in SESSIONS_JS
assert "ensureSessionEventsSSE();" in SESSIONS_JS
@@ -48,8 +50,8 @@ def test_session_list_external_refresh_uses_sse_invalidation_not_polling():
def test_pwa_pull_to_refresh_refreshes_session_list_not_page_when_available():
assert "window.refreshSessionList('pull', {force:true})" in UI_JS
assert "Promise.resolve(window.refreshSessionList('pull', {force:true})).catch(()=>{}).finally(_ptrReset)" in UI_JS
assert "window.refreshSessionList('pull', {force:true, refreshActive:true})" in UI_JS
assert "Promise.resolve(window.refreshSessionList('pull', {force:true, refreshActive:true})).catch(()=>{}).finally(_ptrReset)" in UI_JS
def test_force_reload_clears_stale_blocking_prompts_immediately():