Skip to main content

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}