WIP: ActiveTools wrapper type, removing SharedActiveTools
New ActiveTools struct with proper methods: push, remove, take_finished, take_foreground, iter, len. Turn loop uses helpers instead of manual index iteration. Removing SharedActiveTools (Arc<Mutex<Vec>>) — active tools live directly in AgentState. A few UI callers still need updating. Co-Authored-By: Proof of Concept <poc@bcachefs.org>
This commit is contained in:
parent
14fd8c9b90
commit
9c9618d034
3 changed files with 56 additions and 52 deletions
|
|
@ -154,7 +154,7 @@ pub struct AgentState {
|
|||
pub conversation_log: Option<ConversationLog>,
|
||||
pub generation: u64,
|
||||
pub memory_scoring_in_flight: bool,
|
||||
pub active_tools: tools::SharedActiveTools,
|
||||
pub active_tools: tools::ActiveTools,
|
||||
pub changed: Arc<tokio::sync::Notify>,
|
||||
}
|
||||
|
||||
|
|
@ -166,7 +166,7 @@ impl Agent {
|
|||
app_config: crate::config::AppConfig,
|
||||
prompt_file: String,
|
||||
conversation_log: Option<ConversationLog>,
|
||||
active_tools: tools::SharedActiveTools,
|
||||
active_tools: tools::ActiveTools,
|
||||
) -> Arc<Self> {
|
||||
let mut context = ContextState::new();
|
||||
context.push(Section::System, AstNode::system_msg(&system_prompt));
|
||||
|
|
@ -248,7 +248,7 @@ impl Agent {
|
|||
conversation_log: None,
|
||||
generation: 0,
|
||||
memory_scoring_in_flight: false,
|
||||
active_tools: tools::shared_active_tools(),
|
||||
active_tools: tools::ActiveTools::new(),
|
||||
changed: Arc::new(tokio::sync::Notify::new()),
|
||||
}),
|
||||
})
|
||||
|
|
@ -279,37 +279,18 @@ impl Agent {
|
|||
pub async fn turn(
|
||||
agent: Arc<Agent>,
|
||||
) -> Result<TurnResult> {
|
||||
let active_tools = {
|
||||
agent.state.lock().await.active_tools.clone()
|
||||
};
|
||||
|
||||
// Collect finished background tools
|
||||
{
|
||||
let mut finished = Vec::new();
|
||||
{
|
||||
let mut tools = active_tools.lock().unwrap();
|
||||
let mut i = 0;
|
||||
while i < tools.len() {
|
||||
if tools[i].handle.is_finished() {
|
||||
finished.push(tools.remove(i));
|
||||
} else {
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
let finished = agent.state.lock().await.active_tools.take_finished();
|
||||
if !finished.is_empty() {
|
||||
let mut results = Vec::new();
|
||||
let mut bg_ds = DispatchState::new();
|
||||
for entry in finished {
|
||||
if let Ok((call, output)) = entry.handle.await {
|
||||
results.push((call, output));
|
||||
}
|
||||
}
|
||||
let mut bg_ds = DispatchState::new();
|
||||
for (call, output) in results {
|
||||
Agent::apply_tool_result(&agent, &call, output, &mut bg_ds).await;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mut overflow_retries: u32 = 0;
|
||||
let mut empty_retries: u32 = 0;
|
||||
|
|
@ -355,7 +336,7 @@ impl Agent {
|
|||
).await;
|
||||
(call_clone, output)
|
||||
});
|
||||
active_tools.lock().unwrap().push(tools::ActiveToolCall {
|
||||
agent.state.lock().await.active_tools.push(tools::ActiveToolCall {
|
||||
id: call.id.clone(),
|
||||
name: call.name.clone(),
|
||||
detail: call.arguments.clone(),
|
||||
|
|
@ -404,20 +385,7 @@ impl Agent {
|
|||
if !pending_calls.is_empty() {
|
||||
ds.had_tool_calls = true;
|
||||
|
||||
// Collect non-background tool handles
|
||||
let mut handles = Vec::new();
|
||||
{
|
||||
let mut tools_guard = active_tools.lock().unwrap();
|
||||
let mut i = 0;
|
||||
while i < tools_guard.len() {
|
||||
if !tools_guard[i].background {
|
||||
handles.push(tools_guard.remove(i));
|
||||
} else {
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let handles = agent.state.lock().await.active_tools.take_foreground();
|
||||
for entry in handles {
|
||||
if let Ok((call, output)) = entry.handle.await {
|
||||
Agent::apply_tool_result(&agent, &call, output, &mut ds).await;
|
||||
|
|
@ -465,7 +433,7 @@ impl Agent {
|
|||
ds.tool_errors += 1;
|
||||
}
|
||||
|
||||
agent.state.lock().await.active_tools.lock().unwrap().retain(|t| t.id != call.id);
|
||||
agent.state.lock().await.active_tools.remove(&call.id);
|
||||
|
||||
if call.name == "memory_render" && !output.starts_with("Error:") {
|
||||
let args: serde_json::Value =
|
||||
|
|
|
|||
|
|
@ -56,10 +56,6 @@ impl Tool {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// A tool call in flight — metadata for TUI + JoinHandle for
|
||||
/// result collection and cancellation.
|
||||
pub struct ActiveToolCall {
|
||||
pub id: String,
|
||||
pub name: String,
|
||||
|
|
@ -69,11 +65,51 @@ pub struct ActiveToolCall {
|
|||
pub handle: tokio::task::JoinHandle<(super::context::PendingToolCall, String)>,
|
||||
}
|
||||
|
||||
/// Shared active tool calls — agent spawns, TUI reads metadata / aborts.
|
||||
pub type SharedActiveTools = Arc<std::sync::Mutex<Vec<ActiveToolCall>>>;
|
||||
pub struct ActiveTools(Vec<ActiveToolCall>);
|
||||
|
||||
pub fn shared_active_tools() -> SharedActiveTools {
|
||||
Arc::new(std::sync::Mutex::new(Vec::new()))
|
||||
impl ActiveTools {
|
||||
pub fn new() -> Self { Self(Vec::new()) }
|
||||
|
||||
pub fn push(&mut self, call: ActiveToolCall) {
|
||||
self.0.push(call);
|
||||
}
|
||||
|
||||
pub fn remove(&mut self, id: &str) {
|
||||
self.0.retain(|t| t.id != id);
|
||||
}
|
||||
|
||||
pub fn take_finished(&mut self) -> Vec<ActiveToolCall> {
|
||||
let mut finished = Vec::new();
|
||||
let mut i = 0;
|
||||
while i < self.0.len() {
|
||||
if self.0[i].handle.is_finished() {
|
||||
finished.push(self.0.remove(i));
|
||||
} else {
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
finished
|
||||
}
|
||||
|
||||
pub fn take_foreground(&mut self) -> Vec<ActiveToolCall> {
|
||||
let mut fg = Vec::new();
|
||||
let mut i = 0;
|
||||
while i < self.0.len() {
|
||||
if !self.0[i].background {
|
||||
fg.push(self.0.remove(i));
|
||||
} else {
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
fg
|
||||
}
|
||||
|
||||
pub fn iter(&self) -> impl Iterator<Item = &ActiveToolCall> {
|
||||
self.0.iter()
|
||||
}
|
||||
|
||||
pub fn len(&self) -> usize { self.0.len() }
|
||||
pub fn is_empty(&self) -> bool { self.0.is_empty() }
|
||||
}
|
||||
|
||||
/// Truncate output if it exceeds max length, appending a truncation notice.
|
||||
|
|
|
|||
|
|
@ -103,7 +103,7 @@ struct App {
|
|||
temperature: f32,
|
||||
top_p: f32,
|
||||
top_k: u32,
|
||||
active_tools: crate::agent::tools::SharedActiveTools,
|
||||
agent: std::sync::Arc<crate::agent::Agent>,
|
||||
should_quit: bool,
|
||||
context_info: Option<ContextInfo>,
|
||||
agent_state: Vec<crate::mind::SubconsciousSnapshot>,
|
||||
|
|
@ -113,7 +113,7 @@ struct App {
|
|||
}
|
||||
|
||||
impl App {
|
||||
fn new(model: String, active_tools: crate::agent::tools::SharedActiveTools) -> Self {
|
||||
fn new(model: String, agent: std::sync::Arc<crate::agent::Agent>) -> Self {
|
||||
Self {
|
||||
status: StatusInfo {
|
||||
dmn_state: "resting".into(), dmn_turns: 0, dmn_max_turns: 20,
|
||||
|
|
@ -126,7 +126,7 @@ impl App {
|
|||
temperature: 0.6,
|
||||
top_p: 0.95,
|
||||
top_k: 20,
|
||||
active_tools,
|
||||
agent: mind.agent.clone(),
|
||||
should_quit: false,
|
||||
context_info: None,
|
||||
agent_state: Vec::new(),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue