use std::sync::Arc;
use crate::audit::AuditEventSender;
use crate::auto_approve::defer::DeferRegistry;
use crate::command_sender::CommandSender;
use crate::config::Settings;
use crate::hooks::registry::{HookRegistry, SessionPaneMap};
use crate::ipc::server::IpcServer;
use crate::pty::PtyRegistry;
use crate::runtime::RuntimeAdapter;
use crate::state::{AppState, SharedState};
use crate::transcript::TranscriptRegistry;
use super::core::TmaiCore;
pub struct TmaiCoreBuilder {
settings: Arc<Settings>,
state: Option<SharedState>,
command_sender: Option<Arc<CommandSender>>,
ipc_server: Option<Arc<IpcServer>>,
audit_tx: Option<AuditEventSender>,
hook_registry: Option<HookRegistry>,
session_pane_map: Option<SessionPaneMap>,
hook_token: Option<String>,
pty_registry: Option<Arc<PtyRegistry>>,
runtime: Option<Arc<dyn RuntimeAdapter>>,
transcript_registry: Option<TranscriptRegistry>,
}
impl TmaiCoreBuilder {
pub fn new(settings: Settings) -> Self {
Self {
settings: Arc::new(settings),
state: None,
command_sender: None,
ipc_server: None,
audit_tx: None,
hook_registry: None,
session_pane_map: None,
hook_token: None,
pty_registry: None,
runtime: None,
transcript_registry: None,
}
}
pub fn from_shared_settings(settings: Arc<Settings>) -> Self {
Self {
settings,
state: None,
command_sender: None,
ipc_server: None,
audit_tx: None,
hook_registry: None,
session_pane_map: None,
hook_token: None,
pty_registry: None,
runtime: None,
transcript_registry: None,
}
}
pub fn with_state(mut self, state: SharedState) -> Self {
self.state = Some(state);
self
}
pub fn with_ipc_server(mut self, ipc_server: Arc<IpcServer>) -> Self {
self.ipc_server = Some(ipc_server);
self
}
pub fn with_command_sender(mut self, sender: Arc<CommandSender>) -> Self {
self.command_sender = Some(sender);
self
}
pub fn with_audit_sender(mut self, tx: AuditEventSender) -> Self {
self.audit_tx = Some(tx);
self
}
pub fn with_hook_registry(mut self, registry: HookRegistry) -> Self {
self.hook_registry = Some(registry);
self
}
pub fn with_session_pane_map(mut self, map: SessionPaneMap) -> Self {
self.session_pane_map = Some(map);
self
}
pub fn with_hook_token(mut self, token: String) -> Self {
self.hook_token = Some(token);
self
}
pub fn with_pty_registry(mut self, registry: Arc<PtyRegistry>) -> Self {
self.pty_registry = Some(registry);
self
}
pub fn with_runtime(mut self, runtime: Arc<dyn RuntimeAdapter>) -> Self {
self.runtime = Some(runtime);
self
}
pub fn with_transcript_registry(mut self, registry: TranscriptRegistry) -> Self {
self.transcript_registry = Some(registry);
self
}
pub fn build(self) -> TmaiCore {
let state = self.state.unwrap_or_else(AppState::shared);
let hook_registry = self
.hook_registry
.unwrap_or_else(crate::hooks::new_hook_registry);
let session_pane_map = self
.session_pane_map
.unwrap_or_else(crate::hooks::new_session_pane_map);
let pty_registry = self
.pty_registry
.unwrap_or_else(|| Arc::new(PtyRegistry::default()));
TmaiCore::new(
state,
self.command_sender,
self.settings,
self.ipc_server,
self.audit_tx,
hook_registry,
session_pane_map,
self.hook_token,
pty_registry,
self.runtime,
self.transcript_registry,
DeferRegistry::new(),
)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_builder_defaults() {
let core = TmaiCoreBuilder::new(Settings::default()).build();
assert_eq!(core.settings().poll_interval_ms, 500);
assert!(core.ipc_server().is_none());
assert!(core.command_sender_ref().is_none());
}
#[test]
fn test_builder_with_state() {
let state = AppState::shared();
let state_clone = state.clone();
let core = TmaiCoreBuilder::new(Settings::default())
.with_state(state)
.build();
#[allow(deprecated)]
let raw = core.raw_state();
assert!(Arc::ptr_eq(raw, &state_clone));
}
#[test]
fn test_builder_from_shared_settings() {
let settings = Arc::new(Settings::default());
let settings_clone = settings.clone();
let core = TmaiCoreBuilder::from_shared_settings(settings).build();
assert_eq!(
core.settings().poll_interval_ms,
settings_clone.poll_interval_ms
);
}
}