feat: add background_process tool for launching long-running processes
Adds a new tool that allows launching processes (like game servers) in the background while g3 continues to operate. The process runs independently with stdout/stderr captured to a log file. Features: - Named process tracking for easy reference - Automatic log capture to logs/background_processes/ - Returns PID and log file path for use with shell tool - Automatic cleanup on agent shutdown via Drop trait Usage: Use shell tool to interact with the process: - Read logs: tail -100 <logfile> - Check status: ps -p <pid> - Stop process: kill <pid> Files: - New: crates/g3-core/src/background_process.rs - New: crates/g3-core/tests/background_process_demo_test.rs - Modified: crates/g3-core/src/lib.rs (tool definition + handler) - Modified: crates/g3-core/src/prompts.rs (documentation)
This commit is contained in:
68
crates/g3-core/tests/background_process_demo_test.rs
Normal file
68
crates/g3-core/tests/background_process_demo_test.rs
Normal file
@@ -0,0 +1,68 @@
|
||||
use g3_core::background_process::BackgroundProcessManager;
|
||||
use std::path::PathBuf;
|
||||
use std::thread;
|
||||
use std::time::Duration;
|
||||
use std::fs;
|
||||
|
||||
#[test]
|
||||
fn demo_background_process_with_script() {
|
||||
// Create temp directories
|
||||
let test_dir = std::env::temp_dir().join("g3_bg_demo");
|
||||
let _ = fs::remove_dir_all(&test_dir);
|
||||
fs::create_dir_all(&test_dir).unwrap();
|
||||
|
||||
// Create a test script
|
||||
let script_path = test_dir.join("test.sh");
|
||||
fs::write(&script_path, r#"#!/bin/bash
|
||||
echo "Starting..."
|
||||
for i in 1 2 3; do
|
||||
echo "Tick $i"
|
||||
sleep 0.5
|
||||
done
|
||||
echo "Done!"
|
||||
"#).unwrap();
|
||||
|
||||
// Make executable
|
||||
#[cfg(unix)]
|
||||
{
|
||||
use std::os::unix::fs::PermissionsExt;
|
||||
fs::set_permissions(&script_path, fs::Permissions::from_mode(0o755)).unwrap();
|
||||
}
|
||||
|
||||
let log_dir = test_dir.join("logs");
|
||||
let manager = BackgroundProcessManager::new(log_dir);
|
||||
|
||||
println!("\n=== Background Process Demo ===");
|
||||
|
||||
match manager.start("demo", "./test.sh", &test_dir) {
|
||||
Ok(info) => {
|
||||
println!("✅ Started '{}' with PID {}", info.name, info.pid);
|
||||
println!(" Log file: {:?}", info.log_file);
|
||||
|
||||
// Wait for script to produce some output
|
||||
thread::sleep(Duration::from_millis(800));
|
||||
|
||||
// Read logs
|
||||
let logs = fs::read_to_string(&info.log_file).unwrap_or_default();
|
||||
println!("\n📜 Logs so far:\n{}", logs);
|
||||
|
||||
// Should still be running
|
||||
assert!(manager.is_running("demo"), "Process should still be running");
|
||||
println!("🔍 Process is running: true");
|
||||
|
||||
// Wait for completion
|
||||
thread::sleep(Duration::from_secs(2));
|
||||
|
||||
// Read final logs
|
||||
let final_logs = fs::read_to_string(&info.log_file).unwrap_or_default();
|
||||
println!("\n📜 Final logs:\n{}", final_logs);
|
||||
|
||||
assert!(final_logs.contains("Done!"), "Should have completed");
|
||||
}
|
||||
Err(e) => panic!("Failed to start: {}", e),
|
||||
}
|
||||
|
||||
// Cleanup
|
||||
let _ = fs::remove_dir_all(&test_dir);
|
||||
println!("\n✅ Demo complete!");
|
||||
}
|
||||
Reference in New Issue
Block a user