forked from kent/consciousness
Revert "replace try_lock() with lock_blocking() across UI thread"
This reverts commit 4225294d16.
This commit is contained in:
parent
4225294d16
commit
09896cd38b
28 changed files with 67 additions and 4199 deletions
|
|
@ -59,7 +59,7 @@ const ACTIVITY_LINGER: std::time::Duration = std::time::Duration::from_secs(5);
|
|||
|
||||
impl Drop for ActivityGuard {
|
||||
fn drop(&mut self) {
|
||||
{ let mut st = self.agent.state.lock_blocking();
|
||||
if let Ok(mut st) = self.agent.state.try_lock() {
|
||||
if let Some(entry) = st.activities.iter_mut().find(|a| a.id == self.id) {
|
||||
entry.label.push_str(" (complete)");
|
||||
entry.expires_at = std::time::Instant::now() + ACTIVITY_LINGER;
|
||||
|
|
|
|||
|
|
@ -152,7 +152,7 @@ async fn ensure_init(agent: Option<&std::sync::Arc<super::super::Agent>>) -> Res
|
|||
let msg = format!("MCP server {} failed: {:#}", cfg.name, e);
|
||||
dbglog!("{}", msg);
|
||||
if let Some(a) = agent {
|
||||
{ let mut st = a.state.lock_blocking();
|
||||
if let Ok(mut st) = a.state.try_lock() {
|
||||
st.notify(msg);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
17
src/locks.rs
17
src/locks.rs
|
|
@ -135,23 +135,6 @@ impl<T> TrackedMutex<T> {
|
|||
location,
|
||||
})
|
||||
}
|
||||
|
||||
/// Block the current thread until the lock is acquired.
|
||||
/// Safe to call from sync contexts (UI thread, slash commands) where
|
||||
/// .await isn't available. Uses block_in_place so the tokio runtime
|
||||
/// can schedule other tasks while we wait.
|
||||
#[track_caller]
|
||||
pub fn lock_blocking(&self) -> TrackedMutexGuard<'_, T> {
|
||||
let location = Location::caller();
|
||||
let guard = tokio::task::block_in_place(|| {
|
||||
futures::executor::block_on(self.inner.lock())
|
||||
});
|
||||
TrackedMutexGuard {
|
||||
guard,
|
||||
acquired_at: Instant::now(),
|
||||
location,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct TrackedMutexGuard<'a, T> {
|
||||
|
|
|
|||
|
|
@ -104,6 +104,6 @@ async fn run(
|
|||
prior_context: render_prior_context(entries, entry_idx, 2),
|
||||
timestamp_ns: node_timestamp_ns(node),
|
||||
});
|
||||
{ let st = agent.state.lock_blocking(); st.changed.notify_one(); }
|
||||
if let Ok(st) = agent.state.try_lock() { st.changed.notify_one(); }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -736,7 +736,7 @@ async fn run_finetune(
|
|||
gen_alternates, &activity,
|
||||
move |c| {
|
||||
shared.lock().unwrap().finetune_candidates.push(c);
|
||||
{ let st = agent.state.lock_blocking(); st.changed.notify_one(); }
|
||||
if let Ok(st) = agent.state.try_lock() { st.changed.notify_one(); }
|
||||
},
|
||||
).await {
|
||||
Ok((above_threshold, max_div)) => FinetuneScoringStats {
|
||||
|
|
|
|||
|
|
@ -34,12 +34,12 @@ fn commands() -> Vec<SlashCommand> { vec![
|
|||
handler: |s, _| { let _ = s.mind_tx.send(MindCommand::NewSession); } },
|
||||
SlashCommand { name: "/save", help: "Save session to disk",
|
||||
handler: |s, _| {
|
||||
{ let mut ag = s.agent.state.lock_blocking(); ag.notify("saved"); }
|
||||
if let Ok(mut ag) = s.agent.state.try_lock() { ag.notify("saved"); }
|
||||
} },
|
||||
SlashCommand { name: "/model", help: "Show/switch model (/model <name>)",
|
||||
handler: |s, arg| {
|
||||
if arg.is_empty() {
|
||||
{ let mut ag = s.agent.state.lock_blocking();
|
||||
if let Ok(mut ag) = s.agent.state.try_lock() {
|
||||
let names = s.agent.app_config.model_names();
|
||||
let label = if names.is_empty() {
|
||||
format!("model: {}", s.agent.model())
|
||||
|
|
@ -62,7 +62,7 @@ fn commands() -> Vec<SlashCommand> { vec![
|
|||
SlashCommand { name: "/dmn", help: "Show DMN state",
|
||||
handler: |s, _| {
|
||||
let st = s.shared_mind.lock().unwrap();
|
||||
{ let mut ag = s.agent.state.lock_blocking();
|
||||
if let Ok(mut ag) = s.agent.state.try_lock() {
|
||||
ag.notify(format!("DMN: {:?} ({}/{})", st.dmn, st.dmn_turns, st.max_dmn_turns));
|
||||
}
|
||||
} },
|
||||
|
|
@ -71,7 +71,7 @@ fn commands() -> Vec<SlashCommand> { vec![
|
|||
let mut st = s.shared_mind.lock().unwrap();
|
||||
st.dmn = crate::mind::subconscious::State::Resting { since: std::time::Instant::now() };
|
||||
st.dmn_turns = 0;
|
||||
{ let mut ag = s.agent.state.lock_blocking(); ag.notify("DMN sleeping"); }
|
||||
if let Ok(mut ag) = s.agent.state.try_lock() { ag.notify("DMN sleeping"); }
|
||||
} },
|
||||
SlashCommand { name: "/wake", help: "Wake DMN to foraging",
|
||||
handler: |s, _| {
|
||||
|
|
@ -79,14 +79,14 @@ fn commands() -> Vec<SlashCommand> { vec![
|
|||
if matches!(st.dmn, crate::mind::subconscious::State::Off) { crate::mind::subconscious::set_off(false); }
|
||||
st.dmn = crate::mind::subconscious::State::Foraging;
|
||||
st.dmn_turns = 0;
|
||||
{ let mut ag = s.agent.state.lock_blocking(); ag.notify("DMN foraging"); }
|
||||
if let Ok(mut ag) = s.agent.state.try_lock() { ag.notify("DMN foraging"); }
|
||||
} },
|
||||
SlashCommand { name: "/pause", help: "Full stop — no autonomous ticks (Ctrl+P)",
|
||||
handler: |s, _| {
|
||||
let mut st = s.shared_mind.lock().unwrap();
|
||||
st.dmn = crate::mind::subconscious::State::Paused;
|
||||
st.dmn_turns = 0;
|
||||
{ let mut ag = s.agent.state.lock_blocking(); ag.notify("DMN paused"); }
|
||||
if let Ok(mut ag) = s.agent.state.try_lock() { ag.notify("DMN paused"); }
|
||||
} },
|
||||
SlashCommand { name: "/help", help: "Show this help",
|
||||
handler: |s, _| { notify_help(&s.agent); } },
|
||||
|
|
@ -116,7 +116,7 @@ pub async fn cmd_switch_model(
|
|||
}
|
||||
|
||||
fn notify_help(agent: &std::sync::Arc<crate::agent::Agent>) {
|
||||
{ let mut ag = agent.state.lock_blocking();
|
||||
if let Ok(mut ag) = agent.state.try_lock() {
|
||||
let mut help = String::new();
|
||||
for cmd in &commands() {
|
||||
help.push_str(&format!("{:12} {}\n", cmd.name, cmd.help));
|
||||
|
|
@ -581,10 +581,16 @@ impl InteractScreen {
|
|||
self.pending_display_count = 0;
|
||||
|
||||
let (generation, entries) = {
|
||||
let st = self.agent.state.lock_blocking();
|
||||
let st = match self.agent.state.try_lock() {
|
||||
Ok(st) => st,
|
||||
Err(_) => return,
|
||||
};
|
||||
let generation = st.generation;
|
||||
drop(st);
|
||||
let ctx = self.agent.context.lock_blocking();
|
||||
let ctx = match self.agent.context.try_lock() {
|
||||
Ok(ctx) => ctx,
|
||||
Err(_) => return,
|
||||
};
|
||||
(generation, ctx.conversation().to_vec())
|
||||
};
|
||||
|
||||
|
|
@ -648,7 +654,7 @@ impl InteractScreen {
|
|||
if let Some(cmd) = dispatch_command(input) {
|
||||
(cmd.handler)(self, &input[cmd.name.len()..].trim_start());
|
||||
} else {
|
||||
{ let mut ag = self.agent.state.lock_blocking();
|
||||
if let Ok(mut ag) = self.agent.state.try_lock() {
|
||||
ag.notify(format!("unknown: {}", input.split_whitespace().next().unwrap_or(input)));
|
||||
}
|
||||
}
|
||||
|
|
@ -764,8 +770,9 @@ impl InteractScreen {
|
|||
/// Draw the main (F1) screen — four-pane layout with status bar.
|
||||
fn draw_main(&mut self, frame: &mut Frame, size: Rect, app: &App) {
|
||||
// Main layout: content area + active tools overlay + status bar
|
||||
let st_guard = app.agent.state.lock_blocking();
|
||||
let tool_lines = st_guard.active_tools.len() as u16;
|
||||
let st_guard = app.agent.state.try_lock().ok();
|
||||
let tool_lines = st_guard.as_ref()
|
||||
.map(|st| st.active_tools.len() as u16).unwrap_or(0);
|
||||
let main_chunks = Layout::default()
|
||||
.direction(Direction::Vertical)
|
||||
.constraints([
|
||||
|
|
@ -854,9 +861,10 @@ impl InteractScreen {
|
|||
frame.render_widget(gutter, input_chunks[0]);
|
||||
frame.render_widget(&self.textarea, input_chunks[1]);
|
||||
|
||||
if !st_guard.active_tools.is_empty() {
|
||||
if let Some(ref st) = st_guard {
|
||||
if !st.active_tools.is_empty() {
|
||||
let tool_style = Style::default().fg(Color::Yellow).add_modifier(Modifier::DIM);
|
||||
let tool_text: Vec<Line> = st_guard.active_tools.iter().map(|t| {
|
||||
let tool_text: Vec<Line> = st.active_tools.iter().map(|t| {
|
||||
let elapsed = t.started.elapsed().as_secs();
|
||||
let line = if t.detail.is_empty() {
|
||||
format!(" [{}] ({}s)", t.name, elapsed)
|
||||
|
|
@ -867,7 +875,7 @@ impl InteractScreen {
|
|||
}).collect();
|
||||
let tool_para = Paragraph::new(tool_text);
|
||||
frame.render_widget(tool_para, tools_overlay_area);
|
||||
}
|
||||
}}
|
||||
|
||||
// Draw status bar with live activity indicator
|
||||
let timer = if !app.activity.is_empty() {
|
||||
|
|
@ -1018,7 +1026,7 @@ impl ScreenView for InteractScreen {
|
|||
self.sync_from_agent();
|
||||
|
||||
// Read status from agent + mind state
|
||||
{ let mut st = self.agent.state.lock_blocking();
|
||||
if let Ok(mut st) = self.agent.state.try_lock() {
|
||||
st.expire_activities();
|
||||
app.status.prompt_tokens = st.last_prompt_tokens;
|
||||
app.status.model = self.agent.model().to_string();
|
||||
|
|
@ -1028,7 +1036,7 @@ impl ScreenView for InteractScreen {
|
|||
app.activity_started = st.activities.last()
|
||||
.map(|a| a.started);
|
||||
}
|
||||
{ let ctx = self.agent.context.lock_blocking();
|
||||
if let Ok(ctx) = self.agent.context.try_lock() {
|
||||
let window = crate::agent::context::context_window();
|
||||
if window > 0 {
|
||||
let sys = ctx.system().iter().map(|n| n.tokens()).sum::<usize>();
|
||||
|
|
|
|||
|
|
@ -20,7 +20,10 @@ impl ConsciousScreen {
|
|||
}
|
||||
|
||||
fn read_context_views(&self) -> Vec<SectionView> {
|
||||
let ctx = self.agent.context.lock_blocking();
|
||||
let ctx = match self.agent.context.try_lock() {
|
||||
Ok(ctx) => ctx,
|
||||
Err(_) => return Vec::new(),
|
||||
};
|
||||
|
||||
let mut views: Vec<SectionView> = Vec::new();
|
||||
|
||||
|
|
@ -158,7 +161,8 @@ impl ScreenView for ConsciousScreen {
|
|||
)));
|
||||
lines.push(Line::raw(format!(" Reasoning: {}", app.reasoning_effort)));
|
||||
lines.push(Line::raw(format!(" Running processes: {}", app.running_processes)));
|
||||
let tool_count = { let st = app.agent.state.lock_blocking(); st.active_tools.len() };
|
||||
let tool_count = app.agent.state.try_lock()
|
||||
.map(|st| st.active_tools.len()).unwrap_or(0);
|
||||
lines.push(Line::raw(format!(" Active tools: {}", tool_count)));
|
||||
|
||||
let block = pane_block("context")
|
||||
|
|
|
|||
|
|
@ -292,7 +292,7 @@ async fn start(cli: crate::user::CliArgs) -> Result<()> {
|
|||
}
|
||||
|
||||
fn hotkey_cycle_reasoning(mind: &crate::mind::Mind) {
|
||||
{ let mut ag = mind.agent.state.lock_blocking();
|
||||
if let Ok(mut ag) = mind.agent.state.try_lock() {
|
||||
let next = match ag.reasoning_effort.as_str() {
|
||||
"none" => "low",
|
||||
"low" => "high",
|
||||
|
|
@ -344,7 +344,7 @@ fn hotkey_cycle_autonomy(mind: &crate::mind::Mind) {
|
|||
};
|
||||
s.dmn_turns = 0;
|
||||
drop(s);
|
||||
{ let mut ag = mind.agent.state.lock_blocking();
|
||||
if let Ok(mut ag) = mind.agent.state.try_lock() {
|
||||
ag.notify(format!("DMN → {}", label));
|
||||
}
|
||||
}
|
||||
|
|
@ -419,7 +419,7 @@ async fn run(
|
|||
|
||||
terminal.hide_cursor()?;
|
||||
|
||||
{ let mut ag = agent.state.lock_blocking(); ag.notify("consciousness v0.3"); }
|
||||
if let Ok(mut ag) = agent.state.try_lock() { ag.notify("consciousness v0.3"); }
|
||||
|
||||
// Initial render
|
||||
{
|
||||
|
|
@ -526,7 +526,7 @@ async fn run(
|
|||
}
|
||||
app.walked_count = mind.subconscious_walked().await.len();
|
||||
if !startup_done {
|
||||
{ let mut ag = agent.state.lock_blocking();
|
||||
if let Ok(mut ag) = agent.state.try_lock() {
|
||||
let model = agent.model().to_string();
|
||||
ag.notify(format!("model: {}", model));
|
||||
startup_done = true;
|
||||
|
|
@ -545,7 +545,7 @@ async fn run(
|
|||
if let Some(rx_mutex) = STDERR_RX.get() {
|
||||
if let Ok(rx) = rx_mutex.try_lock() {
|
||||
while let Ok(line) = rx.try_recv() {
|
||||
{ let mut ag = agent.state.lock_blocking();
|
||||
if let Ok(mut ag) = agent.state.try_lock() {
|
||||
ag.notify(format!("stderr: {}", line));
|
||||
dirty = true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -222,30 +222,31 @@ impl SubconsciousScreen {
|
|||
let fork_point = app.agent_state.get(self.selected())
|
||||
.map(|s| s.fork_point).unwrap_or(0);
|
||||
|
||||
{
|
||||
let ctx = agent.context.lock_blocking();
|
||||
let mut views = Vec::new();
|
||||
views.push(section_to_view("System", ctx.system()));
|
||||
views.push(section_to_view("Identity", ctx.identity()));
|
||||
views.push(section_to_view("Journal", ctx.journal()));
|
||||
agent.context.try_lock().ok()
|
||||
.map(|ctx| {
|
||||
let mut views = Vec::new();
|
||||
views.push(section_to_view("System", ctx.system()));
|
||||
views.push(section_to_view("Identity", ctx.identity()));
|
||||
views.push(section_to_view("Journal", ctx.journal()));
|
||||
|
||||
// Conversation: skip to fork point for subconscious agents
|
||||
let conv = ctx.conversation();
|
||||
let conv_view = section_to_view("Conversation", conv);
|
||||
let fork = fork_point.min(conv_view.children.len());
|
||||
let conv_children: Vec<SectionView> = conv_view.children
|
||||
.into_iter().skip(fork).collect();
|
||||
views.push(SectionView {
|
||||
name: format!("Conversation ({} entries)", conv_children.len()),
|
||||
tokens: conv_children.iter().map(|c| c.tokens).sum(),
|
||||
content: String::new(),
|
||||
token_ids: Vec::new(),
|
||||
children: conv_children,
|
||||
status: String::new(),
|
||||
});
|
||||
// Conversation: skip to fork point for subconscious agents
|
||||
let conv = ctx.conversation();
|
||||
let conv_view = section_to_view("Conversation", conv);
|
||||
let fork = fork_point.min(conv_view.children.len());
|
||||
let conv_children: Vec<SectionView> = conv_view.children
|
||||
.into_iter().skip(fork).collect();
|
||||
views.push(SectionView {
|
||||
name: format!("Conversation ({} entries)", conv_children.len()),
|
||||
tokens: conv_children.iter().map(|c| c.tokens).sum(),
|
||||
content: String::new(),
|
||||
token_ids: Vec::new(),
|
||||
children: conv_children,
|
||||
status: String::new(),
|
||||
});
|
||||
|
||||
views
|
||||
}
|
||||
views
|
||||
})
|
||||
.unwrap_or_default()
|
||||
}
|
||||
|
||||
fn draw_list(&mut self, frame: &mut Frame, area: Rect, app: &App) {
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ impl ScreenView for ThalamusScreen {
|
|||
}
|
||||
KeyCode::Char('t') => {
|
||||
app.think_native = !app.think_native;
|
||||
{ let mut st = app.agent.state.lock_blocking();
|
||||
if let Ok(mut st) = app.agent.state.try_lock() {
|
||||
st.think_native = app.think_native;
|
||||
let status = if app.think_native { "enabled" } else { "disabled" };
|
||||
st.notify(format!("native thinking {}", status));
|
||||
|
|
@ -53,7 +53,7 @@ impl ScreenView for ThalamusScreen {
|
|||
}
|
||||
KeyCode::Char('T') => {
|
||||
app.think_tool = !app.think_tool;
|
||||
{ let mut st = app.agent.state.lock_blocking();
|
||||
if let Ok(mut st) = app.agent.state.try_lock() {
|
||||
st.think_tool = app.think_tool;
|
||||
// Add or remove the think tool from the tools list
|
||||
if app.think_tool {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue