move startup orchestration from mind to event_loop
The top-level run() that creates Mind, wires channels, spawns the Mind event loop, and starts the UI event loop is orchestration — it belongs with the UI entry point, not in the cognitive layer. Renamed to event_loop::start(cli). mind/mod.rs is now purely the Mind struct: state machine, MindCommand, and the run loop. Co-Authored-By: Kent Overstreet <kent.overstreet@linux.dev>
This commit is contained in:
parent
e449cda40f
commit
57b0f94b54
3 changed files with 38 additions and 40 deletions
|
|
@ -24,10 +24,9 @@ use tokio::sync::{mpsc, Mutex};
|
||||||
|
|
||||||
use crate::agent::{Agent, TurnResult};
|
use crate::agent::{Agent, TurnResult};
|
||||||
use crate::agent::api::ApiClient;
|
use crate::agent::api::ApiClient;
|
||||||
use crate::config::{self, AppConfig, SessionConfig};
|
use crate::config::{AppConfig, SessionConfig};
|
||||||
use crate::user::{self as tui};
|
|
||||||
use crate::user::ui_channel::{self, StreamTarget};
|
|
||||||
use crate::subconscious::learn;
|
use crate::subconscious::learn;
|
||||||
|
use crate::user::ui_channel::{self, StreamTarget};
|
||||||
|
|
||||||
/// Compaction threshold — context is rebuilt when prompt tokens exceed this.
|
/// Compaction threshold — context is rebuilt when prompt tokens exceed this.
|
||||||
fn compaction_threshold(app: &AppConfig) -> u32 {
|
fn compaction_threshold(app: &AppConfig) -> u32 {
|
||||||
|
|
@ -92,7 +91,7 @@ impl MindState {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Consume pending input, return a Turn command if ready.
|
/// Consume pending input, return a Turn command if ready.
|
||||||
pub fn take_pending_input(&mut self) -> MindCommand {
|
fn take_pending_input(&mut self) -> MindCommand {
|
||||||
if self.turn_active || self.input.is_empty() {
|
if self.turn_active || self.input.is_empty() {
|
||||||
return MindCommand::None;
|
return MindCommand::None;
|
||||||
}
|
}
|
||||||
|
|
@ -106,7 +105,7 @@ impl MindState {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Process turn completion, return model switch name if requested.
|
/// Process turn completion, return model switch name if requested.
|
||||||
pub fn complete_turn(&mut self, result: &Result<TurnResult>, target: StreamTarget) -> Option<String> {
|
fn complete_turn(&mut self, result: &Result<TurnResult>, target: StreamTarget) -> Option<String> {
|
||||||
self.turn_active = false;
|
self.turn_active = false;
|
||||||
match result {
|
match result {
|
||||||
Ok(turn_result) => {
|
Ok(turn_result) => {
|
||||||
|
|
@ -137,7 +136,7 @@ impl MindState {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// DMN tick — returns a Turn action with the DMN prompt, or None.
|
/// DMN tick — returns a Turn action with the DMN prompt, or None.
|
||||||
pub fn dmn_tick(&mut self) -> MindCommand {
|
fn dmn_tick(&mut self) -> MindCommand {
|
||||||
if matches!(self.dmn, dmn::State::Paused | dmn::State::Off) {
|
if matches!(self.dmn, dmn::State::Paused | dmn::State::Off) {
|
||||||
return MindCommand::None;
|
return MindCommand::None;
|
||||||
}
|
}
|
||||||
|
|
@ -158,7 +157,7 @@ impl MindState {
|
||||||
MindCommand::Turn(prompt, StreamTarget::Autonomous)
|
MindCommand::Turn(prompt, StreamTarget::Autonomous)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn interrupt(&mut self) {
|
fn interrupt(&mut self) {
|
||||||
self.input.clear();
|
self.input.clear();
|
||||||
self.dmn = dmn::State::Resting { since: Instant::now() };
|
self.dmn = dmn::State::Resting { since: Instant::now() };
|
||||||
}
|
}
|
||||||
|
|
@ -383,35 +382,3 @@ impl Mind {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- Startup ---
|
|
||||||
|
|
||||||
pub async fn run(cli: crate::user::CliArgs) -> Result<()> {
|
|
||||||
let (config, _figment) = config::load_session(&cli)?;
|
|
||||||
|
|
||||||
if config.app.debug {
|
|
||||||
unsafe { std::env::set_var("POC_DEBUG", "1") };
|
|
||||||
}
|
|
||||||
|
|
||||||
let (ui_tx, ui_rx) = ui_channel::channel();
|
|
||||||
let (turn_tx, turn_rx) = mpsc::channel::<(Result<TurnResult>, StreamTarget)>(1);
|
|
||||||
let (mind_tx, mind_rx) = tokio::sync::mpsc::unbounded_channel();
|
|
||||||
|
|
||||||
let mut 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;
|
|
||||||
});
|
|
||||||
|
|
||||||
crate::user::event_loop::run(
|
|
||||||
tui::App::new(String::new(), shared_context, shared_active_tools),
|
|
||||||
ui_agent, shared_mind, turn_watch, mind_tx, ui_tx, ui_rx,
|
|
||||||
).await
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,37 @@ use crate::user::ui_channel::{self, UiMessage};
|
||||||
|
|
||||||
pub use crate::mind::MindCommand;
|
pub use crate::mind::MindCommand;
|
||||||
|
|
||||||
|
/// Top-level entry point — creates Mind and UI, wires them together.
|
||||||
|
pub async fn start(cli: crate::user::CliArgs) -> Result<()> {
|
||||||
|
let (config, _figment) = crate::config::load_session(&cli)?;
|
||||||
|
|
||||||
|
if config.app.debug {
|
||||||
|
unsafe { std::env::set_var("POC_DEBUG", "1") };
|
||||||
|
}
|
||||||
|
|
||||||
|
let (ui_tx, ui_rx) = ui_channel::channel();
|
||||||
|
let (turn_tx, turn_rx) = tokio::sync::mpsc::channel(1);
|
||||||
|
let (mind_tx, mind_rx) = tokio::sync::mpsc::unbounded_channel();
|
||||||
|
|
||||||
|
let mut 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;
|
||||||
|
});
|
||||||
|
|
||||||
|
run(
|
||||||
|
tui::App::new(String::new(), shared_context, shared_active_tools),
|
||||||
|
ui_agent, shared_mind, turn_watch, mind_tx, ui_tx, ui_rx,
|
||||||
|
).await
|
||||||
|
}
|
||||||
|
|
||||||
fn send_help(ui_tx: &ui_channel::UiSender) {
|
fn send_help(ui_tx: &ui_channel::UiSender) {
|
||||||
let commands = &[
|
let commands = &[
|
||||||
("/quit", "Exit consciousness"),
|
("/quit", "Exit consciousness"),
|
||||||
|
|
|
||||||
|
|
@ -757,7 +757,7 @@ pub async fn main() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Err(e) = crate::mind::run(cli).await {
|
if let Err(e) = crate::user::event_loop::start(cli).await {
|
||||||
let _ = crossterm::terminal::disable_raw_mode();
|
let _ = crossterm::terminal::disable_raw_mode();
|
||||||
let _ = crossterm::execute!(
|
let _ = crossterm::execute!(
|
||||||
std::io::stdout(),
|
std::io::stdout(),
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue