Shared subconscious state — walked keys are Mind-level, not per-agent
SubconsciousSharedState holds walked keys shared between all subconscious agents. Enables splitting surface-observe into separate surface and observe agents that share the same walked state. Walked is passed to run_forked() at run time instead of living on AutoAgent. UI shows walked count in the subconscious screen header. Co-Authored-By: Proof of Concept <poc@bcachefs.org>
This commit is contained in:
parent
ef868cb98f
commit
f3ba7e7097
4 changed files with 37 additions and 23 deletions
|
|
@ -91,6 +91,14 @@ impl SubconsciousAgent {
|
|||
}
|
||||
}
|
||||
|
||||
/// State shared between all subconscious agents. Lives on Mind,
|
||||
/// passed to agents at run time. Enables splitting surface/observe
|
||||
/// into separate agents that share walked keys.
|
||||
#[derive(Clone, Default)]
|
||||
pub struct SubconsciousSharedState {
|
||||
pub walked: Vec<String>,
|
||||
}
|
||||
|
||||
/// Lightweight snapshot of subconscious agent state for the TUI.
|
||||
#[derive(Clone, Default)]
|
||||
pub struct SubconsciousSnapshot {
|
||||
|
|
@ -98,7 +106,6 @@ pub struct SubconsciousSnapshot {
|
|||
pub running: bool,
|
||||
pub current_phase: String,
|
||||
pub turn: usize,
|
||||
pub walked_count: usize,
|
||||
pub last_run_secs_ago: Option<f64>,
|
||||
/// Entries from the last forked run (after fork point).
|
||||
pub last_run_entries: Vec<crate::agent::context::ConversationEntry>,
|
||||
|
|
@ -111,7 +118,6 @@ impl SubconsciousAgent {
|
|||
running: self.is_running(),
|
||||
current_phase: self.auto.current_phase.clone(),
|
||||
turn: self.auto.turn,
|
||||
walked_count: self.auto.walked.len(),
|
||||
last_run_secs_ago: self.last_run.map(|t| t.elapsed().as_secs_f64()),
|
||||
last_run_entries: self.auto.last_run_entries.clone(),
|
||||
}
|
||||
|
|
@ -293,6 +299,7 @@ pub struct Mind {
|
|||
pub shared: Arc<SharedMindState>,
|
||||
pub config: SessionConfig,
|
||||
subconscious: Arc<tokio::sync::Mutex<Vec<SubconsciousAgent>>>,
|
||||
subconscious_state: Arc<tokio::sync::Mutex<SubconsciousSharedState>>,
|
||||
turn_tx: mpsc::Sender<(Result<TurnResult>, StreamTarget)>,
|
||||
turn_watch: tokio::sync::watch::Sender<bool>,
|
||||
bg_tx: mpsc::UnboundedSender<BgEvent>,
|
||||
|
|
@ -337,14 +344,19 @@ impl Mind {
|
|||
sup.load_config();
|
||||
sup.ensure_running();
|
||||
|
||||
Self { agent, shared, config, subconscious: Arc::new(tokio::sync::Mutex::new(subconscious)),
|
||||
let subconscious_state = Arc::new(tokio::sync::Mutex::new(SubconsciousSharedState::default()));
|
||||
Self { agent, shared, config,
|
||||
subconscious: Arc::new(tokio::sync::Mutex::new(subconscious)),
|
||||
subconscious_state,
|
||||
turn_tx, turn_watch, bg_tx,
|
||||
bg_rx: std::sync::Mutex::new(Some(bg_rx)), _supervisor: sup }
|
||||
}
|
||||
|
||||
/// Initialize — restore log, start daemons and background agents.
|
||||
pub async fn subconscious_snapshots(&self) -> Vec<SubconsciousSnapshot> {
|
||||
self.subconscious.lock().await.iter().map(|s| s.snapshot()).collect()
|
||||
pub async fn subconscious_snapshots(&self) -> (Vec<SubconsciousSnapshot>, SubconsciousSharedState) {
|
||||
let snaps = self.subconscious.lock().await.iter().map(|s| s.snapshot()).collect();
|
||||
let shared = self.subconscious_state.lock().await.clone();
|
||||
(snaps, shared)
|
||||
}
|
||||
|
||||
pub async fn init(&self) {
|
||||
|
|
@ -468,15 +480,13 @@ impl Mind {
|
|||
let name = subs[idx].auto.name.clone();
|
||||
let outputs = std::mem::take(&mut subs[idx].auto.outputs);
|
||||
|
||||
// Walked keys — update all subconscious agents
|
||||
// Walked keys — update shared state
|
||||
if let Some(walked_str) = outputs.get("walked") {
|
||||
let walked: Vec<String> = walked_str.lines()
|
||||
.map(|l| l.trim().to_string())
|
||||
.filter(|l| !l.is_empty())
|
||||
.collect();
|
||||
for sub in subs.iter_mut() {
|
||||
sub.auto.walked = walked.clone();
|
||||
}
|
||||
self.subconscious_state.lock().await.walked = walked;
|
||||
}
|
||||
drop(subs);
|
||||
|
||||
|
|
@ -557,15 +567,17 @@ impl Mind {
|
|||
|
||||
// Fork from conscious agent and spawn tasks
|
||||
let conscious = self.agent.lock().await;
|
||||
let walked = self.subconscious_state.lock().await.walked.clone();
|
||||
let mut spawns = Vec::new();
|
||||
for (idx, mut auto) in to_run {
|
||||
dbglog!("[mind] triggering {}", auto.name);
|
||||
|
||||
let forked = conscious.fork(auto.tools.clone());
|
||||
let keys = memory_keys.clone();
|
||||
let w = walked.clone();
|
||||
let handle: tokio::task::JoinHandle<(AutoAgent, Result<String, String>)> =
|
||||
tokio::spawn(async move {
|
||||
let result = auto.run_forked(&forked, &keys).await;
|
||||
let result = auto.run_forked(&forked, &keys, &w).await;
|
||||
(auto, result)
|
||||
});
|
||||
spawns.push((idx, handle));
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue