use anyhow::Result;
use sacp::{Component, DynComponent};
use sacp_conductor::{Conductor, McpBridgeMode};
use std::path::PathBuf;
pub struct Symposium {
crate_sources_proxy: bool,
sparkle: bool,
trace_dir: Option<PathBuf>,
agent: Option<DynComponent>,
}
impl Symposium {
pub fn new() -> Self {
Symposium {
sparkle: true,
crate_sources_proxy: true,
trace_dir: None,
agent: None,
}
}
pub fn sparkle(mut self, enable: bool) -> Self {
self.sparkle = enable;
self
}
pub fn crate_sources_proxy(mut self, enable: bool) -> Self {
self.crate_sources_proxy = enable;
self
}
pub fn agent<C: Component>(mut self, agent: C) -> Self {
self.agent = Some(DynComponent::new(agent));
self
}
pub fn trace_dir(mut self, dir: impl Into<PathBuf>) -> Self {
self.trace_dir = Some(dir.into());
self
}
}
impl sacp::Component for Symposium {
async fn serve(self, client: impl Component) -> Result<(), sacp::Error> {
tracing::debug!("Symposium::serve starting");
let Self {
crate_sources_proxy,
sparkle,
trace_dir,
agent,
} = self;
tracing::debug!("Creating conductor");
let mut conductor = Conductor::new(
"symposium".to_string(),
move |init_req| async move {
tracing::info!("Building proxy chain based on capabilities");
let mut components = vec![];
if crate_sources_proxy {
components.push(sacp::DynComponent::new(
symposium_crate_sources_proxy::CrateSourcesProxy {},
));
}
if sparkle {
components.push(sacp::DynComponent::new(sparkle::SparkleComponent::new()));
}
if let Some(agent) = agent {
components.push(agent);
}
Ok((init_req, components))
},
McpBridgeMode::default(),
);
if let Some(dir) = trace_dir {
std::fs::create_dir_all(&dir).map_err(sacp::Error::into_internal_error)?;
let timestamp = chrono::Utc::now().format("%Y%m%d-%H%M%S");
let trace_path = dir.join(format!("{}.jsons", timestamp));
conductor = conductor
.trace_to_path(&trace_path)
.map_err(sacp::Error::into_internal_error)?;
tracing::info!("Tracing to {}", trace_path.display());
}
tracing::debug!("Starting conductor.run()");
conductor.run(client).await
}
}