MCPcopy Create free account
hub / github.com/agentforce314/clawcodex / SessionManager

Class SessionManager

src/server/session_manager.py:42–200  ·  view source on GitHub ↗

In-memory + on-disk Direct Connect session registry. The manager owns the map of live sessions; the server-loop module drives them via ``create_session``, ``mark_running``, ``mark_detached``, ``mark_stopped``, and ``stop_session``.

Source from the content-addressed store, hash-verified

40
41@dataclass
42class SessionManager:
43 """In-memory + on-disk Direct Connect session registry.
44
45 The manager owns the map of live sessions; the server-loop module
46 drives them via ``create_session``, ``mark_running``,
47 ``mark_detached``, ``mark_stopped``, and ``stop_session``.
48 """
49
50 workspace: str
51 max_sessions: int | None = None
52 idle_timeout_ms: int = 0
53 index_path: Path = DEFAULT_INDEX_PATH
54 _sessions: dict[str, SessionInfo] = field(default_factory=dict)
55
56 # ─── Mutators ──────────────────────────────────────────────────────
57
58 def create_session(
59 self,
60 *,
61 cwd: str | None = None,
62 permission_mode: str | None = None,
63 ) -> SessionInfo:
64 """Allocate a new session ID and record it in STARTING state.
65
66 Raises ``RuntimeError`` if ``max_sessions`` would be exceeded.
67 Caller is responsible for actually spawning the agent
68 subprocess and then calling ``attach_process`` + ``mark_running``.
69 """
70 if self.max_sessions is not None and self._active_count() >= self.max_sessions:
71 raise RuntimeError(
72 f'Direct Connect server: max_sessions ({self.max_sessions}) reached'
73 )
74 sid = f'ds_{_uuid.uuid4().hex}'
75 now = time.time()
76 info = SessionInfo(
77 id=sid,
78 status=SessionState.STARTING,
79 created_at=now,
80 work_dir=cwd or self.workspace,
81 last_active_at=now,
82 )
83 self._sessions[sid] = info
84 # Persist so a server restart can resume — even before the
85 # subprocess actually starts. The transcript_session_id
86 # initially equals the session_id; if the subprocess uses a
87 # different transcript ID, the server can update via
88 # ``update_transcript_id`` (out of scope for this minimal cut).
89 add_entry(
90 SessionIndexEntry(
91 session_id=sid,
92 transcript_session_id=sid,
93 cwd=info.work_dir,
94 created_at=info.created_at,
95 last_active_at=info.created_at,
96 permission_mode=permission_mode,
97 ),
98 path=self.index_path,
99 )

Calls

no outgoing calls