1use std::any::Any;
10use std::sync::Arc;
11use std::sync::atomic::{AtomicU64, Ordering};
12
13use serde::{Deserialize, Serialize};
14use uuid::Uuid;
15
16use crate::completion_feed::CompletionSeq;
17use crate::handles::{
18 AuthLeaseHandle, CommsDrainHandle, ExternalToolSurfaceHandle, InteractionStreamHandle,
19 McpServerLifecycleHandle, ModelRoutingHandle, PeerCommsHandle, PeerInteractionHandle,
20 SessionAdmissionHandle, SessionClaimHandle, SessionContextHandle, TurnStateHandle,
21};
22use crate::ops_lifecycle::OpsLifecycleRegistry;
23use crate::tool_scope::ToolVisibilityOwner;
24use crate::types::SessionId;
25
26#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
33pub struct RuntimeEpochId(pub Uuid);
34
35impl RuntimeEpochId {
36 pub fn new() -> Self {
38 Self(crate::time_compat::new_uuid_v7())
39 }
40
41 pub fn from_uuid(uuid: Uuid) -> Self {
43 Self(uuid)
44 }
45}
46
47impl Default for RuntimeEpochId {
48 fn default() -> Self {
49 Self::new()
50 }
51}
52
53impl std::fmt::Display for RuntimeEpochId {
54 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
55 write!(f, "{}", self.0)
56 }
57}
58
59pub struct EpochCursorState {
68 pub agent_applied_cursor: AtomicU64,
70 pub runtime_observed_seq: AtomicU64,
72 pub runtime_last_injected_seq: AtomicU64,
74}
75
76impl EpochCursorState {
77 pub fn new() -> Self {
79 Self {
80 agent_applied_cursor: AtomicU64::new(0),
81 runtime_observed_seq: AtomicU64::new(0),
82 runtime_last_injected_seq: AtomicU64::new(0),
83 }
84 }
85
86 pub fn from_recovered(
88 agent_applied_cursor: CompletionSeq,
89 runtime_observed_seq: CompletionSeq,
90 runtime_last_injected_seq: CompletionSeq,
91 ) -> Self {
92 Self {
93 agent_applied_cursor: AtomicU64::new(agent_applied_cursor),
94 runtime_observed_seq: AtomicU64::new(runtime_observed_seq),
95 runtime_last_injected_seq: AtomicU64::new(runtime_last_injected_seq),
96 }
97 }
98
99 pub fn snapshot(&self) -> EpochCursorSnapshot {
101 EpochCursorSnapshot {
102 agent_applied_cursor: self.agent_applied_cursor.load(Ordering::Acquire),
103 runtime_observed_seq: self.runtime_observed_seq.load(Ordering::Acquire),
104 runtime_last_injected_seq: self.runtime_last_injected_seq.load(Ordering::Acquire),
105 }
106 }
107}
108
109impl Default for EpochCursorState {
110 fn default() -> Self {
111 Self::new()
112 }
113}
114
115impl std::fmt::Debug for EpochCursorState {
116 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
117 f.debug_struct("EpochCursorState")
118 .field(
119 "agent_applied_cursor",
120 &self.agent_applied_cursor.load(Ordering::Relaxed),
121 )
122 .field(
123 "runtime_observed_seq",
124 &self.runtime_observed_seq.load(Ordering::Relaxed),
125 )
126 .field(
127 "runtime_last_injected_seq",
128 &self.runtime_last_injected_seq.load(Ordering::Relaxed),
129 )
130 .finish()
131 }
132}
133
134#[derive(Debug, Clone, Serialize, Deserialize)]
136pub struct EpochCursorSnapshot {
137 pub agent_applied_cursor: CompletionSeq,
138 pub runtime_observed_seq: CompletionSeq,
139 pub runtime_last_injected_seq: CompletionSeq,
140}
141
142pub struct SessionRuntimeBindings {
151 session_id: SessionId,
154 epoch_id: RuntimeEpochId,
157 ops_lifecycle: Arc<dyn OpsLifecycleRegistry>,
159 cursor_state: Arc<EpochCursorState>,
161 tool_visibility_owner: Arc<dyn ToolVisibilityOwner>,
163 turn_state: Arc<dyn TurnStateHandle>,
165 comms_drain: Arc<dyn CommsDrainHandle>,
167 external_tool_surface: Arc<dyn ExternalToolSurfaceHandle>,
169 peer_comms: Arc<dyn PeerCommsHandle>,
171 session_admission: Arc<dyn SessionAdmissionHandle>,
173 model_routing: Arc<dyn ModelRoutingHandle>,
178 auth_lease: Arc<dyn AuthLeaseHandle>,
180 mcp_server_lifecycle: Arc<dyn McpServerLifecycleHandle>,
186 peer_interaction: Arc<dyn PeerInteractionHandle>,
193 session_context: Arc<dyn SessionContextHandle>,
200 session_claim_handle: Arc<dyn SessionClaimHandle>,
209 interaction_stream: Arc<dyn InteractionStreamHandle>,
214 runtime_authority: Arc<dyn Any + Send + Sync>,
215}
216
217impl SessionRuntimeBindings {
218 #[doc(hidden)]
224 #[allow(clippy::too_many_arguments)]
225 pub fn __from_runtime_authority(
226 session_id: SessionId,
227 epoch_id: RuntimeEpochId,
228 ops_lifecycle: Arc<dyn OpsLifecycleRegistry>,
229 cursor_state: Arc<EpochCursorState>,
230 tool_visibility_owner: Arc<dyn ToolVisibilityOwner>,
231 turn_state: Arc<dyn TurnStateHandle>,
232 comms_drain: Arc<dyn CommsDrainHandle>,
233 external_tool_surface: Arc<dyn ExternalToolSurfaceHandle>,
234 peer_comms: Arc<dyn PeerCommsHandle>,
235 session_admission: Arc<dyn SessionAdmissionHandle>,
236 model_routing: Arc<dyn ModelRoutingHandle>,
237 auth_lease: Arc<dyn AuthLeaseHandle>,
238 mcp_server_lifecycle: Arc<dyn McpServerLifecycleHandle>,
239 peer_interaction: Arc<dyn PeerInteractionHandle>,
240 session_context: Arc<dyn SessionContextHandle>,
241 session_claim_handle: Arc<dyn SessionClaimHandle>,
242 interaction_stream: Arc<dyn InteractionStreamHandle>,
243 runtime_authority: Arc<dyn Any + Send + Sync>,
244 ) -> Self {
245 Self {
246 session_id,
247 epoch_id,
248 ops_lifecycle,
249 cursor_state,
250 tool_visibility_owner,
251 turn_state,
252 comms_drain,
253 external_tool_surface,
254 peer_comms,
255 session_admission,
256 model_routing,
257 auth_lease,
258 mcp_server_lifecycle,
259 peer_interaction,
260 session_context,
261 session_claim_handle,
262 interaction_stream,
263 runtime_authority,
264 }
265 }
266
267 pub fn session_id(&self) -> &SessionId {
268 &self.session_id
269 }
270
271 pub fn epoch_id(&self) -> &RuntimeEpochId {
272 &self.epoch_id
273 }
274
275 pub fn ops_lifecycle(&self) -> &Arc<dyn OpsLifecycleRegistry> {
276 &self.ops_lifecycle
277 }
278
279 pub fn cursor_state(&self) -> &Arc<EpochCursorState> {
280 &self.cursor_state
281 }
282
283 pub fn tool_visibility_owner(&self) -> &Arc<dyn ToolVisibilityOwner> {
284 &self.tool_visibility_owner
285 }
286
287 pub fn turn_state(&self) -> &Arc<dyn TurnStateHandle> {
288 &self.turn_state
289 }
290
291 pub fn comms_drain(&self) -> &Arc<dyn CommsDrainHandle> {
292 &self.comms_drain
293 }
294
295 pub fn external_tool_surface(&self) -> &Arc<dyn ExternalToolSurfaceHandle> {
296 &self.external_tool_surface
297 }
298
299 pub fn peer_comms(&self) -> &Arc<dyn PeerCommsHandle> {
300 &self.peer_comms
301 }
302
303 pub fn session_admission(&self) -> &Arc<dyn SessionAdmissionHandle> {
304 &self.session_admission
305 }
306
307 pub fn model_routing(&self) -> &Arc<dyn ModelRoutingHandle> {
308 &self.model_routing
309 }
310
311 pub fn auth_lease(&self) -> &Arc<dyn AuthLeaseHandle> {
312 &self.auth_lease
313 }
314
315 pub fn mcp_server_lifecycle(&self) -> &Arc<dyn McpServerLifecycleHandle> {
316 &self.mcp_server_lifecycle
317 }
318
319 pub fn peer_interaction(&self) -> &Arc<dyn PeerInteractionHandle> {
320 &self.peer_interaction
321 }
322
323 pub fn session_context(&self) -> &Arc<dyn SessionContextHandle> {
324 &self.session_context
325 }
326
327 pub fn session_claim_handle(&self) -> &Arc<dyn SessionClaimHandle> {
328 &self.session_claim_handle
329 }
330
331 pub fn interaction_stream(&self) -> &Arc<dyn InteractionStreamHandle> {
332 &self.interaction_stream
333 }
334
335 #[doc(hidden)]
336 pub fn __runtime_authority(&self) -> &(dyn Any + Send + Sync) {
337 self.runtime_authority.as_ref()
338 }
339}
340
341impl Clone for SessionRuntimeBindings {
342 fn clone(&self) -> Self {
343 Self {
344 session_id: self.session_id.clone(),
345 epoch_id: self.epoch_id.clone(),
346 ops_lifecycle: Arc::clone(&self.ops_lifecycle),
347 cursor_state: Arc::clone(&self.cursor_state),
348 tool_visibility_owner: Arc::clone(&self.tool_visibility_owner),
349 turn_state: Arc::clone(&self.turn_state),
350 comms_drain: Arc::clone(&self.comms_drain),
351 external_tool_surface: Arc::clone(&self.external_tool_surface),
352 peer_comms: Arc::clone(&self.peer_comms),
353 session_admission: Arc::clone(&self.session_admission),
354 model_routing: Arc::clone(&self.model_routing),
355 auth_lease: Arc::clone(&self.auth_lease),
356 mcp_server_lifecycle: Arc::clone(&self.mcp_server_lifecycle),
357 peer_interaction: Arc::clone(&self.peer_interaction),
358 session_context: Arc::clone(&self.session_context),
359 session_claim_handle: Arc::clone(&self.session_claim_handle),
360 interaction_stream: Arc::clone(&self.interaction_stream),
361 runtime_authority: Arc::clone(&self.runtime_authority),
362 }
363 }
364}
365
366impl std::fmt::Debug for SessionRuntimeBindings {
367 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
368 f.debug_struct("SessionRuntimeBindings")
369 .field("session_id", &self.session_id)
370 .field("epoch_id", &self.epoch_id)
371 .field("ops_lifecycle", &"<dyn OpsLifecycleRegistry>")
372 .field("cursor_state", &self.cursor_state)
373 .field("tool_visibility_owner", &"<dyn ToolVisibilityOwner>")
374 .field("turn_state", &"<dyn TurnStateHandle>")
375 .field("comms_drain", &"<dyn CommsDrainHandle>")
376 .field("external_tool_surface", &"<dyn ExternalToolSurfaceHandle>")
377 .field("peer_comms", &"<dyn PeerCommsHandle>")
378 .field("session_admission", &"<dyn SessionAdmissionHandle>")
379 .field("model_routing", &"<dyn ModelRoutingHandle>")
380 .field("auth_lease", &"<dyn AuthLeaseHandle>")
381 .field("mcp_server_lifecycle", &"<dyn McpServerLifecycleHandle>")
382 .field("peer_interaction", &"<dyn PeerInteractionHandle>")
383 .field("session_context", &"<dyn SessionContextHandle>")
384 .field("session_claim_handle", &"<dyn SessionClaimHandle>")
385 .field("interaction_stream", &"<dyn InteractionStreamHandle>")
386 .finish()
387 }
388}
389
390#[allow(clippy::large_enum_variant)]
406pub enum RuntimeBuildMode {
407 StandaloneEphemeral,
409 SessionOwned(SessionRuntimeBindings),
412}
413
414impl Clone for RuntimeBuildMode {
415 fn clone(&self) -> Self {
416 match self {
417 Self::StandaloneEphemeral => Self::StandaloneEphemeral,
418 Self::SessionOwned(b) => Self::SessionOwned(b.clone()),
419 }
420 }
421}
422
423impl std::fmt::Debug for RuntimeBuildMode {
424 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
425 match self {
426 Self::StandaloneEphemeral => write!(f, "StandaloneEphemeral"),
427 Self::SessionOwned(b) => f
428 .debug_tuple("SessionOwned")
429 .field(&b.session_id)
430 .field(&b.epoch_id)
431 .finish(),
432 }
433 }
434}