feat(daemon): RestartSurface honors resume — swap to resume_args when mapped
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -291,6 +291,23 @@ fn spawn_env(sid: &SurfaceId, spec: &spacesh_proto::workspace::SurfaceSpec) -> (
|
|||||||
(env, active)
|
(env, active)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Build the spawn spec for a (re)start. When `resume` and the command has a
|
||||||
|
/// resume mapping, its args are replaced with the resume args; otherwise the
|
||||||
|
/// original spec args are kept.
|
||||||
|
fn resume_spec(
|
||||||
|
spec: &spacesh_proto::workspace::SurfaceSpec,
|
||||||
|
resume: bool,
|
||||||
|
cfg: &crate::config::Config,
|
||||||
|
) -> spacesh_proto::workspace::SurfaceSpec {
|
||||||
|
let mut out = spec.clone();
|
||||||
|
if resume {
|
||||||
|
if let Some(args) = cfg.resume_args(&spec.command) {
|
||||||
|
out.args = args;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out
|
||||||
|
}
|
||||||
|
|
||||||
/// Emit a `layout_changed` event for a workspace's current tree.
|
/// Emit a `layout_changed` event for a workspace's current tree.
|
||||||
fn emit_layout(reg: &Registry, ws_id: &WorkspaceId, clients: &HashMap<ClientId, ClientTx>) {
|
fn emit_layout(reg: &Registry, ws_id: &WorkspaceId, clients: &HashMap<ClientId, ClientTx>) {
|
||||||
if let Some(w) = reg.workspace(ws_id) {
|
if let Some(w) = reg.workspace(ws_id) {
|
||||||
@@ -475,13 +492,14 @@ async fn handle_request(
|
|||||||
let _ = out.send(ok(id, serde_json::json!({ "surface_ids": new_ids.iter().map(|s| s.0.clone()).collect::<Vec<_>>() }))).await;
|
let _ = out.send(ok(id, serde_json::json!({ "surface_ids": new_ids.iter().map(|s| s.0.clone()).collect::<Vec<_>>() }))).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
Cmd::RestartSurface { surface_id } => {
|
Cmd::RestartSurface { surface_id, resume } => {
|
||||||
if reg.is_running(&surface_id) {
|
if reg.is_running(&surface_id) {
|
||||||
let _ = out.send(ok(id, serde_json::Value::Null)).await; return; // already running
|
let _ = out.send(ok(id, serde_json::Value::Null)).await; return; // already running
|
||||||
}
|
}
|
||||||
let Some(spec) = reg.surface_spec(&surface_id) else {
|
let Some(spec) = reg.surface_spec(&surface_id) else {
|
||||||
let _ = out.send(err(id, "NOT_FOUND", "surface")).await; return;
|
let _ = out.send(err(id, "NOT_FOUND", "surface")).await; return;
|
||||||
};
|
};
|
||||||
|
let spec = resume_spec(&spec, resume, config);
|
||||||
let ws_id = reg.workspace_of(&surface_id).unwrap();
|
let ws_id = reg.workspace_of(&surface_id).unwrap();
|
||||||
let (env, hooks_active) = spawn_env(&surface_id, &spec);
|
let (env, hooks_active) = spawn_env(&surface_id, &spec);
|
||||||
match crate::surface::spawn_from_spec(surface_id.clone(), ws_id.clone(), &spec, env, hooks_active, state_tx.clone(), exit_tx.clone(), snapshot_tx.clone()) {
|
match crate::surface::spawn_from_spec(surface_id.clone(), ws_id.clone(), &spec, env, hooks_active, state_tx.clone(), exit_tx.clone(), snapshot_tx.clone()) {
|
||||||
@@ -1607,4 +1625,25 @@ mod tests {
|
|||||||
let snap = data["snapshot"].as_str().unwrap_or("");
|
let snap = data["snapshot"].as_str().unwrap_or("");
|
||||||
assert!(snap.contains("SNAPDISK"), "on-disk snapshot should contain SNAPDISK, got: {snap:?}");
|
assert!(snap.contains("SNAPDISK"), "on-disk snapshot should contain SNAPDISK, got: {snap:?}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn resume_spec_swaps_args_when_mapped() {
|
||||||
|
use spacesh_proto::workspace::SurfaceSpec;
|
||||||
|
let spec = SurfaceSpec {
|
||||||
|
command: "claude".into(), args: vec!["--foo".into()], cwd: "/tmp".into(),
|
||||||
|
agent_label: Some("claude".into()), cols: 80, rows: 24, autostart: false,
|
||||||
|
};
|
||||||
|
let cfg = crate::config::Config::default();
|
||||||
|
// resume=false → original args
|
||||||
|
let plain = resume_spec(&spec, false, &cfg);
|
||||||
|
assert_eq!(plain.args, vec!["--foo".to_string()]);
|
||||||
|
// resume=true with a default mapping → resume args
|
||||||
|
let resumed = resume_spec(&spec, true, &cfg);
|
||||||
|
assert_eq!(resumed.args, vec!["--continue".to_string()]);
|
||||||
|
// resume=true for an unmapped command → original args (graceful fallback)
|
||||||
|
let mut shell = spec.clone();
|
||||||
|
shell.command = "bash".into();
|
||||||
|
let resumed_shell = resume_spec(&shell, true, &cfg);
|
||||||
|
assert_eq!(resumed_shell.args, shell.args);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user