use crate::DriverCallback;
use crate::DriverContext;
use crate::{
DriverCategory,
types::{Driver, DriverParameter},
};
use crate::{
calculate_all_hashes, calculate_md5, calculate_sha1, calculate_sha256, calculate_sha512,
file_exists, validate_path,
};
use anyhow::Result;
use serde_json::{Value, json};
use std::collections::HashMap;
#[derive(Debug)]
pub struct HashMd5Driver;
#[async_trait::async_trait]
impl Driver for HashMd5Driver {
fn name(&self) -> &str {
"hash_md5"
}
fn description(&self) -> &str {
"Calculate MD5 hash of a file"
}
fn usage_hint(&self) -> &str {
"Use this skill to get the MD5 checksum of a file for integrity verification."
}
fn parameters(&self) -> Vec<DriverParameter> {
vec![DriverParameter {
name: "path".to_string(),
param_type: "string".to_string(),
description: "Path to the file to hash".to_string(),
required: true,
default: None,
example: Some(Value::String("/tmp/file.txt".to_string())),
enum_values: None,
}]
}
fn example_call(&self) -> Value {
json!({
"action": "hash_md5",
"parameters": {
"path": "/tmp/file.txt"
}
})
}
fn example_output(&self) -> String {
"MD5 hash of /tmp/file.txt: d41d8cd98f00b204e9800998ecf8427e".to_string()
}
fn category(&self) -> DriverCategory {
DriverCategory::File
}
async fn execute(
&self,
parameters: &HashMap<String, Value>,
callback: Option<&dyn DriverCallback>,
context: Option<&DriverContext>,
) -> Result<String> {
let path = parameters
.get("path")
.and_then(|v| v.as_str())
.ok_or_else(|| anyhow::anyhow!("Missing 'path' parameter"))?;
let validated_path = validate_path(path, None)?;
if !file_exists(&validated_path.to_string_lossy()) {
anyhow::bail!("File not found: {}", path);
}
let hash = calculate_md5(&validated_path.to_string_lossy())?;
Ok(format!("MD5 hash of {}: {}", path, hash))
}
}
#[derive(Debug)]
pub struct HashSha1Driver;
#[async_trait::async_trait]
impl Driver for HashSha1Driver {
fn name(&self) -> &str {
"hash_sha1"
}
fn description(&self) -> &str {
"Calculate SHA1 hash of a file"
}
fn usage_hint(&self) -> &str {
"Use this skill to get the SHA1 checksum of a file for integrity verification."
}
fn parameters(&self) -> Vec<DriverParameter> {
vec![DriverParameter {
name: "path".to_string(),
param_type: "string".to_string(),
description: "Path to the file to hash".to_string(),
required: true,
default: None,
example: Some(Value::String("/tmp/file.txt".to_string())),
enum_values: None,
}]
}
fn example_call(&self) -> Value {
json!({
"action": "hash_sha1",
"parameters": {
"path": "/tmp/file.txt"
}
})
}
fn example_output(&self) -> String {
"SHA1 hash of /tmp/file.txt: da39a3ee5e6b4b0d3255bfef95601890afd80709".to_string()
}
fn category(&self) -> DriverCategory {
DriverCategory::File
}
async fn execute(
&self,
parameters: &HashMap<String, Value>,
callback: Option<&dyn DriverCallback>,
context: Option<&DriverContext>,
) -> Result<String> {
let path = parameters
.get("path")
.and_then(|v| v.as_str())
.ok_or_else(|| anyhow::anyhow!("Missing 'path' parameter"))?;
let validated_path = validate_path(path, None)?;
if !file_exists(&validated_path.to_string_lossy()) {
anyhow::bail!("File not found: {}", path);
}
let hash = calculate_sha1(&validated_path.to_string_lossy())?;
Ok(format!("SHA1 hash of {}: {}", path, hash))
}
}
#[derive(Debug)]
pub struct HashSha256Driver;
#[async_trait::async_trait]
impl Driver for HashSha256Driver {
fn name(&self) -> &str {
"hash_sha256"
}
fn description(&self) -> &str {
"Calculate SHA256 hash of a file"
}
fn usage_hint(&self) -> &str {
"Use this skill to get the SHA256 checksum of a file for integrity verification."
}
fn parameters(&self) -> Vec<DriverParameter> {
vec![DriverParameter {
name: "path".to_string(),
param_type: "string".to_string(),
description: "Path to the file to hash".to_string(),
required: true,
default: None,
example: Some(Value::String("/tmp/file.txt".to_string())),
enum_values: None,
}]
}
fn example_call(&self) -> Value {
json!({
"action": "hash_sha256",
"parameters": {
"path": "/tmp/file.txt"
}
})
}
fn example_output(&self) -> String {
"SHA256 hash of /tmp/file.txt: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855".to_string()
}
fn category(&self) -> DriverCategory {
DriverCategory::File
}
async fn execute(
&self,
parameters: &HashMap<String, Value>,
callback: Option<&dyn DriverCallback>,
context: Option<&DriverContext>,
) -> Result<String> {
let path = parameters
.get("path")
.and_then(|v| v.as_str())
.ok_or_else(|| anyhow::anyhow!("Missing 'path' parameter"))?;
let validated_path = validate_path(path, None)?;
if !file_exists(&validated_path.to_string_lossy()) {
anyhow::bail!("File not found: {}", path);
}
let hash = calculate_sha256(&validated_path.to_string_lossy())?;
Ok(format!("SHA256 hash of {}: {}", path, hash))
}
}
#[derive(Debug)]
pub struct HashSha512Driver;
#[async_trait::async_trait]
impl Driver for HashSha512Driver {
fn name(&self) -> &str {
"hash_sha512"
}
fn description(&self) -> &str {
"Calculate SHA512 hash of a file"
}
fn usage_hint(&self) -> &str {
"Use this skill to get the SHA512 checksum of a file for integrity verification."
}
fn parameters(&self) -> Vec<DriverParameter> {
vec![DriverParameter {
name: "path".to_string(),
param_type: "string".to_string(),
description: "Path to the file to hash".to_string(),
required: true,
default: None,
example: Some(Value::String("/tmp/file.txt".to_string())),
enum_values: None,
}]
}
fn example_call(&self) -> Value {
json!({
"action": "hash_sha512",
"parameters": {
"path": "/tmp/file.txt"
}
})
}
fn example_output(&self) -> String {
"SHA512 hash of /tmp/file.txt: cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e".to_string()
}
fn category(&self) -> DriverCategory {
DriverCategory::File
}
async fn execute(
&self,
parameters: &HashMap<String, Value>,
callback: Option<&dyn DriverCallback>,
context: Option<&DriverContext>,
) -> Result<String> {
let path = parameters
.get("path")
.and_then(|v| v.as_str())
.ok_or_else(|| anyhow::anyhow!("Missing 'path' parameter"))?;
let validated_path = validate_path(path, None)?;
if !file_exists(&validated_path.to_string_lossy()) {
anyhow::bail!("File not found: {}", path);
}
let hash = calculate_sha512(&validated_path.to_string_lossy())?;
Ok(format!("SHA512 hash of {}: {}", path, hash))
}
}
#[derive(Debug)]
pub struct HashFileDriver;
#[async_trait::async_trait]
impl Driver for HashFileDriver {
fn name(&self) -> &str {
"hash_file"
}
fn description(&self) -> &str {
"Calculate all hashes (MD5, SHA1, SHA256, SHA512, BLAKE3) of a file"
}
fn usage_hint(&self) -> &str {
"Use this skill to get comprehensive hash information for a file."
}
fn parameters(&self) -> Vec<DriverParameter> {
vec![DriverParameter {
name: "path".to_string(),
param_type: "string".to_string(),
description: "Path to the file to hash".to_string(),
required: true,
default: None,
example: Some(Value::String("/tmp/file.txt".to_string())),
enum_values: None,
}]
}
fn example_call(&self) -> Value {
json!({
"action": "hash_file",
"parameters": {
"path": "/tmp/file.txt"
}
})
}
fn example_output(&self) -> String {
"File: /tmp/file.txt\nMD5: d41d8cd98f00b204e9800998ecf8427e\nSHA1: da39a3ee5e6b4b0d3255bfef95601890afd80709\nSHA256: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\nSHA512: cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e\nBLAKE3: ...".to_string()
}
fn category(&self) -> DriverCategory {
DriverCategory::File
}
async fn execute(
&self,
parameters: &HashMap<String, Value>,
callback: Option<&dyn DriverCallback>,
context: Option<&DriverContext>,
) -> Result<String> {
let path = parameters
.get("path")
.and_then(|v| v.as_str())
.ok_or_else(|| anyhow::anyhow!("Missing 'path' parameter"))?;
let validated_path = validate_path(path, None)?;
if !file_exists(&validated_path.to_string_lossy()) {
anyhow::bail!("File not found: {}", path);
}
let result = calculate_all_hashes(&validated_path.to_string_lossy())?;
let mut output = format!("File: {}\n", result.path);
if let Some(hash) = result.md5 {
output.push_str(&format!("MD5: {}\n", hash));
}
if let Some(hash) = result.sha1 {
output.push_str(&format!("SHA1: {}\n", hash));
}
if let Some(hash) = result.sha256 {
output.push_str(&format!("SHA256: {}\n", hash));
}
if let Some(hash) = result.sha512 {
output.push_str(&format!("SHA512: {}\n", hash));
}
if let Some(hash) = result.blake3 {
output.push_str(&format!("BLAKE3: {}\n", hash));
}
Ok(output)
}
}