use std::sync::Arc;
use std::sync::Mutex;
use lash_trace::{TraceContext, TraceLevel, TraceSink};
use super::process::ProcessRegistry;
use super::{
EffectHost, InlineEffectHost, ProcessWorkPoke, QueuedWorkPoke, SessionStoreFactory,
TerminationPolicy,
};
#[derive(Clone)]
pub struct RuntimeHostConfig {
pub profile: RuntimeHostProfileConfig,
pub durability: RuntimeDurabilityConfig,
pub providers: RuntimeProviderConfig,
pub prompt: RuntimePromptConfig,
pub control: RuntimeControlConfig,
pub tracing: RuntimeTracingConfig,
}
#[derive(Clone)]
pub struct RuntimeHostProfileConfig {
pub host_profile_id: String,
}
#[derive(Clone)]
pub struct RuntimeDurabilityConfig {
pub attachment_store: Arc<dyn crate::AttachmentStore>,
pub lashlang_artifact_store: Arc<dyn lashlang::LashlangArtifactStore>,
pub lashlang_process_cache: Arc<Mutex<lashlang::CompiledProcessCache>>,
}
#[derive(Clone)]
pub struct RuntimeProviderConfig {
pub provider_resolver: Arc<dyn crate::RuntimeProviderResolver>,
}
#[derive(Clone)]
pub struct RuntimePromptConfig {
pub prompt: crate::PromptLayer,
}
#[derive(Clone)]
pub struct RuntimeControlConfig {
pub effect_host: Arc<dyn EffectHost>,
pub process_cancel_ability: Arc<dyn crate::ProcessCancelAbility>,
pub termination: TerminationPolicy,
}
#[derive(Clone)]
pub struct RuntimeTracingConfig {
pub trace_sink: Option<Arc<dyn TraceSink>>,
pub lashlang_execution_sink: Option<Arc<dyn TraceSink>>,
pub trace_level: TraceLevel,
pub trace_context: TraceContext,
}
impl RuntimeHostConfig {
pub fn new(
effect_host: Arc<dyn EffectHost>,
lashlang_artifact_store: Arc<dyn lashlang::LashlangArtifactStore>,
attachment_store: Arc<dyn crate::AttachmentStore>,
) -> Self {
Self {
profile: RuntimeHostProfileConfig {
host_profile_id: "default".to_string(),
},
durability: RuntimeDurabilityConfig {
attachment_store,
lashlang_artifact_store,
lashlang_process_cache: Arc::new(Mutex::new(lashlang::CompiledProcessCache::new())),
},
providers: RuntimeProviderConfig {
provider_resolver: Arc::new(crate::EmptyProviderResolver),
},
prompt: RuntimePromptConfig {
prompt: crate::PromptLayer::new(),
},
control: RuntimeControlConfig {
termination: TerminationPolicy::default(),
effect_host,
process_cancel_ability: Arc::new(crate::DefaultProcessCancelAbility),
},
tracing: RuntimeTracingConfig {
trace_sink: None,
lashlang_execution_sink: None,
trace_level: TraceLevel::Standard,
trace_context: TraceContext::default(),
},
}
}
pub fn in_memory() -> Self {
Self::new(
Arc::new(InlineEffectHost::default()),
lashlang::global_in_memory_lashlang_artifact_store(),
Arc::new(crate::InMemoryAttachmentStore::new()),
)
}
pub fn with_process_cancel_ability(
mut self,
process_cancel_ability: Arc<dyn crate::ProcessCancelAbility>,
) -> Self {
self.control.process_cancel_ability = process_cancel_ability;
self
}
}
#[derive(Clone)]
pub struct EmbeddedRuntimeHost {
pub core: RuntimeHostConfig,
pub session_store_factory: Option<Arc<dyn SessionStoreFactory>>,
pub host_event_store: Option<Arc<dyn crate::HostEventStore>>,
}
impl EmbeddedRuntimeHost {
pub fn new(core: RuntimeHostConfig) -> Self {
Self {
core,
session_store_factory: None,
host_event_store: Some(Arc::new(crate::InMemoryHostEventStore::default())),
}
}
pub fn with_session_store_factory(
mut self,
session_store_factory: Arc<dyn SessionStoreFactory>,
) -> Self {
self.session_store_factory = Some(session_store_factory);
self
}
pub fn with_host_event_store(mut self, store: Arc<dyn crate::HostEventStore>) -> Self {
self.host_event_store = Some(store);
self
}
}
#[derive(Clone)]
pub struct ProcessRuntimeHost {
pub embedded: EmbeddedRuntimeHost,
pub process_registry: Arc<dyn ProcessRegistry>,
}
impl ProcessRuntimeHost {
pub fn new(embedded: EmbeddedRuntimeHost, process_registry: Arc<dyn ProcessRegistry>) -> Self {
Self {
embedded,
process_registry,
}
}
}
#[derive(Clone)]
pub(crate) struct RuntimeHost {
pub core: RuntimeHostConfig,
pub session_store_factory: Option<Arc<dyn SessionStoreFactory>>,
pub host_event_store: Option<Arc<dyn crate::HostEventStore>>,
pub process_registry: Option<Arc<dyn ProcessRegistry>>,
pub process_work_poke: Option<ProcessWorkPoke>,
pub queued_work_poke: Option<QueuedWorkPoke>,
}
impl RuntimeHost {
pub(crate) fn resolve_session_policy(
&self,
session_id: &str,
policy: crate::SessionPolicy,
) -> Result<crate::RuntimeSessionPolicy, crate::SessionError> {
let provider_id = policy.recorded_provider_id();
let binding = self
.core
.providers
.provider_resolver
.resolve_provider_binding(provider_id)
.map_err(|err| match err {
crate::ProviderResolutionError::MissingProviderId => {
crate::SessionError::ProviderUnconfigured {
session_id: session_id.to_string(),
}
}
crate::ProviderResolutionError::UnknownProvider { provider_id } => {
crate::SessionError::ProviderUnavailable {
provider_id,
session_id: session_id.to_string(),
}
}
crate::ProviderResolutionError::ProviderIdMismatch { expected, actual } => {
crate::SessionError::ProviderMismatch {
expected,
actual,
session_id: session_id.to_string(),
}
}
})?;
Ok(crate::RuntimeSessionPolicy::new(policy, binding))
}
}
impl From<EmbeddedRuntimeHost> for RuntimeHost {
fn from(value: EmbeddedRuntimeHost) -> Self {
Self {
core: value.core,
session_store_factory: value.session_store_factory,
host_event_store: value.host_event_store,
process_registry: None,
process_work_poke: None,
queued_work_poke: None,
}
}
}
impl From<ProcessRuntimeHost> for RuntimeHost {
fn from(value: ProcessRuntimeHost) -> Self {
Self {
core: value.embedded.core,
session_store_factory: value.embedded.session_store_factory,
host_event_store: value.embedded.host_event_store,
process_registry: Some(value.process_registry),
process_work_poke: None,
queued_work_poke: None,
}
}
}