Summary
Add a task_output tool to retrieve stdout/stderr from background tasks spawned via the task or bash tools.
Current State (as of PR #87)
BACKGROUND_TASKS: HashMap<String, tokio::process::Child> lives in bash.rs
task.rs imports it from bash.rs (tight coupling)
- Background tasks use
Stdio::null() - no output capture
- Foreground tasks have
kill_on_drop(true) for proper cleanup
kill_shell tool works for both bash and task background processes
Proposed Design (Revised)
Step 1: Extract Background Registry Module
First, extract shared state to src/tools/background.rs:
// src/tools/background.rs
use std::collections::HashMap;
use std::sync::{Arc, LazyLock, Mutex};
use std::sync::atomic::{AtomicUsize, AtomicBool, AtomicI32};
use tokio::process::Child;
pub static NEXT_TASK_ID: AtomicUsize = AtomicUsize::new(1);
pub struct BackgroundTask {
pub child: Child,
pub stdout_buffer: Arc<Mutex<String>>,
pub stderr_buffer: Arc<Mutex<String>>,
pub completed: AtomicBool,
pub exit_code: AtomicI32,
}
pub static BACKGROUND_TASKS: LazyLock<Mutex<HashMap<String, BackgroundTask>>> =
LazyLock::new(|| Mutex::new(HashMap::new()));
This cleans up the bash→task coupling and prepares for output capture.
Step 2: Async Output Collection
When spawning background tasks, create collection tasks:
let (stdout_tx, stdout_buffer) = create_output_collector();
let (stderr_tx, stderr_buffer) = create_output_collector();
let child = Command::new(&cmd)
.args(&args)
.stdout(Stdio::piped())
.stderr(Stdio::piped())
.spawn()?;
// Spawn collectors
let stdout = child.stdout.take().unwrap();
tokio::spawn(collect_output(stdout, stdout_tx));
let stderr = child.stderr.take().unwrap();
tokio::spawn(collect_output(stderr, stderr_tx));
Step 3: TaskOutput Tool
struct TaskOutputTool;
// Parameters
{
"task_id": "string", // Required
"wait": "boolean", // Wait for completion (default: false)
"timeout": "integer" // Max wait time in seconds (default: 30)
}
// Returns
{
"task_id": "abc123",
"status": "running" | "completed",
"exit_code": 0, // Only if completed
"stdout": "output...",
"stderr": "errors..."
}
Implementation Order
- Extract
background.rs - Move registry, clean up imports in bash.rs and task.rs
- Add output capture - Modify background spawning in both tools
- Implement TaskOutput tool - New tool that reads from buffers
- Add integration tests (per comments below)
Complexity
Medium - requires:
- New module extraction (straightforward refactor)
- Registry structure change
- Async output collection tasks
- New tool implementation
- Integration tests
Related
Summary
Add a
task_outputtool to retrieve stdout/stderr from background tasks spawned via thetaskorbashtools.Current State (as of PR #87)
BACKGROUND_TASKS: HashMap<String, tokio::process::Child>lives inbash.rstask.rsimports it frombash.rs(tight coupling)Stdio::null()- no output capturekill_on_drop(true)for proper cleanupkill_shelltool works for both bash and task background processesProposed Design (Revised)
Step 1: Extract Background Registry Module
First, extract shared state to
src/tools/background.rs:This cleans up the bash→task coupling and prepares for output capture.
Step 2: Async Output Collection
When spawning background tasks, create collection tasks:
Step 3: TaskOutput Tool
Implementation Order
background.rs- Move registry, clean up imports in bash.rs and task.rsComplexity
Medium - requires:
Related
kill_on_drop(true)for foreground tasks