diff --git a/src/mind/mod.rs b/src/mind/mod.rs index ca7180e..565f509 100644 --- a/src/mind/mod.rs +++ b/src/mind/mod.rs @@ -454,45 +454,6 @@ impl Mind { } /// Cycle reasoning effort: none → low → high → none. - fn cycle_reasoning(&mut self) { - if let Ok(mut agent_guard) = self.agent.try_lock() { - let next = match agent_guard.reasoning_effort.as_str() { - "none" => "low", - "low" => "high", - _ => "none", - }; - agent_guard.reasoning_effort = next.to_string(); - let label = match next { - "none" => "off (monologue hidden)", - "low" => "low (brief monologue)", - "high" => "high (full monologue)", - _ => next, - }; - let _ = self.ui_tx.send(UiMessage::Info(format!("Reasoning: {} — ^R to cycle", label))); - } else { - let _ = self.ui_tx.send(UiMessage::Info( - "(agent busy — reasoning change takes effect next turn)".into(), - )); - } - } - - /// Show and kill running tool calls (Ctrl+K). - async fn kill_processes(&mut self) { - let active_tools = self.agent.lock().await.active_tools.clone(); - let mut tools = active_tools.lock().unwrap(); - if tools.is_empty() { - let _ = self.ui_tx.send(UiMessage::Info("(no running tool calls)".into())); - } else { - for entry in tools.drain(..) { - let elapsed = entry.started.elapsed(); - let _ = self.ui_tx.send(UiMessage::Info(format!( - " killing {} ({:.0}s): {}", entry.name, elapsed.as_secs_f64(), entry.detail, - ))); - entry.handle.abort(); - } - } - } - /// Cycle DMN autonomy: foraging → resting → paused → off → foraging. fn cycle_autonomy(&mut self) { let (new_state, label) = match &self.dmn { @@ -578,20 +539,9 @@ impl Mind { MindMessage::UserInput(input) => self.submit_input(input), MindMessage::Hotkey(action) => { match action { - HotkeyAction::CycleReasoning => self.cycle_reasoning(), - HotkeyAction::KillProcess => self.kill_processes().await, HotkeyAction::Interrupt => self.interrupt().await, HotkeyAction::CycleAutonomy => self.cycle_autonomy(), - HotkeyAction::AdjustSampling(param, delta) => { - if let Ok(mut agent) = self.agent.try_lock() { - match param { - 0 => agent.temperature = (agent.temperature + delta).clamp(0.0, 2.0), - 1 => agent.top_p = (agent.top_p + delta).clamp(0.0, 1.0), - 2 => agent.top_k = (agent.top_k as f32 + delta).max(0.0) as u32, - _ => {} - } - } - } + _ => {} // Other hotkeys handled directly by UI } } MindMessage::NewSession => self.cmd_new().await, diff --git a/src/user/event_loop.rs b/src/user/event_loop.rs index 3112b37..a42399a 100644 --- a/src/user/event_loop.rs +++ b/src/user/event_loop.rs @@ -86,6 +86,55 @@ async fn cmd_retry( } } +fn cmd_cycle_reasoning(agent: &Arc>, ui_tx: &ui_channel::UiSender) { + if let Ok(mut ag) = agent.try_lock() { + let next = match ag.reasoning_effort.as_str() { + "none" => "low", + "low" => "high", + _ => "none", + }; + ag.reasoning_effort = next.to_string(); + let label = match next { + "none" => "off (monologue hidden)", + "low" => "low (brief monologue)", + "high" => "high (full monologue)", + _ => next, + }; + let _ = ui_tx.send(UiMessage::Info(format!("Reasoning: {} — ^R to cycle", label))); + } else { + let _ = ui_tx.send(UiMessage::Info( + "(agent busy — reasoning change takes effect next turn)".into(), + )); + } +} + +async fn cmd_kill_processes(agent: &Arc>, ui_tx: &ui_channel::UiSender) { + let active_tools = agent.lock().await.active_tools.clone(); + let mut tools = active_tools.lock().unwrap(); + if tools.is_empty() { + let _ = ui_tx.send(UiMessage::Info("(no running tool calls)".into())); + } else { + for entry in tools.drain(..) { + let elapsed = entry.started.elapsed(); + let _ = ui_tx.send(UiMessage::Info(format!( + " killing {} ({:.0}s): {}", entry.name, elapsed.as_secs_f64(), entry.detail, + ))); + entry.handle.abort(); + } + } +} + +fn cmd_adjust_sampling(agent: &Arc>, param: usize, delta: f32) { + if let Ok(mut ag) = agent.try_lock() { + match param { + 0 => ag.temperature = (ag.temperature + delta).clamp(0.0, 2.0), + 1 => ag.top_p = (ag.top_p + delta).clamp(0.0, 1.0), + 2 => ag.top_k = (ag.top_k as f32 + delta).max(0.0) as u32, + _ => {} + } + } +} + pub async fn cmd_switch_model( agent: &Arc>, name: &str, @@ -271,10 +320,16 @@ pub async fn run( } } - // Send hotkey actions to Mind + // Handle hotkey actions let actions: Vec = app.hotkey_actions.drain(..).collect(); for action in actions { - let _ = mind_tx.send(MindMessage::Hotkey(action)); + match action { + HotkeyAction::CycleReasoning => cmd_cycle_reasoning(&agent, &ui_tx), + HotkeyAction::KillProcess => cmd_kill_processes(&agent, &ui_tx).await, + HotkeyAction::Interrupt => { let _ = mind_tx.send(MindMessage::Hotkey(action)); } + HotkeyAction::CycleAutonomy => { let _ = mind_tx.send(MindMessage::Hotkey(action)); } + HotkeyAction::AdjustSampling(param, delta) => cmd_adjust_sampling(&agent, param, delta), + } } if app.drain_messages(&mut ui_rx) {