mind: use tokio-scoped for Mind/UI loop lifetimes

Both event loops borrow &mind through a scoped spawn — no Arc on
Mind needed. Interior Arcs on agent/shared stay (background spawns
need 'static), but event_loop::run() now takes &Arc refs instead
of cloned Arcs.

Co-Authored-By: Kent Overstreet <kent.overstreet@linux.dev>
This commit is contained in:
Kent Overstreet 2026-04-05 04:53:33 -04:00
parent aae9687de2
commit 5eaba3c951
3 changed files with 30 additions and 12 deletions

View file

@ -31,22 +31,28 @@ pub async fn start(cli: crate::user::CliArgs) -> Result<()> {
let (mind_tx, mind_rx) = tokio::sync::mpsc::unbounded_channel();
let mind = crate::mind::Mind::new(config, ui_tx.clone(), turn_tx);
mind.init().await;
let ui_agent = mind.agent.clone();
let shared_mind = mind.shared.clone();
let shared_context = mind.agent.lock().await.shared_context.clone();
let shared_active_tools = mind.agent.lock().await.active_tools.clone();
let turn_watch = mind.turn_watch();
tokio::spawn(async move {
mind.run(mind_rx, turn_rx).await;
});
let mut result = Ok(());
tokio_scoped::scope(|s| {
// Mind event loop — init + run
s.spawn(async {
mind.init().await;
mind.run(mind_rx, turn_rx).await;
});
run(
tui::App::new(String::new(), shared_context, shared_active_tools),
ui_agent, shared_mind, turn_watch, mind_tx, ui_tx, ui_rx,
).await
// UI event loop
s.spawn(async {
result = run(
tui::App::new(String::new(), shared_context, shared_active_tools),
&mind.agent, &mind.shared, turn_watch, mind_tx, ui_tx, ui_rx,
).await;
});
});
result
}
fn send_help(ui_tx: &ui_channel::UiSender) {
@ -210,8 +216,8 @@ pub async fn cmd_switch_model(
pub async fn run(
mut app: tui::App,
agent: Arc<Mutex<Agent>>,
shared_mind: crate::mind::SharedMindState,
agent: &Arc<Mutex<Agent>>,
shared_mind: &crate::mind::SharedMindState,
turn_watch: tokio::sync::watch::Receiver<bool>,
mind_tx: tokio::sync::mpsc::UnboundedSender<MindCommand>,
ui_tx: ui_channel::UiSender,