[eric] agents: cloud_sync convention-clean (sync_session_close off leading-_, @typechecked, typed)

This commit is contained in:
ciregenz
2026-06-23 11:51:29 -07:00
parent df82a4632c
commit 68beb599c9
2 changed files with 14 additions and 24 deletions
@@ -18,7 +18,7 @@ from backend.apps.agents.manager.session.session_store import (
_save_session as save_session,
build_search_text,
)
from backend.apps.agents.manager.session.cloud_sync import _sync_session_close as sync_session_close
from backend.apps.agents.manager.session.cloud_sync import sync_session_close
from backend.apps.agents.manager.session.apply_context_window import apply_context_window
from backend.apps.agents.manager.session import lifecycle
from backend.apps.agents.manager.view_builder_state import (
@@ -1,36 +1,26 @@
"""Submit a session snapshot to the cloud on close. The cloud consumes the dump however it sees
fit; the desktop just hands off a snapshot. Skipped for mock sessions so dev runs don't post to
the real backend. Synthesizes a closed_at timestamp on the cloud-bound dump if the session lacks
one (two paths, browser_agent close and shutdown_all_sessions, previously sent it null, which
left the cloud unable to compute duration_ms). Fixed here at the bottleneck so no call site can
miss it; the on-disk session JSON keeps its original (possibly None) closed_at."""
from datetime import datetime
from typeguard import typechecked
from backend.apps.agents.core.models import AgentSession
from backend.apps.service.client import sync as _sync
from backend.apps.service.client import sync as submit_to_cloud
def _sync_session_close(session: AgentSession, close_reason: str = "user"):
"""Submit the session state to the cloud on close. The cloud
consumes the dump however it sees fit; the desktop just hands off
a snapshot. Skipped for mock sessions so dev runs don't post to
the real backend.
Synthesizes a `closed_at` timestamp on the dump if the session
doesn't have one. Two paths previously sent close-events without
a timestamp and made the cloud unable to compute duration_ms
(which surfaced as duration_ms=null on 90% of session.ended events,
browser-agent and shutdown paths in particular):
1. browser_agent.py calls this without setting closed_at.
2. shutdown_all_sessions() clears closed_at to None for the
on-disk restore mechanism, then syncs.
Fix is here at the bottleneck rather than at every caller so we
can't miss a future call site. The on-disk session JSON keeps its
original (possibly None) closed_at, only the cloud-bound dump
gets the synthesized timestamp.
"""
@typechecked
def sync_session_close(session: AgentSession, close_reason: str = "user") -> None:
if close_reason == "mock" or getattr(session, "_mock_run", False):
return
try:
dump = session.model_dump(mode="json")
if not dump.get("closed_at"):
dump["closed_at"] = datetime.now().isoformat()
_sync(dump)
submit_to_cloud(dump)
except Exception:
pass