diff --git a/tools/wta/src/app.rs b/tools/wta/src/app.rs index 305ae438e..bcf2781ec 100644 --- a/tools/wta/src/app.rs +++ b/tools/wta/src/app.rs @@ -3674,10 +3674,12 @@ impl App { } fn begin_pending_agent_reconnect_preflight(&mut self) -> Option { - let AgentReconnectState::Disconnecting(latest) = - std::mem::take(&mut self.agent_reconnect_state) - else { - return None; + let latest = match std::mem::take(&mut self.agent_reconnect_state) { + AgentReconnectState::Disconnecting(latest) => latest, + state => { + self.agent_reconnect_state = state; + return None; + } }; self.pending_session_load = None; self.reset_agent_scoped_state(); diff --git a/tools/wta/src/app_tests.rs b/tools/wta/src/app_tests.rs index 07bb1203b..d42130b1f 100644 --- a/tools/wta/src/app_tests.rs +++ b/tools/wta/src/app_tests.rs @@ -4524,6 +4524,62 @@ fn settings_agent_rebind_targets_owner_and_resets_only_agent_state() { )); } +#[test] +fn agent_rebind_duplicate_retirement_notification_preserves_target_preflight() { + let (mut app, mut restart_rx) = test_app_with_restart_rx(); + app.owner_tab_id = Some("owner-tab".into()); + app.window_id = Some("window-1".into()); + app.tab_id = Some("owner-tab".into()); + app.current_agent_id = "copilot".into(); + app.tab_mut("owner-tab"); + app.set_master_pipe_acp_params( + "master-pipe".into(), + "copilot --acp".into(), + Some("copilot".into()), + None, + None, + crate::agent_source::AgentSource::Host, + None, + Some("owner-tab".into()), + Arc::clone(&app.shell_mgr), + true, + ); + + app.handle_event(agent_rebind_event("owner-tab", 1, "opencode")); + let request = match restart_rx + .try_recv() + .expect("agent rebind should retire the current transport") + { + AgentLifecycleRequest::RebindAgent(request) => request, + other => panic!("expected RebindAgent, got {other:?}"), + }; + + app.handle_event(AppEvent::AgentTransportRetired); + assert!(matches!( + &app.agent_reconnect_state, + AgentReconnectState::Preflighting(pending) + if pending.agent_id == "opencode" && pending.generation == 1 + )); + + app.handle_event(AppEvent::AgentReconnectReady(request)); + assert!(matches!( + &app.agent_reconnect_state, + AgentReconnectState::Preflighting(pending) + if pending.agent_id == "opencode" && pending.generation == 1 + )); + + app.handle_event(AppEvent::AgentReconnectPreflightComplete { + operation_id: "op-1".into(), + generation: 1, + result: passed_preflight("opencode", "OpenCode"), + }); + assert!(app.pending_acp_start); + assert!(matches!( + &app.agent_reconnect_state, + AgentReconnectState::Idle + )); +} + #[test] fn agent_rebind_accepts_only_the_helpers_current_execution_source() { let (mut app, mut restart_rx) = test_app_with_restart_rx();