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}