- Added a `tool_output` color to the `Theme` struct. - Updated all built-in themes to include the new color. - Modified the TUI to use the `tool_output` color for rendering tool output.
112 lines
2.7 KiB
Rust
112 lines
2.7 KiB
Rust
use crate::tools::{Tool, ToolResult};
|
|
use anyhow::Result;
|
|
use async_trait::async_trait;
|
|
use serde::Deserialize;
|
|
use serde_json::json;
|
|
use std::env;
|
|
use std::fs;
|
|
use std::path::{Path, PathBuf};
|
|
use path_clean::PathClean;
|
|
|
|
#[derive(Deserialize)]
|
|
struct FileArgs {
|
|
path: String,
|
|
}
|
|
|
|
fn sanitize_path(path: &str, root: &Path) -> Result<PathBuf> {
|
|
let path = Path::new(path);
|
|
let path = if path.is_absolute() {
|
|
path.strip_prefix("/")
|
|
.map_err(|_| anyhow::anyhow!("Invalid path"))?
|
|
.to_path_buf()
|
|
} else {
|
|
path.to_path_buf()
|
|
};
|
|
|
|
let full_path = root.join(path).clean();
|
|
|
|
if !full_path.starts_with(root) {
|
|
return Err(anyhow::anyhow!("Path traversal detected"));
|
|
}
|
|
|
|
Ok(full_path)
|
|
}
|
|
|
|
pub struct ResourcesListTool;
|
|
|
|
#[async_trait]
|
|
impl Tool for ResourcesListTool {
|
|
fn name(&self) -> &'static str {
|
|
"resources/list"
|
|
}
|
|
|
|
fn description(&self) -> &'static str {
|
|
"Lists directory contents."
|
|
}
|
|
|
|
fn schema(&self) -> serde_json::Value {
|
|
json!({
|
|
"type": "object",
|
|
"properties": {
|
|
"path": {
|
|
"type": "string",
|
|
"description": "The path to the directory to list."
|
|
}
|
|
},
|
|
"required": ["path"]
|
|
})
|
|
}
|
|
|
|
async fn execute(&self, args: serde_json::Value) -> Result<ToolResult> {
|
|
let args: FileArgs = serde_json::from_value(args)?;
|
|
let root = env::current_dir()?;
|
|
let full_path = sanitize_path(&args.path, &root)?;
|
|
|
|
let entries = fs::read_dir(full_path)?;
|
|
|
|
let mut result = Vec::new();
|
|
for entry in entries {
|
|
let entry = entry?;
|
|
result.push(entry.file_name().to_string_lossy().to_string());
|
|
}
|
|
|
|
Ok(ToolResult::success(serde_json::to_value(result)?))
|
|
}
|
|
}
|
|
|
|
pub struct ResourcesGetTool;
|
|
|
|
#[async_trait]
|
|
impl Tool for ResourcesGetTool {
|
|
fn name(&self) -> &'static str {
|
|
"resources/get"
|
|
}
|
|
|
|
fn description(&self) -> &'static str {
|
|
"Reads file content."
|
|
}
|
|
|
|
fn schema(&self) -> serde_json::Value {
|
|
json!({
|
|
"type": "object",
|
|
"properties": {
|
|
"path": {
|
|
"type": "string",
|
|
"description": "The path to the file to read."
|
|
}
|
|
},
|
|
"required": ["path"]
|
|
})
|
|
}
|
|
|
|
async fn execute(&self, args: serde_json::Value) -> Result<ToolResult> {
|
|
let args: FileArgs = serde_json::from_value(args)?;
|
|
let root = env::current_dir()?;
|
|
let full_path = sanitize_path(&args.path, &root)?;
|
|
|
|
let content = fs::read_to_string(full_path)?;
|
|
|
|
Ok(ToolResult::success(serde_json::to_value(content)?))
|
|
}
|
|
}
|