use async_trait::async_trait;
use crate::client::proxy::{ActivityDigest, ManagedBackend};
use crate::client::resolve_target;
use crate::client::resolver::Resolvable;
use crate::daemon::state::DaemonState;
use crate::session_manager::record::{ManagedSessionId, SessionRecord};
impl Resolvable for SessionRecord {
fn id_matches(&self, query: &str) -> bool {
self.id.to_string() == query
}
fn resolve_name(&self) -> &str {
&self.tmux_name
}
}
pub struct DirectManagedBackend {
state: std::sync::Arc<DaemonState>,
}
impl DirectManagedBackend {
pub fn new(state: std::sync::Arc<DaemonState>) -> Self {
Self { state }
}
}
#[async_trait]
impl ManagedBackend for DirectManagedBackend {
async fn resolve(&self, target: &str) -> Result<(String, String), String> {
let mgr = self.state.session_manager().await;
let records = mgr.list().await;
match resolve_target(&records, target) {
Some(r) => Ok((r.id.to_string(), r.tmux_name.clone())),
None => Err(format!("managed session {target} not found")),
}
}
async fn send(&self, id: &str, text: &str) -> Result<(), String> {
let parsed = parse_managed_id(id)?;
let mgr = self.state.session_manager().await;
mgr.send_input(&parsed, text)
.await
.map_err(|e| e.to_string())
}
async fn activity(&self, id: &str) -> Result<ActivityDigest, String> {
let parsed = parse_managed_id(id)?;
let mgr = self.state.session_manager().await;
let record = mgr
.get(&parsed)
.await
.map_err(|_| format!("managed session {id} not found"))?;
let summary = match &record.pending_decision {
Some(d) => format!("blocked on decision: {d}"),
None if record.task.trim().is_empty() => {
format!("state={}", record.state)
}
None => format!("state={} task={}", record.state, record.task),
};
Ok(ActivityDigest {
state: record.state.to_string(),
summary,
pending_decision: record.pending_decision,
})
}
}
pub(super) fn parse_managed_id(id: &str) -> Result<ManagedSessionId, String> {
id.parse::<uuid::Uuid>()
.map(ManagedSessionId::from)
.map_err(|_| format!("invalid managed session id: {id}"))
}