use serde_json::Value;
use crate::agent_surface::AppMode;
use crate::tools::spec::{ToolError, ToolResult};
use zagens_core::engine::dispatch::{self, ToolParallelPlanFlags};
use zagens_core::engine::streaming::ToolUseState;
pub use zagens_core::engine::dispatch::{
mcp_tool_is_parallel_safe, mcp_tool_is_read_only, parse_parallel_tool_calls,
};
pub use zagens_core::engine::turn_loop::ToolExecutionPlan;
#[derive(Debug, serde::Serialize)]
pub(super) struct ParallelToolResultEntry {
pub(super) tool_name: String,
pub(super) success: bool,
pub(super) content: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub(super) error: Option<String>,
}
#[derive(Debug, serde::Serialize)]
pub(super) struct ParallelToolResult {
pub(super) results: Vec<ParallelToolResultEntry>,
}
pub(super) enum ToolExecGuard<'a> {
Read(#[allow(dead_code)] tokio::sync::RwLockReadGuard<'a, ()>),
Write(#[allow(dead_code)] tokio::sync::RwLockWriteGuard<'a, ()>),
}
pub(super) fn parse_tool_input(buffer: &str) -> Option<Value> {
if let Ok(value) = crate::tools::arg_repair::repair(buffer) {
return Some(value);
}
dispatch::parse_tool_input_json(buffer)
}
#[must_use]
pub(super) fn final_tool_input(state: &ToolUseState) -> Value {
if !state.input_buffer.trim().is_empty()
&& let Some(parsed) = parse_tool_input(&state.input_buffer)
{
return parsed;
}
state.input.clone()
}
pub(super) fn should_parallelize_tool_batch(plans: &[ToolExecutionPlan]) -> bool {
let flags: Vec<ToolParallelPlanFlags> = plans
.iter()
.map(|plan| ToolParallelPlanFlags {
read_only: plan.read_only,
supports_parallel: plan.supports_parallel,
approval_required: plan.approval_required,
interactive: plan.interactive,
})
.collect();
dispatch::should_parallelize_tool_batch(&flags)
}
pub(super) fn should_stop_after_plan_tool(
mode: AppMode,
tool_name: &str,
result: &Result<ToolResult, ToolError>,
) -> bool {
dispatch::should_stop_after_plan_tool(mode == AppMode::Plan, tool_name, result)
}
pub(super) fn should_force_update_plan_first(mode: AppMode, content: &str) -> bool {
dispatch::should_force_update_plan_first(mode == AppMode::Plan, content)
}