aboutsummaryrefslogtreecommitdiff
path: root/src/app
diff options
context:
space:
mode:
authorOgulcan Celik <ogulcancelik@gmail.com>2026-05-29 21:01:03 +0300
committerOgulcan Celik <ogulcancelik@gmail.com>2026-05-29 21:01:03 +0300
commit1f2b0f71b54467a9749b0d3b6945b5322d0aa42a (patch)
tree2695c3f992f6aad89839a3e90fdfce2741092844 /src/app
parent9e302984ccb13a65e3e504fa7692b223f546ff84 (diff)
fix: keep restored agent panes after exit
Diffstat (limited to 'src/app')
-rw-r--r--src/app/api.rs53
1 files changed, 50 insertions, 3 deletions
diff --git a/src/app/api.rs b/src/app/api.rs
index e69ab0eb..df20cd34 100644
--- a/src/app/api.rs
+++ b/src/app/api.rs
@@ -330,9 +330,7 @@ impl App {
self.terminal_runtimes.insert(terminal_id.clone(), runtime);
if let Some(terminal) = self.state.terminals.get_mut(&terminal_id) {
- terminal.launch_argv = None;
- terminal.respawn_shell_on_exit = false;
- terminal.clear_agent_name();
+ terminal.clear_agent_runtime_identity_after_respawn();
}
self.state.focus_pane_in_workspace(ws_idx, pane_id);
self.schedule_session_save();
@@ -690,6 +688,55 @@ mod tests {
let _ = std::fs::remove_dir_all(temp_root);
}
+ #[tokio::test]
+ async fn pane_died_respawns_shell_and_clears_restored_agent_session() {
+ let (_api_tx, api_rx) = tokio::sync::mpsc::unbounded_channel();
+ let mut app = App::new(
+ &crate::config::Config::default(),
+ true,
+ None,
+ api_rx,
+ crate::api::EventHub::default(),
+ );
+ let workspace = crate::workspace::Workspace::test_new("restored");
+ let pane_id = workspace.tabs[0].root_pane;
+ let terminal_id = workspace.terminal_id(pane_id).cloned().unwrap();
+ app.state.workspaces = vec![workspace];
+ app.state.ensure_test_terminals();
+ let terminal = app
+ .state
+ .terminals
+ .get_mut(&terminal_id)
+ .expect("test terminal should exist");
+ terminal.respawn_shell_on_exit = true;
+ terminal.set_agent_name("codex".into());
+ terminal.set_persisted_agent_session(crate::agent_resume::PersistedAgentSession {
+ source: "herdr:codex".into(),
+ agent: "codex".into(),
+ session_ref: crate::agent_resume::AgentSessionRef::id("codex-session")
+ .expect("test session id should be valid"),
+ });
+
+ app.handle_internal_event(AppEvent::PaneDied { pane_id });
+
+ assert!(
+ app.find_pane(pane_id).is_some(),
+ "respawnable agent pane should stay attached after the agent process exits"
+ );
+ let terminal = app
+ .state
+ .terminals
+ .get(&terminal_id)
+ .expect("terminal should survive respawn");
+ assert!(!terminal.respawn_shell_on_exit);
+ assert!(terminal.persisted_agent_session.is_none());
+ assert!(terminal.agent_name.is_none());
+
+ for (_, runtime) in app.terminal_runtimes.drain() {
+ runtime.shutdown();
+ }
+ }
+
#[test]
fn terminal_delivery_does_not_refresh_existing_targeted_toast() {
let (_api_tx, api_rx) = tokio::sync::mpsc::unbounded_channel();