M1: read, write, bash, glob, and grep tools

Implements the first five harness-tools: read, write, bash (with timeout/output truncation), glob, and grep, plus shared path-resolution helpers. Wires them into the core tool registry and processor.
This commit is contained in:
2026-07-10 16:19:38 +02:00
parent 5ac646b3c6
commit a5af873924
12 changed files with 1224 additions and 1 deletions
+52
View File
@@ -0,0 +1,52 @@
use std::path::{Path, PathBuf};
/// Resolves a (possibly relative) tool-supplied path against `cwd`.
pub fn resolve(cwd: &Path, file_path: &str) -> PathBuf {
let path = Path::new(file_path);
if path.is_absolute() {
path.to_path_buf()
} else {
cwd.join(path)
}
}
/// Slash-separated path relative to `cwd`, used as the permission pattern — falls back to
/// the absolute path (still slash-separated) when `path` isn't under `cwd`.
pub fn relative_pattern(cwd: &Path, path: &Path) -> String {
let rel = path.strip_prefix(cwd).unwrap_or(path);
rel.to_string_lossy().replace('\\', "/")
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn resolve_joins_relative_paths_to_cwd() {
let cwd = Path::new("/home/user/project");
assert_eq!(
resolve(cwd, "src/main.rs"),
PathBuf::from("/home/user/project/src/main.rs")
);
}
#[test]
fn resolve_leaves_absolute_paths_untouched() {
let cwd = Path::new("/home/user/project");
assert_eq!(resolve(cwd, "/etc/hosts"), PathBuf::from("/etc/hosts"));
}
#[test]
fn relative_pattern_strips_cwd_prefix() {
let cwd = Path::new("/home/user/project");
let path = Path::new("/home/user/project/src/main.rs");
assert_eq!(relative_pattern(cwd, path), "src/main.rs");
}
#[test]
fn relative_pattern_falls_back_to_absolute_outside_cwd() {
let cwd = Path::new("/home/user/project");
let path = Path::new("/etc/hosts");
assert_eq!(relative_pattern(cwd, path), "/etc/hosts");
}
}