1use super::*;
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
6#[serde(rename_all = "kebab-case")]
7pub enum ResumeQueueDisposition {
8 Start,
9 Discard,
10}
11
12#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
13#[serde(deny_unknown_fields)]
14pub struct MoveSelection {
15 #[serde(default)]
16 pub clear_resource_allocation: bool,
17 pub session_id: String,
18 pub profile_id: Option<String>,
19 pub target_template_id: Option<String>,
20 pub additional_mounts: Option<Vec<AdditionalMount>>,
21 pub resource_allocation: Option<SessionResourceAllocation>,
22}
23
24#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
25#[serde(deny_unknown_fields)]
26pub struct MovePreparation {
27 #[serde(default)]
28 pub source_unavailable: bool,
29 pub selection: MoveSelection,
30 pub source_profile_id: String,
31 pub source_target_template_id: String,
32 pub cross_harness: bool,
33 pub active: bool,
34 pub queued_commands: Vec<MaterializedQueuedPrompt>,
35 pub fingerprint: String,
36 pub operation_id: String,
37}
38
39#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
40#[serde(deny_unknown_fields)]
41pub struct MoveSessionRequest {
42 pub preparation: MovePreparation,
43 pub queue: Option<ResumeQueueDisposition>,
44 pub acknowledge_interruption: bool,
45}
46
47#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
48#[serde(deny_unknown_fields)]
49pub struct MoveOutcome {
50 pub operation_id: String,
51 pub session_id: String,
52 pub profile_id: String,
53 pub target_template_id: String,
54 pub outcome: String,
55 pub error: Option<String>,
56 pub recovery: Option<String>,
57}
58
59#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
60#[serde(rename_all = "snake_case")]
61pub enum MovePhase {
62 Preparing,
63 ClosingSource,
64 ResumingDestination,
65 StartingQueue,
66 Completed,
67 Failed,
68 Cancelled,
69}
70
71#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
72#[serde(deny_unknown_fields)]
73pub struct MoveOperation {
74 #[serde(default)]
76 pub source_checkpoint_only: bool,
77 pub operation_id: String,
78 pub selection: MoveSelection,
79 pub source_profile_id: String,
80 pub source_target_template_id: String,
81 pub source_target: Option<TargetLocator>,
82 pub source_native_session_id: Option<String>,
83 pub source_additional_mounts: Vec<AdditionalMount>,
84 pub source_resource_allocation: Option<SessionResourceAllocation>,
85 pub destination_target: Option<TargetLocator>,
86 pub destination_native_session_id: Option<String>,
87 pub destination_store_id: Option<String>,
88 pub configuration_fingerprint: String,
89 pub checkpoint: Option<CheckpointMetadata>,
90 pub recovery_session: Option<SessionRecord>,
92 pub queue: ResumeQueueDisposition,
93 pub phase: MovePhase,
94 pub queue_admission_started: bool,
96 pub queue_admission_finished: bool,
97 pub cancellation_requested: bool,
98 pub created_at: String,
99 pub updated_at: String,
100 pub error: Option<String>,
101}
102
103impl MoveOperation {
104 pub fn retains_checkpoint(&self) -> bool {
105 !matches!(self.phase, MovePhase::Completed | MovePhase::Cancelled)
106 || (self.queue_admission_started && !self.queue_admission_finished)
107 }
108
109 pub fn is_active(&self) -> bool {
110 matches!(
111 self.phase,
112 MovePhase::Preparing
113 | MovePhase::ClosingSource
114 | MovePhase::ResumingDestination
115 | MovePhase::StartingQueue
116 )
117 }
118}