diff --git a/agent-client-protocol-schema/src/v1/client.rs b/agent-client-protocol-schema/src/v1/client.rs index 2c41319e..57909c68 100644 --- a/agent-client-protocol-schema/src/v1/client.rs +++ b/agent-client-protocol-schema/src/v1/client.rs @@ -2513,11 +2513,11 @@ pub enum ClientResponse { /// Successful result returned for a `mcp/disconnect` request. #[cfg(feature = "unstable_mcp_over_acp")] DisconnectMcpResponse(#[serde(default)] DisconnectMcpResponse), - /// Successful result returned by an extension method outside the core ACP method set. - ExtMethodResponse(ExtResponse), /// Successful result returned by an MCP-over-ACP `mcp/message` request. #[cfg(feature = "unstable_mcp_over_acp")] MessageMcpResponse(MessageMcpResponse), + /// Successful result returned by an extension method outside the core ACP method set. + ExtMethodResponse(ExtResponse), } /// All possible notifications that an agent can send to a client. diff --git a/agent-client-protocol-schema/src/v2/client.rs b/agent-client-protocol-schema/src/v2/client.rs index 4d2a1e60..c1cdf83c 100644 --- a/agent-client-protocol-schema/src/v2/client.rs +++ b/agent-client-protocol-schema/src/v2/client.rs @@ -48,7 +48,7 @@ use super::{ClientNesCapabilities, PositionEncodingKind}; #[schemars(extend("x-side" = "client", "x-method" = SESSION_UPDATE_NOTIFICATION))] #[serde(rename_all = "camelCase")] #[non_exhaustive] -pub struct SessionNotification { +pub struct UpdateSessionNotification { /// The ID of the session this update pertains to. pub session_id: SessionId, /// The actual update content. @@ -65,7 +65,7 @@ pub struct SessionNotification { pub meta: Option, } -impl SessionNotification { +impl UpdateSessionNotification { /// Builds [`SessionNotification`] with the required notification fields set; optional fields start unset or empty. #[must_use] pub fn new(session_id: impl Into, update: SessionUpdate) -> Self { @@ -743,13 +743,13 @@ impl Cost { #[serde(rename_all = "camelCase")] #[non_exhaustive] pub struct ContentChunk { - /// A single item of content - pub content: ContentBlock, /// A unique identifier for the message this chunk belongs to. /// /// All chunks belonging to the same message share the same `messageId`. /// A change in `messageId` indicates a new message has started. pub message_id: MessageId, + /// A single item of content + pub content: ContentBlock, /// The _meta property is reserved by ACP to allow clients and agents to attach additional /// metadata to their interactions. Implementations MUST NOT make assumptions about values at /// these keys. @@ -1424,7 +1424,6 @@ pub enum PermissionOptionKind { #[non_exhaustive] pub struct RequestPermissionResponse { /// The user's decision on the permission request. - // This extra-level is unfortunately needed because the output must be an object pub outcome: RequestPermissionOutcome, /// The _meta property is reserved by ACP to allow clients and agents to attach additional /// metadata to their interactions. Implementations MUST NOT make assumptions about values at @@ -1547,7 +1546,7 @@ pub struct ClientCapabilities { #[serde_as(deserialize_as = "DefaultOnError")] #[schemars(extend("x-deserialize-default-on-error" = true))] #[serde(default)] - pub auth: AuthCapabilities, + pub auth: Option, /// **UNSTABLE** /// /// This capability is not part of the spec yet, and may be removed or changed at any point. @@ -1608,8 +1607,8 @@ impl ClientCapabilities { /// in its `InitializeResponse`. #[cfg(feature = "unstable_auth_methods")] #[must_use] - pub fn auth(mut self, auth: AuthCapabilities) -> Self { - self.auth = auth; + pub fn auth(mut self, auth: impl IntoOption) -> Self { + self.auth = auth.into_option(); self } @@ -1926,11 +1925,11 @@ pub enum ClientResponse { /// Successful result returned for a `mcp/disconnect` request. #[cfg(feature = "unstable_mcp_over_acp")] DisconnectMcpResponse(#[serde(default)] DisconnectMcpResponse), - /// Successful result returned by an extension method outside the core ACP method set. - ExtMethodResponse(ExtResponse), /// Successful result returned by an MCP-over-ACP `mcp/message` request. #[cfg(feature = "unstable_mcp_over_acp")] MessageMcpResponse(MessageMcpResponse), + /// Successful result returned by an extension method outside the core ACP method set. + ExtMethodResponse(ExtResponse), } /// All possible notifications that an agent can send to a client. @@ -1956,7 +1955,7 @@ pub enum AgentNotification { /// stop reason. /// /// See protocol docs: [Agent Reports Output](https://agentclientprotocol.com/protocol/prompt-lifecycle#3-agent-reports-output) - SessionNotification(Box), + UpdateSessionNotification(Box), /// **UNSTABLE** /// /// This capability is not part of the spec yet, and may be removed or changed at any point. @@ -1986,7 +1985,7 @@ impl AgentNotification { #[must_use] pub fn method(&self) -> &str { match self { - Self::SessionNotification(_) => CLIENT_METHOD_NAMES.session_update, + Self::UpdateSessionNotification(_) => CLIENT_METHOD_NAMES.session_update, #[cfg(feature = "unstable_elicitation")] Self::CompleteElicitationNotification(_) => CLIENT_METHOD_NAMES.elicitation_complete, #[cfg(feature = "unstable_mcp_over_acp")] @@ -2010,7 +2009,7 @@ mod tests { })) .unwrap(); - assert_eq!(capabilities.auth, AuthCapabilities::default()); + assert_eq!(capabilities.auth, None); } #[test] diff --git a/agent-client-protocol-schema/src/v2/conversion.rs b/agent-client-protocol-schema/src/v2/conversion.rs index 7c8d8954..36bb4ef6 100644 --- a/agent-client-protocol-schema/src/v2/conversion.rs +++ b/agent-client-protocol-schema/src/v2/conversion.rs @@ -949,7 +949,7 @@ impl IntoV2 for crate::v1::ProtocolLevelNotification { } } -impl IntoV1Many for super::SessionNotification { +impl IntoV1Many for super::UpdateSessionNotification { type Output = crate::v1::SessionNotification; fn into_v1_many(self) -> Result> { @@ -975,7 +975,7 @@ impl IntoV1Many for super::SessionNotification { } impl IntoV2 for crate::v1::SessionNotification { - type Output = super::SessionNotification; + type Output = super::UpdateSessionNotification; fn into_v2(self) -> Result { let Self { @@ -983,7 +983,7 @@ impl IntoV2 for crate::v1::SessionNotification { update, meta, } = self; - Ok(super::SessionNotification { + Ok(super::UpdateSessionNotification { session_id: session_id.into_v2()?, update: update.into_v2()?, meta: meta.into_v2()?, @@ -1907,7 +1907,7 @@ impl IntoV1 for super::ClientCapabilities { #[cfg(feature = "unstable_plan_operations")] plan: None, #[cfg(feature = "unstable_auth_methods")] - auth: auth.into_v1()?, + auth: auth.map(IntoV1::into_v1).transpose()?.unwrap_or_default(), #[cfg(feature = "unstable_elicitation")] elicitation: into_v1_default_on_error(elicitation), #[cfg(feature = "unstable_nes")] @@ -1942,7 +1942,7 @@ impl IntoV2 for crate::v1::ClientCapabilities { } = self; Ok(super::ClientCapabilities { #[cfg(feature = "unstable_auth_methods")] - auth: auth.into_v2()?, + auth: Some(auth.into_v2()?), #[cfg(feature = "unstable_elicitation")] elicitation: into_v2_default_on_error(elicitation), #[cfg(feature = "unstable_nes")] @@ -2169,7 +2169,7 @@ impl IntoV1Many for super::AgentNotification { fn into_v1_many(self) -> Result> { Ok(match self { - Self::SessionNotification(value) => { + Self::UpdateSessionNotification(value) => { return value .into_v1_many()? .into_iter() @@ -2203,7 +2203,7 @@ impl IntoV2 for crate::v1::AgentNotification { fn into_v2(self) -> Result { Ok(match self { Self::SessionNotification(value) => { - super::AgentNotification::SessionNotification(Box::new(value.into_v2()?)) + super::AgentNotification::UpdateSessionNotification(Box::new(value.into_v2()?)) } #[cfg(feature = "unstable_elicitation")] Self::CompleteElicitationNotification(value) => { @@ -9641,7 +9641,7 @@ mod tests { for update in cases { let notification = v1::SessionNotification::new("sess", update); let original_json = serde_json::to_value(¬ification).expect("v1 serialize"); - let as_v2: v2::SessionNotification = + let as_v2: v2::UpdateSessionNotification = v1_to_v2(notification.clone()).expect("v1 -> v2 conversion"); let v2_json = serde_json::to_value(&as_v2).expect("v2 serialize"); assert_eq!( @@ -9665,7 +9665,8 @@ mod tests { "sess", v1::SessionUpdate::ToolCall(v1::ToolCall::new("tc", "title")), ); - let create_v2: v2::SessionNotification = v1_to_v2(create).expect("v1 -> v2 conversion"); + let create_v2: v2::UpdateSessionNotification = + v1_to_v2(create).expect("v1 -> v2 conversion"); assert!(matches!( create_v2.update, v2::SessionUpdate::ToolCallUpdate(_) @@ -9689,7 +9690,8 @@ mod tests { v1::ToolCallUpdateFields::new().status(v1::ToolCallStatus::Completed), )), ); - let update_v2: v2::SessionNotification = v1_to_v2(update).expect("v1 -> v2 conversion"); + let update_v2: v2::UpdateSessionNotification = + v1_to_v2(update).expect("v1 -> v2 conversion"); assert!(matches!( update_v2.update, v2::SessionUpdate::ToolCallUpdate(_) @@ -9765,7 +9767,7 @@ mod tests { #[test] fn v2_full_message_session_notification_fans_out_to_v1_chunk_notifications() { - let notification = v2::SessionNotification::new( + let notification = v2::UpdateSessionNotification::new( "sess", v2::SessionUpdate::AgentMessage(v2::AgentMessage::new("msg_agent").content(vec![ v2::ContentBlock::Text(v2::TextContent::new("hello")), @@ -9803,8 +9805,8 @@ mod tests { fn v2_json_rpc_agent_notification_fans_out_to_v1_chunk_notifications() { let message = v2::JsonRpcMessage::wrap(v2::Notification { method: "session/update".into(), - params: Some(v2::AgentNotification::SessionNotification(Box::new( - v2::SessionNotification::new( + params: Some(v2::AgentNotification::UpdateSessionNotification(Box::new( + v2::UpdateSessionNotification::new( "sess", v2::SessionUpdate::AgentMessage(v2::AgentMessage::new("msg_agent").content( vec![ diff --git a/docs/protocol/v2/draft/schema.mdx b/docs/protocol/v2/draft/schema.mdx index 21348c77..30c691b6 100644 --- a/docs/protocol/v2/draft/schema.mdx +++ b/docs/protocol/v2/draft/schema.mdx @@ -324,7 +324,7 @@ See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/v2/d ClientCapabilities} > Capabilities supported by the client. - - Default: `{"auth":{}}` + - Default: `{}` Implementation} required> @@ -2005,7 +2005,7 @@ stop reason. See protocol docs: [Agent Reports Output](https://agentclientprotocol.com/protocol/v2/draft/prompt-lifecycle#3-agent-reports-output) -#### SessionNotification +#### UpdateSessionNotification Notification containing a session update from the agent. @@ -2807,7 +2807,7 @@ these keys. See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/v2/draft/extensibility) -AuthCapabilities} > +AuthCapabilities | null} > **UNSTABLE** This capability is not part of the spec yet, and may be removed or changed at any point. @@ -2816,8 +2816,6 @@ Authentication capabilities supported by the client. Determines which authentication method types the agent may include in its `InitializeResponse`. - - Default: `{}` - ElicitationCapabilities | null} > **UNSTABLE** diff --git a/docs/protocol/v2/schema.mdx b/docs/protocol/v2/schema.mdx index d8446541..8ef59f4a 100644 --- a/docs/protocol/v2/schema.mdx +++ b/docs/protocol/v2/schema.mdx @@ -839,7 +839,7 @@ stop reason. See protocol docs: [Agent Reports Output](https://agentclientprotocol.com/protocol/v2/prompt-lifecycle#3-agent-reports-output) -#### SessionNotification +#### UpdateSessionNotification Notification containing a session update from the agent. diff --git a/schema-generator/src/main.rs b/schema-generator/src/main.rs index d0e24f95..51ea31d5 100644 --- a/schema-generator/src/main.rs +++ b/schema-generator/src/main.rs @@ -1915,7 +1915,11 @@ starting with '$/' it is free to ignore the notification." } "fs/write_text_file" => self.client.get("WriteTextFileRequest").unwrap(), "fs/read_text_file" => self.client.get("ReadTextFileRequest").unwrap(), - "session/update" => self.client.get("SessionNotification").unwrap(), + "session/update" => self + .client + .get("UpdateSessionNotification") + .or_else(|| self.client.get("SessionNotification")) + .unwrap(), "terminal/create" => self.client.get("CreateTerminalRequest").unwrap(), "terminal/output" => self.client.get("TerminalOutputRequest").unwrap(), "terminal/release" => self.client.get("ReleaseTerminalRequest").unwrap(), diff --git a/schema/v1/schema.unstable.json b/schema/v1/schema.unstable.json index 6b9174e5..cd608976 100644 --- a/schema/v1/schema.unstable.json +++ b/schema/v1/schema.unstable.json @@ -7746,20 +7746,20 @@ ] }, { - "title": "ExtMethodResponse", - "description": "Successful result returned by an extension method outside the core ACP method set.", + "title": "MessageMcpResponse", + "description": "Successful result returned by an MCP-over-ACP `mcp/message` request.", "allOf": [ { - "$ref": "#/$defs/ExtResponse" + "$ref": "#/$defs/MessageMcpResponse" } ] }, { - "title": "MessageMcpResponse", - "description": "Successful result returned by an MCP-over-ACP `mcp/message` request.", + "title": "ExtMethodResponse", + "description": "Successful result returned by an extension method outside the core ACP method set.", "allOf": [ { - "$ref": "#/$defs/MessageMcpResponse" + "$ref": "#/$defs/ExtResponse" } ] } diff --git a/schema/v2/schema.json b/schema/v2/schema.json index b5469539..ede20c7b 100644 --- a/schema/v2/schema.json +++ b/schema/v2/schema.json @@ -2685,11 +2685,11 @@ "description": "All possible notifications that an agent can send to a client.\n\nThis enum is used internally for routing RPC notifications. You typically won't need\nto use this directly.\n\nNotifications do not expect a response.", "anyOf": [ { - "title": "SessionNotification", + "title": "UpdateSessionNotification", "description": "Handles session update notifications from the agent.\n\nThis is a notification endpoint (no response expected) that receives\nreal-time updates about session progress, including message updates,\nmessage chunks, tool calls, and execution plans.\n\nNote: Clients SHOULD continue accepting tool call updates even after\nsending a `session/cancel` notification, as the agent may send final\nupdates before reporting an idle `state_update` with the cancelled\nstop reason.\n\nSee protocol docs: [Agent Reports Output](https://agentclientprotocol.com/protocol/v2/prompt-lifecycle#3-agent-reports-output)", "allOf": [ { - "$ref": "#/$defs/SessionNotification" + "$ref": "#/$defs/UpdateSessionNotification" } ] }, @@ -2713,7 +2713,7 @@ "required": ["method"], "x-docs-ignore": true }, - "SessionNotification": { + "UpdateSessionNotification": { "description": "Notification containing a session update from the agent.\n\nUsed to stream real-time progress and results during prompt processing.\n\nSee protocol docs: [Agent Reports Output](https://agentclientprotocol.com/protocol/v2/prompt-lifecycle#3-agent-reports-output)", "type": "object", "properties": { @@ -3141,19 +3141,19 @@ "description": "A streamed item of content", "type": "object", "properties": { - "content": { - "description": "A single item of content", + "messageId": { + "description": "A unique identifier for the message this chunk belongs to.\n\nAll chunks belonging to the same message share the same `messageId`.\nA change in `messageId` indicates a new message has started.", "allOf": [ { - "$ref": "#/$defs/ContentBlock" + "$ref": "#/$defs/MessageId" } ] }, - "messageId": { - "description": "A unique identifier for the message this chunk belongs to.\n\nAll chunks belonging to the same message share the same `messageId`.\nA change in `messageId` indicates a new message has started.", + "content": { + "description": "A single item of content", "allOf": [ { - "$ref": "#/$defs/MessageId" + "$ref": "#/$defs/ContentBlock" } ] }, @@ -3164,7 +3164,7 @@ "additionalProperties": true } }, - "required": ["content", "messageId"] + "required": ["messageId", "content"] }, "UserMessage": { "description": "A user message upsert.\n\nOnly [`UserMessage::message_id`] is required. Other fields have patch\nsemantics: omitted fields leave the existing message value unchanged, `null`\nclears or unsets the value, and concrete values replace the previous value.\nFor a new `messageId`, omitted fields use client defaults. `content` is\nreplaced as a whole array; send `[]` or `null` to clear it.\n\nMessage updates and chunks are applied in the order they are received. When\na `user_message` update includes `content`, that array replaces any content\npreviously accumulated for the message, including content from earlier\nchunks. Later chunks with the same `messageId` append to the current\ncontent.", diff --git a/schema/v2/schema.unstable.json b/schema/v2/schema.unstable.json index 0a827301..17297c6a 100644 --- a/schema/v2/schema.unstable.json +++ b/schema/v2/schema.unstable.json @@ -477,20 +477,20 @@ ] }, { - "title": "ExtMethodResponse", - "description": "Successful result returned by an extension method outside the core ACP method set.", + "title": "MessageMcpResponse", + "description": "Successful result returned by an MCP-over-ACP `mcp/message` request.", "allOf": [ { - "$ref": "#/$defs/ExtResponse" + "$ref": "#/$defs/MessageMcpResponse" } ] }, { - "title": "MessageMcpResponse", - "description": "Successful result returned by an MCP-over-ACP `mcp/message` request.", + "title": "ExtMethodResponse", + "description": "Successful result returned by an extension method outside the core ACP method set.", "allOf": [ { - "$ref": "#/$defs/MessageMcpResponse" + "$ref": "#/$defs/ExtResponse" } ] } @@ -5098,11 +5098,11 @@ "description": "All possible notifications that an agent can send to a client.\n\nThis enum is used internally for routing RPC notifications. You typically won't need\nto use this directly.\n\nNotifications do not expect a response.", "anyOf": [ { - "title": "SessionNotification", + "title": "UpdateSessionNotification", "description": "Handles session update notifications from the agent.\n\nThis is a notification endpoint (no response expected) that receives\nreal-time updates about session progress, including message updates,\nmessage chunks, tool calls, and execution plans.\n\nNote: Clients SHOULD continue accepting tool call updates even after\nsending a `session/cancel` notification, as the agent may send final\nupdates before reporting an idle `state_update` with the cancelled\nstop reason.\n\nSee protocol docs: [Agent Reports Output](https://agentclientprotocol.com/protocol/v2/draft/prompt-lifecycle#3-agent-reports-output)", "allOf": [ { - "$ref": "#/$defs/SessionNotification" + "$ref": "#/$defs/UpdateSessionNotification" } ] }, @@ -5144,7 +5144,7 @@ "required": ["method"], "x-docs-ignore": true }, - "SessionNotification": { + "UpdateSessionNotification": { "description": "Notification containing a session update from the agent.\n\nUsed to stream real-time progress and results during prompt processing.\n\nSee protocol docs: [Agent Reports Output](https://agentclientprotocol.com/protocol/v2/draft/prompt-lifecycle#3-agent-reports-output)", "type": "object", "properties": { @@ -5598,19 +5598,19 @@ "description": "A streamed item of content", "type": "object", "properties": { - "content": { - "description": "A single item of content", + "messageId": { + "description": "A unique identifier for the message this chunk belongs to.\n\nAll chunks belonging to the same message share the same `messageId`.\nA change in `messageId` indicates a new message has started.", "allOf": [ { - "$ref": "#/$defs/ContentBlock" + "$ref": "#/$defs/MessageId" } ] }, - "messageId": { - "description": "A unique identifier for the message this chunk belongs to.\n\nAll chunks belonging to the same message share the same `messageId`.\nA change in `messageId` indicates a new message has started.", + "content": { + "description": "A single item of content", "allOf": [ { - "$ref": "#/$defs/MessageId" + "$ref": "#/$defs/ContentBlock" } ] }, @@ -5621,7 +5621,7 @@ "additionalProperties": true } }, - "required": ["content", "messageId"] + "required": ["messageId", "content"] }, "UserMessage": { "description": "A user message upsert.\n\nOnly [`UserMessage::message_id`] is required. Other fields have patch\nsemantics: omitted fields leave the existing message value unchanged, `null`\nclears or unsets the value, and concrete values replace the previous value.\nFor a new `messageId`, omitted fields use client defaults. `content` is\nreplaced as a whole array; send `[]` or `null` to clear it.\n\nMessage updates and chunks are applied in the order they are received. When\na `user_message` update includes `content`, that array replaces any content\npreviously accumulated for the message, including content from earlier\nchunks. Later chunks with the same `messageId` append to the current\ncontent.", @@ -6813,9 +6813,7 @@ "capabilities": { "description": "Capabilities supported by the client.", "x-deserialize-default-on-error": true, - "default": { - "auth": {} - }, + "default": {}, "allOf": [ { "$ref": "#/$defs/ClientCapabilities" @@ -6839,13 +6837,15 @@ "properties": { "auth": { "description": "**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nAuthentication capabilities supported by the client.\nDetermines which authentication method types the agent may include\nin its `InitializeResponse`.", - "x-deserialize-default-on-error": true, - "default": {}, - "allOf": [ + "anyOf": [ { "$ref": "#/$defs/AuthCapabilities" + }, + { + "type": "null" } - ] + ], + "x-deserialize-default-on-error": true }, "elicitation": { "description": "**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nElicitation capabilities supported by the client.\nDetermines which elicitation modes the agent may use.", @@ -8304,20 +8304,20 @@ ] }, { - "title": "ExtMethodResponse", - "description": "Successful result returned by an extension method outside the core ACP method set.", + "title": "MessageMcpResponse", + "description": "Successful result returned by an MCP-over-ACP `mcp/message` request.", "allOf": [ { - "$ref": "#/$defs/ExtResponse" + "$ref": "#/$defs/MessageMcpResponse" } ] }, { - "title": "MessageMcpResponse", - "description": "Successful result returned by an MCP-over-ACP `mcp/message` request.", + "title": "ExtMethodResponse", + "description": "Successful result returned by an extension method outside the core ACP method set.", "allOf": [ { - "$ref": "#/$defs/MessageMcpResponse" + "$ref": "#/$defs/ExtResponse" } ] }