Skip to main content

ahp_types/
lib.rs

1//! Wire protocol types for the [Agent Host Protocol (AHP)][spec].
2//!
3//! `ahp-types` is the data-only crate of the AHP family. Every command,
4//! action, notification, and state object defined by the protocol has a
5//! Rust counterpart here — `Serialize` + `Deserialize`, using the exact
6//! same JSON field names as the wire format. There is no I/O, no async
7//! runtime, and no transport code; if you only need to parse or
8//! construct AHP messages, this is the only crate you need.
9//!
10//! These types are generated from the TypeScript source of truth in
11//! `types/*.ts`, so any change to the protocol surfaces here first.
12//!
13//! [spec]: https://microsoft.github.io/agent-host-protocol/
14//!
15//! # Companion crates
16//!
17//! | Crate | What it adds |
18//! |---|---|
19//! | [`ahp`](https://docs.rs/ahp) | Async client, reducers, and pluggable [`Transport`](https://docs.rs/ahp/latest/ahp/transport/trait.Transport.html) trait |
20//! | [`ahp-ws`](https://docs.rs/ahp-ws) | WebSocket transport built on `tokio-tungstenite` |
21//!
22//! # Module map
23//!
24//! | Module | Contents |
25//! |---|---|
26//! | [`state`]         | [`RootState`], [`SessionState`], [`TerminalState`], tool-call lifecycle |
27//! | [`actions`]       | [`StateAction`] discriminated union and [`ActionEnvelope`] |
28//! | [`commands`]      | Request/response parameter and result types (`initialize`, `subscribe`, …) |
29//! | [`notifications`] | Server-pushed protocol notification params ([`SessionAddedParams`], [`AuthRequiredParams`], …) |
30//! | [`messages`]      | JSON-RPC wire envelopes ([`JsonRpcMessage`] and friends) |
31//! | [`errors`]        | AHP and JSON-RPC [error codes][errors::AhpErrorCode] |
32//! | [`version`]       | Negotiation constants ([`PROTOCOL_VERSION`]) |
33//! | [`common`]        | Hand-written primitives ([`Uri`], [`StringOrMarkdown`], …) |
34//!
35//! # Examples
36//!
37//! ## Parse an action envelope
38//!
39//! ```
40//! use ahp_types::actions::{ActionEnvelope, StateAction};
41//!
42//! let json = r#"{
43//!   "channel": "ahp-session:/s1",
44//!   "action": { "type": "session/titleChanged", "title": "Hi" },
45//!   "serverSeq": 7,
46//!   "origin": null
47//! }"#;
48//! let env: ActionEnvelope = serde_json::from_str(json)?;
49//! assert_eq!(env.server_seq, 7);
50//! assert_eq!(env.channel, "ahp-session:/s1");
51//! match env.action {
52//!     StateAction::SessionTitleChanged(a) => assert_eq!(a.title, "Hi"),
53//!     _ => panic!("unexpected variant"),
54//! }
55//! # Ok::<_, serde_json::Error>(())
56//! ```
57//!
58//! ## Build an `initialize` request
59//!
60//! ```
61//! use ahp_types::commands::InitializeParams;
62//! use ahp_types::messages::{JsonRpcMessage, JsonRpcRequest, JsonRpcVersion};
63//! use ahp_types::common::AnyValue;
64//!
65//! let params = InitializeParams {
66//!     channel: "ahp-root://".into(),
67//!     protocol_versions: vec![ahp_types::PROTOCOL_VERSION.to_string()],
68//!     client_id: "my-host/1.0".into(),
69//!     initial_subscriptions: Some(vec!["ahp-root://".into()]),
70//!     locale: Some("en".into()),
71//! };
72//!
73//! let req = JsonRpcMessage::Request(JsonRpcRequest {
74//!     jsonrpc: JsonRpcVersion::V2,
75//!     id: 1,
76//!     method: "initialize".into(),
77//!     params: Some(AnyValue::from(serde_json::to_value(&params)?)),
78//! });
79//!
80//! let wire = serde_json::to_string(&req)?;
81//! assert!(wire.contains("\"method\":\"initialize\""));
82//! # Ok::<_, serde_json::Error>(())
83//! ```
84//!
85//! ## Inspect a session status bitset
86//!
87//! [`SessionStatus`](state::SessionStatus) packs activity and metadata
88//! flags into a single value — use bitwise checks rather than equality:
89//!
90//! ```
91//! use ahp_types::state::SessionStatus;
92//!
93//! let status = SessionStatus::InProgress as u32 | SessionStatus::IsArchived as u32;
94//! assert_ne!(status & SessionStatus::InProgress as u32, 0);
95//! assert_ne!(status & SessionStatus::IsArchived as u32, 0);
96//! ```
97//!
98//! # Compatibility
99//!
100//! - JSON field names match the protocol exactly (`camelCase`); use the
101//!   provided `Serialize`/`Deserialize` derives rather than manually
102//!   building JSON.
103//! - Unknown enum variants surface as a generic `Unknown` arm where the
104//!   protocol allows forward-compatible extension (see e.g.
105//!   [`state::ToolCallState`]).
106//! - The protocol version this crate speaks is exposed as
107//!   [`PROTOCOL_VERSION`].
108
109#![forbid(unsafe_code)]
110#![warn(missing_docs)]
111#![cfg_attr(docsrs, feature(doc_cfg))]
112
113pub mod actions;
114pub mod commands;
115pub mod common;
116pub mod errors;
117pub mod messages;
118pub mod notifications;
119pub mod state;
120pub mod version;
121
122pub use actions::{ActionEnvelope, ActionOrigin, ActionType, StateAction};
123pub use common::{StringOrMarkdown, Uri, ROOT_RESOURCE_URI};
124pub use errors::{AhpErrorCode, JsonRpcErrorCode};
125pub use messages::{JsonRpcError, JsonRpcErrorResponse, JsonRpcMessage};
126pub use notifications::{
127    AuthRequiredParams, SessionAddedParams, SessionRemovedParams, SessionSummaryChangedParams,
128};
129pub use state::{Icon, ProtectedResourceMetadata, RootState, SessionState, TerminalState};
130pub use version::{PROTOCOL_VERSION, SUPPORTED_PROTOCOL_VERSIONS};