In-memory record of a server-side session. Mirrors ``server/types.ts:33-41``. ``process`` is a Popen-equivalent handle (``asyncio.subprocess.Process``); ``None`` when the session is being torn down. ``last_active_at`` is bumped on state transitions and per-message activity; the
| 49 | |
| 50 | @dataclass |
| 51 | class SessionInfo: |
| 52 | """In-memory record of a server-side session. |
| 53 | |
| 54 | Mirrors ``server/types.ts:33-41``. ``process`` is a Popen-equivalent |
| 55 | handle (``asyncio.subprocess.Process``); ``None`` when the session |
| 56 | is being torn down. |
| 57 | |
| 58 | ``last_active_at`` is bumped on state transitions and per-message |
| 59 | activity; the idle-timeout reaper compares against this field, NOT |
| 60 | against ``created_at`` — otherwise a long-lived active-then-detached |
| 61 | session would be reaped purely because it was created hours ago. |
| 62 | """ |
| 63 | |
| 64 | id: str |
| 65 | status: SessionState |
| 66 | created_at: float |
| 67 | work_dir: str |
| 68 | process: asyncio.subprocess.Process | None = None |
| 69 | session_key: str | None = None |
| 70 | last_active_at: float = 0.0 # initialized to created_at by SessionManager.create_session |
| 71 | |
| 72 | |
| 73 | @dataclass(frozen=True) |