fix(#4766): close review gaps in sidebar source filtering

This commit is contained in:
Rod Boev committed 2026-06-23 06:10:16 -04:00
1 parent 9a5a3eb6d5
commit 73a209aca7
3 files changed
+91 -4

No files matched your search

+6 -3
View File
@@ -2145,14 +2145,12 @@ def _session_list_payload_to_response(payload: dict) -> dict:
for s in runtime_rows:
item = _sidebar_session_response_item(s) if isinstance(s, dict) else {}
safe_merged.append(item)
return {
response = {
"sessions": safe_merged,
"cli_count": int(payload.get("cli_count", 0)),
"archived_count": int(payload.get("archived_count", 0)),
"archived_webui_count": int(payload.get("archived_webui_count", 0)),
"archived_cli_count": int(payload.get("archived_cli_count", 0)),
"webui_session_count": int(payload.get("webui_session_count", 0)),
"cli_session_count": int(payload.get("cli_session_count", 0)),
"include_archived": bool(payload.get("include_archived", False)),
"all_profiles": bool(payload.get("all_profiles", False)),
"active_profile": payload.get("active_profile"),
@@ -2160,6 +2158,11 @@ def _session_list_payload_to_response(payload: dict) -> dict:
"server_time": time.time(),
"server_tz": time.strftime("%z"),
}
if "webui_session_count" in payload:
response["webui_session_count"] = int(payload.get("webui_session_count", 0))
if "cli_session_count" in payload:
response["cli_session_count"] = int(payload.get("cli_session_count", 0))
return response
def _get_cached_session_list_payload(
+1 -1
View File
@@ -1569,7 +1569,7 @@ function _setSessionSourceFilter(filter) {
_selectedSessions.clear();
_sessionSelectMode = false;
try { localStorage.setItem('hermes-session-source-filter', next); } catch (_e) {}
renderSessionListFromCache();
void renderSessionList({deferWhileInteracting:false});
}
function _restoreSessionSourceFilter() {
@@ -3,6 +3,8 @@
import io
import json
from pathlib import Path
import shutil
import subprocess
from urllib.parse import urlparse
import api.profiles as profiles
@@ -12,6 +14,7 @@ import pytest
ROOT = Path(__file__).resolve().parents[1]
SESSIONS_JS = ROOT / "static" / "sessions.js"
NODE = shutil.which("node")
class _FakeHandler:
@@ -82,6 +85,22 @@ def _handle_sessions(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}")
@pytest.fixture(autouse=True)
def _clear_cache():
routes._session_list_cache_clear()
@@ -229,6 +248,71 @@ def test_frontend_avoids_cli_bucket_request_when_cli_hidden():
assert "window._showCliSessions ? _sessionSourceFilter : 'webui'" in src
@pytest.mark.skipif(NODE is None, reason="node not on PATH")
def test_session_source_switch_fetches_selected_bucket():
src = SESSIONS_JS.read_text(encoding="utf-8")
fn_source = _extract_function(src, "_setSessionSourceFilter")
script = f"""
const renderCalls = [];
global._sessionSourceFilter = 'webui';
global._activeProject = 'demo-project';
global._selectedSessions = new Set(['first', 'second']);
global._sessionSelectMode = true;
global.localStorage = {{
writes: [],
setItem(key, value) {{
this.writes.push([key, value]);
}},
}};
global.renderSessionList = (opts) => {{
renderCalls.push(opts);
return Promise.resolve();
}};
{fn_source}
_setSessionSourceFilter('cli');
console.log(JSON.stringify({{
sourceFilter: global._sessionSourceFilter,
activeProject: global._activeProject,
selectedSize: global._selectedSessions.size,
sessionSelectMode: global._sessionSelectMode,
storageWrites: global.localStorage.writes,
renderCalls,
}}));
"""
proc = subprocess.run([NODE, "-e", script], capture_output=True, text=True, check=True)
body = json.loads(proc.stdout)
assert body["sourceFilter"] == "cli"
assert body["activeProject"] is None
assert body["selectedSize"] == 0
assert body["sessionSelectMode"] is False
assert body["storageWrites"] == [["hermes-session-source-filter", "cli"]]
assert body["renderCalls"] == [{"deferWhileInteracting": False}]
def test_session_list_response_omits_bucket_counts_when_missing(monkeypatch):
monkeypatch.setattr(routes, "_session_list_cache_overlay_runtime_rows", lambda rows: rows)
monkeypatch.setattr(routes, "_sidebar_session_response_item", lambda row: row)
body = routes._session_list_payload_to_response(
{
"sessions": [{"session_id": "webui-1", "title": "WebUI Session"}],
"cli_count": 0,
"archived_count": 0,
"archived_webui_count": 0,
"archived_cli_count": 0,
"include_archived": False,
"all_profiles": False,
"active_profile": "default",
"other_profile_count": 0,
}
)
assert "webui_session_count" not in body
assert "cli_session_count" not in body
assert body["sessions"][0]["session_id"] == "webui-1"
def test_payload_row_count_regression(monkeypatch):
rows = _session_rows(webui_count=30, cli_count=20)
_install_common_monkeypatches(monkeypatch, rows)