feat(maestro): serve structured session API

This commit is contained in:
Miguel Palhas
2026-09-05 01:46:21 +01:00
parent 0f5576c77a
commit b98f5cb3e5
9 changed files with 534 additions and 7 deletions
+35
View File
@@ -417,6 +417,41 @@ impl SessionManager {
Ok(true)
}
/// Begin an ACP turn only when the previous one has ended. The projection
/// lock makes the rejection and lifecycle update one indivisible action.
pub async fn begin_acp_turn(&self, id: Uuid) -> Result<Option<Arc<AcpSession>>, SessionError> {
let (acp, stream) = {
let sessions = self.inner.sessions.lock().await;
let record = sessions.get(&id).ok_or(SessionError::NotFound(id))?;
(record.acp.clone(), record.acp_events.clone())
};
let (Some(acp), Some(stream)) = (acp, stream) else {
return Ok(None);
};
let mut stream = stream.lock().await;
if stream.projection.turn_active() {
return Ok(None);
}
let update = stream.projection.turn_lifecycle(TurnLifecycle::Begin);
let _ = stream.projected_live.send(update);
Ok(Some(acp))
}
/// Cancel an ACP turn and immediately clear its client-facing lifecycle.
pub async fn cancel_acp_turn(&self, id: Uuid) -> Result<bool, SessionError> {
let acp = {
let sessions = self.inner.sessions.lock().await;
let record = sessions.get(&id).ok_or(SessionError::NotFound(id))?;
record.acp.clone()
};
let Some(acp) = acp else {
return Ok(false);
};
acp.cancel();
self.apply_acp_turn_lifecycle(id, TurnLifecycle::Cancel)
.await
}
/// End every adapter child before the daemon exits (#134): each gets
/// `session/cancel`, then SIGTERM, concurrently. The sessions stay in
/// the map, marked Dead and written through to their sidecars, so what