diff --git a/src/user/event_loop.rs b/src/user/event_loop.rs index fc1045f..4a454a0 100644 --- a/src/user/event_loop.rs +++ b/src/user/event_loop.rs @@ -215,6 +215,46 @@ pub async fn cmd_switch_model( } } +fn diff_mind_state( + cur: &crate::mind::MindState, + prev: &crate::mind::MindState, + ui_tx: &ui_channel::UiSender, + dirty: &mut bool, +) { + if cur.dmn.label() != prev.dmn.label() || cur.dmn_turns != prev.dmn_turns { + let _ = ui_tx.send(UiMessage::StatusUpdate(ui_channel::StatusInfo { + dmn_state: cur.dmn.label().to_string(), + dmn_turns: cur.dmn_turns, + dmn_max_turns: cur.max_dmn_turns, + prompt_tokens: 0, completion_tokens: 0, + model: String::new(), turn_tools: 0, + context_budget: String::new(), + })); + *dirty = true; + } + // Turn started — input was consumed + if cur.turn_active && !prev.turn_active && !prev.input.is_empty() { + let text = prev.input.join("\n"); + let _ = ui_tx.send(UiMessage::UserInput(text)); + *dirty = true; + } + if cur.turn_active != prev.turn_active { + *dirty = true; + } + if cur.scoring_in_flight != prev.scoring_in_flight { + if !cur.scoring_in_flight && prev.scoring_in_flight { + let _ = ui_tx.send(UiMessage::Info("[scoring complete]".into())); + } + *dirty = true; + } + if cur.compaction_in_flight != prev.compaction_in_flight { + if !cur.compaction_in_flight && prev.compaction_in_flight { + let _ = ui_tx.send(UiMessage::Info("[compacted]".into())); + } + *dirty = true; + } +} + pub async fn run( mut app: tui::App, agent: &Arc>, @@ -304,39 +344,9 @@ pub async fn run( // Diff MindState — generate UI messages from changes { - let cur = shared_mind.lock().unwrap().clone(); - if cur.dmn.label() != prev_mind.dmn.label() || cur.dmn_turns != prev_mind.dmn_turns { - let _ = ui_tx.send(UiMessage::StatusUpdate(ui_channel::StatusInfo { - dmn_state: cur.dmn.label().to_string(), - dmn_turns: cur.dmn_turns, - dmn_max_turns: cur.max_dmn_turns, - prompt_tokens: 0, completion_tokens: 0, - model: String::new(), turn_tools: 0, - context_budget: String::new(), - })); - dirty = true; - } - if cur.turn_active && !prev_mind.turn_active && !prev_mind.input.is_empty() { - let text = prev_mind.input.join("\n"); - let _ = ui_tx.send(UiMessage::UserInput(text)); - dirty = true; - } - if cur.turn_active != prev_mind.turn_active { - dirty = true; - } - if cur.scoring_in_flight != prev_mind.scoring_in_flight { - if !cur.scoring_in_flight && prev_mind.scoring_in_flight { - let _ = ui_tx.send(UiMessage::Info("[scoring complete]".into())); - } - dirty = true; - } - if cur.compaction_in_flight != prev_mind.compaction_in_flight { - if !cur.compaction_in_flight && prev_mind.compaction_in_flight { - let _ = ui_tx.send(UiMessage::Info("[compacted]".into())); - } - dirty = true; - } - prev_mind = cur; + let cur = shared_mind.lock().unwrap(); + diff_mind_state(&cur, &prev_mind, &ui_tx, &mut dirty); + prev_mind = cur.clone(); } while let Ok(notif) = notify_rx.try_recv() { @@ -433,7 +443,10 @@ pub async fn run( } } _ => { - shared_mind.lock().unwrap().input.push(input); + let mut s = shared_mind.lock().unwrap(); + diff_mind_state(&s, &prev_mind, &ui_tx, &mut dirty); + s.input.push(input); + prev_mind = s.clone(); } } }