Coverage for /home/admin/Documents/AI/applications/lexigram-dev/lexigram/experimental/ai/lexigram-ai-session/src/lexigram/ai/session/state/core.py: 62%
13 statements
« prev ^ index » next coverage.py v7.15.4, created at 2026-08-25 07:19 +0800
« prev ^ index » next coverage.py v7.15.4, created at 2026-08-25 07:19 +0800
1"""Session state machine — validates and executes status transitions."""
3from __future__ import annotations
5from lexigram.ai.session.exceptions import SessionTransitionError
7# Allowed transitions: from_status -> set of allowed to_statuses
8_TRANSITIONS: dict[str, set[str]] = {
9 "active": {"suspended", "closed"},
10 "suspended": {"active", "closed"},
11 "closed": set(),
12 "expired": set(),
13}
16class SessionStateMachine:
17 """Validates and enforces session lifecycle status transitions.
19 Encodes the allowed state graph:
20 - ACTIVE → SUSPENDED or CLOSED
21 - SUSPENDED → ACTIVE or CLOSED
22 - CLOSED / EXPIRED → terminal (no transitions allowed)
23 """
25 def validate(self, session_id: str, from_status: str, to_status: str) -> None:
26 """Assert that a transition is allowed, raise otherwise.
28 Args:
29 session_id: The session being transitioned (for error messages).
30 from_status: Current status string.
31 to_status: Desired target status string.
33 Raises:
34 SessionTransitionError: If the transition is not permitted.
35 """
36 allowed = _TRANSITIONS.get(from_status, set())
37 if to_status not in allowed:
38 raise SessionTransitionError(session_id, from_status, to_status)
40 def can_transition(self, from_status: str, to_status: str) -> bool:
41 """Return True if the transition from *from_status* to *to_status* is valid.
43 Args:
44 from_status: Current status string.
45 to_status: Desired target status string.
47 Returns:
48 True when the transition is allowed.
49 """
50 return to_status in _TRANSITIONS.get(from_status, set())
52 def is_terminal(self, status: str) -> bool:
53 """Return True if the given status is a terminal (no-exit) state.
55 Args:
56 status: Status string to check.
58 Returns:
59 True for ``closed`` and ``expired``.
60 """
61 return not _TRANSITIONS.get(status)
64__all__ = ["SessionStateMachine"]