fix(maestro): mark graceful ACP recovery
This commit is contained in:
@@ -930,9 +930,9 @@ impl SessionManager {
|
||||
adopted += 1;
|
||||
}
|
||||
|
||||
// Structured sessions have no tmux process to discover. Their
|
||||
// sidecars are the recovery inventory: when an ACP id exists, start a
|
||||
// fresh adapter process and load that conversation into it.
|
||||
// Structured sessions have no tmux process to discover. A durable
|
||||
// marker written during graceful shutdown is the only evidence that a
|
||||
// sidecar may be resumed; older and naturally-dead sidecars stay dead.
|
||||
for mut session in self
|
||||
.inner
|
||||
.sidecar
|
||||
@@ -945,6 +945,7 @@ impl SessionManager {
|
||||
}
|
||||
|
||||
let id = session.id;
|
||||
let recoverable = self.inner.sidecar.take_recovery_marker(id)?;
|
||||
let mut session_env = sanitize_env(&session.env)?;
|
||||
let fifo_path = self.inner.fifo_dir.join(format!("{id}.fifo"));
|
||||
let bridge =
|
||||
@@ -960,40 +961,50 @@ impl SessionManager {
|
||||
session_env.insert("MAESTRO_URL".into(), url);
|
||||
}
|
||||
|
||||
let (acp, failure) = match session.acp_session_id.clone() {
|
||||
Some(acp_session_id) => {
|
||||
let config = SpawnConfig::new(
|
||||
&session.cwd,
|
||||
session_env
|
||||
.iter()
|
||||
.map(|(key, value)| (key.clone(), value.clone()))
|
||||
.collect(),
|
||||
)
|
||||
.load_session(acp_session_id);
|
||||
match maestro_acp::spawn(config).await {
|
||||
Ok(acp) => (Some(Arc::new(acp)), None),
|
||||
Err(error) => {
|
||||
tracing::warn!(%id, %error, "structured session: adapter failed to resume");
|
||||
(None, Some(error.to_string()))
|
||||
let (acp, failure) = if recoverable {
|
||||
match session.acp_session_id.clone() {
|
||||
Some(acp_session_id) => {
|
||||
let config = SpawnConfig::new(
|
||||
&session.cwd,
|
||||
session_env
|
||||
.iter()
|
||||
.map(|(key, value)| (key.clone(), value.clone()))
|
||||
.collect(),
|
||||
)
|
||||
.load_session(acp_session_id);
|
||||
match maestro_acp::spawn(config).await {
|
||||
Ok(acp) => (Some(Arc::new(acp)), None),
|
||||
Err(error) => {
|
||||
tracing::warn!(%id, %error, "structured session: adapter failed to resume");
|
||||
(None, Some(error.to_string()))
|
||||
}
|
||||
}
|
||||
}
|
||||
None => (
|
||||
None,
|
||||
Some("structured session has no stored ACP session id".into()),
|
||||
),
|
||||
}
|
||||
None => (
|
||||
None,
|
||||
Some("structured session has no stored ACP session id".into()),
|
||||
),
|
||||
} else {
|
||||
(None, None)
|
||||
};
|
||||
session.status = if failure.is_some() {
|
||||
session.status = if recoverable {
|
||||
if failure.is_some() {
|
||||
SessionStatus::Dead
|
||||
} else {
|
||||
SessionStatus::Running
|
||||
}
|
||||
} else {
|
||||
SessionStatus::Dead
|
||||
} else {
|
||||
SessionStatus::Running
|
||||
};
|
||||
session.activity = if failure.is_some() {
|
||||
ActivityState::Error
|
||||
} else {
|
||||
ActivityState::Active
|
||||
};
|
||||
session.activity_detail = failure;
|
||||
if recoverable {
|
||||
session.activity = if failure.is_some() {
|
||||
ActivityState::Error
|
||||
} else {
|
||||
ActivityState::Active
|
||||
};
|
||||
session.activity_detail = failure;
|
||||
}
|
||||
|
||||
let acp_events = if let Some(acp) = &acp {
|
||||
match self.inner.sidecar.open_events(id) {
|
||||
@@ -1724,6 +1735,7 @@ async fn mark_session_dead(inner: &Arc<Inner>, id: Uuid) {
|
||||
/// exit: the sidecar is the recovery inventory, including its worktree.
|
||||
async fn mark_session_dead_after_shutdown(inner: &Arc<Inner>, id: Uuid) {
|
||||
mark_session_dead_with_worktree_settlement(inner, id, false).await;
|
||||
let _ = inner.sidecar.mark_for_recovery(id);
|
||||
}
|
||||
|
||||
async fn mark_session_dead_with_worktree_settlement(
|
||||
|
||||
Reference in New Issue
Block a user