use thiserror::Error;
use typesec_core::SecureValue;
use typesec_core::resource::GenericResource;
use typesec_core::secure_value::PrivacyLevel;
use super::call::{GuardedToolCall, ToolCallVerdict};
pub const TOOL_OUTPUT_KIND: &str = "tool_output";
#[derive(Debug, Error)]
pub enum TaintError {
#[error("cannot protect output of a call that was not allowed: {reason}")]
NotAllowed {
reason: String,
},
#[error("call has no resolved resource to tie the output to")]
UnresolvedResource,
}
impl GuardedToolCall {
pub fn protect_output<L: PrivacyLevel, T>(
&self,
output: T,
) -> Result<SecureValue<L, T, GenericResource>, TaintError> {
if let ToolCallVerdict::Deny { reason } | ToolCallVerdict::Delegate { reason } =
&self.verdict
{
return Err(TaintError::NotAllowed {
reason: reason.clone(),
});
}
let resource_id = self
.resource
.as_deref()
.ok_or(TaintError::UnresolvedResource)?;
let resource = GenericResource::new(resource_id, TOOL_OUTPUT_KIND);
Ok(SecureValue::protect(output, &resource))
}
}