diff --git a/crates/maestro-cli/src/sessions.rs b/crates/maestro-cli/src/sessions.rs index 57ea9ef..4a996de 100644 --- a/crates/maestro-cli/src/sessions.rs +++ b/crates/maestro-cli/src/sessions.rs @@ -345,6 +345,7 @@ mod tests { blocked_work: None, last_focused_at: None, acp_session_id: None, + auto_approve: false, } } diff --git a/crates/maestro-daemon/src/session.rs b/crates/maestro-daemon/src/session.rs index 112fab2..1e37be5 100644 --- a/crates/maestro-daemon/src/session.rs +++ b/crates/maestro-daemon/src/session.rs @@ -1404,6 +1404,7 @@ impl SessionManager { last_focused_at: None, acp_session_id: None, view: req.view, + auto_approve: req.auto_approve, }; if let Err(e) = self.inner.sidecar.write(&session) { @@ -1678,6 +1679,7 @@ impl SessionManager { // Unknown on adoption without a sidecar; matches every // other field's forward-compat default. view: maestro_protocol::SessionView::Terminal, + auto_approve: false, }, }; let fifo_path = self.inner.fifo_dir.join(format!("{id}.fifo")); @@ -1715,7 +1717,7 @@ impl SessionManager { acp_events: None, structured_activity_watermark: None, acp_event_pump: None, - auto_approve: false, + auto_approve: session.auto_approve, pending_prompt: None, }, ); @@ -1894,15 +1896,13 @@ impl SessionManager { acp_events, structured_activity_watermark: None, acp_event_pump: None, - // Recovery cannot know the original preset's flag; the - // operator re-enables it by restarting with the preset. - auto_approve: false, + auto_approve: session.auto_approve, pending_prompt: None, }, ); if let Some((acp, events)) = event_pump { let done = start_acp_event_pump(&self.inner, id, &acp, events.clone()); - start_acp_permission_pump(&self.inner, id, &acp, events, false); + start_acp_permission_pump(&self.inner, id, &acp, events, session.auto_approve); if let Some(record) = self.inner.sessions.lock().await.get_mut(&id) { record.acp_event_pump = Some(done); } @@ -3023,12 +3023,7 @@ async fn settle_worktree_on_exit( /// gone from the authoritative in-memory map, so a stray FIFO or sidecar can't /// resurrect it. `kill_tmux` is `true` for an explicit kill and `false` for the /// liveness reaper (tmux already lost the session). -async fn cleanup_record( - inner: &Arc, - id: Uuid, - record: SessionRecord, - kill_tmux: bool, -) { +async fn cleanup_record(inner: &Arc, id: Uuid, record: SessionRecord, kill_tmux: bool) { if kill_tmux { let tmux = inner.tmux.clone(); let _ = tmux_blocking(move || tmux.kill_session(id)).await; diff --git a/crates/maestro-daemon/tests/sidecar.rs b/crates/maestro-daemon/tests/sidecar.rs index e5f1612..426fb75 100644 --- a/crates/maestro-daemon/tests/sidecar.rs +++ b/crates/maestro-daemon/tests/sidecar.rs @@ -34,6 +34,7 @@ fn sample(id: Uuid) -> Session { last_focused_at: None, acp_session_id: None, view: SessionView::Terminal, + auto_approve: false, } } diff --git a/crates/maestro-protocol/src/display.rs b/crates/maestro-protocol/src/display.rs index c71ada8..7c326ac 100644 --- a/crates/maestro-protocol/src/display.rs +++ b/crates/maestro-protocol/src/display.rs @@ -744,6 +744,7 @@ mod tests { blocked_work: None, last_focused_at: None, acp_session_id: None, + auto_approve: false, } } diff --git a/crates/maestro-protocol/src/lib.rs b/crates/maestro-protocol/src/lib.rs index 7a87b61..ac48117 100644 --- a/crates/maestro-protocol/src/lib.rs +++ b/crates/maestro-protocol/src/lib.rs @@ -132,6 +132,12 @@ pub struct Session { /// the two are minted by different processes with different lifetimes. #[serde(default, skip_serializing_if = "Option::is_none")] pub acp_session_id: Option, + /// When `true` the daemon auto-approves every ACP permission request for + /// this session instead of surfacing them to the client. Set at spawn time + /// from the preset or the `CreateSessionRequest`; persisted so it survives + /// a daemon restart. + #[serde(default)] + pub auto_approve: bool, } /// A session's process shape (#133): a plain terminal, or a structured agent @@ -1054,6 +1060,7 @@ mod tests { last_focused_at: None, view: SessionView::Terminal, acp_session_id: None, + auto_approve: false, } } diff --git a/crates/maestro-testing/src/lib.rs b/crates/maestro-testing/src/lib.rs index dc63b2d..ef7806b 100644 --- a/crates/maestro-testing/src/lib.rs +++ b/crates/maestro-testing/src/lib.rs @@ -50,6 +50,7 @@ pub fn session(id: Uuid, cwd: &str, command: &str) -> Session { blocked_work: None, last_focused_at: None, acp_session_id: None, + auto_approve: false, } } diff --git a/crates/maestro-tui/src/app.rs b/crates/maestro-tui/src/app.rs index dc59335..8849809 100644 --- a/crates/maestro-tui/src/app.rs +++ b/crates/maestro-tui/src/app.rs @@ -2216,6 +2216,7 @@ mod tests { blocked_work: None, last_focused_at: None, acp_session_id: None, + auto_approve: false, }) .collect(), }); @@ -2399,6 +2400,7 @@ mod tests { blocked_work: None, last_focused_at: None, acp_session_id: None, + auto_approve: false, }], }); app.dispatch(Action::SidebarNext); @@ -2428,6 +2430,7 @@ mod tests { blocked_work: None, last_focused_at: None, acp_session_id: None, + auto_approve: false, } } @@ -3590,6 +3593,7 @@ mod tests { blocked_work: None, last_focused_at: focused, acp_session_id: None, + auto_approve: false, }; let older = Utc::now() - chrono::Duration::seconds(60); app.catalog.apply_event(CatalogEvent::Snapshot { @@ -3870,6 +3874,7 @@ mod tests { blocked_work: None, last_focused_at: None, acp_session_id: None, + auto_approve: false, }], }); app.dispatch(Action::KillHighlighted); @@ -3907,6 +3912,7 @@ mod tests { blocked_work: None, last_focused_at: None, acp_session_id: None, + auto_approve: false, }], }); } diff --git a/crates/maestro-tui/src/catalog.rs b/crates/maestro-tui/src/catalog.rs index 4a42e4f..d734493 100644 --- a/crates/maestro-tui/src/catalog.rs +++ b/crates/maestro-tui/src/catalog.rs @@ -225,6 +225,7 @@ mod tests { blocked_work: None, last_focused_at: None, acp_session_id: None, + auto_approve: false, } } diff --git a/crates/maestro-tui/src/command_bar.rs b/crates/maestro-tui/src/command_bar.rs index 095dee7..2feace8 100644 --- a/crates/maestro-tui/src/command_bar.rs +++ b/crates/maestro-tui/src/command_bar.rs @@ -811,6 +811,7 @@ mod tests { blocked_work: None, last_focused_at: None, acp_session_id: None, + auto_approve: false, } } diff --git a/crates/maestro-tui/src/sidebar.rs b/crates/maestro-tui/src/sidebar.rs index 6d02373..d397734 100644 --- a/crates/maestro-tui/src/sidebar.rs +++ b/crates/maestro-tui/src/sidebar.rs @@ -502,6 +502,7 @@ mod tests { blocked_work: None, last_focused_at: None, acp_session_id: None, + auto_approve: false, } } @@ -1272,6 +1273,7 @@ mod tests { blocked_work: None, last_focused_at: None, acp_session_id: None, + auto_approve: false, }; let sb = Sidebar { sessions: vec![s],