perf(sidebar): trim hidden and empty sidebar payload rows (#4775)

This commit is contained in:
Rod Boev 2026-06-23 10:29:06 -04:00
parent 8a98626967
commit e27b7cf042
4 changed files with 353 additions and 3 deletions

View file

@ -1597,6 +1597,8 @@ def _session_list_cache_key(
show_previous_messaging_sessions: bool,
show_cron_sessions: bool,
include_archived: bool = False,
exclude_hidden: bool = False,
visible_only: bool = False,
source_filter: str | None = None,
sidebar_source: str | None = None,
) -> tuple:
@ -1607,6 +1609,8 @@ def _session_list_cache_key(
bool(show_previous_messaging_sessions),
bool(show_cron_sessions),
bool(include_archived),
bool(exclude_hidden),
bool(visible_only),
source_filter,
sidebar_source,
)
@ -1926,12 +1930,37 @@ def _build_session_list_cache_payload(
show_previous_messaging_sessions: bool,
show_cron_sessions: bool,
include_archived: bool = False,
exclude_hidden: bool = False,
visible_only: bool = False,
source_filter: str | None = None,
sidebar_source: str | None = None,
diag=None,
) -> dict:
diag_stage = diag.stage if diag is not None else lambda *_a, **_k: None
def _session_has_server_visible_messages(session: dict) -> bool:
"""Return True when a non-active sidebar row has a visibility signal.
Keep this mirror of the non-active server filter narrow and local to
route behavior so model-layer behavior remains unchanged.
"""
if not isinstance(session, dict):
return False
if _numeric_count(session.get("message_count")) > 0:
return True
attention = session.get("attention")
if isinstance(attention, dict) and attention.get("kind"):
if _numeric_count(attention.get("count")) > 0:
return True
return bool(
session.get("is_streaming")
or session.get("active_stream_id")
or session.get("pending_user_message")
or session.get("has_pending_user_message")
)
def _all_sessions_for_sidebar():
try:
return all_sessions(diag=diag, include_lineage_metadata=False)
@ -2090,6 +2119,16 @@ def _build_session_list_cache_payload(
diag_stage("cli_cap")
archived_scoped = _cap_recent_cli_sessions(archived_scoped, cli_cap=CLI_VISIBLE_SESSION_CAP)
visible_scoped = _cap_recent_cli_sessions(visible_scoped, cli_cap=CLI_VISIBLE_SESSION_CAP)
if visible_only:
archived_scoped = [
s for s in archived_scoped if _session_has_server_visible_messages(s)
]
visible_scoped = [
s for s in visible_scoped if _session_has_server_visible_messages(s)
]
if exclude_hidden:
archived_scoped = [s for s in archived_scoped if not s.get("default_hidden")]
visible_scoped = [s for s in visible_scoped if not s.get("default_hidden")]
archived_webui_count = sum(
1 for s in archived_scoped
if s.get("archived") and not _is_cli_session_for_settings(s)
@ -9794,6 +9833,7 @@ def handle_get(handler, parsed) -> bool:
active_profile = get_active_profile_name()
all_profiles = _all_profiles_enabled(parsed)
include_archived = _query_flag(parsed, "include_archived")
exclude_hidden = _query_flag(parsed, "exclude_hidden")
sidebar_source = parse_qs(parsed.query).get("sidebar_source", [""])[0].strip().lower() or None
if sidebar_source not in ("webui", "cli"):
sidebar_source = None
@ -9804,6 +9844,8 @@ def handle_get(handler, parsed) -> bool:
show_previous_messaging_sessions=show_previous_messaging_sessions,
show_cron_sessions=show_cron_sessions,
include_archived=include_archived,
exclude_hidden=exclude_hidden,
visible_only=True,
source_filter=agent_session_source_filter,
sidebar_source=sidebar_source,
)
@ -9820,6 +9862,8 @@ def handle_get(handler, parsed) -> bool:
show_previous_messaging_sessions=show_previous_messaging_sessions,
show_cron_sessions=show_cron_sessions,
include_archived=include_archived,
exclude_hidden=exclude_hidden,
visible_only=True,
source_filter=agent_session_source_filter,
sidebar_source=sidebar_source,
diag=diag,

View file

@ -1640,6 +1640,7 @@ function _requestedSessionSidebarSource() {
function _sessionListQueryString() {
const qs = new URLSearchParams();
qs.set('sidebar_source', _requestedSessionSidebarSource());
if(_activeProject===null || _activeProject===NO_PROJECT_FILTER) qs.set('exclude_hidden','1');
if(_showAllProfiles) qs.set('all_profiles','1');
if(_showArchived) qs.set('include_archived','1');
return `?${qs.toString()}`;

View file

@ -253,6 +253,7 @@ def test_session_list_query_string_respects_sidebar_source_and_flags():
query_fn = _extract_function(src, "_sessionListQueryString")
script = f"""
global.window = {{ _showCliSessions: true }};
global._activeProject = null;
global._sessionSourceFilter = 'cli';
global._showAllProfiles = true;
global._showArchived = false;
@ -262,12 +263,18 @@ const first = _sessionListQueryString();
window._showCliSessions = false;
global._showArchived = true;
const second = _sessionListQueryString();
console.log(JSON.stringify({{ first, second }}));
global._activeProject = '__none__';
global.NO_PROJECT_FILTER = '__none__';
global._showAllProfiles = false;
global._showArchived = false;
const third = _sessionListQueryString();
console.log(JSON.stringify({{ first, second, third }}));
"""
body = _run_node(script)
assert body["first"] == "?sidebar_source=cli&all_profiles=1"
assert body["second"] == "?sidebar_source=webui&all_profiles=1&include_archived=1"
assert body["first"] == "?sidebar_source=cli&exclude_hidden=1&all_profiles=1"
assert body["second"] == "?sidebar_source=webui&exclude_hidden=1&all_profiles=1&include_archived=1"
assert body["third"] == "?sidebar_source=webui&exclude_hidden=1"
@pytest.mark.skipif(NODE is None, reason="node not on PATH")

View file

@ -0,0 +1,298 @@
"""Regression coverage for issue #4775: hide zero-message and default_hidden rows for default sidebar loads."""
import io
import json
from pathlib import Path
import shutil
import subprocess
from urllib.parse import urlparse
import api.profiles as profiles
import api.routes as routes
import pytest
ROOT = Path(__file__).resolve().parents[1]
SESSIONS_JS = ROOT / "static" / "sessions.js"
NODE = shutil.which("node")
class _FakeHandler:
def __init__(self):
self.status = None
self.headers = {}
self.wfile = io.BytesIO()
def send_response(self, status):
self.status = status
def send_header(self, key, value):
self.headers[key] = value
def end_headers(self):
pass
def json_body(self):
return json.loads(self.wfile.getvalue().decode("utf-8"))
def _session_rows():
return [
{
"session_id": "visible-with-message",
"title": "Visible message",
"profile": "default",
"archived": False,
"message_count": 3,
"updated_at": 1000,
"last_message_at": 1000,
"source": "webui",
"raw_source": "webui",
"session_source": "webui",
"source_tag": "webui",
"default_hidden": False,
},
{
"session_id": "hidden-by-default",
"title": "Default hidden",
"profile": "default",
"archived": False,
"message_count": 1,
"updated_at": 900,
"last_message_at": 900,
"source": "webui",
"raw_source": "webui",
"session_source": "webui",
"source_tag": "webui",
"default_hidden": True,
},
{
"session_id": "zero-message",
"title": "Plain zero message",
"profile": "default",
"archived": False,
"message_count": 0,
"updated_at": 800,
"last_message_at": 800,
"source": "webui",
"raw_source": "webui",
"session_source": "webui",
"source_tag": "webui",
"default_hidden": False,
},
{
"session_id": "active-stream-row",
"title": "Streaming row",
"profile": "default",
"archived": False,
"message_count": 0,
"active_stream_id": "stream-active",
"updated_at": 700,
"last_message_at": 700,
"source": "webui",
"raw_source": "webui",
"session_source": "webui",
"source_tag": "webui",
"default_hidden": False,
},
{
"session_id": "attention-row",
"title": "Attention row",
"profile": "default",
"archived": False,
"message_count": 0,
"attention": {"kind": "clarify", "count": 1},
"updated_at": 600,
"last_message_at": 600,
"source": "webui",
"raw_source": "webui",
"session_source": "webui",
"source_tag": "webui",
"default_hidden": False,
},
{
"session_id": "pending-user-row",
"title": "Pending user row",
"profile": "default",
"archived": False,
"message_count": 0,
"pending_user_message": "user typing",
"updated_at": 500,
"last_message_at": 500,
"source": "webui",
"raw_source": "webui",
"session_source": "webui",
"source_tag": "webui",
"default_hidden": False,
},
{
"session_id": "pending-flag-row",
"title": "Pending flag row",
"profile": "default",
"archived": False,
"message_count": 0,
"has_pending_user_message": True,
"updated_at": 550,
"last_message_at": 550,
"source": "webui",
"raw_source": "webui",
"session_source": "webui",
"source_tag": "webui",
"default_hidden": False,
},
]
def _handle_sessions(url):
handler = _FakeHandler()
routes.handle_get(handler, urlparse(url))
return handler
def _extract_function(source_text, function_name):
marker = f"function {function_name}("
start = source_text.index(marker)
brace_start = source_text.index("{", start)
depth = 0
for index in range(brace_start, len(source_text)):
char = source_text[index]
if char == "{":
depth += 1
elif char == "}":
depth -= 1
if depth == 0:
return source_text[start : index + 1]
raise AssertionError(f"Could not extract {function_name}")
def _run_node(script):
proc = subprocess.run([NODE, "-e", script], capture_output=True, text=True, check=True)
return json.loads(proc.stdout)
@pytest.fixture(autouse=True)
def _clear_cache():
routes._session_list_cache_clear()
yield
routes._session_list_cache_clear()
def _install_common_monkeypatches(monkeypatch, rows):
session_ids = {str(row["session_id"]) for row in rows if row.get("session_id")}
monkeypatch.setattr(routes, "all_sessions", lambda diag=None: list(rows))
monkeypatch.setattr(routes, "_reconcile_stale_stream_state_for_session_rows", lambda _rows: False)
monkeypatch.setattr(routes, "_enrich_sidebar_lineage_metadata", lambda _rows: None)
monkeypatch.setattr(routes, "get_cli_sessions", lambda source_filter=None, all_profiles=False: [])
monkeypatch.setattr(routes, "agent_session_rows_existing", lambda ids, profile=None: set(ids) & session_ids)
monkeypatch.setattr(routes, "load_settings", lambda: {"show_cli_sessions": True})
monkeypatch.setattr(profiles, "get_active_profile_name", lambda: "default")
return rows
def test_default_sidebar_excludes_hidden_and_plain_zero_message_rows(monkeypatch):
rows = _session_rows()
_install_common_monkeypatches(monkeypatch, rows)
handler = _handle_sessions("http://example.com/api/sessions?sidebar_source=webui&exclude_hidden=1")
body = handler.json_body()
assert handler.status == 200
assert [r["session_id"] for r in body["sessions"]] == [
"visible-with-message",
"active-stream-row",
"attention-row",
"pending-flag-row",
"pending-user-row",
]
def test_zero_message_rows_with_visibility_signals_survive(monkeypatch):
rows = _session_rows()
_install_common_monkeypatches(monkeypatch, rows)
handler = _handle_sessions("http://example.com/api/sessions?sidebar_source=webui&exclude_hidden=1")
body = handler.json_body()
assert handler.status == 200
assert [r["session_id"] for r in body["sessions"]] == [
"visible-with-message",
"active-stream-row",
"attention-row",
"pending-flag-row",
"pending-user-row",
]
def test_omit_exclude_hidden_still_returns_default_hidden_rows(monkeypatch):
rows = _session_rows()
_install_common_monkeypatches(monkeypatch, rows)
handler = _handle_sessions("http://example.com/api/sessions?sidebar_source=webui")
body = handler.json_body()
assert handler.status == 200
session_ids = {row["session_id"] for row in body["sessions"]}
assert "hidden-by-default" in session_ids
def test_default_and_unassigned_queries_send_exclude_hidden(monkeypatch):
src = SESSIONS_JS.read_text(encoding="utf-8")
requested_source_fn = _extract_function(src, "_requestedSessionSidebarSource")
query_fn = _extract_function(src, "_sessionListQueryString")
script = f"""
global.window = {{ _showCliSessions: false }};
global._showCliSessions = false;
global._showAllProfiles = false;
global._showArchived = false;
global._activeProject = null;
global.NO_PROJECT_FILTER = '__none__';
{requested_source_fn}
{query_fn}
const default_query = _sessionListQueryString();
global._activeProject = '__none__';
const unassigned_query = _sessionListQueryString();
global._activeProject = 'demo-project';
const named_project_query = _sessionListQueryString();
console.log(JSON.stringify({{ default_query, unassigned_query, named_project_query }}));
"""
body = _run_node(script)
assert body["default_query"] == "?sidebar_source=webui&exclude_hidden=1"
assert body["unassigned_query"] == "?sidebar_source=webui&exclude_hidden=1"
assert body["named_project_query"] == "?sidebar_source=webui"
def test_cache_key_varies_for_exclude_hidden_and_visible_only():
key_without_filters = routes._session_list_cache_key(
active_profile="default",
all_profiles=False,
show_cli_sessions=True,
show_previous_messaging_sessions=False,
show_cron_sessions=False,
include_archived=False,
sidebar_source="webui",
)
key_exclude_hidden = routes._session_list_cache_key(
active_profile="default",
all_profiles=False,
show_cli_sessions=True,
show_previous_messaging_sessions=False,
show_cron_sessions=False,
include_archived=False,
exclude_hidden=True,
sidebar_source="webui",
)
key_visible_only = routes._session_list_cache_key(
active_profile="default",
all_profiles=False,
show_cli_sessions=True,
show_previous_messaging_sessions=False,
show_cron_sessions=False,
include_archived=False,
visible_only=True,
sidebar_source="webui",
)
assert key_without_filters != key_exclude_hidden
assert key_without_filters != key_visible_only
assert key_exclude_hidden != key_visible_only