use std::sync::{Arc, Mutex};
use crate::meerkat_machine::dsl as mm_dsl;
use crate::meerkat_machine_types::MeerkatMachineFieldlessRuntimeInternalInput;
use meerkat_core::handles::DslTransitionError;
fn map_kernel_error(
err: mm_dsl::MeerkatMachineTransitionError,
context: &'static str,
) -> DslTransitionError {
let reason = err.to_string();
match err {
mm_dsl::MeerkatMachineTransitionError::GuardRejected { .. } => {
DslTransitionError::guard_rejected(context, reason)
}
mm_dsl::MeerkatMachineTransitionError::NoMatchingTransition { .. } => {
DslTransitionError::no_matching(context, reason)
}
}
}
mod auth_lease;
mod comms_drain;
mod external_tool_surface;
mod interaction_stream;
mod mcp_server_lifecycle;
mod model_routing;
#[cfg(not(target_arch = "wasm32"))]
mod oauth_flow;
mod peer_comms;
mod peer_interaction;
mod realtime_product_turn;
mod session_admission;
mod session_claim;
mod session_context;
mod turn_state;
pub use auth_lease::RuntimeAuthLeaseHandle;
pub use comms_drain::RuntimeCommsDrainHandle;
pub use external_tool_surface::RuntimeExternalToolSurfaceHandle;
pub use interaction_stream::RuntimeInteractionStreamHandle;
pub use mcp_server_lifecycle::RuntimeMcpServerLifecycleHandle;
pub use model_routing::RuntimeModelRoutingHandle;
#[cfg(not(target_arch = "wasm32"))]
pub use oauth_flow::RuntimeOAuthFlowHandle;
pub use peer_comms::RuntimePeerCommsHandle;
pub use peer_interaction::RuntimePeerInteractionHandle;
pub use realtime_product_turn::RuntimeRealtimeProductTurnHandle;
pub use session_admission::RuntimeSessionAdmissionHandle;
pub use session_claim::RuntimeSessionClaimRegistry;
pub use session_context::RuntimeSessionContextHandle;
pub use turn_state::RuntimeTurnStateHandle;
pub struct HandleDslAuthority {
inner: Arc<Mutex<mm_dsl::MeerkatMachineAuthority>>,
}
impl HandleDslAuthority {
pub fn from_shared(inner: Arc<Mutex<mm_dsl::MeerkatMachineAuthority>>) -> Self {
Self { inner }
}
pub fn ephemeral() -> Self {
let state = mm_dsl::MeerkatMachineState::default();
Self {
inner: Arc::new(Mutex::new(mm_dsl::MeerkatMachineAuthority::from_state(
state,
))),
}
}
pub fn apply_input(
&self,
input: mm_dsl::MeerkatMachineInput,
context: &'static str,
) -> Result<(), DslTransitionError> {
self.apply_input_with_effects(input, context).map(|_| ())
}
pub fn apply_input_with_effects(
&self,
input: mm_dsl::MeerkatMachineInput,
context: &'static str,
) -> Result<Vec<mm_dsl::MeerkatMachineEffect>, DslTransitionError> {
MeerkatMachineFieldlessRuntimeInternalInput::reject_raw_dsl_input(&input)
.map_err(|reason| DslTransitionError::no_matching(context, reason))?;
let mut guard = self
.inner
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner);
mm_dsl::MeerkatMachineMutator::apply(&mut *guard, input)
.map(|transition| transition.effects)
.map_err(|err| map_kernel_error(err, context))
}
pub fn apply_input_with_effects_and_sample<S>(
&self,
input: mm_dsl::MeerkatMachineInput,
context: &'static str,
sample: impl FnOnce(&[mm_dsl::MeerkatMachineEffect]) -> S,
) -> Result<S, DslTransitionError> {
MeerkatMachineFieldlessRuntimeInternalInput::reject_raw_dsl_input(&input)
.map_err(|reason| DslTransitionError::no_matching(context, reason))?;
let mut guard = self
.inner
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner);
let effects = mm_dsl::MeerkatMachineMutator::apply(&mut *guard, input)
.map(|transition| transition.effects)
.map_err(|err| map_kernel_error(err, context))?;
Ok(sample(&effects))
}
pub fn apply_signal(
&self,
signal: mm_dsl::MeerkatMachineSignal,
context: &'static str,
) -> Result<(), DslTransitionError> {
self.apply_signal_with_effects(signal, context).map(|_| ())
}
pub fn apply_signal_with_effects(
&self,
signal: mm_dsl::MeerkatMachineSignal,
context: &'static str,
) -> Result<Vec<mm_dsl::MeerkatMachineEffect>, DslTransitionError> {
let mut guard = self
.inner
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner);
guard
.apply_signal(signal)
.map(|transition| transition.effects)
.map_err(|err| map_kernel_error(err, context))
}
pub fn apply_signal_and_sample<S>(
&self,
signal: mm_dsl::MeerkatMachineSignal,
context: &'static str,
sample: impl FnOnce(&mm_dsl::MeerkatMachineState) -> S,
) -> Result<S, DslTransitionError> {
let mut guard = self
.inner
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner);
guard
.apply_signal(signal)
.map_err(|err| map_kernel_error(err, context))?;
Ok(sample(&guard.state))
}
pub fn snapshot_state(&self) -> mm_dsl::MeerkatMachineState {
let guard = self
.inner
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner);
guard.state.clone()
}
pub fn with_state_lock<R>(&self, body: impl FnOnce(&mm_dsl::MeerkatMachineState) -> R) -> R {
let guard = self
.inner
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner);
body(&guard.state)
}
}
impl std::fmt::Debug for HandleDslAuthority {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("HandleDslAuthority").finish_non_exhaustive()
}
}