tui: cancel paused turns with ctrl-x

This commit is contained in:
2026-06-23 22:37:40 +09:00
parent 5954021cc5
commit 90b1a1fccb
5 changed files with 207 additions and 9 deletions
+30 -6
View File
@@ -900,12 +900,36 @@ async fn controller_loop<C, St>(
pending = Some(PendingRun::Resume);
}
Method::Cancel => {
let _ = event_tx.send(Event::Error {
code: ErrorCode::NotRunning,
message: "Pod is not running".into(),
});
}
Method::Cancel => match shared_state.get_status() {
PodStatus::Paused => match pod.cancel_paused_turn() {
Ok(()) => {
set_controller_status(
&shared_state,
&runtime_dir,
&event_tx,
PodStatus::Idle,
)
.await;
}
Err(error) => {
let _ = event_tx.send(Event::Error {
code: worker_error_code(&error),
message: error.to_string(),
});
}
},
PodStatus::Idle => {
let _ = event_tx.send(Event::Error {
code: ErrorCode::NotRunning,
message: "Pod is not running".into(),
});
}
PodStatus::Running => {
// Running turns receive Cancel through drive_turn; this is
// only reachable across a defensive race window.
let _ = cancel_tx.try_send(());
}
},
Method::Pause => {
// Already paused → idempotent no-op. Otherwise the
+22
View File
@@ -1863,6 +1863,28 @@ impl<C: LlmClient, St: Store> Pod<C, St> {
Ok(())
}
/// Abandon a paused/interrupted turn without resuming it.
///
/// This uses the same explicit interrupt preparation as the next fresh
/// `run` would have used, then clears the worker's interrupted marker so
/// future input is treated as a normal new turn instead of a resume.
/// The `RunCompleted` marker is a state-reset record for session replay;
/// no provider stream is resumed or mutated here.
pub fn cancel_paused_turn(&mut self) -> Result<(), PodError> {
if !self.worker().last_run_interrupted() {
return Ok(());
}
self.apply_interrupt_prep()?;
self.worker_mut().set_last_run_interrupted(false);
self.commit_entry(LogEntry::RunCompleted {
ts: segment_log::now_millis(),
result: WorkerResult::Finished,
interrupted: false,
})?;
Ok(())
}
/// Validate explicit workflow invocations without reading dependency
/// bodies. Called from `Pod::run` entry so an invalid slug aborts
/// the turn before any session-log commit or interrupt-prep side