mind: Mind is fully &self — no &mut needed
Move turn_handle into MindState (behind the mutex). All Mind methods now take &self. Mind can be shared across tasks without Arc — it's Send + Sync and immutable from the outside. Manual Clone impl for MindState skips turn_handle (not needed for UI diffing). Co-Authored-By: Kent Overstreet <kent.overstreet@linux.dev>
This commit is contained in:
parent
8e3137fe3f
commit
aae9687de2
2 changed files with 33 additions and 17 deletions
|
|
@ -35,7 +35,6 @@ fn compaction_threshold(app: &AppConfig) -> u32 {
|
||||||
|
|
||||||
|
|
||||||
/// Shared state between Mind and UI.
|
/// Shared state between Mind and UI.
|
||||||
#[derive(Clone)]
|
|
||||||
pub struct MindState {
|
pub struct MindState {
|
||||||
/// Pending user input — UI pushes, Mind consumes after turn completes.
|
/// Pending user input — UI pushes, Mind consumes after turn completes.
|
||||||
pub input: Vec<String>,
|
pub input: Vec<String>,
|
||||||
|
|
@ -53,6 +52,26 @@ pub struct MindState {
|
||||||
pub last_user_input: Instant,
|
pub last_user_input: Instant,
|
||||||
pub consecutive_errors: u32,
|
pub consecutive_errors: u32,
|
||||||
pub last_turn_had_tools: bool,
|
pub last_turn_had_tools: bool,
|
||||||
|
/// Handle to the currently running turn task.
|
||||||
|
pub turn_handle: Option<tokio::task::JoinHandle<()>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Clone for MindState {
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
Self {
|
||||||
|
input: self.input.clone(),
|
||||||
|
turn_active: self.turn_active,
|
||||||
|
dmn: self.dmn.clone(),
|
||||||
|
dmn_turns: self.dmn_turns,
|
||||||
|
max_dmn_turns: self.max_dmn_turns,
|
||||||
|
scoring_in_flight: self.scoring_in_flight,
|
||||||
|
compaction_in_flight: self.compaction_in_flight,
|
||||||
|
last_user_input: self.last_user_input,
|
||||||
|
consecutive_errors: self.consecutive_errors,
|
||||||
|
last_turn_had_tools: self.last_turn_had_tools,
|
||||||
|
turn_handle: None, // Not cloned — only Mind's loop uses this
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type SharedMindState = Arc<std::sync::Mutex<MindState>>;
|
pub type SharedMindState = Arc<std::sync::Mutex<MindState>>;
|
||||||
|
|
@ -87,6 +106,7 @@ impl MindState {
|
||||||
last_user_input: Instant::now(),
|
last_user_input: Instant::now(),
|
||||||
consecutive_errors: 0,
|
consecutive_errors: 0,
|
||||||
last_turn_had_tools: false,
|
last_turn_had_tools: false,
|
||||||
|
turn_handle: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -175,16 +195,12 @@ pub struct Mind {
|
||||||
pub config: SessionConfig,
|
pub config: SessionConfig,
|
||||||
ui_tx: ui_channel::UiSender,
|
ui_tx: ui_channel::UiSender,
|
||||||
turn_tx: mpsc::Sender<(Result<TurnResult>, StreamTarget)>,
|
turn_tx: mpsc::Sender<(Result<TurnResult>, StreamTarget)>,
|
||||||
turn_handle: Option<tokio::task::JoinHandle<()>>,
|
|
||||||
turn_watch: tokio::sync::watch::Sender<bool>,
|
turn_watch: tokio::sync::watch::Sender<bool>,
|
||||||
_supervisor: crate::thalamus::supervisor::Supervisor,
|
_supervisor: crate::thalamus::supervisor::Supervisor,
|
||||||
}
|
}
|
||||||
|
|
||||||
const _: () = {
|
fn _assert_send_sync<T: Send + Sync>() {}
|
||||||
fn _assert_send<T: Send>() {}
|
const _: fn() = _assert_send_sync::<Mind>;
|
||||||
fn _assert_sync<T: Sync>() {}
|
|
||||||
fn _check() { _assert_send::<Mind>(); _assert_sync::<Mind>(); }
|
|
||||||
};
|
|
||||||
|
|
||||||
impl Mind {
|
impl Mind {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
|
|
@ -218,11 +234,11 @@ impl Mind {
|
||||||
sup.load_config();
|
sup.load_config();
|
||||||
sup.ensure_running();
|
sup.ensure_running();
|
||||||
|
|
||||||
Self { agent, shared, config, ui_tx, turn_tx, turn_handle: None, turn_watch, _supervisor: sup }
|
Self { agent, shared, config, ui_tx, turn_tx, turn_watch, _supervisor: sup }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Initialize — restore log, start daemons and background agents.
|
/// Initialize — restore log, start daemons and background agents.
|
||||||
pub async fn init(&mut self) {
|
pub async fn init(&self) {
|
||||||
// Restore conversation
|
// Restore conversation
|
||||||
let mut ag = self.agent.lock().await;
|
let mut ag = self.agent.lock().await;
|
||||||
ag.restore_from_log();
|
ag.restore_from_log();
|
||||||
|
|
@ -242,7 +258,7 @@ impl Mind {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Execute an Action from a MindState method.
|
/// Execute an Action from a MindState method.
|
||||||
async fn run_commands(&mut self, cmds: Vec<MindCommand>) {
|
async fn run_commands(&self, cmds: Vec<MindCommand>) {
|
||||||
for cmd in cmds {
|
for cmd in cmds {
|
||||||
match cmd {
|
match cmd {
|
||||||
MindCommand::None => {}
|
MindCommand::None => {}
|
||||||
|
|
@ -267,7 +283,7 @@ impl Mind {
|
||||||
let mut tools = ag.active_tools.lock().unwrap();
|
let mut tools = ag.active_tools.lock().unwrap();
|
||||||
for entry in tools.drain(..) { entry.handle.abort(); }
|
for entry in tools.drain(..) { entry.handle.abort(); }
|
||||||
drop(tools); drop(ag);
|
drop(tools); drop(ag);
|
||||||
if let Some(h) = self.turn_handle.take() { h.abort(); }
|
if let Some(h) = self.shared.lock().unwrap().turn_handle.take() { h.abort(); }
|
||||||
self.shared.lock().unwrap().turn_active = false;
|
self.shared.lock().unwrap().turn_active = false;
|
||||||
let _ = self.turn_watch.send(false);
|
let _ = self.turn_watch.send(false);
|
||||||
}
|
}
|
||||||
|
|
@ -296,7 +312,7 @@ impl Mind {
|
||||||
let agent = self.agent.clone();
|
let agent = self.agent.clone();
|
||||||
let ui_tx = self.ui_tx.clone();
|
let ui_tx = self.ui_tx.clone();
|
||||||
let result_tx = self.turn_tx.clone();
|
let result_tx = self.turn_tx.clone();
|
||||||
self.turn_handle = Some(tokio::spawn(async move {
|
self.shared.lock().unwrap().turn_handle = Some(tokio::spawn(async move {
|
||||||
let result = Agent::turn(agent, &input, &ui_tx, target).await;
|
let result = Agent::turn(agent, &input, &ui_tx, target).await;
|
||||||
let _ = result_tx.send((result, target)).await;
|
let _ = result_tx.send((result, target)).await;
|
||||||
}));
|
}));
|
||||||
|
|
@ -331,13 +347,13 @@ impl Mind {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn shutdown(&mut self) {
|
pub async fn shutdown(&self) {
|
||||||
if let Some(handle) = self.turn_handle.take() { handle.abort(); }
|
if let Some(handle) = self.shared.lock().unwrap().turn_handle.take() { handle.abort(); }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Mind event loop — locks MindState, calls state methods, executes actions.
|
/// Mind event loop — locks MindState, calls state methods, executes actions.
|
||||||
pub async fn run(
|
pub async fn run(
|
||||||
&mut self,
|
&self,
|
||||||
mut input_rx: tokio::sync::mpsc::UnboundedReceiver<MindCommand>,
|
mut input_rx: tokio::sync::mpsc::UnboundedReceiver<MindCommand>,
|
||||||
mut turn_rx: mpsc::Receiver<(Result<TurnResult>, StreamTarget)>,
|
mut turn_rx: mpsc::Receiver<(Result<TurnResult>, StreamTarget)>,
|
||||||
) {
|
) {
|
||||||
|
|
@ -355,7 +371,7 @@ impl Mind {
|
||||||
}
|
}
|
||||||
|
|
||||||
Some((result, target)) = turn_rx.recv() => {
|
Some((result, target)) = turn_rx.recv() => {
|
||||||
self.turn_handle = None;
|
self.shared.lock().unwrap().turn_handle = None;
|
||||||
let model_switch = self.shared.lock().unwrap().complete_turn(&result, target);
|
let model_switch = self.shared.lock().unwrap().complete_turn(&result, target);
|
||||||
let _ = self.turn_watch.send(false);
|
let _ = self.turn_watch.send(false);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ pub async fn start(cli: crate::user::CliArgs) -> Result<()> {
|
||||||
let (turn_tx, turn_rx) = tokio::sync::mpsc::channel(1);
|
let (turn_tx, turn_rx) = tokio::sync::mpsc::channel(1);
|
||||||
let (mind_tx, mind_rx) = tokio::sync::mpsc::unbounded_channel();
|
let (mind_tx, mind_rx) = tokio::sync::mpsc::unbounded_channel();
|
||||||
|
|
||||||
let mut mind = crate::mind::Mind::new(config, ui_tx.clone(), turn_tx);
|
let mind = crate::mind::Mind::new(config, ui_tx.clone(), turn_tx);
|
||||||
mind.init().await;
|
mind.init().await;
|
||||||
|
|
||||||
let ui_agent = mind.agent.clone();
|
let ui_agent = mind.agent.clone();
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue