1use super::*;
2use crate::input_state::StoredInputState;
3
4#[cfg_attr(not(target_arch = "wasm32"), async_trait::async_trait)]
5#[cfg_attr(target_arch = "wasm32", async_trait::async_trait(?Send))]
6impl SessionServiceRuntimeExt for MeerkatMachine {
7 fn runtime_mode(&self) -> RuntimeMode {
8 self.mode
9 }
10
11 async fn accept_input(
12 &self,
13 session_id: &SessionId,
14 input: Input,
15 ) -> Result<AcceptOutcome, RuntimeDriverError> {
16 let runtime_id = MeerkatMachine::logical_runtime_id(session_id);
17 match self
18 .execute_meerkat_machine_command(
19 None,
20 MeerkatMachineCommand::Ingest { runtime_id, input },
21 )
22 .await
23 .map_err(MeerkatMachine::driver_error_from_command_error)?
24 {
25 MeerkatMachineCommandResult::AcceptOutcome(outcome) => Ok(outcome),
26 other => Err(RuntimeDriverError::Internal(format!(
27 "unexpected MeerkatMachineCommandResult for SessionServiceRuntimeExt::accept_input: {other:?}"
28 ))),
29 }
30 }
31
32 async fn accept_input_with_completion(
33 &self,
34 session_id: &SessionId,
35 input: Input,
36 ) -> Result<(AcceptOutcome, Option<crate::completion::CompletionHandle>), RuntimeDriverError>
37 {
38 Box::pin(MeerkatMachine::accept_input_with_completion(
39 self, session_id, input,
40 ))
41 .await
42 }
43
44 async fn runtime_state(
45 &self,
46 session_id: &SessionId,
47 ) -> Result<RuntimeState, RuntimeDriverError> {
48 let runtime_id = MeerkatMachine::logical_runtime_id(session_id);
49 match self
50 .execute_meerkat_machine_command(
51 None,
52 MeerkatMachineCommand::RuntimeState { runtime_id },
53 )
54 .await
55 .map_err(MeerkatMachine::driver_error_from_command_error)?
56 {
57 MeerkatMachineCommandResult::RuntimeState(state) => Ok(state),
58 other => Err(RuntimeDriverError::Internal(format!(
59 "unexpected MeerkatMachineCommandResult for SessionServiceRuntimeExt::runtime_state: {other:?}"
60 ))),
61 }
62 }
63
64 async fn retire_runtime(
65 &self,
66 session_id: &SessionId,
67 ) -> Result<RetireReport, RuntimeDriverError> {
68 let runtime_id = MeerkatMachine::logical_runtime_id(session_id);
69 match self
70 .execute_meerkat_machine_command(None, MeerkatMachineCommand::Retire { runtime_id })
71 .await
72 .map_err(MeerkatMachine::driver_error_from_command_error)?
73 {
74 MeerkatMachineCommandResult::RetireReport(report) => Ok(report),
75 other => Err(RuntimeDriverError::Internal(format!(
76 "unexpected MeerkatMachineCommandResult for SessionServiceRuntimeExt::retire_runtime: {other:?}"
77 ))),
78 }
79 }
80
81 async fn reset_runtime(
82 &self,
83 session_id: &SessionId,
84 ) -> Result<ResetReport, RuntimeDriverError> {
85 let runtime_id = MeerkatMachine::logical_runtime_id(session_id);
86 match self
87 .execute_meerkat_machine_command(None, MeerkatMachineCommand::Reset { runtime_id })
88 .await
89 .map_err(MeerkatMachine::driver_error_from_command_error)?
90 {
91 MeerkatMachineCommandResult::ResetReport(report) => Ok(report),
92 other => Err(RuntimeDriverError::Internal(format!(
93 "unexpected MeerkatMachineCommandResult for SessionServiceRuntimeExt::reset_runtime: {other:?}"
94 ))),
95 }
96 }
97
98 async fn input_state(
99 &self,
100 session_id: &SessionId,
101 input_id: &InputId,
102 ) -> Result<Option<StoredInputState>, RuntimeDriverError> {
103 match self
104 .execute_meerkat_machine_command(
105 None,
106 MeerkatMachineCommand::InputState {
107 session_id: session_id.clone(),
108 input_id: input_id.clone(),
109 },
110 )
111 .await
112 .map_err(MeerkatMachine::driver_error_from_command_error)?
113 {
114 MeerkatMachineCommandResult::InputState(state) => Ok(state),
115 other => Err(RuntimeDriverError::Internal(format!(
116 "unexpected MeerkatMachineCommandResult for SessionServiceRuntimeExt::input_state: {other:?}"
117 ))),
118 }
119 }
120
121 async fn list_active_inputs(
122 &self,
123 session_id: &SessionId,
124 ) -> Result<Vec<InputId>, RuntimeDriverError> {
125 match self
126 .execute_meerkat_machine_command(
127 None,
128 MeerkatMachineCommand::ListActiveInputs {
129 session_id: session_id.clone(),
130 },
131 )
132 .await
133 .map_err(MeerkatMachine::driver_error_from_command_error)?
134 {
135 MeerkatMachineCommandResult::ActiveInputs(inputs) => Ok(inputs),
136 other => Err(RuntimeDriverError::Internal(format!(
137 "unexpected MeerkatMachineCommandResult for SessionServiceRuntimeExt::list_active_inputs: {other:?}"
138 ))),
139 }
140 }
141
142 async fn reconfigure_session_llm_identity(
143 &self,
144 session_id: &SessionId,
145 request: SessionLlmReconfigureRequest,
146 ) -> Result<SessionLlmReconfigureReport, RuntimeDriverError> {
147 let command = self
148 .prepare_reconfigure_session_llm_command(session_id, request)
149 .await?;
150 match self
151 .execute_meerkat_machine_command(None, command)
152 .await
153 .map_err(MeerkatMachine::driver_error_from_command_error)?
154 {
155 MeerkatMachineCommandResult::LlmReconfigured(report) => Ok(report),
156 other => Err(RuntimeDriverError::Internal(format!(
157 "unexpected MeerkatMachineCommandResult for SessionServiceRuntimeExt::reconfigure_session_llm_identity: {other:?}"
158 ))),
159 }
160 }
161
162 async fn resolved_session_llm_capabilities(
163 &self,
164 session_id: &SessionId,
165 ) -> Result<Option<SessionLlmCapabilitySurface>, RuntimeDriverError> {
166 match self
167 .execute_meerkat_machine_command(
168 None,
169 MeerkatMachineCommand::ResolvedSessionLlmCapabilities {
170 session_id: session_id.clone(),
171 },
172 )
173 .await
174 .map_err(MeerkatMachine::driver_error_from_command_error)?
175 {
176 MeerkatMachineCommandResult::ResolvedSessionLlmCapabilities(capabilities) => {
177 Ok(capabilities)
178 }
179 other => Err(RuntimeDriverError::Internal(format!(
180 "unexpected MeerkatMachineCommandResult for SessionServiceRuntimeExt::resolved_session_llm_capabilities: {other:?}"
181 ))),
182 }
183 }
184
185 async fn configure_model_routing_baseline(
186 &self,
187 session_id: &SessionId,
188 baseline_model: meerkat_core::lifecycle::run_primitive::ModelId,
189 realtime_capable: bool,
190 ) -> Result<(), RuntimeDriverError> {
191 match self
192 .execute_meerkat_machine_command(
193 None,
194 MeerkatMachineCommand::ConfigureModelRoutingBaseline {
195 session_id: session_id.clone(),
196 baseline_model,
197 realtime_capable,
198 },
199 )
200 .await
201 .map_err(MeerkatMachine::driver_error_from_command_error)?
202 {
203 MeerkatMachineCommandResult::Unit => Ok(()),
204 other => Err(RuntimeDriverError::Internal(format!(
205 "unexpected MeerkatMachineCommandResult for SessionServiceRuntimeExt::configure_model_routing_baseline: {other:?}"
206 ))),
207 }
208 }
209
210 async fn session_model_routing_status(
211 &self,
212 session_id: &SessionId,
213 ) -> Result<meerkat_core::image_generation::SessionModelRoutingStatus, RuntimeDriverError> {
214 match self
215 .execute_meerkat_machine_command(
216 None,
217 MeerkatMachineCommand::SessionModelRoutingStatus {
218 session_id: session_id.clone(),
219 },
220 )
221 .await
222 .map_err(MeerkatMachine::driver_error_from_command_error)?
223 {
224 MeerkatMachineCommandResult::SessionModelRoutingStatus(status) => Ok(status),
225 other => Err(RuntimeDriverError::Internal(format!(
226 "unexpected MeerkatMachineCommandResult for SessionServiceRuntimeExt::session_model_routing_status: {other:?}"
227 ))),
228 }
229 }
230
231 async fn request_switch_turn(
232 &self,
233 session_id: &SessionId,
234 request: crate::meerkat_machine_types::SwitchTurnRequest,
235 ) -> Result<meerkat_core::image_generation::SwitchTurnControlResult, RuntimeDriverError> {
236 match self
237 .execute_meerkat_machine_command(
238 None,
239 MeerkatMachineCommand::RequestSwitchTurn {
240 session_id: session_id.clone(),
241 request: Box::new(request),
242 },
243 )
244 .await
245 .map_err(MeerkatMachine::driver_error_from_command_error)?
246 {
247 MeerkatMachineCommandResult::SwitchTurnControlResult(result) => Ok(result),
248 other => Err(RuntimeDriverError::Internal(format!(
249 "unexpected MeerkatMachineCommandResult for SessionServiceRuntimeExt::request_switch_turn: {other:?}"
250 ))),
251 }
252 }
253
254 async fn admit_model_routing_assistant_turn(
255 &self,
256 session_id: &SessionId,
257 ) -> Result<(), RuntimeDriverError> {
258 match self
259 .execute_meerkat_machine_command(
260 None,
261 MeerkatMachineCommand::AdmitModelRoutingAssistantTurn {
262 session_id: session_id.clone(),
263 },
264 )
265 .await
266 .map_err(MeerkatMachine::driver_error_from_command_error)?
267 {
268 MeerkatMachineCommandResult::Unit => Ok(()),
269 other => Err(RuntimeDriverError::Internal(format!(
270 "unexpected MeerkatMachineCommandResult for SessionServiceRuntimeExt::admit_model_routing_assistant_turn: {other:?}"
271 ))),
272 }
273 }
274
275 async fn begin_image_operation(
276 &self,
277 session_id: &SessionId,
278 request: crate::meerkat_machine_types::ImageOperationRoutingRequest,
279 ) -> Result<crate::meerkat_machine_types::ImageOperationRoutingResult, RuntimeDriverError> {
280 match self
281 .execute_meerkat_machine_command(
282 None,
283 MeerkatMachineCommand::BeginImageOperation {
284 session_id: session_id.clone(),
285 request: Box::new(request),
286 },
287 )
288 .await
289 .map_err(MeerkatMachine::driver_error_from_command_error)?
290 {
291 MeerkatMachineCommandResult::ImageOperationRoutingResult(result) => Ok(result),
292 other => Err(RuntimeDriverError::Internal(format!(
293 "unexpected MeerkatMachineCommandResult for SessionServiceRuntimeExt::begin_image_operation: {other:?}"
294 ))),
295 }
296 }
297
298 async fn activate_image_operation_override(
299 &self,
300 session_id: &SessionId,
301 operation_id: meerkat_core::image_generation::ImageOperationId,
302 ) -> Result<meerkat_core::image_generation::ImageOperationPhase, RuntimeDriverError> {
303 match self
304 .execute_meerkat_machine_command(
305 None,
306 MeerkatMachineCommand::ActivateImageOperationOverride {
307 session_id: session_id.clone(),
308 operation_id,
309 },
310 )
311 .await
312 .map_err(MeerkatMachine::driver_error_from_command_error)?
313 {
314 MeerkatMachineCommandResult::ImageOperationPhase(phase) => Ok(phase),
315 other => Err(RuntimeDriverError::Internal(format!(
316 "unexpected MeerkatMachineCommandResult for SessionServiceRuntimeExt::activate_image_operation_override: {other:?}"
317 ))),
318 }
319 }
320
321 async fn complete_image_operation(
322 &self,
323 session_id: &SessionId,
324 operation_id: meerkat_core::image_generation::ImageOperationId,
325 terminal: meerkat_core::image_generation::ImageOperationTerminalClass,
326 ) -> Result<meerkat_core::image_generation::ImageOperationPhase, RuntimeDriverError> {
327 match self
328 .execute_meerkat_machine_command(
329 None,
330 MeerkatMachineCommand::CompleteImageOperation {
331 session_id: session_id.clone(),
332 operation_id,
333 terminal,
334 },
335 )
336 .await
337 .map_err(MeerkatMachine::driver_error_from_command_error)?
338 {
339 MeerkatMachineCommandResult::ImageOperationPhase(phase) => Ok(phase),
340 other => Err(RuntimeDriverError::Internal(format!(
341 "unexpected MeerkatMachineCommandResult for SessionServiceRuntimeExt::complete_image_operation: {other:?}"
342 ))),
343 }
344 }
345
346 async fn restore_image_operation_override(
347 &self,
348 session_id: &SessionId,
349 operation_id: meerkat_core::image_generation::ImageOperationId,
350 ) -> Result<meerkat_core::image_generation::ImageOperationPhase, RuntimeDriverError> {
351 match self
352 .execute_meerkat_machine_command(
353 None,
354 MeerkatMachineCommand::RestoreImageOperationOverride {
355 session_id: session_id.clone(),
356 operation_id,
357 },
358 )
359 .await
360 .map_err(MeerkatMachine::driver_error_from_command_error)?
361 {
362 MeerkatMachineCommandResult::ImageOperationPhase(phase) => Ok(phase),
363 other => Err(RuntimeDriverError::Internal(format!(
364 "unexpected MeerkatMachineCommandResult for SessionServiceRuntimeExt::restore_image_operation_override: {other:?}"
365 ))),
366 }
367 }
368}
369
370impl MeerkatMachine {
375 pub(crate) fn logical_runtime_id(session_id: &SessionId) -> LogicalRuntimeId {
376 LogicalRuntimeId::for_session(session_id)
377 }
378
379 pub(super) fn post_admission_signal_from_effects(
380 effects: &[crate::meerkat_machine::dsl::MeerkatMachineEffect],
381 ) -> crate::driver::ephemeral::PostAdmissionSignal {
382 effects
383 .iter()
384 .find_map(|effect| match effect {
385 crate::meerkat_machine::dsl::MeerkatMachineEffect::PostAdmissionSignal {
386 signal,
387 } => Some(match signal {
388 crate::meerkat_machine::dsl::PostAdmissionSignalKind::WakeLoop => {
389 crate::driver::ephemeral::PostAdmissionSignal::WakeLoop
390 }
391 crate::meerkat_machine::dsl::PostAdmissionSignalKind::InterruptYielding => {
392 crate::driver::ephemeral::PostAdmissionSignal::InterruptYielding
393 }
394 crate::meerkat_machine::dsl::PostAdmissionSignalKind::RequestImmediateProcessing => {
395 crate::driver::ephemeral::PostAdmissionSignal::RequestImmediateProcessing
396 }
397 }),
398 _ => None,
399 })
400 .unwrap_or(crate::driver::ephemeral::PostAdmissionSignal::None)
401 }
402
403 pub(super) fn driver_error_from_command_error(
404 err: MeerkatMachineCommandError,
405 ) -> RuntimeDriverError {
406 match err {
407 MeerkatMachineCommandError::Driver(err) => err,
408 MeerkatMachineCommandError::Control(err) => {
409 Self::driver_error_from_control_plane_error(err)
410 }
411 }
412 }
413
414 pub(super) fn control_plane_error_from_command_error(
415 err: MeerkatMachineCommandError,
416 ) -> RuntimeControlPlaneError {
417 match err {
418 MeerkatMachineCommandError::Control(err) => err,
419 MeerkatMachineCommandError::Driver(err) => {
420 RuntimeControlPlaneError::Internal(err.to_string())
421 }
422 }
423 }
424
425 pub(super) fn driver_error_from_control_plane_error(
426 err: RuntimeControlPlaneError,
427 ) -> RuntimeDriverError {
428 match err {
429 RuntimeControlPlaneError::NotFound(_) => RuntimeDriverError::NotReady {
430 state: RuntimeState::Destroyed,
431 },
432 RuntimeControlPlaneError::InvalidState { state } => {
433 RuntimeDriverError::NotReady { state }
434 }
435 RuntimeControlPlaneError::StoreError(message)
436 | RuntimeControlPlaneError::Internal(message) => RuntimeDriverError::Internal(message),
437 }
438 }
439
440 pub(super) async fn resolve_session_id(
442 &self,
443 runtime_id: &LogicalRuntimeId,
444 ) -> Result<SessionId, RuntimeControlPlaneError> {
445 let sessions = self.sessions.read().await;
446 sessions
447 .iter()
448 .find_map(|(session_id, entry)| {
449 (&entry.runtime_id == runtime_id).then(|| session_id.clone())
450 })
451 .ok_or_else(|| RuntimeControlPlaneError::NotFound(runtime_id.clone()))
452 }
453
454 pub(super) async fn existing_session_runtime_state(
455 &self,
456 session_id: &SessionId,
457 ) -> Option<RuntimeState> {
458 let sessions = self.sessions.read().await;
459 let entry = sessions.get(session_id)?;
460 let control = entry.control_snapshot();
465 let authority = entry
466 .dsl_authority
467 .lock()
468 .unwrap_or_else(std::sync::PoisonError::into_inner);
469 let dsl_phase = dsl_authority::runtime_phase_from_authority(&authority);
470 let dsl_pre_run_phase = dsl_authority::pre_run_phase_from_authority(&authority);
471 if self.has_runtime_persistence()
472 && dsl_authority::should_publish_control_over_dsl(
473 control.phase,
474 dsl_phase,
475 dsl_pre_run_phase,
476 )
477 {
478 Some(control.phase)
479 } else {
480 Some(dsl_phase)
481 }
482 }
483
484 pub(super) async fn existing_session_visible_runtime_state(
485 &self,
486 session_id: &SessionId,
487 ) -> Option<RuntimeState> {
488 let sessions = self.sessions.read().await;
489 let entry = sessions.get(session_id)?;
490 let control = entry.control_snapshot();
491 let authority = entry
492 .dsl_authority
493 .lock()
494 .unwrap_or_else(std::sync::PoisonError::into_inner);
495 let dsl_phase = dsl_authority::runtime_phase_from_authority(&authority);
496 let dsl_pre_run_phase = dsl_authority::pre_run_phase_from_authority(&authority);
497 if self.has_runtime_persistence()
498 && dsl_authority::should_publish_control_over_dsl(
499 control.phase,
500 dsl_phase,
501 dsl_pre_run_phase,
502 )
503 {
504 Some(dsl_authority::visible_runtime_phase(
505 control.phase,
506 control.pre_run_phase,
507 ))
508 } else {
509 Some(dsl_authority::visible_runtime_phase(
510 dsl_phase,
511 dsl_pre_run_phase,
512 ))
513 }
514 }
515
516 pub(super) async fn lookup_entry(
519 &self,
520 runtime_id: &LogicalRuntimeId,
521 ) -> Result<
522 (
523 SessionId,
524 SharedDriver,
525 SharedCompletionRegistry,
526 Option<mpsc::Sender<()>>,
527 ),
528 RuntimeControlPlaneError,
529 > {
530 let sessions = self.sessions.read().await;
531 let (session_id, entry) = sessions
532 .iter()
533 .find(|(_, entry)| &entry.runtime_id == runtime_id)
534 .ok_or_else(|| RuntimeControlPlaneError::NotFound(runtime_id.clone()))?;
535 Ok((
536 session_id.clone(),
537 entry.driver.clone(),
538 entry.completions.clone(),
539 entry.wake_sender(),
540 ))
541 }
542}
543
544#[cfg_attr(not(target_arch = "wasm32"), async_trait::async_trait)]
545#[cfg_attr(target_arch = "wasm32", async_trait::async_trait(?Send))]
546impl crate::traits::RuntimeControlPlane for MeerkatMachine {
547 async fn ingest(
548 &self,
549 runtime_id: &LogicalRuntimeId,
550 input: Input,
551 ) -> Result<AcceptOutcome, RuntimeControlPlaneError> {
552 match self
553 .execute_meerkat_machine_command(
554 None,
555 MeerkatMachineCommand::Ingest {
556 runtime_id: runtime_id.clone(),
557 input,
558 },
559 )
560 .await
561 .map_err(MeerkatMachine::control_plane_error_from_command_error)?
562 {
563 MeerkatMachineCommandResult::AcceptOutcome(outcome) => Ok(outcome),
564 other => Err(RuntimeControlPlaneError::Internal(format!(
565 "unexpected MeerkatMachineCommandResult for ingest: {other:?}"
566 ))),
567 }
568 }
569
570 async fn publish_event(
571 &self,
572 event: crate::runtime_event::RuntimeEventEnvelope,
573 ) -> Result<(), RuntimeControlPlaneError> {
574 match self
575 .execute_meerkat_machine_command(None, MeerkatMachineCommand::PublishEvent { event })
576 .await
577 .map_err(MeerkatMachine::control_plane_error_from_command_error)?
578 {
579 MeerkatMachineCommandResult::Unit => Ok(()),
580 other => Err(RuntimeControlPlaneError::Internal(format!(
581 "unexpected MeerkatMachineCommandResult for publish_event: {other:?}"
582 ))),
583 }
584 }
585
586 async fn retire(
587 &self,
588 runtime_id: &LogicalRuntimeId,
589 ) -> Result<RetireReport, RuntimeControlPlaneError> {
590 match self
591 .execute_meerkat_machine_command(
592 None,
593 MeerkatMachineCommand::Retire {
594 runtime_id: runtime_id.clone(),
595 },
596 )
597 .await
598 .map_err(MeerkatMachine::control_plane_error_from_command_error)?
599 {
600 MeerkatMachineCommandResult::RetireReport(report) => Ok(report),
601 other => Err(RuntimeControlPlaneError::Internal(format!(
602 "unexpected MeerkatMachineCommandResult for retire: {other:?}"
603 ))),
604 }
605 }
606
607 async fn recycle(
608 &self,
609 runtime_id: &LogicalRuntimeId,
610 ) -> Result<RecycleReport, RuntimeControlPlaneError> {
611 match self
612 .execute_meerkat_machine_command(
613 None,
614 MeerkatMachineCommand::Recycle {
615 runtime_id: runtime_id.clone(),
616 },
617 )
618 .await
619 .map_err(MeerkatMachine::control_plane_error_from_command_error)?
620 {
621 MeerkatMachineCommandResult::RecycleReport(report) => Ok(report),
622 other => Err(RuntimeControlPlaneError::Internal(format!(
623 "unexpected MeerkatMachineCommandResult for recycle: {other:?}"
624 ))),
625 }
626 }
627
628 async fn reset(
629 &self,
630 runtime_id: &LogicalRuntimeId,
631 ) -> Result<crate::traits::ResetReport, RuntimeControlPlaneError> {
632 match self
633 .execute_meerkat_machine_command(
634 None,
635 MeerkatMachineCommand::Reset {
636 runtime_id: runtime_id.clone(),
637 },
638 )
639 .await
640 .map_err(MeerkatMachine::control_plane_error_from_command_error)?
641 {
642 MeerkatMachineCommandResult::ResetReport(report) => Ok(report),
643 other => Err(RuntimeControlPlaneError::Internal(format!(
644 "unexpected MeerkatMachineCommandResult for reset: {other:?}"
645 ))),
646 }
647 }
648
649 async fn recover(
650 &self,
651 runtime_id: &LogicalRuntimeId,
652 ) -> Result<RecoveryReport, RuntimeControlPlaneError> {
653 match self
654 .execute_meerkat_machine_command(
655 None,
656 MeerkatMachineCommand::Recover {
657 runtime_id: runtime_id.clone(),
658 },
659 )
660 .await
661 .map_err(MeerkatMachine::control_plane_error_from_command_error)?
662 {
663 MeerkatMachineCommandResult::RecoveryReport(report) => Ok(report),
664 other => Err(RuntimeControlPlaneError::Internal(format!(
665 "unexpected MeerkatMachineCommandResult for recover: {other:?}"
666 ))),
667 }
668 }
669
670 async fn destroy(
671 &self,
672 runtime_id: &LogicalRuntimeId,
673 ) -> Result<DestroyReport, RuntimeControlPlaneError> {
674 match self
675 .execute_meerkat_machine_command(
676 None,
677 MeerkatMachineCommand::Destroy {
678 runtime_id: runtime_id.clone(),
679 },
680 )
681 .await
682 .map_err(MeerkatMachine::control_plane_error_from_command_error)?
683 {
684 MeerkatMachineCommandResult::DestroyReport(report) => Ok(report),
685 other => Err(RuntimeControlPlaneError::Internal(format!(
686 "unexpected MeerkatMachineCommandResult for destroy: {other:?}"
687 ))),
688 }
689 }
690
691 async fn runtime_state(
692 &self,
693 runtime_id: &LogicalRuntimeId,
694 ) -> Result<RuntimeState, RuntimeControlPlaneError> {
695 match self
696 .execute_meerkat_machine_command(
697 None,
698 MeerkatMachineCommand::RuntimeState {
699 runtime_id: runtime_id.clone(),
700 },
701 )
702 .await
703 .map_err(MeerkatMachine::control_plane_error_from_command_error)?
704 {
705 MeerkatMachineCommandResult::RuntimeState(state) => Ok(state),
706 other => Err(RuntimeControlPlaneError::Internal(format!(
707 "unexpected MeerkatMachineCommandResult for runtime_state: {other:?}"
708 ))),
709 }
710 }
711
712 async fn load_boundary_receipt(
713 &self,
714 runtime_id: &LogicalRuntimeId,
715 run_id: &RunId,
716 sequence: u64,
717 ) -> Result<Option<meerkat_core::lifecycle::RunBoundaryReceipt>, RuntimeControlPlaneError> {
718 match self
719 .execute_meerkat_machine_command(
720 None,
721 MeerkatMachineCommand::LoadBoundaryReceipt {
722 runtime_id: runtime_id.clone(),
723 run_id: run_id.clone(),
724 sequence,
725 },
726 )
727 .await
728 .map_err(MeerkatMachine::control_plane_error_from_command_error)?
729 {
730 MeerkatMachineCommandResult::BoundaryReceipt(receipt) => Ok(receipt),
731 other => Err(RuntimeControlPlaneError::Internal(format!(
732 "unexpected MeerkatMachineCommandResult for load_boundary_receipt: {other:?}"
733 ))),
734 }
735 }
736}