feat(maestro): rename a session over PATCH /api/sessions/:id

The daemon trims and caps the name, persists it to the sidecar under the
sessions lock, and broadcasts SessionUpdated. A blank name clears
metadata.name so the card falls back to the command, matching the rule the
spawn form already uses.

Refs #125

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Miguel Palhas
2026-08-30 11:26:12 +01:00
co-authored by Claude Opus 5
parent 999dbe3ea3
commit 345650172b
6 changed files with 315 additions and 3 deletions
+42
View File
@@ -323,6 +323,48 @@ async fn delete_unknown_session_returns_404() {
assert_eq!(resp.status(), reqwest::StatusCode::NOT_FOUND);
}
/// #125: the rename endpoint answers with the updated session, and the name
/// it stored is the trimmed one.
#[tokio::test]
async fn patch_session_renames_it() {
let h = spawn("naps-laptop").await;
let session = h
.manager
.create(CreateSessionRequest {
cwd: "/tmp".into(),
command: "sleep 60".into(),
env: HashMap::new(),
metadata: HashMap::new(),
worktree: None,
})
.await
.unwrap();
let resp = reqwest::Client::new()
.patch(url(h.addr, &format!("/api/sessions/{}", session.id)))
.json(&serde_json::json!({ "name": " crimson-otter " }))
.send()
.await
.unwrap();
assert_eq!(resp.status(), reqwest::StatusCode::OK);
let updated: Session = resp.json().await.unwrap();
assert_eq!(
updated.metadata.get("name").and_then(|v| v.as_str()),
Some("crimson-otter")
);
}
#[tokio::test]
async fn patch_unknown_session_returns_404() {
let h = spawn("naps-laptop").await;
let resp = reqwest::Client::new()
.patch(url(h.addr, &format!("/api/sessions/{}", Uuid::new_v4())))
.json(&serde_json::json!({ "name": "nope" }))
.send()
.await
.unwrap();
assert_eq!(resp.status(), reqwest::StatusCode::NOT_FOUND);
}
#[tokio::test]
async fn delete_owned_session_kills_it() {
let h = spawn("naps-laptop").await;