agent_bridle_core/
error.rs1use std::fmt;
4
5pub type ToolResult<T> = Result<T, ToolError>;
7
8#[derive(Debug)]
15pub enum ToolError {
16 Denied {
20 reason: String,
22 },
23 NotFound {
25 name: String,
27 },
28 Budget,
30 Generation,
32 Exec(std::io::Error),
34 Other(anyhow::Error),
36}
37
38impl ToolError {
39 pub fn denied(reason: impl Into<String>) -> Self {
41 Self::Denied {
42 reason: reason.into(),
43 }
44 }
45
46 pub fn not_found(name: impl Into<String>) -> Self {
48 Self::NotFound { name: name.into() }
49 }
50}
51
52impl fmt::Display for ToolError {
53 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
54 match self {
55 Self::Denied { reason } => write!(f, "denied: {reason}"),
56 Self::NotFound { name } => write!(f, "no such tool: {name}"),
57 Self::Budget => write!(f, "denied: call budget (max_calls) exhausted"),
58 Self::Generation => {
59 write!(f, "denied: grant is not valid for the gate's generation")
60 }
61 Self::Exec(e) => write!(f, "tool execution failed: {e}"),
62 Self::Other(e) => write!(f, "{e}"),
63 }
64 }
65}
66
67impl std::error::Error for ToolError {
68 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
69 match self {
70 Self::Exec(e) => Some(e),
71 Self::Other(e) => e.source(),
72 _ => None,
73 }
74 }
75}
76
77impl From<std::io::Error> for ToolError {
78 fn from(e: std::io::Error) -> Self {
79 Self::Exec(e)
80 }
81}
82
83impl From<anyhow::Error> for ToolError {
84 fn from(e: anyhow::Error) -> Self {
85 Self::Other(e)
86 }
87}
88
89#[cfg(test)]
90mod tests {
91 use super::*;
92
93 #[test]
94 fn display_is_stable_and_safe() {
95 assert_eq!(
96 ToolError::denied("nope").to_string(),
97 "denied: nope".to_string()
98 );
99 assert_eq!(
100 ToolError::Budget.to_string(),
101 "denied: call budget (max_calls) exhausted"
102 );
103 assert!(ToolError::not_found("shell").to_string().contains("shell"));
104 }
105}