Agent/AgentState split complete — separate context and state locks

Agent is now Arc<Agent> (immutable config). ContextState and AgentState
have separate tokio::sync::Mutex locks. The parser locks only context,
tool dispatch locks only state. No contention between the two.

All callers migrated: mind/, user/, tools/, oneshot, dmn, learn.
28 tests pass, zero errors.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
This commit is contained in:
Kent Overstreet 2026-04-08 15:47:21 -04:00
parent 1d61b091b0
commit 0b9813431a
8 changed files with 156 additions and 159 deletions

View file

@ -150,9 +150,9 @@ impl SubconsciousScreen {
None => return Vec::new(),
};
snap.forked_agent.as_ref()
.and_then(|agent| agent.try_lock().ok())
.map(|ag| {
let conv = ag.context.conversation();
.and_then(|agent| agent.context.try_lock().ok())
.map(|ctx| {
let conv = ctx.conversation();
let mut view = section_to_view("Conversation", conv);
let fork = snap.fork_point.min(view.children.len());
view.children = view.children.split_off(fork);
@ -177,8 +177,8 @@ impl SubconsciousScreen {
.map(|s| format_age(s))
.unwrap_or_else(|| "".to_string());
let entries = snap.forked_agent.as_ref()
.and_then(|a| a.try_lock().ok())
.map(|ag| ag.context.conversation().len().saturating_sub(snap.fork_point))
.and_then(|a| a.context.try_lock().ok())
.map(|ctx| ctx.conversation().len().saturating_sub(snap.fork_point))
.unwrap_or(0);
ListItem::from(Line::from(vec![
Span::styled(&snap.name, Style::default().fg(Color::Gray)),