adk_computer_use/error.rs
1//! Typed errors for the computer-use orchestration layer.
2//!
3//! The runtime boundary ([`crate::ComputerUseRuntime`]) and the MCP adapter
4//! ([`crate::ComputerUseMcpRuntime`]) return [`ComputerUseError`] instead of
5//! stringly-typed failures. Each variant carries enough context to map cleanly
6//! onto [`adk_core::AdkError`] at the host boundary via the provided
7//! [`From`] implementation.
8
9use adk_core::{AdkError, ErrorCategory, ErrorComponent};
10use thiserror::Error;
11
12/// Convenience alias for fallible computer-use operations.
13pub type Result<T, E = ComputerUseError> = std::result::Result<T, E>;
14
15/// Structured error surfaced by the computer-use graph, runtime trait, and MCP adapter.
16///
17/// The variants distinguish caller mistakes ([`InvalidRequest`](Self::InvalidRequest)),
18/// transport faults ([`Mcp`](Self::Mcp)), payload decoding failures
19/// ([`Decode`](Self::Decode)), identity/authorization mismatches
20/// ([`IdentityMismatch`](Self::IdentityMismatch)), unimplemented adapter
21/// capabilities ([`Unsupported`](Self::Unsupported)), and residual invariant
22/// violations ([`Runtime`](Self::Runtime)). Convert to [`adk_core::AdkError`]
23/// with `?` or `.into()` when returning through an ADK trait boundary.
24#[derive(Debug, Error)]
25pub enum ComputerUseError {
26 /// The underlying MCP transport or tool invocation failed.
27 #[error("computer-use MCP call failed: {0}")]
28 Mcp(String),
29
30 /// A wire payload could not be decoded into the expected contract type.
31 #[error("failed to decode computer-use payload: {0}")]
32 Decode(String),
33
34 /// A runtime response did not match the authenticated ADK principal or session.
35 #[error("computer-use identity mismatch: {0}")]
36 IdentityMismatch(String),
37
38 /// A request argument violated a documented precondition.
39 #[error("invalid computer-use request: {0}")]
40 InvalidRequest(String),
41
42 /// The runtime adapter does not implement the requested control operation.
43 #[error("{operation} is not implemented by this runtime adapter")]
44 Unsupported {
45 /// The control operation the caller attempted (e.g. `pause_session`).
46 operation: &'static str,
47 },
48
49 /// A runtime invariant expected by the graph was not satisfied.
50 #[error("computer-use runtime error: {0}")]
51 Runtime(String),
52}
53
54impl From<serde_json::Error> for ComputerUseError {
55 fn from(error: serde_json::Error) -> Self {
56 ComputerUseError::Decode(error.to_string())
57 }
58}
59
60impl From<ComputerUseError> for AdkError {
61 fn from(error: ComputerUseError) -> Self {
62 let (component, category, code) = match &error {
63 ComputerUseError::Mcp(_) => {
64 (ErrorComponent::Tool, ErrorCategory::Unavailable, "tool.computer_use.mcp")
65 }
66 ComputerUseError::Decode(_) => {
67 (ErrorComponent::Tool, ErrorCategory::InvalidInput, "tool.computer_use.decode")
68 }
69 ComputerUseError::IdentityMismatch(_) => {
70 (ErrorComponent::Auth, ErrorCategory::Forbidden, "auth.computer_use.identity")
71 }
72 ComputerUseError::InvalidRequest(_) => (
73 ErrorComponent::Tool,
74 ErrorCategory::InvalidInput,
75 "tool.computer_use.invalid_request",
76 ),
77 ComputerUseError::Unsupported { .. } => {
78 (ErrorComponent::Tool, ErrorCategory::Unsupported, "tool.computer_use.unsupported")
79 }
80 ComputerUseError::Runtime(_) => {
81 (ErrorComponent::Tool, ErrorCategory::Internal, "tool.computer_use.runtime")
82 }
83 };
84 AdkError::new(component, category, code, error.to_string())
85 }
86}