Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions codi-rs/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,8 @@ tree-sitter-rust = "0.23"
tree-sitter-python = "0.23"
tree-sitter-go = "0.23"
tree-sitter-json = "0.24"
tree-sitter-bash = "0.25"
tree-sitter-markdown = "0.7"
sha2 = "0.10"

# MCP Protocol (Phase 6.5)
Expand All @@ -98,6 +100,7 @@ tempfile = "3"
tokio-test = "0.4"
wiremock = "0.6"
criterion = { version = "0.6", features = ["async_tokio"] }
insta = { version = "1.41", features = ["yaml"] }

[[bench]]
name = "tools"
Expand Down
4 changes: 2 additions & 2 deletions codi-rs/src/agent/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,7 @@ impl Agent {
async fn execute_tool(&self, tool_call: &ToolCall) -> ToolResult {
// Notify callback
if let Some(ref on_tool_call) = self.callbacks.on_tool_call {
on_tool_call(&tool_call.name, &tool_call.input);
on_tool_call(&tool_call.id, &tool_call.input);
}

// Execute the tool
Expand Down Expand Up @@ -326,7 +326,7 @@ impl Agent {

// Notify callback
if let Some(ref on_tool_result) = self.callbacks.on_tool_result {
on_tool_result(&tool_call.name, &result.content, result.is_error.unwrap_or(false));
on_tool_result(&tool_call.id, &result.content, result.is_error.unwrap_or(false));
}

result
Expand Down
8 changes: 4 additions & 4 deletions codi-rs/src/agent/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@

use std::sync::Arc;

use crate::types::{BoxedProvider, Message, StreamEvent};
use crate::tools::ToolRegistry;
use crate::types::{BoxedProvider, Message, StreamEvent};

/// Statistics for a single turn (user message -> final response).
#[derive(Debug, Clone, Default)]
Expand Down Expand Up @@ -69,9 +69,9 @@ pub enum ConfirmationResult {
pub struct AgentCallbacks {
/// Called when the model outputs text (streaming deltas).
pub on_text: Option<Arc<dyn Fn(&str) + Send + Sync>>,
/// Called when a tool is about to be executed.
pub on_tool_call: Option<Arc<dyn Fn(&str, &serde_json::Value) + Send + Sync>>,
/// Called when a tool execution completes.
/// Called when a tool is about to be executed (tool_id, tool_name, input).
pub on_tool_call: Option<Arc<dyn Fn(&str, &str, &serde_json::Value) + Send + Sync>>,
/// Called when a tool execution completes (tool_id, result, is_error).
pub on_tool_result: Option<Arc<dyn Fn(&str, &str, bool) + Send + Sync>>,
/// Called to confirm destructive operations. Returns approval result.
pub on_confirm: Option<Arc<dyn Fn(ToolConfirmation) -> ConfirmationResult + Send + Sync>>,
Expand Down
2 changes: 1 addition & 1 deletion codi-rs/src/orchestrate/child_agent.rs
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ impl ChildAgent {
on_text: None,
on_tool_call: Some(Arc::new({
let ipc = Arc::clone(&self.ipc);
move |tool_name: &str, _input: &serde_json::Value| {
move |_tool_id: &str, tool_name: &str, _input: &serde_json::Value| {
let ipc = Arc::clone(&ipc);
let tool = tool_name.to_string();
tokio::spawn(async move {
Expand Down
51 changes: 38 additions & 13 deletions codi-rs/src/tui/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,9 +144,11 @@ impl Message {
pub enum AppEvent {
/// Text delta received from streaming.
TextDelta(String),
/// Tool call started.
ToolStart(String, serde_json::Value),
/// Tool call completed.
/// Tool call started (id, name, input).
ToolStart(String, String, serde_json::Value),
/// Tool output line received during execution.
ToolOutput(String, String),
/// Tool call completed (id, result, is_error).
ToolResult(String, String, bool),
/// Turn completed with stats.
TurnComplete(TurnStats),
Expand Down Expand Up @@ -219,6 +221,10 @@ pub struct App {
/// Receiver for agent returning from a background chat task.
pending_agent: Option<tokio::sync::oneshot::Receiver<(Agent, CodiResult<String>)>>,

// Tool execution visualization
/// Manager for tool execution cells.
pub exec_cells: crate::tui::components::ExecCellManager,

// Orchestration
/// Commander for multi-agent orchestration.
commander: Option<Commander>,
Expand Down Expand Up @@ -266,6 +272,7 @@ impl App {
config: None,
auto_approve_all: false,
pending_agent: None,
exec_cells: crate::tui::components::ExecCellManager::new(),
commander: None,
pending_worker_permissions: Vec::new(),
}
Expand Down Expand Up @@ -343,14 +350,14 @@ impl App {
})),
on_tool_call: Some(Arc::new({
let tx = event_tx.clone();
move |name: &str, input: &serde_json::Value| {
let _ = tx.send(AppEvent::ToolStart(name.to_string(), input.clone()));
move |tool_id: &str, name: &str, input: &serde_json::Value| {
let _ = tx.send(AppEvent::ToolStart(tool_id.to_string(), name.to_string(), input.clone()));
}
})),
on_tool_result: Some(Arc::new({
let tx = event_tx.clone();
move |name: &str, result: &str, is_error: bool| {
let _ = tx.send(AppEvent::ToolResult(name.to_string(), result.to_string(), is_error));
move |tool_id: &str, result: &str, is_error: bool| {
let _ = tx.send(AppEvent::ToolResult(tool_id.to_string(), result.to_string(), is_error));
}
})),
on_confirm: None, // Handled via channel-based approach
Expand Down Expand Up @@ -459,14 +466,32 @@ impl App {
AppEvent::TextDelta(text) => {
self.handle_text_delta(&text);
}
AppEvent::ToolStart(name, _input) => {
AppEvent::ToolStart(id, name, input) => {
// Create a new exec cell for this tool
let cell = crate::tui::components::ExecCell::new(
id.clone(),
name.clone(),
input,
);
self.exec_cells.add(cell);
self.status = Some(format!("Running: {} ...", name));
}
AppEvent::ToolResult(name, _result, is_error) => {
if is_error {
self.status = Some(format!("Tool {} failed", name));
} else {
self.status = Some(format!("Completed: {}", name));
AppEvent::ToolOutput(id, line) => {
// Add output line to the exec cell
if let Some(cell) = self.exec_cells.get_mut(&id) {
cell.add_output_line(line);
}
}
AppEvent::ToolResult(id, result, is_error) => {
// Update the exec cell with the result
if let Some(cell) = self.exec_cells.get_mut(&id) {
if is_error {
cell.mark_error(&result);
self.status = Some(format!("Tool {} failed", cell.tool_name));
} else {
cell.mark_success(&result);
self.status = Some(format!("Completed: {}", cell.tool_name));
}
}
}
AppEvent::TurnComplete(stats) => {
Expand Down
Loading