use std::sync::OnceLock;
pub fn linked_core_names() -> &'static [&'static str] {
static NAMES: OnceLock<Vec<&'static str>> = OnceLock::new();
NAMES.get_or_init(|| {
let mut names: Vec<&'static str> = Vec::new();
#[cfg(feature = "d2b")]
names.push("dig2browser");
#[cfg(feature = "m4a")]
names.push("mail4agent");
#[cfg(feature = "session-restore")]
names.push("session-restore");
#[cfg(feature = "wireguard")]
names.push("wireguard");
names
})
}
pub fn force_link() -> usize {
let mut acc: usize = 0;
#[cfg(feature = "d2b")]
{
acc = acc.wrapping_add(dig2browser::browser_stream::LOCAL_PAGE_HTML.len());
}
#[cfg(feature = "m4a")]
{
let mail: fn() -> Result<(), mail4agent::MainError> = mail4agent::run;
acc = acc.wrapping_add(mail as usize);
}
#[cfg(feature = "session-restore")]
{
let claude = std::mem::size_of::<claude_session_restore::transcript::SessionEvent>();
let codex = codex_session_restore::MAX_HEAD_BYTES;
let grok: fn() = grok_session_restore::main;
let kimi: fn() = kimi_session_restore::main;
acc = acc
.wrapping_add(claude)
.wrapping_add(codex)
.wrapping_add(grok as usize)
.wrapping_add(kimi as usize);
}
#[cfg(feature = "wireguard")]
{
let wireguard: fn(
&crate::kit_wireguard::NodeWgPeerConfig,
) -> Result<std::net::IpAddr, crate::kit_wireguard::NodeWgPeerError> =
crate::kit_wireguard::bring_up_node_wireguard;
acc = acc
.wrapping_add(wireguard as usize)
.wrapping_add(crate::kit_wireguard::LINK_TAG.len());
}
acc
}
#[cfg(feature = "m4a")]
pub fn start_mailbox() -> Result<MailboxHandle, mail4agent::MainError> {
let join = std::thread::Builder::new()
.name("mail4agent".to_owned())
.spawn(|| {
let result = mail4agent::run();
if let Err(error) = &result {
tracing::error!(%error, "mail4agent mailbox stopped");
}
result
})
.map_err(mail4agent::MainError::Runtime)?;
Ok(MailboxHandle { join })
}
#[cfg(feature = "m4a")]
pub struct MailboxHandle {
join: std::thread::JoinHandle<Result<(), mail4agent::MainError>>,
}
#[cfg(feature = "m4a")]
impl MailboxHandle {
pub fn is_finished(&self) -> bool {
self.join.is_finished()
}
pub fn join(self) -> Result<(), mail4agent::MainError> {
self.join.join().unwrap_or_else(|_| {
Err(mail4agent::MainError::Runtime(std::io::Error::other("mail4agent thread panicked")))
})
}
}
#[cfg(test)]
mod tests {
use super::*;
#[cfg(all(feature = "d2b", feature = "m4a", feature = "session-restore", feature = "wireguard"))]
#[test]
fn kit_names_the_four_cores() {
assert_eq!(
linked_core_names(),
["dig2browser", "mail4agent", "session-restore", "wireguard"]
);
assert!(force_link() > 0);
}
#[test]
fn linked_names_match_enabled_features() {
let expected = cfg!(feature = "d2b") as usize
+ cfg!(feature = "m4a") as usize
+ cfg!(feature = "session-restore") as usize
+ cfg!(feature = "wireguard") as usize;
assert_eq!(linked_core_names().len(), expected);
}
#[cfg(feature = "m4a")]
#[test]
fn kit_exposes_mailbox_automaton_entry() {
let start: fn() -> Result<MailboxHandle, mail4agent::MainError> = start_mailbox;
assert!(start as usize != 0);
}
}