use super::super::*;
use super::MissionControlApp;
impl MissionControlApp {
pub(crate) fn finish_worker_if_ready(
&mut self,
ui_state: &mut state::MissionControlState,
) -> bool {
let Some(mut worker) = self.worker.take() else {
return false;
};
let worker_id = worker.outcome.worker_id();
let completion_reconciled =
worker.outcome_reconciled || ui_state.last_run_finished_worker_id == Some(worker_id);
if completion_reconciled {
worker.outcome_reconciled = true;
}
let handle_finished = worker.handle.is_finished();
if handle_finished && !completion_reconciled {
worker.outcome.mark_unexpected_worker_failure_if_pending();
}
let can_retire = completion_reconciled || worker.outcome.completion_delivery_failed();
if handle_finished && can_retire {
self.reconcile_worker_outcome(ui_state, &worker);
let _ = worker.handle.join();
self.active_run = false;
true
} else {
self.worker = Some(worker);
false
}
}
pub(crate) fn join_completed_worker(
&mut self,
ui_state: &mut state::MissionControlState,
) -> bool {
self.finish_worker_if_ready(ui_state)
}
pub(in crate::tui) fn reconcile_worker_outcome(
&mut self,
ui_state: &mut state::MissionControlState,
worker: &WorkerState,
) {
ui_state.session_usage.merge(
&worker
.outcome
.usage
.lock()
.unwrap_or_else(|error| error.into_inner()),
);
ui_state.refresh_session_cache_percent();
if !worker.outcome_reconciled
&& worker.outcome.completion_delivery_failed()
&& let Some(event) = worker.outcome.final_event()
{
let effect = apply_worker_final_event(ui_state, event);
self.reconcile_worker_final_event_effect(ui_state, effect);
}
let pending_steering = worker.steering.pending_count();
if ui_state.set_pending_steering_count(pending_steering) {
self.last_steering_pending_count = pending_steering;
}
ui_state.finish_assistant_streaming();
ui_state.clear_running_prompt();
if ui_state.active_worker_id == Some(worker.outcome.worker_id()) {
ui_state.active_worker_id = None;
}
}
pub(in crate::tui) fn reconcile_worker_final_event_effect(
&mut self,
ui_state: &mut state::MissionControlState,
effect: WorkerFinalEventEffect,
) {
match effect {
WorkerFinalEventEffect::CustomProviderFinished {
provider_id,
result,
} if result.is_ok() => {
self.refresh_runtime_after_custom_provider(&provider_id, ui_state);
}
WorkerFinalEventEffect::CompactionRuntimeRefresh(refresh) => {
let _ = self.apply_compaction_runtime_refresh(ui_state, *refresh);
}
WorkerFinalEventEffect::None
| WorkerFinalEventEffect::CustomProviderFinished { .. } => {}
}
}
pub(crate) fn request_cancel_active_worker(
&mut self,
ui_state: &mut state::MissionControlState,
) -> Option<String> {
let Some(worker) = self.worker.as_ref() else {
self.active_run = false;
return None;
};
let can_cancel = worker.shutdown_policy == WorkerShutdownPolicy::Cancel;
if can_cancel {
worker.cancel.store(true, Ordering::SeqCst);
let cleared = worker.steering.clear();
if cleared > 0 || ui_state.pending_steering_count > 0 {
ui_state.set_pending_steering_count(0);
self.last_steering_pending_count = 0;
}
}
self.active_run = false;
Some(if can_cancel {
"cancellation requested; provider worker is still shutting down its current blocking call"
.to_string()
} else {
"provider configuration save is in progress; please wait".to_string()
})
}
pub(crate) fn cancel_active_worker(
&mut self,
ui_state: &mut state::MissionControlState,
) -> Option<String> {
let status = self.request_cancel_active_worker(ui_state);
let finished = self
.worker
.as_ref()
.is_some_and(|worker| worker.handle.is_finished());
if finished && self.finish_worker_if_ready(ui_state) {
None
} else {
status
}
}
pub(crate) fn cancel_running_prompt(&mut self, ui_state: &mut state::MissionControlState) {
let prompt = ui_state.request_running_prompt_cancel().unwrap_or_default();
let preview = crate::tui::transcript::sanitize_preview(&prompt);
if preview.trim().is_empty() {
ui_state.status = "prompt cancellation requested".to_string();
} else {
ui_state.status = format!("canceling: {preview}");
}
let _ = self.cancel_active_worker(ui_state);
}
}