fix: keep agent cron sessions in project chips
This commit is contained in:
parent
3005811200
commit
e68c670bba
4 changed files with 83 additions and 9 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)]
|
||||
|
|
|
|||
|
|
@ -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')
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue