zeph_acp/client/error.rs
1// SPDX-FileCopyrightText: 2026 Andrei G <bug-ops>
2// SPDX-License-Identifier: MIT OR Apache-2.0
3
4use thiserror::Error;
5
6/// Step in the ACP handshake sequence at which a failure occurred.
7#[derive(Debug, Clone, PartialEq, Eq)]
8#[non_exhaustive]
9pub enum HandshakeStep {
10 /// The `initialize` request round-trip failed.
11 Initialize,
12 /// The `session/new` request round-trip failed.
13 NewSession,
14}
15
16impl std::fmt::Display for HandshakeStep {
17 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
18 match self {
19 Self::Initialize => f.write_str("initialize"),
20 Self::NewSession => f.write_str("session/new"),
21 }
22 }
23}
24
25/// Errors returned by the ACP sub-agent client.
26#[derive(Debug, Error)]
27#[non_exhaustive]
28pub enum AcpClientError {
29 /// The command string was empty or could not be shell-split.
30 #[error("invalid command config: {0}")]
31 InvalidConfig(String),
32
33 /// The subprocess failed to spawn.
34 #[error("failed to spawn subprocess: {0}")]
35 Spawn(#[source] std::io::Error),
36
37 /// The ACP handshake failed at the named step.
38 #[error("handshake failed at {step}: {source}")]
39 Handshake {
40 /// Which handshake step failed.
41 step: HandshakeStep,
42 /// The underlying protocol error.
43 #[source]
44 source: agent_client_protocol::Error,
45 },
46
47 /// The prompt or notification could not be sent to the sub-agent.
48 #[error("failed to send to sub-agent: {0}")]
49 SendFailed(#[source] agent_client_protocol::Error),
50
51 /// A second command was sent while the driver was already servicing a read.
52 ///
53 /// The caller should wait for the in-flight operation to complete before retrying.
54 #[error("driver is busy servicing another read operation")]
55 DriverBusy,
56
57 /// The driver task exited unexpectedly before the operation could complete.
58 ///
59 /// This usually means the subprocess crashed or the transport was closed.
60 #[error("driver task exited unexpectedly")]
61 DriverDied,
62
63 /// The operation timed out.
64 #[error("operation timed out")]
65 Timeout,
66
67 /// The session was closed by a call to [`super::SubagentHandle::close`] or via
68 /// a `SubagentCommand::Close` command.
69 #[error("session is closed")]
70 Closed,
71
72 /// A cancel was requested and the sub-agent acknowledged it by returning a
73 /// `StopReason::Cancelled` update.
74 #[error("operation cancelled")]
75 Cancelled,
76
77 /// Underlying SDK/protocol error not covered by the variants above.
78 #[error("ACP SDK error: {0}")]
79 Sdk(#[source] agent_client_protocol::Error),
80}