use std::sync::Arc;
use async_trait::async_trait;
pub use crate::core::sm::control::{LaunchParams, SessionControl, SessionControlError};
use crate::daemon::managed_routes::{SpawnParams, record_to_json, resume_managed, spawn_managed};
use crate::daemon::state::DaemonState;
use crate::session_manager::{ManagedError, ManagedSessionId};
pub struct DaemonSessionControl {
state: Arc<DaemonState>,
}
impl DaemonSessionControl {
pub fn new(state: Arc<DaemonState>) -> Self {
Self { state }
}
fn parse_id(session_id: &str) -> Result<ManagedSessionId, SessionControlError> {
session_id
.parse::<uuid::Uuid>()
.map(ManagedSessionId::from)
.map_err(|_| SessionControlError::NotFound(session_id.to_string()))
}
fn map_managed_err(e: ManagedError) -> SessionControlError {
match e {
ManagedError::SessionNotFound(msg) => SessionControlError::NotFound(msg),
other => SessionControlError::Backend(other.to_string()),
}
}
}
#[async_trait]
impl SessionControl for DaemonSessionControl {
async fn launch(&self, params: LaunchParams) -> Result<serde_json::Value, SessionControlError> {
let task = params
.prompt
.filter(|p| !p.trim().is_empty())
.unwrap_or_else(|| "session-manager launched task".to_string());
let spawn = SpawnParams {
repo_url: params.workdir,
git_ref: String::new(),
task,
name_hint: None,
runtime: params.model,
};
let record = spawn_managed(&self.state, spawn)
.await
.map_err(SessionControlError::Backend)?;
Ok(serde_json::json!({ "session_id": record.id.to_string() }))
}
async fn list(&self) -> Result<serde_json::Value, SessionControlError> {
let mgr = self.state.session_manager().await;
let sessions: Vec<serde_json::Value> =
mgr.list().await.iter().map(record_to_json).collect();
Ok(serde_json::json!({ "sessions": sessions }))
}
async fn get(&self, session_id: &str) -> Result<serde_json::Value, SessionControlError> {
let id = Self::parse_id(session_id)?;
let mgr = self.state.session_manager().await;
let record = mgr.get(&id).await.map_err(Self::map_managed_err)?;
Ok(serde_json::json!({ "session": record_to_json(&record) }))
}
async fn send(
&self,
session_id: &str,
text: &str,
) -> Result<serde_json::Value, SessionControlError> {
let id = Self::parse_id(session_id)?;
let mgr = self.state.session_manager().await;
mgr.send_input(&id, text)
.await
.map_err(|e| SessionControlError::Backend(e.to_string()))?;
Ok(serde_json::json!({ "ok": true }))
}
async fn stop(&self, session_id: &str) -> Result<serde_json::Value, SessionControlError> {
let id = Self::parse_id(session_id)?;
let mgr = self.state.session_manager().await;
mgr.stop(&id).await.map_err(Self::map_managed_err)?;
Ok(serde_json::json!({ "ok": true }))
}
async fn resume(&self, session_id: &str) -> Result<serde_json::Value, SessionControlError> {
let id = Self::parse_id(session_id)?;
resume_managed(&self.state, &id)
.await
.map_err(|e| SessionControlError::Backend(e.to_string()))?;
Ok(serde_json::json!({ "ok": true }))
}
async fn kill(&self, session_id: &str) -> Result<serde_json::Value, SessionControlError> {
let id = Self::parse_id(session_id)?;
let mgr = self.state.session_manager().await;
mgr.decommission(&id).await.map_err(Self::map_managed_err)?;
Ok(serde_json::json!({ "ok": true }))
}
}