fix: keep agent cron sessions in project chips

This commit is contained in:
AJV20 2026-05-29 21:59:22 -04:00 committed by nesquena-hermes
parent 3005811200
commit e68c670bba
4 changed files with 83 additions and 9 deletions

View file

@ -3,6 +3,10 @@
## [Unreleased]
### Fixed
- Agent-side cron sessions imported from state.db now remain available to their assigned project chip as `default_hidden` rows instead of being filtered out before project reveal logic can see them (#3134).
## [v0.51.165] — 2026-05-30 — Release EK (stage-batch47 — stop EventSource reconnect storm on long-lived SSE streams)
### Fixed

View file

@ -2530,6 +2530,29 @@ def _is_duplicate_webui_state_projection(session: dict, represented_webui_ids: s
return bool(_session_lineage_ids(session) & represented_webui_ids)
def _dedupe_cli_sidebar_sessions_for_api(cli: list[dict], represented_webui_ids: set[str]) -> list[dict]:
"""Return CLI/state sidebar rows while preserving project-hidden cron rows.
Agent-side cron sessions come from state.db rather than the WebUI session
store. They should stay hidden from the default sidebar, but project-assigned
messageful rows must remain in the `/api/sessions` payload with
`default_hidden` so the matching project chip can reveal them (#3134).
"""
from api.models import (
_hide_from_default_sidebar as _cron_hide,
_include_project_hidden_background_sidebar_sessions,
)
candidates = [
s for s in cli
if s["session_id"] not in represented_webui_ids
and not _is_duplicate_webui_state_projection(s, represented_webui_ids)
and is_cli_session_row_visible(s)
]
visible = [s for s in candidates if not _cron_hide(s)]
return _include_project_hidden_background_sidebar_sessions(candidates, visible)
CLI_VISIBLE_SESSION_CAP = 20
@ -4625,14 +4648,7 @@ def handle_get(handler, parsed) -> bool:
represented_webui_ids = set()
for s in webui_sessions:
represented_webui_ids.update(_session_lineage_ids(s))
from api.models import _hide_from_default_sidebar as _cron_hide
deduped_cli = [
s for s in cli
if s["session_id"] not in represented_webui_ids
and not _is_duplicate_webui_state_projection(s, represented_webui_ids)
and is_cli_session_row_visible(s)
and not _cron_hide(s)
]
deduped_cli = _dedupe_cli_sidebar_sessions_for_api(cli, represented_webui_ids)
else:
diag.stage("filter_webui_sessions")
webui_sessions = [s for s in webui_sessions if not _is_cli_session_for_settings(s)]

View file

@ -1529,7 +1529,11 @@ def test_cron_sessions_hidden_from_sidebar_by_default():
sessions = data.get('sessions', [])
ids = {s['session_id'] for s in sessions}
assert 'gw_noncron_001' in ids, "Non-cron agent session should still appear"
assert 'cron_job123_20260427' not in ids, "Cron session should be hidden by default"
cron_row = next((s for s in sessions if s['session_id'] == 'cron_job123_20260427'), None)
assert cron_row is None or cron_row.get('default_hidden') is True, (
"Cron session should either be omitted from /api/sessions or marked "
"default_hidden so the default sidebar filter keeps it hidden"
)
finally:
try:
_remove_test_sessions(conn, 'cron_job123_20260427', 'gw_noncron_001')

View file

@ -38,6 +38,56 @@ def test_project_assigned_cron_rows_are_returned_but_default_hidden():
assert by_id["cron_visible"]["default_hidden"] is True
def test_agent_side_cron_rows_keep_project_chip_visibility():
from api.routes import _dedupe_cli_sidebar_sessions_for_api
represented_webui_ids = {"webui-1"}
cli_rows = [
{
"session_id": "cli-normal",
"source_tag": "cli",
"title": "Manual deployment notes",
"message_count": 1,
"updated_at": 5,
},
{
"session_id": "cron-agent-project",
"source_tag": "cron",
"title": "Cron agent run",
"message_count": 3,
"project_id": "cron-project",
"updated_at": 4,
},
{
"session_id": "cron-agent-unassigned",
"source_tag": "cron",
"title": "Cron hidden",
"message_count": 3,
"updated_at": 3,
},
{
"session_id": "cron-agent-empty",
"source_tag": "cron",
"title": "Cron empty",
"message_count": 0,
"project_id": "cron-project",
"updated_at": 2,
},
{
"session_id": "webui-1",
"source_tag": "cli",
"title": "Duplicate imported copy",
"message_count": 1,
},
]
rows = _dedupe_cli_sidebar_sessions_for_api(cli_rows, represented_webui_ids)
by_id = {row["session_id"]: row for row in rows}
assert set(by_id) == {"cli-normal", "cron-agent-project"}
assert by_id["cron-agent-project"]["default_hidden"] is True
def test_session_list_project_filter_can_reveal_default_hidden_cron_rows():
src = ( __import__("pathlib").Path(__file__).parent.parent / "static" / "sessions.js").read_text(encoding="utf-8")