use crate::ids::MeerkatId;
use meerkat_core::types::SessionId;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[serde(tag = "mode", rename_all = "snake_case")]
#[non_exhaustive]
pub enum MemberLaunchMode {
#[default]
Fresh,
Resume {
#[serde(alias = "session_id")]
bridge_session_id: SessionId,
},
Fork {
source_member_id: MeerkatId,
#[serde(default)]
fork_context: ForkContext,
},
}
impl MemberLaunchMode {
pub fn resume_bridge_session_id(&self) -> Option<&SessionId> {
match self {
Self::Resume { bridge_session_id } => Some(bridge_session_id),
_ => None,
}
}
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[serde(tag = "type", rename_all = "snake_case")]
#[non_exhaustive]
pub enum ForkContext {
#[default]
FullHistory,
LastMessages { count: u32 },
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[serde(tag = "type", content = "value", rename_all = "snake_case")]
#[non_exhaustive]
pub enum BudgetSplitPolicy {
#[default]
Equal,
Proportional,
Remaining,
Fixed(u64),
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn resume_launch_mode_bridge_session_accessors_stay_additive() {
let sid = SessionId::new();
let mode = MemberLaunchMode::Resume {
bridge_session_id: sid.clone(),
};
assert_eq!(mode.resume_bridge_session_id(), Some(&sid));
}
#[test]
fn resume_launch_mode_deserializes_bridge_session_id_alias() {
let sid = SessionId::new();
let payload = serde_json::json!({
"mode": "resume",
"bridge_session_id": sid,
});
let mode: MemberLaunchMode =
serde_json::from_value(payload).expect("resume launch mode should deserialize");
assert_eq!(mode.resume_bridge_session_id(), Some(&sid));
}
#[test]
fn member_launch_mode_public_seam_covers_all_variants() {
use crate::ids::MeerkatId;
let fresh = MemberLaunchMode::default();
assert!(fresh.resume_bridge_session_id().is_none());
let sid = SessionId::new();
let resume = MemberLaunchMode::Resume {
bridge_session_id: sid.clone(),
};
assert_eq!(resume.resume_bridge_session_id(), Some(&sid));
let fork_full = MemberLaunchMode::Fork {
source_member_id: MeerkatId::from("lead"),
fork_context: ForkContext::default(),
};
assert!(fork_full.resume_bridge_session_id().is_none());
let fork_last = MemberLaunchMode::Fork {
source_member_id: MeerkatId::from("lead"),
fork_context: ForkContext::LastMessages { count: 5 },
};
assert!(fork_last.resume_bridge_session_id().is_none());
for mode in [fresh, resume, fork_full, fork_last] {
let encoded = serde_json::to_value(&mode).expect("mode serializes");
let decoded: MemberLaunchMode =
serde_json::from_value(encoded).expect("mode roundtrips");
assert_eq!(
mode.resume_bridge_session_id().is_some(),
decoded.resume_bridge_session_id().is_some(),
);
}
}
}