#![allow(unused_imports, reason = "re-exports consumed via engine prelude_uses")]
use std::path::Path;
use std::time::Duration;
use serde_json::Value;
use zagens_core::turn::TurnLoopMode;
use crate::agent_surface::AppMode;
use crate::models::Tool;
use crate::tools::spec::{ToolError, ToolResult};
pub use zagens_core::engine::tool_catalog::{
CODE_EXECUTION_TOOL_NAME, MULTI_TOOL_PARALLEL_NAME, REQUEST_USER_INPUT_NAME,
TOOL_SEARCH_BM25_NAME, active_tools_for_step, apply_mcp_tool_deferral,
apply_native_tool_deferral, build_model_tool_catalog as build_model_tool_catalog_for_mode,
ensure_advanced_tooling, execute_tool_search, initial_active_tools, is_tool_search_tool,
maybe_activate_requested_deferred_tool, missing_tool_error_message,
should_default_defer_tool as should_default_defer_tool_for_mode,
};
fn app_mode_to_turn_loop(mode: AppMode) -> TurnLoopMode {
match mode {
AppMode::Agent => TurnLoopMode::Agent,
AppMode::Yolo => TurnLoopMode::Yolo,
AppMode::Plan => TurnLoopMode::Plan,
}
}
pub(super) fn should_default_defer_tool(name: &str, mode: AppMode) -> bool {
should_default_defer_tool_for_mode(name, app_mode_to_turn_loop(mode))
}
pub(super) fn build_model_tool_catalog(
native_tools: Vec<Tool>,
mcp_tools: Vec<Tool>,
mode: AppMode,
scratchpad_run_id: Option<&str>,
) -> Vec<Tool> {
build_model_tool_catalog_for_mode(
native_tools,
mcp_tools,
app_mode_to_turn_loop(mode),
scratchpad_run_id,
)
}
pub(super) async fn execute_code_execution_tool(
input: &Value,
workspace: &Path,
) -> Result<ToolResult, ToolError> {
let code = zagens_tools::required_str(input, "code")?;
let python_bin = crate::python_env::find_python()
.map(|(bin, _, _)| bin)
.unwrap_or_else(|| "python3".to_string());
let mut cmd = tokio::process::Command::new(&python_bin);
cmd.arg("-c");
cmd.arg(code);
cmd.current_dir(workspace);
let output = tokio::time::timeout(Duration::from_secs(120), cmd.output())
.await
.map_err(|_| ToolError::Timeout { seconds: 120 })
.and_then(|res| res.map_err(|e| ToolError::execution_failed(e.to_string())))?;
let stdout = String::from_utf8_lossy(&output.stdout).to_string();
let stderr = String::from_utf8_lossy(&output.stderr).to_string();
let return_code = output.status.code().unwrap_or(-1);
let success = output.status.success();
let payload = serde_json::json!({
"type": "code_execution_result",
"stdout": stdout,
"stderr": stderr,
"return_code": return_code,
"content": [],
});
Ok(ToolResult {
content: serde_json::to_string(&payload).unwrap_or_else(|_| payload.to_string()),
success,
metadata: Some(payload),
})
}