1use std::sync::Arc;
2use std::sync::Mutex;
3
4use lash_trace::{TraceContext, TraceLevel, TraceSink};
5
6use super::process::ProcessRegistry;
7use super::{
8 EffectHost, InlineEffectHost, ProcessWorkPoke, QueuedWorkPoke, SessionStoreFactory,
9 TerminationPolicy,
10};
11
12#[derive(Clone)]
14pub struct RuntimeHostConfig {
15 pub durability: RuntimeDurabilityConfig,
16 pub providers: RuntimeProviderConfig,
17 pub prompt: RuntimePromptConfig,
18 pub control: RuntimeControlConfig,
19 pub tracing: RuntimeTracingConfig,
20}
21
22#[derive(Clone)]
23pub struct RuntimeDurabilityConfig {
24 pub attachment_store: Arc<dyn crate::AttachmentStore>,
25 pub lashlang_artifact_store: Arc<dyn lashlang::LashlangArtifactStore>,
26 pub lashlang_process_cache: Arc<Mutex<lashlang::CompiledProcessCache>>,
27}
28
29#[derive(Clone)]
30pub struct RuntimeProviderConfig {
31 pub provider_resolver: Arc<dyn crate::RuntimeProviderResolver>,
32}
33
34#[derive(Clone)]
35pub struct RuntimePromptConfig {
36 pub prompt: crate::PromptLayer,
37}
38
39#[derive(Clone)]
40pub struct RuntimeControlConfig {
41 pub effect_host: Arc<dyn EffectHost>,
42 pub process_cancel_ability: Arc<dyn crate::ProcessCancelAbility>,
43 pub termination: TerminationPolicy,
44}
45
46#[derive(Clone)]
47pub struct RuntimeTracingConfig {
48 pub trace_sink: Option<Arc<dyn TraceSink>>,
49 pub lashlang_execution_sink: Option<Arc<dyn TraceSink>>,
50 pub trace_level: TraceLevel,
51 pub trace_context: TraceContext,
52}
53
54impl RuntimeHostConfig {
55 pub fn new(
64 effect_host: Arc<dyn EffectHost>,
65 lashlang_artifact_store: Arc<dyn lashlang::LashlangArtifactStore>,
66 attachment_store: Arc<dyn crate::AttachmentStore>,
67 ) -> Self {
68 Self {
69 durability: RuntimeDurabilityConfig {
70 attachment_store,
71 lashlang_artifact_store,
72 lashlang_process_cache: Arc::new(Mutex::new(lashlang::CompiledProcessCache::new())),
73 },
74 providers: RuntimeProviderConfig {
75 provider_resolver: Arc::new(crate::EmptyProviderResolver),
76 },
77 prompt: RuntimePromptConfig {
78 prompt: crate::PromptLayer::new(),
79 },
80 control: RuntimeControlConfig {
81 termination: TerminationPolicy::default(),
82 effect_host,
83 process_cancel_ability: Arc::new(crate::DefaultProcessCancelAbility),
84 },
85 tracing: RuntimeTracingConfig {
86 trace_sink: None,
87 lashlang_execution_sink: None,
88 trace_level: TraceLevel::Standard,
89 trace_context: TraceContext::default(),
90 },
91 }
92 }
93
94 pub fn in_memory() -> Self {
101 Self::new(
102 Arc::new(InlineEffectHost::default()),
103 lashlang::global_in_memory_lashlang_artifact_store(),
104 Arc::new(crate::InMemoryAttachmentStore::new()),
105 )
106 }
107
108 pub fn with_process_cancel_ability(
109 mut self,
110 process_cancel_ability: Arc<dyn crate::ProcessCancelAbility>,
111 ) -> Self {
112 self.control.process_cancel_ability = process_cancel_ability;
113 self
114 }
115}
116
117#[derive(Clone)]
119pub struct EmbeddedRuntimeHost {
120 pub core: RuntimeHostConfig,
121 pub session_store_factory: Option<Arc<dyn SessionStoreFactory>>,
122 pub trigger_store: Option<Arc<dyn crate::TriggerStore>>,
123}
124
125impl EmbeddedRuntimeHost {
126 pub fn new(core: RuntimeHostConfig) -> Self {
127 Self {
128 core,
129 session_store_factory: None,
130 trigger_store: Some(Arc::new(crate::InMemoryTriggerStore::default())),
131 }
132 }
133
134 pub fn with_session_store_factory(
135 mut self,
136 session_store_factory: Arc<dyn SessionStoreFactory>,
137 ) -> Self {
138 self.session_store_factory = Some(session_store_factory);
139 self
140 }
141
142 pub fn with_trigger_store(mut self, store: Arc<dyn crate::TriggerStore>) -> Self {
143 self.trigger_store = Some(store);
144 self
145 }
146}
147
148#[derive(Clone)]
150pub struct ProcessRuntimeHost {
151 pub embedded: EmbeddedRuntimeHost,
152 pub process_registry: Arc<dyn ProcessRegistry>,
153}
154
155impl ProcessRuntimeHost {
156 pub fn new(embedded: EmbeddedRuntimeHost, process_registry: Arc<dyn ProcessRegistry>) -> Self {
157 Self {
158 embedded,
159 process_registry,
160 }
161 }
162}
163
164#[derive(Clone)]
165pub(crate) struct RuntimeHost {
166 pub core: RuntimeHostConfig,
167 pub session_store_factory: Option<Arc<dyn SessionStoreFactory>>,
168 pub trigger_store: Option<Arc<dyn crate::TriggerStore>>,
169 pub process_registry: Option<Arc<dyn ProcessRegistry>>,
170 pub process_work_poke: Option<ProcessWorkPoke>,
174 pub queued_work_poke: Option<QueuedWorkPoke>,
177}
178
179impl RuntimeHost {
180 pub(crate) fn resolve_session_policy(
181 &self,
182 session_id: &str,
183 policy: crate::SessionPolicy,
184 ) -> Result<crate::RuntimeSessionPolicy, crate::SessionError> {
185 let provider_id = policy.recorded_provider_id();
186 let binding = self
187 .core
188 .providers
189 .provider_resolver
190 .resolve_provider_binding(provider_id)
191 .map_err(|err| match err {
192 crate::ProviderResolutionError::MissingProviderId => {
193 crate::SessionError::ProviderUnconfigured {
194 session_id: session_id.to_string(),
195 }
196 }
197 crate::ProviderResolutionError::UnknownProvider { provider_id } => {
198 crate::SessionError::ProviderUnavailable {
199 provider_id,
200 session_id: session_id.to_string(),
201 }
202 }
203 crate::ProviderResolutionError::ProviderIdMismatch { expected, actual } => {
204 crate::SessionError::ProviderMismatch {
205 expected,
206 actual,
207 session_id: session_id.to_string(),
208 }
209 }
210 })?;
211 Ok(crate::RuntimeSessionPolicy::new(policy, binding))
212 }
213}
214
215impl From<EmbeddedRuntimeHost> for RuntimeHost {
216 fn from(value: EmbeddedRuntimeHost) -> Self {
217 Self {
218 core: value.core,
219 session_store_factory: value.session_store_factory,
220 trigger_store: value.trigger_store,
221 process_registry: None,
222 process_work_poke: None,
223 queued_work_poke: None,
224 }
225 }
226}
227
228impl From<ProcessRuntimeHost> for RuntimeHost {
229 fn from(value: ProcessRuntimeHost) -> Self {
230 Self {
231 core: value.embedded.core,
232 session_store_factory: value.embedded.session_store_factory,
233 trigger_store: value.embedded.trigger_store,
234 process_registry: Some(value.process_registry),
235 process_work_poke: None,
236 queued_work_poke: None,
237 }
238 }
239}