Core features: - OpenAI-compatible streaming provider (vLLM, Ollama, OpenAI, etc.) - Agent loop with tool use (bash, read, write, edit, glob, grep) - Permission system: ask/yolo/sandbox/allowEdits + glob patterns - SLUG.md hierarchy loaded every turn (CLAUDE.md equivalent) - Session persistence with --continue/--resume/--fork-session - Hook system: 5 lifecycle events, command + prompt types - Compaction: ToolResultTrim/Truncate strategies, /compact command - Config via TOML, CLI args, env vars Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
56 lines
1.6 KiB
Rust
56 lines
1.6 KiB
Rust
use super::{Tool, ToolDefinition};
|
|
use anyhow::Result;
|
|
use serde_json::Value;
|
|
use std::process::Command;
|
|
|
|
pub struct BashTool;
|
|
|
|
impl Tool for BashTool {
|
|
fn definition(&self) -> ToolDefinition {
|
|
ToolDefinition {
|
|
name: "bash".to_string(),
|
|
description: "Execute a bash command and return its output.".to_string(),
|
|
parameters: serde_json::json!({
|
|
"type": "object",
|
|
"properties": {
|
|
"command": {
|
|
"type": "string",
|
|
"description": "The bash command to execute"
|
|
}
|
|
},
|
|
"required": ["command"]
|
|
}),
|
|
}
|
|
}
|
|
|
|
fn execute(&self, args: &Value) -> Result<String> {
|
|
let command = args["command"]
|
|
.as_str()
|
|
.ok_or_else(|| anyhow::anyhow!("Missing 'command' argument"))?;
|
|
|
|
let output = Command::new("bash")
|
|
.arg("-c")
|
|
.arg(command)
|
|
.output()?;
|
|
|
|
let stdout = String::from_utf8_lossy(&output.stdout);
|
|
let stderr = String::from_utf8_lossy(&output.stderr);
|
|
|
|
let mut result = String::new();
|
|
if !stdout.is_empty() {
|
|
result.push_str(&stdout);
|
|
}
|
|
if !stderr.is_empty() {
|
|
if !result.is_empty() {
|
|
result.push('\n');
|
|
}
|
|
result.push_str("STDERR:\n");
|
|
result.push_str(&stderr);
|
|
}
|
|
if !output.status.success() {
|
|
result.push_str(&format!("\nExit code: {}", output.status.code().unwrap_or(-1)));
|
|
}
|
|
|
|
Ok(result)
|
|
}
|
|
}
|