use std::collections::VecDeque;
use std::time::Instant;
use crossterm::style::Color;
use serde_json::Value;
use crate::ui::agent_io::render_agent_stream;
use crate::ui::avatar;
use crate::ui::colors::{c_agent, c_tool};
use crate::ui::events::sanitize_output;
use crate::ui::panel_data::tool_call_label;
use crate::ui::run_handlers::RunCtx;
use crate::ui::tool_display::{
chamber_widths, close_tool_chamber_passive, fit_banner_header, format_tool_banner_value,
};
#[allow(clippy::too_many_arguments)]
pub(crate) fn handle_tool_call(
ctx: &mut RunCtx<'_>,
id: &str,
name: &str,
args: &Value,
was_reasoning: &mut bool,
last_token_render: &mut Option<Instant>,
tool_activity: &mut VecDeque<String>,
activity_cap: usize,
) -> anyhow::Result<()> {
tool_activity.push_back(tool_call_label(name, args));
while tool_activity.len() > activity_cap {
tool_activity.pop_front();
}
tracing::trace!(
target: "dirge::ui::chamber",
event = "tool_call_in",
id = %id,
name = %name,
last_tool_call_id_before = ?ctx.last_tool_call_id,
tool_chamber_open_before = *ctx.tool_chamber_open,
chamber_top_start_before = ?ctx.chamber_top_start,
chamber_top_end_before = ?ctx.chamber_top_end,
buffer_len = ctx.renderer.buffer_len(),
"ToolCall handler entry"
);
*was_reasoning = false;
ctx.tool_calls_buf.push(crate::session::ToolCallEntry {
id: id.to_string(),
name: name.to_string(),
args: args.clone(),
state: crate::session::ToolCallState::Interrupted,
});
*ctx.tool_calls_this_run = ctx.tool_calls_this_run.saturating_add(1);
ctx.renderer
.set_avatar_state(avatar::AvatarState::from_tool_name(name));
#[cfg(feature = "experimental-ui-terminal-tab")]
ctx.renderer.set_last_tool_name(name);
close_tool_chamber_passive(
ctx.renderer,
ctx.last_tool_name,
ctx.tool_chamber_open,
ctx.chamber_top_start,
ctx.chamber_top_end,
)?;
*ctx.last_tool_name = Some(name.to_string());
*ctx.last_tool_call_id = Some(id.to_string());
if !ctx.response_buf.is_empty() {
render_agent_stream(
ctx.response_buf,
ctx.response_start_line,
c_agent(),
ctx.renderer,
)?;
}
*last_token_render = None;
if *ctx.agent_line_started {
ctx.renderer.write_line("", Color::White)?;
*ctx.agent_line_started = false;
}
ctx.response_buf.clear();
*ctx.response_start_line = None;
ctx.end_reasoning();
*ctx.reasoning_start_line = None;
let upper = name.to_ascii_uppercase();
*ctx.chamber_top_start = Some(ctx.renderer.buffer_len());
ctx.renderer.write_line("", Color::White)?;
let raw_value = format_tool_banner_value(name, args);
let raw_value = sanitize_output(&raw_value).into_string();
let (frame_w, _) = chamber_widths(&*ctx.renderer);
let header = fit_banner_header(&upper, &raw_value, frame_w);
ctx.renderer.write_line_raw(&header, c_tool())?;
*ctx.chamber_top_end = Some(ctx.renderer.buffer_len());
*ctx.tool_chamber_open = true;
tracing::trace!(
target: "dirge::ui::chamber",
event = "tool_call_painted",
id = %id,
name = %name,
chamber_top_start_after = ?ctx.chamber_top_start,
chamber_top_end_after = ?ctx.chamber_top_end,
buffer_len = ctx.renderer.buffer_len(),
"ToolCall TOP painted"
);
Ok(())
}