Files
zesdex/apps/infrastructure/src/tools/bash_tools.rs
T
asepharyana 16494d4b1e Enhance logging and documentation across utility tools and TUI overlays
- Added tracing instrumentation and improved logging messages in the Pong, Todofinish, and Todowrite tools for better debugging and monitoring.
- Enhanced documentation comments for clarity on tool functionalities and workflows.
- Implemented tracing in WorkflowRun, NoteFinding, ReadFindings, and HiveMind tools to track execution phases and findings.
- Updated TUI overlays (e.g., Bash, Clear Confirm, Editor, Effort Level, Help, Key Input, Learning, Loading, MCP, Model Selector, Plan, Quit Confirm, Rewind, Settings, Todo, Usage) with debug logging to capture rendering details.
- Improved the status bar and workflow panel rendering with additional debug information.
- Added tracing to various utility functions to facilitate better performance monitoring and error tracking.
2026-07-20 15:53:43 +07:00

107 lines
3.2 KiB
Rust

//! Background bash process output and kill tools.
//!
//! These tools allow the agent to inspect the output of a background shell job
//! (`BashOutput`) and to terminate a running background job (`BashKill`).
use anyhow::Result;
use serde_json::{json, Value};
use tracing::{info, instrument, warn};
use crate::tools::{arg_str, Tool, ToolCtx};
/// Get the output of a background bash job by ID.
///
/// Flow: look up `{session_dir}/bash-outputs/{job_id}` → read content back.
/// Path traversal in `job_id` is explicitly rejected.
pub struct BashOutput;
impl Tool for BashOutput {
fn name(&self) -> &'static str {
"bash_output"
}
fn description(&self) -> &'static str {
"Get the output of a background bash job by ID"
}
fn parameters(&self) -> Value {
json!({
"type": "object",
"properties": {
"job_id": {
"type": "string",
"description": "Background job ID"
}
},
"required": ["job_id"]
})
}
#[instrument(skip(self, ctx, args))]
fn run(&self, ctx: &ToolCtx, args: &Value) -> Result<String> {
let job_id = arg_str(args, "job_id")?;
info!("Getting output for job: {job_id}");
// Prevent path traversal
if job_id.contains('/') || job_id.contains('\\') || job_id.contains("..") {
anyhow::bail!("invalid job_id '{job_id}': must not contain path separators");
}
// Read from the session's bash output directory
let output_dir = ctx.session_dir.join("bash-outputs");
let output_file = output_dir.join(&job_id);
if output_file.exists() {
let content = std::fs::read_to_string(&output_file)
.unwrap_or_else(|e| format!("Error reading output: {e}"));
Ok(format!("Output for job '{job_id}':\n{content}"))
} else {
Ok(format!(
"No output found for job '{job_id}'. The job may still be running."
))
}
}
}
/// Kill a background bash job by ID.
///
/// Flow: parse job_id → look up in the global bash controller → cancel the job.
pub struct BashKill;
impl Tool for BashKill {
fn name(&self) -> &'static str {
"bash_kill"
}
fn description(&self) -> &'static str {
"Kill a background bash job by ID"
}
fn parameters(&self) -> Value {
json!({
"type": "object",
"properties": {
"job_id": {
"type": "string",
"description": "Background job ID to kill"
}
},
"required": ["job_id"]
})
}
#[instrument(skip(self, _ctx, args))]
fn run(&self, _ctx: &ToolCtx, args: &Value) -> Result<String> {
let job_id = crate::tools::arg_str(args, "job_id")?;
info!("bash_kill called for job: {job_id}");
if crate::bgbash::control::bash_control().cancel(&job_id) {
info!(job = %job_id, "background job killed");
Ok(format!("Killed background job '{job_id}'"))
} else {
warn!(job = %job_id, "no active background job found");
anyhow::bail!("no active background job found with ID '{job_id}'")
}
}
}