Skip to main content

tools_kit/
error.rs

1use serde::{Deserialize, Serialize};
2
3use crate::{name::ToolName, schema::ValidationIssue};
4
5/// Portable executable-tool errors.
6#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, thiserror::Error)]
7#[serde(tag = "type", rename_all = "snake_case", deny_unknown_fields)]
8pub enum ToolError {
9    /// Toolset, registration, client, or server configuration is invalid.
10    #[error("invalid configuration: {message}")]
11    InvalidConfiguration {
12        /// Caller-safe validation failure.
13        message: String,
14    },
15    /// The requested tool name is not present in the inventory.
16    #[error("tool `{name}` was not found")]
17    UnknownTool {
18        /// Requested caller-facing name.
19        name: ToolName,
20    },
21    /// More than one registration resolves to the same caller-facing name.
22    #[error("duplicate tool name `{name}`")]
23    DuplicateName {
24        /// Duplicated caller-facing name.
25        name: ToolName,
26    },
27    /// Invocation arguments failed source-neutral validation.
28    #[error("invalid tool arguments for `{tool}`: {message}")]
29    InvalidArguments {
30        /// Tool whose invocation was rejected.
31        tool: ToolName,
32        /// Caller-safe validation summary.
33        message: String,
34        /// Structured schema diagnostics, when available.
35        issues: Vec<ValidationIssue>,
36    },
37    /// A completed result failed source-neutral output validation.
38    #[error("invalid tool output: {message}")]
39    InvalidOutput {
40        /// Caller-safe validation summary.
41        message: String,
42        /// Structured schema diagnostics, when available.
43        issues: Vec<ValidationIssue>,
44    },
45    /// A caller response does not match the pending interaction.
46    #[error("invalid interaction `{id}`: {message}")]
47    InvalidInteraction {
48        /// Interaction id supplied by the caller.
49        id: String,
50        /// Caller-safe validation summary.
51        message: String,
52    },
53    /// A local tool requested an interaction capability it did not declare.
54    #[error("tool `{tool}` requested undeclared {kind} interaction")]
55    UndeclaredInteraction {
56        /// Tool that requested the interaction.
57        tool: ToolName,
58        /// Source-neutral interaction kind.
59        kind: String,
60    },
61    /// The caller declined a pending interaction.
62    #[error("interaction for tool `{tool}` was declined")]
63    InteractionDeclined {
64        /// Tool whose interaction was declined.
65        tool: ToolName,
66        /// Optional caller-safe reason.
67        reason: Option<String>,
68    },
69    /// Tool execution or interaction resolution was cancelled.
70    #[error("tool `{tool}` was cancelled")]
71    Cancelled {
72        /// Cancelled tool.
73        tool: ToolName,
74        /// Optional caller-safe cancellation reason.
75        reason: Option<String>,
76    },
77    /// The executable source or interaction transport is unavailable.
78    #[error("tool transport is unavailable: {message}")]
79    Transport {
80        /// Affected tool, when known.
81        tool: Option<ToolName>,
82        /// Sanitized transport failure.
83        message: String,
84    },
85    /// The source returned or received invalid protocol data.
86    #[error("tool protocol error: {message}")]
87    Protocol {
88        /// Sanitized protocol failure.
89        message: String,
90    },
91    /// A bounded tool operation exceeded its deadline.
92    #[error("tool `{tool}` timed out after {timeout_secs}s")]
93    Timeout {
94        /// Tool whose operation timed out.
95        tool: ToolName,
96        /// Applied timeout in whole seconds.
97        timeout_secs: u64,
98    },
99    /// The selected source does not support an operation.
100    #[error("unsupported operation: {operation}")]
101    Unsupported {
102        /// Portable operation name.
103        operation: String,
104    },
105    /// Admission was rejected because Toolset shutdown has begun.
106    #[error("toolset is closed for operation `{operation}`")]
107    Closed {
108        /// Rejected operation name.
109        operation: String,
110    },
111    /// Toolset construction failed and its compensating cleanup also failed.
112    #[error("tool construction failed and cleanup also failed")]
113    BuildCleanup {
114        /// Original construction failure.
115        primary: Box<ToolError>,
116        /// Failure produced while cleaning up partial construction.
117        cleanup: Box<ToolError>,
118    },
119}
120
121impl ToolError {
122    pub(crate) fn closed(operation: impl Into<String>) -> Self {
123        Self::Closed {
124            operation: operation.into(),
125        }
126    }
127}