refactor(tools): replace manual Display impl with thiserror derive (#2442)

* refactor(tools): replace manual Display impl with thiserror derive

Replace the hand-rolled Display implementation for ToolError with
thiserror derive macros. The thiserror crate is already a workspace
dependency. Error messages remain identical (verified by existing
test tool_error_display_matches_legacy_text).

This reduces boilerplate and ensures consistency with other error
types in the codebase (secrets, state crates already use thiserror).

* chore: add thiserror to Cargo.lock

---------

Co-authored-by: Hu Qiantao <huqiantao@HudeMacBook-Air.local>
This commit is contained in:
HUQIANTAO
2026-06-01 01:18:05 +08:00
committed by GitHub
parent aea924adf2
commit 311333d887
3 changed files with 23 additions and 54 deletions
Generated
+14 -13
View File
@@ -952,7 +952,7 @@ dependencies = [
"serde",
"serde_json",
"tempfile",
"thiserror 2.0.17",
"thiserror 2.0.18",
"tracing",
]
@@ -977,6 +977,7 @@ dependencies = [
"codewhale-protocol",
"serde",
"serde_json",
"thiserror 2.0.18",
"tokio",
"uuid",
]
@@ -1031,7 +1032,7 @@ dependencies = [
"starlark",
"tar",
"tempfile",
"thiserror 2.0.17",
"thiserror 2.0.18",
"tiny_http",
"tokio",
"tokio-util",
@@ -2723,7 +2724,7 @@ checksum = "bde5057d6143cc94e861d90f591b9303d6716c6b9602309150bd068853c10899"
dependencies = [
"hashbrown 0.16.1",
"portable-atomic",
"thiserror 2.0.17",
"thiserror 2.0.18",
]
[[package]]
@@ -3735,7 +3736,7 @@ dependencies = [
"rustc-hash",
"rustls",
"socket2",
"thiserror 2.0.17",
"thiserror 2.0.18",
"tokio",
"tracing",
"web-time",
@@ -3757,7 +3758,7 @@ dependencies = [
"rustls",
"rustls-pki-types",
"slab",
"thiserror 2.0.17",
"thiserror 2.0.18",
"tinyvec",
"tracing",
"web-time",
@@ -3895,7 +3896,7 @@ dependencies = [
"kasuari",
"lru",
"strum",
"thiserror 2.0.17",
"thiserror 2.0.18",
"unicode-segmentation",
"unicode-truncate",
"unicode-width 0.2.0",
@@ -3989,7 +3990,7 @@ checksum = "a4e608c6638b9c18977b00b475ac1f28d14e84b27d8d42f70e0bf1e3dec127ac"
dependencies = [
"getrandom 0.2.16",
"libredox",
"thiserror 2.0.17",
"thiserror 2.0.18",
]
[[package]]
@@ -5049,11 +5050,11 @@ dependencies = [
[[package]]
name = "thiserror"
version = "2.0.17"
version = "2.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8"
checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4"
dependencies = [
"thiserror-impl 2.0.17",
"thiserror-impl 2.0.18",
]
[[package]]
@@ -5069,9 +5070,9 @@ dependencies = [
[[package]]
name = "thiserror-impl"
version = "2.0.17"
version = "2.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913"
checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5"
dependencies = [
"proc-macro2",
"quote",
@@ -5376,7 +5377,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "786d480bce6247ab75f005b14ae1624ad978d3029d9113f0a22fa1ac773faeaf"
dependencies = [
"crossbeam-channel",
"thiserror 2.0.17",
"thiserror 2.0.18",
"time",
"tracing-subscriber",
]
+1
View File
@@ -12,5 +12,6 @@ async-trait.workspace = true
codewhale-protocol = { path = "../protocol", version = "0.8.46" }
serde.workspace = true
serde_json.workspace = true
thiserror.workspace = true
tokio.workspace = true
uuid.workspace = true
+8 -41
View File
@@ -44,57 +44,24 @@ pub enum ApprovalRequirement {
}
/// Errors that can occur during tool execution.
#[derive(Debug, Clone)]
#[derive(Debug, Clone, thiserror::Error)]
pub enum ToolError {
#[error("Failed to validate input: {message}")]
InvalidInput { message: String },
#[error("Failed to validate input: missing required field '{field}'")]
MissingField { field: String },
#[error("Failed to resolve path '{}': path escapes workspace", path.display())]
PathEscape { path: PathBuf },
#[error("Failed to execute tool: {message}")]
ExecutionFailed { message: String },
#[error("Failed to execute tool: operation timed out after {seconds}s")]
Timeout { seconds: u64 },
#[error("Failed to locate tool: {message}")]
NotAvailable { message: String },
#[error("Failed to authorize tool execution: {message}")]
PermissionDenied { message: String },
}
impl std::fmt::Display for ToolError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::InvalidInput { message } => {
write!(f, "Failed to validate input: {message}")
}
Self::MissingField { field } => {
write!(
f,
"Failed to validate input: missing required field '{field}'"
)
}
Self::PathEscape { path } => {
write!(
f,
"Failed to resolve path '{}': path escapes workspace",
path.display()
)
}
Self::ExecutionFailed { message } => {
write!(f, "Failed to execute tool: {message}")
}
Self::Timeout { seconds } => {
write!(
f,
"Failed to execute tool: operation timed out after {seconds}s"
)
}
Self::NotAvailable { message } => {
write!(f, "Failed to locate tool: {message}")
}
Self::PermissionDenied { message } => {
write!(f, "Failed to authorize tool execution: {message}")
}
}
}
}
impl std::error::Error for ToolError {}
impl ToolError {
#[must_use]
pub fn invalid_input(msg: impl Into<String>) -> Self {