Skip to main content

a2a_protocol_types/
lib.rs

1// SPDX-License-Identifier: Apache-2.0
2// Copyright 2026 Tom F.
3
4//! A2A protocol v1.0 — pure data types with serde support.
5//!
6//! This crate provides all wire types for the A2A protocol with zero I/O
7//! dependencies. Add `a2a-client` or `a2a-server` for HTTP transport.
8//!
9//! # Module overview
10//!
11//! | Module | Contents |
12//! |---|---|
13//! | [`error`] | [`error::A2aError`], [`error::ErrorCode`], [`error::A2aResult`] |
14//! | [`task`] | [`task::Task`], [`task::TaskStatus`], [`task::TaskState`], ID newtypes |
15//! | [`message`] | [`message::Message`], [`message::Part`], [`message::PartContent`] |
16//! | [`artifact`] | [`artifact::Artifact`], [`artifact::ArtifactId`] |
17//! | [`agent_card`] | [`agent_card::AgentCard`], capabilities, skills |
18//! | [`security`] | [`security::SecurityScheme`] variants, OAuth flows |
19//! | [`events`] | [`events::StreamResponse`], status/artifact update events |
20//! | [`jsonrpc`] | [`jsonrpc::JsonRpcRequest`], [`jsonrpc::JsonRpcResponse`] |
21//! | [`params`] | Method parameter structs |
22//! | [`push`] | [`push::TaskPushNotificationConfig`] |
23//! | [`extensions`] | [`extensions::AgentExtension`], [`extensions::AgentCardSignature`] |
24//! | [`responses`] | [`responses::SendMessageResponse`], [`responses::TaskListResponse`] |
25
26#![deny(missing_docs)]
27#![deny(unsafe_op_in_unsafe_fn)]
28#![warn(clippy::all, clippy::pedantic, clippy::nursery)]
29#![allow(clippy::module_name_repetitions)]
30
31// ── Protocol constants ────────────────────────────────────────────────────────
32
33/// A2A protocol version string.
34pub const A2A_VERSION: &str = "1.0.0";
35
36/// A2A-specific content type for JSON payloads.
37pub const A2A_CONTENT_TYPE: &str = "application/a2a+json";
38
39/// HTTP header name for the A2A protocol version.
40pub const A2A_VERSION_HEADER: &str = "A2A-Version";
41
42pub mod agent_card;
43pub mod artifact;
44pub mod error;
45pub mod events;
46pub mod extensions;
47pub mod jsonrpc;
48pub mod message;
49pub mod params;
50pub mod push;
51pub mod responses;
52pub mod security;
53#[cfg(feature = "signing")]
54pub mod signing;
55pub mod task;
56
57// ── Flat re-exports ───────────────────────────────────────────────────────────
58
59pub use agent_card::{AgentCapabilities, AgentCard, AgentInterface, AgentProvider, AgentSkill};
60pub use artifact::{Artifact, ArtifactId};
61pub use error::{A2aError, A2aResult, ErrorCode};
62pub use events::{StreamResponse, TaskArtifactUpdateEvent, TaskStatusUpdateEvent};
63pub use extensions::{AgentCardSignature, AgentExtension};
64pub use jsonrpc::{
65    JsonRpcError, JsonRpcErrorResponse, JsonRpcId, JsonRpcRequest, JsonRpcResponse,
66    JsonRpcSuccessResponse, JsonRpcVersion,
67};
68pub use message::{Message, MessageId, MessageRole, Part, PartContent};
69pub use params::{
70    CancelTaskParams, DeletePushConfigParams, GetExtendedAgentCardParams, GetPushConfigParams,
71    ListPushConfigsParams, ListTasksParams, MessageSendParams, SendMessageConfiguration,
72    TaskIdParams, TaskQueryParams,
73};
74pub use push::{AuthenticationInfo, TaskPushNotificationConfig};
75pub use responses::{
76    AuthenticatedExtendedCardResponse, ListPushConfigsResponse, SendMessageResponse,
77    TaskListResponse,
78};
79pub use security::{
80    ApiKeyLocation, ApiKeySecurityScheme, AuthorizationCodeFlow, ClientCredentialsFlow,
81    DeviceCodeFlow, HttpAuthSecurityScheme, ImplicitFlow, MutualTlsSecurityScheme,
82    NamedSecuritySchemes, OAuth2SecurityScheme, OAuthFlows, OpenIdConnectSecurityScheme,
83    PasswordOAuthFlow, SecurityRequirement, SecurityScheme, StringList,
84};
85pub use task::{ContextId, Task, TaskId, TaskState, TaskStatus, TaskVersion};
86
87// ── Utilities ─────────────────────────────────────────────────────────────
88
89/// Returns the current UTC time as an ISO 8601 string (e.g. `"2026-03-15T12:00:00Z"`).
90///
91/// Uses [`std::time::SystemTime`] — no external dependency required.
92#[must_use]
93pub fn utc_now_iso8601() -> String {
94    use std::time::{SystemTime, UNIX_EPOCH};
95    let secs = SystemTime::now()
96        .duration_since(UNIX_EPOCH)
97        .unwrap_or_default()
98        .as_secs();
99    // Decompose seconds into y/m/d H:M:S — simplified UTC-only implementation.
100    let (y, m, d, hh, mm, ss) = secs_to_ymd_hms(secs);
101    format!("{y:04}-{m:02}-{d:02}T{hh:02}:{mm:02}:{ss:02}Z")
102}
103
104/// Converts UNIX epoch seconds to (year, month, day, hour, minute, second).
105const fn secs_to_ymd_hms(epoch: u64) -> (u64, u64, u64, u64, u64, u64) {
106    let secs_per_day = 86400_u64;
107    let mut days = epoch / secs_per_day;
108    let time_of_day = epoch % secs_per_day;
109    let hh = time_of_day / 3600;
110    let mm = (time_of_day % 3600) / 60;
111    let ss = time_of_day % 60;
112
113    // Civil date from day count (days since 1970-01-01).
114    // Algorithm from Howard Hinnant.
115    days += 719_468;
116    let era = days / 146_097;
117    let doe = days - era * 146_097;
118    let yoe = (doe - doe / 1460 + doe / 36524 - doe / 146_096) / 365;
119    let y = yoe + era * 400;
120    let doy = doe - (365 * yoe + yoe / 4 - yoe / 100);
121    let mp = (5 * doy + 2) / 153;
122    let d = doy - (153 * mp + 2) / 5 + 1;
123    let m = if mp < 10 { mp + 3 } else { mp - 9 };
124    let y = if m <= 2 { y + 1 } else { y };
125    (y, m, d, hh, mm, ss)
126}