Skip to main content

lash_core/session/
execution_context.rs

1use std::sync::Arc;
2
3use tokio::sync::{mpsc::Sender, mpsc::UnboundedSender};
4use tokio_util::sync::CancellationToken;
5
6use super::async_handles::AsyncToolHandleMap;
7use crate::tool_dispatch::ToolDispatchContext;
8use crate::{SandboxMessage, TurnActivity, TurnActivityId, TurnEvent};
9
10#[derive(Clone)]
11pub struct ModeExecutionContext {
12    pub(super) session_id: String,
13    pub(super) execution_mode: crate::ExecutionMode,
14    pub(super) dispatch: Arc<ToolDispatchContext>,
15    pub(super) async_tool_handles: AsyncToolHandleMap,
16    pub(super) message_tx: Option<UnboundedSender<SandboxMessage>>,
17    attachment_store: Arc<dyn crate::AttachmentStore>,
18    chronological_projection: Arc<crate::ChronologicalProjection>,
19    mode_extension: Option<crate::ModeTurnExtensionHandle>,
20    turn_context: crate::TurnContext,
21    pub(super) turn_event_tx: Option<Sender<TurnActivity>>,
22    pub(super) cancellation_token: Option<CancellationToken>,
23}
24
25impl ModeExecutionContext {
26    #[allow(
27        clippy::too_many_arguments,
28        reason = "mode execution bridge carries explicit per-turn runtime dependencies"
29    )]
30    pub(super) fn new(
31        session_id: String,
32        execution_mode: crate::ExecutionMode,
33        dispatch: Arc<ToolDispatchContext>,
34        async_tool_handles: AsyncToolHandleMap,
35        message_tx: Option<UnboundedSender<SandboxMessage>>,
36        attachment_store: Arc<dyn crate::AttachmentStore>,
37        chronological_projection: Arc<crate::ChronologicalProjection>,
38        mode_extension: Option<crate::ModeTurnExtensionHandle>,
39        turn_context: crate::TurnContext,
40    ) -> Self {
41        Self {
42            session_id,
43            execution_mode,
44            dispatch,
45            async_tool_handles,
46            message_tx,
47            attachment_store,
48            chronological_projection,
49            mode_extension,
50            turn_context,
51            turn_event_tx: None,
52            cancellation_token: None,
53        }
54    }
55
56    pub fn session_id(&self) -> &str {
57        &self.session_id
58    }
59
60    pub fn execution_mode(&self) -> &crate::ExecutionMode {
61        &self.execution_mode
62    }
63
64    pub fn attachment_store(&self) -> Arc<dyn crate::AttachmentStore> {
65        Arc::clone(&self.attachment_store)
66    }
67
68    pub fn chronological_projection(&self) -> Arc<crate::ChronologicalProjection> {
69        Arc::clone(&self.chronological_projection)
70    }
71
72    pub fn mode_extension<T: 'static>(&self) -> Option<&T> {
73        self.mode_extension
74            .as_ref()
75            .and_then(|extension| extension.as_any().downcast_ref::<T>())
76    }
77
78    pub fn turn_context(&self) -> &crate::TurnContext {
79        &self.turn_context
80    }
81
82    pub(super) async fn emit_turn_activity(
83        &self,
84        correlation_id: TurnActivityId,
85        event: TurnEvent,
86    ) {
87        if let Some(tx) = &self.turn_event_tx {
88            let _ = tx.send(TurnActivity::new(correlation_id, event)).await;
89        }
90    }
91
92    pub(crate) fn with_turn_event_sender(mut self, turn_event_tx: Sender<TurnActivity>) -> Self {
93        self.turn_event_tx = Some(turn_event_tx);
94        self
95    }
96
97    pub(crate) fn with_cancellation_token(mut self, cancellation_token: CancellationToken) -> Self {
98        self.cancellation_token = Some(cancellation_token);
99        self
100    }
101
102    pub(crate) fn tool_execution_mode(&self, name: &str) -> crate::ToolExecutionMode {
103        crate::tool_dispatch::resolve_tool_execution_mode(&self.dispatch, name)
104    }
105}