lash_core/runtime/
environment.rs1use std::path::PathBuf;
26use std::sync::Arc;
27
28use lash_trace::{JsonlTraceSink, TraceContext, TraceLevel, TraceSink};
29
30use super::TerminationPolicy;
31use super::host::BackgroundTaskHost;
32
33#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
42pub enum Residency {
43 #[default]
46 KeepAll,
47 ActivePathOnly,
53}
54
55#[derive(Clone)]
62pub struct RuntimeEnvironment {
63 pub plugin_host: Option<Arc<crate::PluginHost>>,
66
67 pub residency: Residency,
73
74 pub background_task_host: Option<Arc<dyn BackgroundTaskHost>>,
76
77 pub session_store_factory: Option<Arc<dyn crate::SessionStoreFactory>>,
80
81 pub attachment_store: Arc<dyn crate::AttachmentStore>,
85 pub prompt: crate::PromptLayer,
86 pub trace_sink: Option<Arc<dyn TraceSink>>,
87 pub trace_level: TraceLevel,
88 pub trace_context: TraceContext,
89 pub termination: TerminationPolicy,
90}
91
92impl Default for RuntimeEnvironment {
93 fn default() -> Self {
94 Self {
95 plugin_host: None,
96 residency: Residency::default(),
97 background_task_host: None,
98 session_store_factory: None,
99 attachment_store: Arc::new(crate::InMemoryAttachmentStore::new()),
100 prompt: crate::PromptLayer::new(),
101 trace_sink: None,
102 trace_level: TraceLevel::Standard,
103 trace_context: TraceContext::default(),
104 termination: TerminationPolicy::default(),
105 }
106 }
107}
108
109impl RuntimeEnvironment {
110 pub fn builder() -> RuntimeEnvironmentBuilder {
111 RuntimeEnvironmentBuilder::default()
112 }
113}
114
115pub struct ParkedSession {
120 pub(crate) session_id: String,
121 pub(crate) store: Arc<dyn crate::store::RuntimePersistence>,
122 pub(crate) policy: crate::SessionPolicy,
123}
124
125impl ParkedSession {
126 pub fn session_id(&self) -> &str {
127 &self.session_id
128 }
129}
130
131#[derive(Default)]
133pub struct RuntimeEnvironmentBuilder {
134 env: RuntimeEnvironment,
135}
136
137impl RuntimeEnvironmentBuilder {
138 pub fn with_plugin_host(mut self, host: Arc<crate::PluginHost>) -> Self {
139 self.env.plugin_host = Some(if self.env.background_task_host.is_some() {
140 Arc::new(host.as_ref().clone().with_background_tasks())
141 } else {
142 host
143 });
144 self
145 }
146
147 pub fn with_residency(mut self, residency: Residency) -> Self {
148 self.env.residency = residency;
149 self
150 }
151
152 pub fn with_background_task_host(
153 mut self,
154 background_task_host: Arc<dyn BackgroundTaskHost>,
155 ) -> Self {
156 self.env.background_task_host = Some(background_task_host);
157 if let Some(host) = self.env.plugin_host.take() {
158 self.env.plugin_host = Some(Arc::new(host.as_ref().clone().with_background_tasks()));
159 }
160 self
161 }
162
163 pub fn with_session_store_factory(
164 mut self,
165 factory: Arc<dyn crate::SessionStoreFactory>,
166 ) -> Self {
167 self.env.session_store_factory = Some(factory);
168 self
169 }
170
171 pub fn with_attachment_store(mut self, store: Arc<dyn crate::AttachmentStore>) -> Self {
172 self.env.attachment_store = store;
173 self
174 }
175
176 pub fn with_prompt_template(mut self, template: crate::PromptTemplate) -> Self {
177 self.env.prompt.template = Some(template);
178 self
179 }
180
181 pub fn with_prompt_contribution(mut self, contribution: crate::PromptContribution) -> Self {
182 self.env.prompt.add_contribution(contribution);
183 self
184 }
185
186 pub fn with_replaced_prompt_slot(
187 mut self,
188 slot: crate::PromptSlot,
189 contributions: impl IntoIterator<Item = crate::PromptContribution>,
190 ) -> Self {
191 self.env.prompt.replace_slot(slot, contributions);
192 self
193 }
194
195 pub fn with_cleared_prompt_slot(mut self, slot: crate::PromptSlot) -> Self {
196 self.env.prompt.clear_slot(slot);
197 self
198 }
199
200 pub fn with_prompt_layer(mut self, prompt: crate::PromptLayer) -> Self {
201 self.env.prompt = prompt;
202 self
203 }
204
205 pub fn with_trace_jsonl_path(mut self, path: Option<PathBuf>) -> Self {
206 self.env.trace_sink = path.map(|p| Arc::new(JsonlTraceSink::new(p)) as Arc<dyn TraceSink>);
207 self
208 }
209
210 pub fn with_trace_sink(mut self, sink: Option<Arc<dyn TraceSink>>) -> Self {
211 self.env.trace_sink = sink;
212 self
213 }
214
215 pub fn with_trace_level(mut self, level: TraceLevel) -> Self {
216 self.env.trace_level = level;
217 self
218 }
219
220 pub fn with_trace_context(mut self, context: TraceContext) -> Self {
221 self.env.trace_context = context;
222 self
223 }
224
225 pub fn with_termination(mut self, termination: TerminationPolicy) -> Self {
226 self.env.termination = termination;
227 self
228 }
229
230 pub fn build(self) -> RuntimeEnvironment {
231 self.env
232 }
233}