use anyhow::{bail, Result};
use std::sync::Arc;
use super::models::HandoffRoute;
use super::storage::SwarmStorage;
pub struct HandoffManager {
storage: Arc<dyn SwarmStorage>,
}
impl HandoffManager {
pub fn new(storage: Arc<dyn SwarmStorage>) -> Self {
Self { storage }
}
pub async fn handoff(
&self,
channel: &str,
chat_id: &str,
from_agent: &str,
to_agent: &str,
context: Option<String>,
) -> Result<HandoffRoute> {
let from = self
.storage
.get_agent_by_name(from_agent)
.await?
.ok_or_else(|| anyhow::anyhow!("Source agent '{}' not found", from_agent))?;
let to = self
.storage
.get_agent_by_name(to_agent)
.await?
.ok_or_else(|| anyhow::anyhow!("Target agent '{}' not found", to_agent))?;
if to.status.to_string() != "active" {
bail!(
"Target agent '{}' is not active (status: {:?})",
to_agent,
to.status
);
}
let mut route = HandoffRoute::new(
channel.to_string(),
chat_id.to_string(),
from.name.clone(),
to.name.clone(),
);
if let Some(ctx) = context {
route = route.with_context(ctx);
}
self.storage.set_handoff_route(&route).await?;
Ok(route)
}
pub async fn get_route(&self, channel: &str, chat_id: &str) -> Result<Option<HandoffRoute>> {
self.storage.get_handoff_route(channel, chat_id).await
}
pub async fn resolve_agent(
&self,
channel: &str,
chat_id: &str,
default_agent: &str,
) -> Result<String> {
match self.storage.get_handoff_route(channel, chat_id).await? {
Some(route) => Ok(route.to_agent_key),
None => Ok(default_agent.to_string()),
}
}
pub async fn return_control(&self, channel: &str, chat_id: &str) -> Result<()> {
self.storage.clear_handoff_route(channel, chat_id).await
}
pub async fn list_routes(&self) -> Result<Vec<HandoffRoute>> {
self.storage.list_handoff_routes().await
}
}