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 profile: RuntimeHostProfileConfig,
16 pub durability: RuntimeDurabilityConfig,
17 pub providers: RuntimeProviderConfig,
18 pub prompt: RuntimePromptConfig,
19 pub control: RuntimeControlConfig,
20 pub tracing: RuntimeTracingConfig,
21}
22
23#[derive(Clone)]
24pub struct RuntimeHostProfileConfig {
25 pub host_profile_id: String,
26}
27
28#[derive(Clone)]
29pub struct RuntimeDurabilityConfig {
30 pub attachment_store: Arc<dyn crate::AttachmentStore>,
31 pub lashlang_artifact_store: Arc<dyn lashlang::LashlangArtifactStore>,
32 pub lashlang_process_cache: Arc<Mutex<lashlang::CompiledProcessCache>>,
33}
34
35#[derive(Clone)]
36pub struct RuntimeProviderConfig {
37 pub provider_resolver: Arc<dyn crate::RuntimeProviderResolver>,
38}
39
40#[derive(Clone)]
41pub struct RuntimePromptConfig {
42 pub prompt: crate::PromptLayer,
43}
44
45#[derive(Clone)]
46pub struct RuntimeControlConfig {
47 pub effect_host: Arc<dyn EffectHost>,
48 pub process_cancel_ability: Arc<dyn crate::ProcessCancelAbility>,
49 pub termination: TerminationPolicy,
50}
51
52#[derive(Clone)]
53pub struct RuntimeTracingConfig {
54 pub trace_sink: Option<Arc<dyn TraceSink>>,
55 pub lashlang_execution_sink: Option<Arc<dyn TraceSink>>,
56 pub trace_level: TraceLevel,
57 pub trace_context: TraceContext,
58}
59
60impl RuntimeHostConfig {
61 pub fn new(
70 effect_host: Arc<dyn EffectHost>,
71 lashlang_artifact_store: Arc<dyn lashlang::LashlangArtifactStore>,
72 attachment_store: Arc<dyn crate::AttachmentStore>,
73 ) -> Self {
74 Self {
75 profile: RuntimeHostProfileConfig {
76 host_profile_id: "default".to_string(),
77 },
78 durability: RuntimeDurabilityConfig {
79 attachment_store,
80 lashlang_artifact_store,
81 lashlang_process_cache: Arc::new(Mutex::new(lashlang::CompiledProcessCache::new())),
82 },
83 providers: RuntimeProviderConfig {
84 provider_resolver: Arc::new(crate::EmptyProviderResolver),
85 },
86 prompt: RuntimePromptConfig {
87 prompt: crate::PromptLayer::new(),
88 },
89 control: RuntimeControlConfig {
90 termination: TerminationPolicy::default(),
91 effect_host,
92 process_cancel_ability: Arc::new(crate::DefaultProcessCancelAbility),
93 },
94 tracing: RuntimeTracingConfig {
95 trace_sink: None,
96 lashlang_execution_sink: None,
97 trace_level: TraceLevel::Standard,
98 trace_context: TraceContext::default(),
99 },
100 }
101 }
102
103 pub fn in_memory() -> Self {
110 Self::new(
111 Arc::new(InlineEffectHost::default()),
112 lashlang::global_in_memory_lashlang_artifact_store(),
113 Arc::new(crate::InMemoryAttachmentStore::new()),
114 )
115 }
116
117 pub fn with_process_cancel_ability(
118 mut self,
119 process_cancel_ability: Arc<dyn crate::ProcessCancelAbility>,
120 ) -> Self {
121 self.control.process_cancel_ability = process_cancel_ability;
122 self
123 }
124}
125
126#[derive(Clone)]
128pub struct EmbeddedRuntimeHost {
129 pub core: RuntimeHostConfig,
130 pub session_store_factory: Option<Arc<dyn SessionStoreFactory>>,
131}
132
133impl EmbeddedRuntimeHost {
134 pub fn new(core: RuntimeHostConfig) -> Self {
135 Self {
136 core,
137 session_store_factory: None,
138 }
139 }
140
141 pub fn with_session_store_factory(
142 mut self,
143 session_store_factory: Arc<dyn SessionStoreFactory>,
144 ) -> Self {
145 self.session_store_factory = Some(session_store_factory);
146 self
147 }
148}
149
150#[derive(Clone)]
152pub struct ProcessRuntimeHost {
153 pub embedded: EmbeddedRuntimeHost,
154 pub process_registry: Arc<dyn ProcessRegistry>,
155}
156
157impl ProcessRuntimeHost {
158 pub fn new(embedded: EmbeddedRuntimeHost, process_registry: Arc<dyn ProcessRegistry>) -> Self {
159 Self {
160 embedded,
161 process_registry,
162 }
163 }
164}
165
166#[derive(Clone)]
167pub(crate) struct RuntimeHost {
168 pub core: RuntimeHostConfig,
169 pub session_store_factory: Option<Arc<dyn SessionStoreFactory>>,
170 pub process_registry: Option<Arc<dyn ProcessRegistry>>,
171 pub process_work_poke: Option<ProcessWorkPoke>,
175 pub queued_work_poke: Option<QueuedWorkPoke>,
178}
179
180impl RuntimeHost {
181 pub(crate) fn resolve_session_policy(
182 &self,
183 session_id: &str,
184 policy: crate::SessionPolicy,
185 ) -> Result<crate::RuntimeSessionPolicy, crate::SessionError> {
186 let provider_id = policy.recorded_provider_id();
187 let binding = self
188 .core
189 .providers
190 .provider_resolver
191 .resolve_provider_binding(provider_id)
192 .map_err(|err| match err {
193 crate::ProviderResolutionError::MissingProviderId => {
194 crate::SessionError::ProviderUnconfigured {
195 session_id: session_id.to_string(),
196 }
197 }
198 crate::ProviderResolutionError::UnknownProvider { provider_id } => {
199 crate::SessionError::ProviderUnavailable {
200 provider_id,
201 session_id: session_id.to_string(),
202 }
203 }
204 crate::ProviderResolutionError::ProviderIdMismatch { expected, actual } => {
205 crate::SessionError::ProviderMismatch {
206 expected,
207 actual,
208 session_id: session_id.to_string(),
209 }
210 }
211 })?;
212 Ok(crate::RuntimeSessionPolicy::new(policy, binding))
213 }
214}
215
216impl From<EmbeddedRuntimeHost> for RuntimeHost {
217 fn from(value: EmbeddedRuntimeHost) -> Self {
218 Self {
219 core: value.core,
220 session_store_factory: value.session_store_factory,
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 process_registry: Some(value.process_registry),
234 process_work_poke: None,
235 queued_work_poke: None,
236 }
237 }
238}