fix(#5307): root-fix subagent classification + GET serialization (Codex round 7)

- api/agent_sessions.py is_cli_session_row(): add 'subagent' to non_cli_sources
  so EVERY consumer (sidebar rows, /api/sessions, etc.) classifies a delegated
  child as non-CLI (the root the per-site fixes were compensating for).
- api/routes.py GET /api/session happy path: coerce is_cli_session=False +
  read_only=True in the serialized payload for a subagent child before redaction,
  so a stale writable sidecar can't be exposed as writable to the browser.
Fixes #5307
This commit is contained in:
nesquena-hermes
2026-07-01 08:10:24 +00:00
parent 2e33e40272
commit 9eb208ebc3
2 changed files with 14 additions and 1 deletions
+5 -1
View File
@@ -176,7 +176,11 @@ def is_cli_session_row(row: dict) -> bool:
source_label = _safe_lower(row.get("source_label"))
if "webui" in {source, source_tag, raw_source, source_name, source_label}:
return False
non_cli_sources = MESSAGING_SOURCES | {"cron", "webhook", "tool", "api", "api_server"}
# 'subagent' is a delegated delegate_task child: view-only, owned by the
# runner, never a writable WebUI/CLI session (#5307). Classify it non-CLI so
# sidebar rows and every is_cli_session_row() consumer keep it out of the
# CLI/writable treatment.
non_cli_sources = MESSAGING_SOURCES | {"cron", "webhook", "tool", "api", "api_server", "subagent"}
if {source, source_tag, raw_source, source_name, source_label} & non_cli_sources:
return False
if source == "messaging":
+9
View File
@@ -11290,6 +11290,15 @@ def handle_get(handler, parsed) -> bool:
raw["model"] = effective_model
if effective_provider:
raw["model_provider"] = effective_provider
# A subagent child (#5307) is view-only regardless of what a stale
# sidecar stored: coerce the serialized flags so the browser never
# treats an existing subagent sidecar as writable / CLI-classified.
if (
(str(raw.get("source_tag") or raw.get("raw_source") or raw.get("session_source") or "").strip().lower() == "subagent")
or _is_subagent_child_session_id(sid)
):
raw["is_cli_session"] = False
raw["read_only"] = True
redact = redact_session_data(raw)
_t5 = _time.monotonic()
resp = j(handler, {"session": redact})