use async_trait::async_trait;
use crate::types::{AgentResult, ApprovalDecision, ApprovalRequest};
#[async_trait]
pub trait ApprovalHandler: Send + Sync {
async fn approve(
&self,
request: ApprovalRequest,
cancel_token: tokio_util::sync::CancellationToken,
) -> AgentResult<ApprovalDecision>;
}
#[derive(Clone, Debug, Default)]
pub struct DenyAllApprovalHandler;
#[async_trait]
impl ApprovalHandler for DenyAllApprovalHandler {
async fn approve(
&self,
_request: ApprovalRequest,
_cancel_token: tokio_util::sync::CancellationToken,
) -> AgentResult<ApprovalDecision> {
Ok(ApprovalDecision::Deny)
}
}
#[derive(Clone, Debug, Default)]
pub struct AllowAllApprovalHandler;
#[async_trait]
impl ApprovalHandler for AllowAllApprovalHandler {
async fn approve(
&self,
_request: ApprovalRequest,
_cancel_token: tokio_util::sync::CancellationToken,
) -> AgentResult<ApprovalDecision> {
Ok(ApprovalDecision::AllowAlways)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::types::RiskLevel;
use tokio_util::sync::CancellationToken;
fn request() -> ApprovalRequest {
ApprovalRequest {
title: "Delete file".to_string(),
message: "Really delete?".to_string(),
action_key: Some("delete".to_string()),
risk_level: RiskLevel::Destructive,
raw: None,
}
}
#[tokio::test]
async fn deny_all_returns_deny() {
let decision = DenyAllApprovalHandler
.approve(request(), CancellationToken::new())
.await
.unwrap();
assert_eq!(decision, ApprovalDecision::Deny);
}
#[tokio::test]
async fn allow_all_returns_allow_always() {
let decision = AllowAllApprovalHandler
.approve(request(), CancellationToken::new())
.await
.unwrap();
assert_eq!(decision, ApprovalDecision::AllowAlways);
}
}