lash_core/session/
execution_context.rs1use 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}