Compare commits
1
Commits
modulation-2
...
staccato
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4727c7dc20 |
@@ -57,6 +57,7 @@ pub async fn run_spawn(client: &DaemonClient, args: SpawnArgs) -> Result<Session
|
|||||||
env,
|
env,
|
||||||
metadata,
|
metadata,
|
||||||
worktree,
|
worktree,
|
||||||
|
auto_approve: false,
|
||||||
};
|
};
|
||||||
client.create_session(&body).await
|
client.create_session(&body).await
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ async fn info_carries_version_and_presets() {
|
|||||||
id: "claude".into(),
|
id: "claude".into(),
|
||||||
label: "Claude".into(),
|
label: "Claude".into(),
|
||||||
command: "claude".into(),
|
command: "claude".into(),
|
||||||
|
auto_approve: false,
|
||||||
}],
|
}],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
});
|
});
|
||||||
@@ -97,6 +98,7 @@ async fn spawn_round_trips_through_the_daemon() {
|
|||||||
env: Default::default(),
|
env: Default::default(),
|
||||||
metadata: Default::default(),
|
metadata: Default::default(),
|
||||||
worktree: None,
|
worktree: None,
|
||||||
|
auto_approve: false,
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.expect("create");
|
.expect("create");
|
||||||
|
|||||||
@@ -313,16 +313,19 @@ pub fn builtin_presets() -> Vec<SpawnPreset> {
|
|||||||
id: "claude".into(),
|
id: "claude".into(),
|
||||||
label: "Claude".into(),
|
label: "Claude".into(),
|
||||||
command: "claude".into(),
|
command: "claude".into(),
|
||||||
|
auto_approve: false,
|
||||||
},
|
},
|
||||||
SpawnPreset {
|
SpawnPreset {
|
||||||
id: "opencode".into(),
|
id: "opencode".into(),
|
||||||
label: "opencode".into(),
|
label: "opencode".into(),
|
||||||
command: "opencode".into(),
|
command: "opencode".into(),
|
||||||
|
auto_approve: false,
|
||||||
},
|
},
|
||||||
SpawnPreset {
|
SpawnPreset {
|
||||||
id: "zsh".into(),
|
id: "zsh".into(),
|
||||||
label: "Shell".into(),
|
label: "Shell".into(),
|
||||||
command: "zsh".into(),
|
command: "zsh".into(),
|
||||||
|
auto_approve: false,
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -334,6 +337,7 @@ pub fn custom_preset() -> SpawnPreset {
|
|||||||
id: CUSTOM_PRESET_ID.into(),
|
id: CUSTOM_PRESET_ID.into(),
|
||||||
label: "Custom…".into(),
|
label: "Custom…".into(),
|
||||||
command: String::new(),
|
command: String::new(),
|
||||||
|
auto_approve: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -515,6 +519,7 @@ auto_install = false
|
|||||||
id: "fish".into(),
|
id: "fish".into(),
|
||||||
label: "fish".into(),
|
label: "fish".into(),
|
||||||
command: "fish".into(),
|
command: "fish".into(),
|
||||||
|
auto_approve: false,
|
||||||
}]),
|
}]),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
@@ -551,6 +556,7 @@ auto_install = false
|
|||||||
id: " ".into(),
|
id: " ".into(),
|
||||||
label: "x".into(),
|
label: "x".into(),
|
||||||
command: "x".into(),
|
command: "x".into(),
|
||||||
|
auto_approve: false,
|
||||||
}]),
|
}]),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
@@ -561,6 +567,7 @@ auto_install = false
|
|||||||
id: "x".into(),
|
id: "x".into(),
|
||||||
label: "x".into(),
|
label: "x".into(),
|
||||||
command: "".into(),
|
command: "".into(),
|
||||||
|
auto_approve: false,
|
||||||
}]),
|
}]),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
@@ -578,11 +585,13 @@ auto_install = false
|
|||||||
id: "a".into(),
|
id: "a".into(),
|
||||||
label: "a".into(),
|
label: "a".into(),
|
||||||
command: "a".into(),
|
command: "a".into(),
|
||||||
|
auto_approve: false,
|
||||||
},
|
},
|
||||||
SpawnPreset {
|
SpawnPreset {
|
||||||
id: "a".into(),
|
id: "a".into(),
|
||||||
label: "a2".into(),
|
label: "a2".into(),
|
||||||
command: "a2".into(),
|
command: "a2".into(),
|
||||||
|
auto_approve: false,
|
||||||
},
|
},
|
||||||
]),
|
]),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@@ -597,6 +606,7 @@ auto_install = false
|
|||||||
id: "custom".into(),
|
id: "custom".into(),
|
||||||
label: "Custom".into(),
|
label: "Custom".into(),
|
||||||
command: "whatever".into(),
|
command: "whatever".into(),
|
||||||
|
auto_approve: false,
|
||||||
}]),
|
}]),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -122,6 +122,9 @@ pub struct SessionRecord {
|
|||||||
/// Completion signal for the task draining ACP notifications into the
|
/// Completion signal for the task draining ACP notifications into the
|
||||||
/// event log. Shutdown waits for it before returning.
|
/// event log. Shutdown waits for it before returning.
|
||||||
acp_event_pump: Option<watch::Receiver<bool>>,
|
acp_event_pump: Option<watch::Receiver<bool>>,
|
||||||
|
/// When `true`, the permission pump auto-responds `AllowAlways` to every
|
||||||
|
/// ACP permission request without surfacing it to clients.
|
||||||
|
pub auto_approve: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SessionRecord {
|
impl SessionRecord {
|
||||||
@@ -1414,7 +1417,7 @@ impl SessionManager {
|
|||||||
let mut sessions = self.inner.sessions.lock().await;
|
let mut sessions = self.inner.sessions.lock().await;
|
||||||
let event_pump = event_pump.map(|(acp, events)| {
|
let event_pump = event_pump.map(|(acp, events)| {
|
||||||
let done = start_acp_event_pump(&self.inner, id, &acp, events.clone());
|
let done = start_acp_event_pump(&self.inner, id, &acp, events.clone());
|
||||||
start_acp_permission_pump(&self.inner, id, &acp, events);
|
start_acp_permission_pump(&self.inner, id, &acp, events, req.auto_approve);
|
||||||
done
|
done
|
||||||
});
|
});
|
||||||
sessions.insert(
|
sessions.insert(
|
||||||
@@ -1435,6 +1438,7 @@ impl SessionManager {
|
|||||||
acp_events,
|
acp_events,
|
||||||
structured_activity_watermark: None,
|
structured_activity_watermark: None,
|
||||||
acp_event_pump: event_pump,
|
acp_event_pump: event_pump,
|
||||||
|
auto_approve: req.auto_approve,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -1647,6 +1651,7 @@ impl SessionManager {
|
|||||||
acp_events: None,
|
acp_events: None,
|
||||||
structured_activity_watermark: None,
|
structured_activity_watermark: None,
|
||||||
acp_event_pump: None,
|
acp_event_pump: None,
|
||||||
|
auto_approve: false,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
let _ = self
|
let _ = self
|
||||||
@@ -1824,11 +1829,14 @@ impl SessionManager {
|
|||||||
acp_events,
|
acp_events,
|
||||||
structured_activity_watermark: None,
|
structured_activity_watermark: None,
|
||||||
acp_event_pump: 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,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
if let Some((acp, events)) = event_pump {
|
if let Some((acp, events)) = event_pump {
|
||||||
let done = start_acp_event_pump(&self.inner, id, &acp, events.clone());
|
let done = start_acp_event_pump(&self.inner, id, &acp, events.clone());
|
||||||
start_acp_permission_pump(&self.inner, id, &acp, events);
|
start_acp_permission_pump(&self.inner, id, &acp, events, false);
|
||||||
if let Some(record) = self.inner.sessions.lock().await.get_mut(&id) {
|
if let Some(record) = self.inner.sessions.lock().await.get_mut(&id) {
|
||||||
record.acp_event_pump = Some(done);
|
record.acp_event_pump = Some(done);
|
||||||
}
|
}
|
||||||
@@ -2327,6 +2335,7 @@ fn start_acp_permission_pump(
|
|||||||
id: Uuid,
|
id: Uuid,
|
||||||
acp: &Arc<AcpSession>,
|
acp: &Arc<AcpSession>,
|
||||||
events: Arc<Mutex<AcpEventStream>>,
|
events: Arc<Mutex<AcpEventStream>>,
|
||||||
|
auto_approve: bool,
|
||||||
) {
|
) {
|
||||||
let Some(mut requests) = acp.take_permission_requests() else {
|
let Some(mut requests) = acp.take_permission_requests() else {
|
||||||
return;
|
return;
|
||||||
@@ -2340,6 +2349,12 @@ fn start_acp_permission_pump(
|
|||||||
response,
|
response,
|
||||||
}) = requests.recv().await
|
}) = requests.recv().await
|
||||||
{
|
{
|
||||||
|
if auto_approve {
|
||||||
|
let outcome =
|
||||||
|
permission_outcome(ApprovalDecision::AllowForSession, &request.options);
|
||||||
|
let _ = response.send(outcome);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
let mut events = events.lock().await;
|
let mut events = events.lock().await;
|
||||||
if events.projection.active_turn() != Some(turn) {
|
if events.projection.active_turn() != Some(turn) {
|
||||||
let _ = response.send(maestro_acp::schema::RequestPermissionOutcome::Cancelled);
|
let _ = response.send(maestro_acp::schema::RequestPermissionOutcome::Cancelled);
|
||||||
@@ -3060,6 +3075,7 @@ mod tests {
|
|||||||
env: std::collections::HashMap::new(),
|
env: std::collections::HashMap::new(),
|
||||||
metadata: std::collections::HashMap::new(),
|
metadata: std::collections::HashMap::new(),
|
||||||
worktree: None,
|
worktree: None,
|
||||||
|
auto_approve: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -112,6 +112,7 @@ fn structured_command(
|
|||||||
env,
|
env,
|
||||||
metadata: HashMap::new(),
|
metadata: HashMap::new(),
|
||||||
worktree: None,
|
worktree: None,
|
||||||
|
auto_approve: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -705,6 +706,7 @@ async fn shutdown_preserves_a_pristine_structured_worktree_for_recovery() {
|
|||||||
branch: branch.into(),
|
branch: branch.into(),
|
||||||
create_branch: true,
|
create_branch: true,
|
||||||
}),
|
}),
|
||||||
|
auto_approve: false,
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.expect("create");
|
.expect("create");
|
||||||
@@ -1187,6 +1189,7 @@ async fn cancelling_a_structured_handshake_rolls_back_and_settles_admission() {
|
|||||||
branch: "cancelled-create".into(),
|
branch: "cancelled-create".into(),
|
||||||
create_branch: true,
|
create_branch: true,
|
||||||
}),
|
}),
|
||||||
|
auto_approve: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
let create = {
|
let create = {
|
||||||
|
|||||||
@@ -48,6 +48,7 @@ async fn spawn_sleeping(manager: &SessionManager) -> Uuid {
|
|||||||
env: Default::default(),
|
env: Default::default(),
|
||||||
metadata: Default::default(),
|
metadata: Default::default(),
|
||||||
worktree: None,
|
worktree: None,
|
||||||
|
auto_approve: false,
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
|||||||
@@ -81,6 +81,7 @@ async fn create_bash_session(h: &Harness) -> Uuid {
|
|||||||
env: HashMap::new(),
|
env: HashMap::new(),
|
||||||
metadata: HashMap::new(),
|
metadata: HashMap::new(),
|
||||||
worktree: None,
|
worktree: None,
|
||||||
|
auto_approve: false,
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|||||||
@@ -56,6 +56,7 @@ async fn spawn(manager: &SessionManager, name: Option<&str>) -> Uuid {
|
|||||||
env: Default::default(),
|
env: Default::default(),
|
||||||
metadata,
|
metadata,
|
||||||
worktree: None,
|
worktree: None,
|
||||||
|
auto_approve: false,
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ fn request(cwd: &std::path::Path, repo: &std::path::Path, branch: &str) -> Creat
|
|||||||
branch: branch.into(),
|
branch: branch.into(),
|
||||||
create_branch: true,
|
create_branch: true,
|
||||||
}),
|
}),
|
||||||
|
auto_approve: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -162,6 +162,7 @@ async fn structured_session_with_env(h: &Harness, env: HashMap<String, String>)
|
|||||||
env,
|
env,
|
||||||
metadata: HashMap::new(),
|
metadata: HashMap::new(),
|
||||||
worktree: None,
|
worktree: None,
|
||||||
|
auto_approve: false,
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.unwrap()
|
.unwrap()
|
||||||
@@ -493,6 +494,7 @@ async fn structured_prompt_rejects_unknown_and_unavailable_sessions() {
|
|||||||
env: HashMap::new(),
|
env: HashMap::new(),
|
||||||
metadata: HashMap::new(),
|
metadata: HashMap::new(),
|
||||||
worktree: None,
|
worktree: None,
|
||||||
|
auto_approve: false,
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
@@ -626,6 +628,7 @@ async fn structured_replay_rejects_unknown_terminal_and_dead_sessions() {
|
|||||||
env: HashMap::new(),
|
env: HashMap::new(),
|
||||||
metadata: HashMap::new(),
|
metadata: HashMap::new(),
|
||||||
worktree: None,
|
worktree: None,
|
||||||
|
auto_approve: false,
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
@@ -768,6 +771,7 @@ async fn list_sessions_starts_empty_and_reflects_creates() {
|
|||||||
env: HashMap::new(),
|
env: HashMap::new(),
|
||||||
metadata: HashMap::new(),
|
metadata: HashMap::new(),
|
||||||
worktree: None,
|
worktree: None,
|
||||||
|
auto_approve: false,
|
||||||
};
|
};
|
||||||
let created: Session = reqwest::Client::new()
|
let created: Session = reqwest::Client::new()
|
||||||
.post(url(h.addr, "/api/sessions"))
|
.post(url(h.addr, "/api/sessions"))
|
||||||
@@ -985,6 +989,7 @@ async fn patch_session_renames_it() {
|
|||||||
env: HashMap::new(),
|
env: HashMap::new(),
|
||||||
metadata: HashMap::new(),
|
metadata: HashMap::new(),
|
||||||
worktree: None,
|
worktree: None,
|
||||||
|
auto_approve: false,
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
@@ -1028,6 +1033,7 @@ async fn post_focus_stamps_last_focused_at() {
|
|||||||
env: HashMap::new(),
|
env: HashMap::new(),
|
||||||
metadata: HashMap::new(),
|
metadata: HashMap::new(),
|
||||||
worktree: None,
|
worktree: None,
|
||||||
|
auto_approve: false,
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
@@ -1062,6 +1068,7 @@ async fn delete_owned_session_kills_it() {
|
|||||||
env: HashMap::new(),
|
env: HashMap::new(),
|
||||||
metadata: HashMap::new(),
|
metadata: HashMap::new(),
|
||||||
worktree: None,
|
worktree: None,
|
||||||
|
auto_approve: false,
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
@@ -1084,6 +1091,7 @@ async fn spawn_via_manager(h: &Harness) -> Uuid {
|
|||||||
env: HashMap::new(),
|
env: HashMap::new(),
|
||||||
metadata: HashMap::new(),
|
metadata: HashMap::new(),
|
||||||
worktree: None,
|
worktree: None,
|
||||||
|
auto_approve: false,
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.unwrap()
|
.unwrap()
|
||||||
@@ -1198,6 +1206,7 @@ async fn delete_a_session_whose_worktree_holds_unsaved_work_returns_409_with_the
|
|||||||
branch: "feat/guarded".into(),
|
branch: "feat/guarded".into(),
|
||||||
create_branch: true,
|
create_branch: true,
|
||||||
}),
|
}),
|
||||||
|
auto_approve: false,
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
@@ -1251,6 +1260,7 @@ async fn delete_with_force_ends_the_session_and_keeps_the_worktree() {
|
|||||||
branch: "feat/guarded".into(),
|
branch: "feat/guarded".into(),
|
||||||
create_branch: true,
|
create_branch: true,
|
||||||
}),
|
}),
|
||||||
|
auto_approve: false,
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
@@ -1281,6 +1291,7 @@ async fn attach_ws_streams_pty_bytes() {
|
|||||||
env: HashMap::new(),
|
env: HashMap::new(),
|
||||||
metadata: HashMap::new(),
|
metadata: HashMap::new(),
|
||||||
worktree: None,
|
worktree: None,
|
||||||
|
auto_approve: false,
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
@@ -1383,6 +1394,7 @@ async fn events_ws_sends_a_snapshot_then_streams_deltas() {
|
|||||||
env: HashMap::new(),
|
env: HashMap::new(),
|
||||||
metadata: HashMap::new(),
|
metadata: HashMap::new(),
|
||||||
worktree: None,
|
worktree: None,
|
||||||
|
auto_approve: false,
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.expect("create");
|
.expect("create");
|
||||||
@@ -1495,6 +1507,7 @@ async fn every_events_subscriber_gets_its_own_snapshot() {
|
|||||||
env: HashMap::new(),
|
env: HashMap::new(),
|
||||||
metadata: HashMap::new(),
|
metadata: HashMap::new(),
|
||||||
worktree: None,
|
worktree: None,
|
||||||
|
auto_approve: false,
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.expect("create");
|
.expect("create");
|
||||||
|
|||||||
@@ -57,6 +57,7 @@ async fn spawn_named(manager: &SessionManager, name: Option<&str>) -> Uuid {
|
|||||||
env: Default::default(),
|
env: Default::default(),
|
||||||
metadata,
|
metadata,
|
||||||
worktree: None,
|
worktree: None,
|
||||||
|
auto_approve: false,
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
|||||||
@@ -70,6 +70,7 @@ impl Fx {
|
|||||||
env: HashMap::new(),
|
env: HashMap::new(),
|
||||||
metadata: HashMap::new(),
|
metadata: HashMap::new(),
|
||||||
worktree: None,
|
worktree: None,
|
||||||
|
auto_approve: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ async fn create_then_kill_round_trip() {
|
|||||||
env: HashMap::new(),
|
env: HashMap::new(),
|
||||||
metadata: HashMap::new(),
|
metadata: HashMap::new(),
|
||||||
worktree: None,
|
worktree: None,
|
||||||
|
auto_approve: false,
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.expect("create");
|
.expect("create");
|
||||||
@@ -70,6 +71,7 @@ async fn create_appends_to_spawn_history() {
|
|||||||
env: HashMap::new(),
|
env: HashMap::new(),
|
||||||
metadata: HashMap::from([("name".into(), serde_json::json!("neon-drifter"))]),
|
metadata: HashMap::from([("name".into(), serde_json::json!("neon-drifter"))]),
|
||||||
worktree: None,
|
worktree: None,
|
||||||
|
auto_approve: false,
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.expect("create");
|
.expect("create");
|
||||||
@@ -100,6 +102,7 @@ async fn create_without_history_logs_nothing() {
|
|||||||
env: HashMap::new(),
|
env: HashMap::new(),
|
||||||
metadata: HashMap::new(),
|
metadata: HashMap::new(),
|
||||||
worktree: None,
|
worktree: None,
|
||||||
|
auto_approve: false,
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.expect("create");
|
.expect("create");
|
||||||
@@ -123,6 +126,7 @@ async fn recover_adopts_existing_tmux_sessions() {
|
|||||||
env: HashMap::new(),
|
env: HashMap::new(),
|
||||||
metadata: HashMap::new(),
|
metadata: HashMap::new(),
|
||||||
worktree: None,
|
worktree: None,
|
||||||
|
auto_approve: false,
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.expect("create");
|
.expect("create");
|
||||||
@@ -166,6 +170,7 @@ async fn create_captures_initial_output_in_replay_buffer() {
|
|||||||
env: HashMap::new(),
|
env: HashMap::new(),
|
||||||
metadata: HashMap::new(),
|
metadata: HashMap::new(),
|
||||||
worktree: None,
|
worktree: None,
|
||||||
|
auto_approve: false,
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.expect("create");
|
.expect("create");
|
||||||
@@ -215,6 +220,7 @@ async fn attach_replay_is_the_current_screen_not_the_byte_tail() {
|
|||||||
env: HashMap::new(),
|
env: HashMap::new(),
|
||||||
metadata: HashMap::new(),
|
metadata: HashMap::new(),
|
||||||
worktree: None,
|
worktree: None,
|
||||||
|
auto_approve: false,
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.expect("create");
|
.expect("create");
|
||||||
@@ -273,6 +279,7 @@ async fn attach_replay_carries_the_panes_mouse_modes() {
|
|||||||
env: HashMap::new(),
|
env: HashMap::new(),
|
||||||
metadata: HashMap::new(),
|
metadata: HashMap::new(),
|
||||||
worktree: None,
|
worktree: None,
|
||||||
|
auto_approve: false,
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.expect("create");
|
.expect("create");
|
||||||
@@ -324,6 +331,7 @@ async fn recover_re_pipes_pane_so_output_reaches_subscribers() {
|
|||||||
env: HashMap::new(),
|
env: HashMap::new(),
|
||||||
metadata: HashMap::new(),
|
metadata: HashMap::new(),
|
||||||
worktree: None,
|
worktree: None,
|
||||||
|
auto_approve: false,
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.expect("create");
|
.expect("create");
|
||||||
@@ -387,6 +395,7 @@ async fn pty_broadcast_delivers_bytes_to_subscribers() {
|
|||||||
env: HashMap::new(),
|
env: HashMap::new(),
|
||||||
metadata: HashMap::new(),
|
metadata: HashMap::new(),
|
||||||
worktree: None,
|
worktree: None,
|
||||||
|
auto_approve: false,
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
@@ -438,6 +447,7 @@ async fn liveness_watcher_marks_dead_sessions_and_keeps_them_until_dismissed() {
|
|||||||
env: HashMap::new(),
|
env: HashMap::new(),
|
||||||
metadata: HashMap::new(),
|
metadata: HashMap::new(),
|
||||||
worktree: None,
|
worktree: None,
|
||||||
|
auto_approve: false,
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.expect("create");
|
.expect("create");
|
||||||
@@ -508,6 +518,7 @@ async fn watcher_refreshes_the_blocked_work_indicator() {
|
|||||||
branch: "feat/indicator".into(),
|
branch: "feat/indicator".into(),
|
||||||
create_branch: true,
|
create_branch: true,
|
||||||
}),
|
}),
|
||||||
|
auto_approve: false,
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.expect("create");
|
.expect("create");
|
||||||
@@ -601,6 +612,7 @@ async fn kill_removes_worktree_even_when_spec_says_keep() {
|
|||||||
branch: "feat/keep".into(),
|
branch: "feat/keep".into(),
|
||||||
create_branch: true,
|
create_branch: true,
|
||||||
}),
|
}),
|
||||||
|
auto_approve: false,
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.expect("create");
|
.expect("create");
|
||||||
@@ -639,6 +651,7 @@ async fn killing_refuses_a_worktree_with_unsaved_work_and_keeps_the_session() {
|
|||||||
branch: "feat/guarded".into(),
|
branch: "feat/guarded".into(),
|
||||||
create_branch: true,
|
create_branch: true,
|
||||||
}),
|
}),
|
||||||
|
auto_approve: false,
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.expect("create");
|
.expect("create");
|
||||||
@@ -703,6 +716,7 @@ async fn killing_refuses_until_the_branch_is_pushed() {
|
|||||||
branch: "feat/pushed".into(),
|
branch: "feat/pushed".into(),
|
||||||
create_branch: true,
|
create_branch: true,
|
||||||
}),
|
}),
|
||||||
|
auto_approve: false,
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.expect("create");
|
.expect("create");
|
||||||
@@ -753,6 +767,7 @@ async fn force_killing_a_guarded_worktree_leaves_it_on_disk() {
|
|||||||
branch: "feat/forced".into(),
|
branch: "feat/forced".into(),
|
||||||
create_branch: true,
|
create_branch: true,
|
||||||
}),
|
}),
|
||||||
|
auto_approve: false,
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.expect("create");
|
.expect("create");
|
||||||
@@ -799,6 +814,7 @@ async fn force_on_a_clear_worktree_removes_it_as_usual() {
|
|||||||
branch: "feat/clear".into(),
|
branch: "feat/clear".into(),
|
||||||
create_branch: true,
|
create_branch: true,
|
||||||
}),
|
}),
|
||||||
|
auto_approve: false,
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.expect("create");
|
.expect("create");
|
||||||
@@ -840,6 +856,7 @@ async fn killing_an_ignored_only_worktree_succeeds() {
|
|||||||
branch: "feat/rusty".into(),
|
branch: "feat/rusty".into(),
|
||||||
create_branch: true,
|
create_branch: true,
|
||||||
}),
|
}),
|
||||||
|
auto_approve: false,
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.expect("create");
|
.expect("create");
|
||||||
@@ -882,6 +899,7 @@ async fn natural_exit_of_a_guarded_worktree_leaves_it_on_disk() {
|
|||||||
branch: "feat/exited".into(),
|
branch: "feat/exited".into(),
|
||||||
create_branch: true,
|
create_branch: true,
|
||||||
}),
|
}),
|
||||||
|
auto_approve: false,
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.expect("create");
|
.expect("create");
|
||||||
@@ -944,6 +962,7 @@ async fn natural_exit_of_a_pristine_worktree_removes_it() {
|
|||||||
branch: "feat/clean".into(),
|
branch: "feat/clean".into(),
|
||||||
create_branch: true,
|
create_branch: true,
|
||||||
}),
|
}),
|
||||||
|
auto_approve: false,
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.expect("create");
|
.expect("create");
|
||||||
@@ -1001,6 +1020,7 @@ async fn liveness_watcher_leaves_running_sessions_alone() {
|
|||||||
env: HashMap::new(),
|
env: HashMap::new(),
|
||||||
metadata: HashMap::new(),
|
metadata: HashMap::new(),
|
||||||
worktree: None,
|
worktree: None,
|
||||||
|
auto_approve: false,
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.expect("create");
|
.expect("create");
|
||||||
@@ -1040,6 +1060,7 @@ async fn worktree_base_repo_records_the_main_checkout_not_the_request() {
|
|||||||
branch: "feat/one".into(),
|
branch: "feat/one".into(),
|
||||||
create_branch: true,
|
create_branch: true,
|
||||||
}),
|
}),
|
||||||
|
auto_approve: false,
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.expect("create first");
|
.expect("create first");
|
||||||
@@ -1058,6 +1079,7 @@ async fn worktree_base_repo_records_the_main_checkout_not_the_request() {
|
|||||||
branch: "feat/two".into(),
|
branch: "feat/two".into(),
|
||||||
create_branch: true,
|
create_branch: true,
|
||||||
}),
|
}),
|
||||||
|
auto_approve: false,
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.expect("create second");
|
.expect("create second");
|
||||||
@@ -1093,6 +1115,7 @@ async fn spawned_sessions_export_maestro_session_id_and_url() {
|
|||||||
env: HashMap::new(),
|
env: HashMap::new(),
|
||||||
metadata: HashMap::new(),
|
metadata: HashMap::new(),
|
||||||
worktree: None,
|
worktree: None,
|
||||||
|
auto_approve: false,
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.expect("create");
|
.expect("create");
|
||||||
@@ -1132,6 +1155,7 @@ async fn a_freshly_created_session_has_never_been_focused() {
|
|||||||
env: HashMap::new(),
|
env: HashMap::new(),
|
||||||
metadata: HashMap::new(),
|
metadata: HashMap::new(),
|
||||||
worktree: None,
|
worktree: None,
|
||||||
|
auto_approve: false,
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.expect("create");
|
.expect("create");
|
||||||
@@ -1158,6 +1182,7 @@ async fn set_focused_true_stamps_last_focused_at() {
|
|||||||
env: HashMap::new(),
|
env: HashMap::new(),
|
||||||
metadata: HashMap::new(),
|
metadata: HashMap::new(),
|
||||||
worktree: None,
|
worktree: None,
|
||||||
|
auto_approve: false,
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.expect("create");
|
.expect("create");
|
||||||
@@ -1207,6 +1232,7 @@ async fn attaching_stamps_last_focused_at() {
|
|||||||
env: HashMap::new(),
|
env: HashMap::new(),
|
||||||
metadata: HashMap::new(),
|
metadata: HashMap::new(),
|
||||||
worktree: None,
|
worktree: None,
|
||||||
|
auto_approve: false,
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.expect("create");
|
.expect("create");
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ fn create_req(cwd: &std::path::Path, command: &str) -> CreateSessionRequest {
|
|||||||
env: HashMap::new(),
|
env: HashMap::new(),
|
||||||
metadata: HashMap::new(),
|
metadata: HashMap::new(),
|
||||||
worktree: None,
|
worktree: None,
|
||||||
|
auto_approve: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -111,6 +112,7 @@ fn worktree_req(base: &std::path::Path, branch: &str, create_branch: bool) -> Cr
|
|||||||
env: HashMap::new(),
|
env: HashMap::new(),
|
||||||
metadata: HashMap::new(),
|
metadata: HashMap::new(),
|
||||||
worktree: Some(worktree_spec(base, branch, create_branch)),
|
worktree: Some(worktree_spec(base, branch, create_branch)),
|
||||||
|
auto_approve: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -206,6 +208,7 @@ async fn kill_removes_clean_worktree() {
|
|||||||
env: HashMap::new(),
|
env: HashMap::new(),
|
||||||
metadata: HashMap::new(),
|
metadata: HashMap::new(),
|
||||||
worktree: Some(worktree_spec(base.path(), "feature/e2e", true)),
|
worktree: Some(worktree_spec(base.path(), "feature/e2e", true)),
|
||||||
|
auto_approve: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
let s = client.spawn_session(&req).await.expect("spawn worktree");
|
let s = client.spawn_session(&req).await.expect("spawn worktree");
|
||||||
@@ -260,6 +263,7 @@ async fn kill_refuses_worktree_with_uncommitted_changes() {
|
|||||||
env: HashMap::new(),
|
env: HashMap::new(),
|
||||||
metadata: HashMap::new(),
|
metadata: HashMap::new(),
|
||||||
worktree: Some(worktree_spec(base.path(), "feature/unsaved", true)),
|
worktree: Some(worktree_spec(base.path(), "feature/unsaved", true)),
|
||||||
|
auto_approve: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
let s = client.spawn_session(&req).await.expect("spawn worktree");
|
let s = client.spawn_session(&req).await.expect("spawn worktree");
|
||||||
@@ -319,6 +323,7 @@ async fn spawn_on_existing_branch_checks_it_out() {
|
|||||||
env: HashMap::new(),
|
env: HashMap::new(),
|
||||||
metadata: HashMap::new(),
|
metadata: HashMap::new(),
|
||||||
worktree: Some(worktree_spec(base.path(), "feature/existing", false)),
|
worktree: Some(worktree_spec(base.path(), "feature/existing", false)),
|
||||||
|
auto_approve: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
let s = client
|
let s = client
|
||||||
@@ -827,6 +832,7 @@ async fn natural_exit_settles_dirty_and_pristine_worktrees_differently() {
|
|||||||
env: HashMap::new(),
|
env: HashMap::new(),
|
||||||
metadata: HashMap::new(),
|
metadata: HashMap::new(),
|
||||||
worktree: Some(worktree_spec(dirty_repo.path(), "feature/messy", true)),
|
worktree: Some(worktree_spec(dirty_repo.path(), "feature/messy", true)),
|
||||||
|
auto_approve: false,
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.expect("spawn dirty");
|
.expect("spawn dirty");
|
||||||
@@ -876,6 +882,7 @@ fn create_req_cmd(cwd: &std::path::Path, command: &str, branch: &str) -> CreateS
|
|||||||
env: HashMap::new(),
|
env: HashMap::new(),
|
||||||
metadata: HashMap::new(),
|
metadata: HashMap::new(),
|
||||||
worktree: Some(worktree_spec(cwd, branch, true)),
|
worktree: Some(worktree_spec(cwd, branch, true)),
|
||||||
|
auto_approve: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1068,6 +1075,7 @@ async fn sigterm_stops_structured_child_before_events_ws_drains() {
|
|||||||
env: fake.env.clone(),
|
env: fake.env.clone(),
|
||||||
metadata: HashMap::new(),
|
metadata: HashMap::new(),
|
||||||
worktree: None,
|
worktree: None,
|
||||||
|
auto_approve: false,
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.expect("spawn structured session");
|
.expect("spawn structured session");
|
||||||
|
|||||||
@@ -383,6 +383,10 @@ pub struct CreateSessionRequest {
|
|||||||
/// untouched.
|
/// untouched.
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub view: SessionView,
|
pub view: SessionView,
|
||||||
|
/// When `true`, the daemon auto-approves every ACP permission request
|
||||||
|
/// for this structured session.
|
||||||
|
#[serde(default)]
|
||||||
|
pub auto_approve: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Result of `GET /api/dirs`: the immediate subdirectories of one directory.
|
/// Result of `GET /api/dirs`: the immediate subdirectories of one directory.
|
||||||
@@ -522,6 +526,11 @@ pub struct SpawnPreset {
|
|||||||
pub id: String,
|
pub id: String,
|
||||||
pub label: String,
|
pub label: String,
|
||||||
pub command: String,
|
pub command: String,
|
||||||
|
/// When `true`, the daemon auto-approves every ACP permission request
|
||||||
|
/// for structured sessions spawned from this preset instead of surfacing
|
||||||
|
/// them to the client.
|
||||||
|
#[serde(default)]
|
||||||
|
pub auto_approve: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Build provenance of the running daemon: the commit it was compiled
|
/// Build provenance of the running daemon: the commit it was compiled
|
||||||
@@ -1251,6 +1260,7 @@ mod tests {
|
|||||||
create_branch: true,
|
create_branch: true,
|
||||||
}),
|
}),
|
||||||
view: SessionView::Terminal,
|
view: SessionView::Terminal,
|
||||||
|
auto_approve: false,
|
||||||
};
|
};
|
||||||
assert_eq!(req, round_trip(&req));
|
assert_eq!(req, round_trip(&req));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3009,6 +3009,7 @@ mod tests {
|
|||||||
env: Default::default(),
|
env: Default::default(),
|
||||||
metadata: Default::default(),
|
metadata: Default::default(),
|
||||||
worktree: None,
|
worktree: None,
|
||||||
|
auto_approve: false,
|
||||||
};
|
};
|
||||||
app.submit_spawn(req).await;
|
app.submit_spawn(req).await;
|
||||||
|
|
||||||
@@ -3057,6 +3058,7 @@ mod tests {
|
|||||||
env: Default::default(),
|
env: Default::default(),
|
||||||
metadata: Default::default(),
|
metadata: Default::default(),
|
||||||
worktree: None,
|
worktree: None,
|
||||||
|
auto_approve: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
let structured_id = Uuid::from_u128(188);
|
let structured_id = Uuid::from_u128(188);
|
||||||
|
|||||||
@@ -718,6 +718,10 @@ impl DraftPane {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
let worktree = self.build_worktree()?;
|
let worktree = self.build_worktree()?;
|
||||||
|
let auto_approve = self
|
||||||
|
.presets
|
||||||
|
.get(self.selected_preset)
|
||||||
|
.is_some_and(|p| p.auto_approve);
|
||||||
Ok(CreateSessionRequest {
|
Ok(CreateSessionRequest {
|
||||||
view: if self.structured_view && self.supports_structured_view() {
|
view: if self.structured_view && self.supports_structured_view() {
|
||||||
SessionView::Structured
|
SessionView::Structured
|
||||||
@@ -729,6 +733,7 @@ impl DraftPane {
|
|||||||
env: Default::default(),
|
env: Default::default(),
|
||||||
metadata,
|
metadata,
|
||||||
worktree,
|
worktree,
|
||||||
|
auto_approve,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1776,6 +1781,7 @@ mod tests {
|
|||||||
id: "aider".into(),
|
id: "aider".into(),
|
||||||
label: "Aider".into(),
|
label: "Aider".into(),
|
||||||
command: "aider".into(),
|
command: "aider".into(),
|
||||||
|
auto_approve: false,
|
||||||
}]);
|
}]);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
draft.command(),
|
draft.command(),
|
||||||
@@ -1798,11 +1804,13 @@ mod tests {
|
|||||||
id: "claude".into(),
|
id: "claude".into(),
|
||||||
label: "Claude".into(),
|
label: "Claude".into(),
|
||||||
command: "claude".into(),
|
command: "claude".into(),
|
||||||
|
auto_approve: false,
|
||||||
},
|
},
|
||||||
SpawnPreset {
|
SpawnPreset {
|
||||||
id: "aider".into(),
|
id: "aider".into(),
|
||||||
label: "Aider".into(),
|
label: "Aider".into(),
|
||||||
command: "aider".into(),
|
command: "aider".into(),
|
||||||
|
auto_approve: false,
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
assert_eq!(draft.command(), "aider");
|
assert_eq!(draft.command(), "aider");
|
||||||
@@ -1822,6 +1830,7 @@ mod tests {
|
|||||||
id: "claude".into(),
|
id: "claude".into(),
|
||||||
label: "Claude".into(),
|
label: "Claude".into(),
|
||||||
command: "claude".into(),
|
command: "claude".into(),
|
||||||
|
auto_approve: false,
|
||||||
}]);
|
}]);
|
||||||
assert!(draft.is_custom());
|
assert!(draft.is_custom());
|
||||||
assert_eq!(draft.command(), "bash -l");
|
assert_eq!(draft.command(), "bash -l");
|
||||||
@@ -1898,16 +1907,19 @@ mod tests {
|
|||||||
id: "claude".into(),
|
id: "claude".into(),
|
||||||
label: "Claude".into(),
|
label: "Claude".into(),
|
||||||
command: "claude".into(),
|
command: "claude".into(),
|
||||||
|
auto_approve: false,
|
||||||
},
|
},
|
||||||
SpawnPreset {
|
SpawnPreset {
|
||||||
id: "codex".into(),
|
id: "codex".into(),
|
||||||
label: "Codex".into(),
|
label: "Codex".into(),
|
||||||
command: "codex".into(),
|
command: "codex".into(),
|
||||||
|
auto_approve: false,
|
||||||
},
|
},
|
||||||
SpawnPreset {
|
SpawnPreset {
|
||||||
id: "opencode".into(),
|
id: "opencode".into(),
|
||||||
label: "OpenCode".into(),
|
label: "OpenCode".into(),
|
||||||
command: "opencode".into(),
|
command: "opencode".into(),
|
||||||
|
auto_approve: false,
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
assert!(!draft.structured_view);
|
assert!(!draft.structured_view);
|
||||||
@@ -2046,16 +2058,19 @@ mod tests {
|
|||||||
id: "claude-wrapped".into(),
|
id: "claude-wrapped".into(),
|
||||||
label: "Claude (npx)".into(),
|
label: "Claude (npx)".into(),
|
||||||
command: "npx claude-code --resume".into(),
|
command: "npx claude-code --resume".into(),
|
||||||
|
auto_approve: false,
|
||||||
},
|
},
|
||||||
SpawnPreset {
|
SpawnPreset {
|
||||||
id: "codex-wrapped".into(),
|
id: "codex-wrapped".into(),
|
||||||
label: "Codex (npx)".into(),
|
label: "Codex (npx)".into(),
|
||||||
command: "npx codex exec".into(),
|
command: "npx codex exec".into(),
|
||||||
|
auto_approve: false,
|
||||||
},
|
},
|
||||||
SpawnPreset {
|
SpawnPreset {
|
||||||
id: "aider".into(),
|
id: "aider".into(),
|
||||||
label: "Aider".into(),
|
label: "Aider".into(),
|
||||||
command: "aider".into(),
|
command: "aider".into(),
|
||||||
|
auto_approve: false,
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|||||||
@@ -121,6 +121,7 @@ impl FastForwardDefaults {
|
|||||||
branch: handle.to_string(),
|
branch: handle.to_string(),
|
||||||
create_branch: true,
|
create_branch: true,
|
||||||
}),
|
}),
|
||||||
|
auto_approve: false,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -184,6 +185,7 @@ mod tests {
|
|||||||
id: id.into(),
|
id: id.into(),
|
||||||
label: id.into(),
|
label: id.into(),
|
||||||
command: command.into(),
|
command: command.into(),
|
||||||
|
auto_approve: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ const base: SpawnFormValues = {
|
|||||||
cwd: "/home/user/project",
|
cwd: "/home/user/project",
|
||||||
name: "amber-fox",
|
name: "amber-fox",
|
||||||
structuredView: false,
|
structuredView: false,
|
||||||
|
autoApprove: false,
|
||||||
worktreeEnabled: false,
|
worktreeEnabled: false,
|
||||||
worktreeBranch: "",
|
worktreeBranch: "",
|
||||||
worktreeBranchMode: "new",
|
worktreeBranchMode: "new",
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ export interface SpawnFormValues {
|
|||||||
cwd: string;
|
cwd: string;
|
||||||
name: string;
|
name: string;
|
||||||
structuredView: boolean;
|
structuredView: boolean;
|
||||||
|
autoApprove: boolean;
|
||||||
worktreeEnabled: boolean;
|
worktreeEnabled: boolean;
|
||||||
worktreeBranch: string;
|
worktreeBranch: string;
|
||||||
worktreeBranchEdited: boolean;
|
worktreeBranchEdited: boolean;
|
||||||
@@ -79,6 +80,10 @@ export function buildSpawnRequest(
|
|||||||
req.view = "Structured";
|
req.view = "Structured";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (values.autoApprove) {
|
||||||
|
req.auto_approve = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (values.worktreeEnabled) {
|
if (values.worktreeEnabled) {
|
||||||
const mode = values.worktreeBranchMode ?? "new";
|
const mode = values.worktreeBranchMode ?? "new";
|
||||||
const branch = values.worktreeBranch.trim();
|
const branch = values.worktreeBranch.trim();
|
||||||
@@ -261,6 +266,8 @@ export function createSpawnForm(opts: SpawnFormOptions): SpawnFormHandle {
|
|||||||
let ready = false;
|
let ready = false;
|
||||||
let destroyed = false;
|
let destroyed = false;
|
||||||
const branchValue = () => (branchMode === "existing" ? branchSelect.value : branchInput.value);
|
const branchValue = () => (branchMode === "existing" ? branchSelect.value : branchInput.value);
|
||||||
|
const selectedAutoApprove = () =>
|
||||||
|
presets.find((p) => p.id === selectedPresetId)?.auto_approve ?? false;
|
||||||
const emit = () => {
|
const emit = () => {
|
||||||
if (!ready || destroyed) return;
|
if (!ready || destroyed) return;
|
||||||
opts.onChange?.({
|
opts.onChange?.({
|
||||||
@@ -268,6 +275,7 @@ export function createSpawnForm(opts: SpawnFormOptions): SpawnFormHandle {
|
|||||||
cwd,
|
cwd,
|
||||||
name: nameInput.value,
|
name: nameInput.value,
|
||||||
structuredView: structuredView.checked,
|
structuredView: structuredView.checked,
|
||||||
|
autoApprove: selectedAutoApprove(),
|
||||||
worktreeEnabled: wtEnabled.checked,
|
worktreeEnabled: wtEnabled.checked,
|
||||||
worktreeBranch: branchValue(),
|
worktreeBranch: branchValue(),
|
||||||
worktreeBranchEdited: branchEdited,
|
worktreeBranchEdited: branchEdited,
|
||||||
@@ -917,6 +925,7 @@ export function createSpawnForm(opts: SpawnFormOptions): SpawnFormHandle {
|
|||||||
cwd,
|
cwd,
|
||||||
name: nameInput.value,
|
name: nameInput.value,
|
||||||
structuredView: structuredView.checked,
|
structuredView: structuredView.checked,
|
||||||
|
autoApprove: selectedAutoApprove(),
|
||||||
worktreeEnabled: wtEnabled.checked,
|
worktreeEnabled: wtEnabled.checked,
|
||||||
worktreeBranch: branchValue(),
|
worktreeBranch: branchValue(),
|
||||||
worktreeBranchEdited: branchEdited,
|
worktreeBranchEdited: branchEdited,
|
||||||
|
|||||||
@@ -91,6 +91,7 @@ export interface SpawnPreset {
|
|||||||
id: string;
|
id: string;
|
||||||
label: string;
|
label: string;
|
||||||
command: string;
|
command: string;
|
||||||
|
auto_approve?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** `GET /api/info` — the daemon's identity plus its spawn presets (#26).
|
/** `GET /api/info` — the daemon's identity plus its spawn presets (#26).
|
||||||
@@ -277,6 +278,7 @@ export interface CreateSessionRequest {
|
|||||||
metadata?: Record<string, unknown>;
|
metadata?: Record<string, unknown>;
|
||||||
worktree?: WorktreeSpec;
|
worktree?: WorktreeSpec;
|
||||||
view?: SessionView;
|
view?: SessionView;
|
||||||
|
auto_approve?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type CatalogEvent =
|
export type CatalogEvent =
|
||||||
|
|||||||
Reference in New Issue
Block a user