feat(maestro): bind a TUI key to resume a dormant session

Adds DaemonClient::resume_session (POST /api/sessions/:id/resume) and a new
ResumeHighlighted action, bound to `u` by default (#166, #169).
This commit is contained in:
Miguel Palhas
2026-09-04 09:43:27 +01:00
parent ec7728afb1
commit 8f1b234a11
3 changed files with 31 additions and 0 deletions
+10
View File
@@ -141,6 +141,16 @@ impl DaemonClient {
json(check(resp).await?).await
}
/// `POST /api/sessions/:id/resume` (#166): respawn a dormant session
/// under its own uuid and sidecar. Refused with `409` (`already_running`
/// / `cwd_missing`) when there is nothing a respawn could fix.
pub async fn resume_session(&self, id: Uuid) -> Result<Session, ClientError> {
let resp = self
.send(Method::POST, &routes::session_resume(id), &[], None::<&()>)
.await?;
json(check(resp).await?).await
}
/// `POST /api/sessions/:id/activity` (#105): report an agent-observed
/// state. The daemon holds it above its own inference for a TTL, then
/// resumes inference. Answers `204 No Content`.
+15
View File
@@ -51,6 +51,9 @@ pub enum Action {
/// Rename the highlighted session (#125): opens a prompt pre-filled with
/// its current name.
RenameHighlighted,
/// Resume the highlighted dormant session (#166, #169): respawns it
/// under its own uuid and sidecar via `POST /api/sessions/:id/resume`.
ResumeHighlighted,
// Chrome
/// Open the `ctrl-k` command bar (`docs/COMMAND-BAR.md`) — a query line
@@ -105,6 +108,7 @@ impl Action {
Action::FastForwardSpawn => "Create session with defaults".into(),
Action::KillHighlighted => "Kill selected session".into(),
Action::RenameHighlighted => "Rename selected session".into(),
Action::ResumeHighlighted => "Resume dormant session".into(),
Action::OpenCommandBar => "Go to a session".into(),
Action::SendLiteralCtrlK => "Send literal Ctrl-K to session".into(),
Action::SendLiteralLeader => "Send literal leader key to session".into(),
@@ -134,6 +138,7 @@ impl Action {
"FastForwardSpawn" => return Ok(Action::FastForwardSpawn),
"KillHighlighted" => return Ok(Action::KillHighlighted),
"RenameHighlighted" => return Ok(Action::RenameHighlighted),
"ResumeHighlighted" => return Ok(Action::ResumeHighlighted),
"OpenCommandBar" => return Ok(Action::OpenCommandBar),
"SendLiteralCtrlK" => return Ok(Action::SendLiteralCtrlK),
"SendLiteralLeader" => return Ok(Action::SendLiteralLeader),
@@ -192,6 +197,16 @@ mod tests {
assert_eq!(Action::parse(" Noop ").unwrap(), Action::Noop);
}
/// #169: resume is its own verb, distinct from rename/kill, so a dormant
/// session's sidebar card has a keyboard-reachable resume.
#[test]
fn parses_resume_highlighted() {
assert_eq!(
Action::parse("ResumeHighlighted").unwrap(),
Action::ResumeHighlighted
);
}
#[test]
fn help_labels_are_plain_language() {
assert_eq!(Action::EnterInsert.help_label(), "Send keys to session");
+6
View File
@@ -59,6 +59,8 @@ const DEFAULT_NORMAL: &[(&str, &str)] = &[
("N", "FastForwardSpawn"),
("x", "KillHighlighted"),
("r", "RenameHighlighted"),
// Resume a dormant session (#166, #169).
("u", "ResumeHighlighted"),
// Focus
("ctrl-w h", "FocusSidebar"),
// Session scrollback
@@ -257,6 +259,10 @@ mod tests {
cfg.keymap.resolve(Mode::Normal, "N"),
Some(Action::FastForwardSpawn),
);
assert_eq!(
cfg.keymap.resolve(Mode::Normal, "u"),
Some(Action::ResumeHighlighted),
);
}
/// AoE-style defaults (#shortcuts): `q` and `tab` are bare because Normal