From 9e4907d5c6c86e0acdbb5d47f4a18ae351ffb2aa Mon Sep 17 00:00:00 2001 From: Ben Brandt Date: Mon, 6 Jul 2026 11:30:13 +0200 Subject: [PATCH] feat(schema): Stabilize boolean session config options Removes the unstable_boolean_config feature gate and moves the Boolean Config Option Type RFD to Completed. Boolean config options and the v1 session.configOptions.boolean client capability are now part of the stable protocol artifacts for both v1 and v2. --- agent-client-protocol-schema/Cargo.toml | 2 - agent-client-protocol-schema/src/v1/agent.rs | 68 +------ agent-client-protocol-schema/src/v1/client.rs | 29 --- agent-client-protocol-schema/src/v2/agent.rs | 92 +-------- .../src/v2/conversion.rs | 27 +-- docs/docs.json | 5 +- docs/protocol/v1/draft/initialization.mdx | 2 +- docs/protocol/v1/draft/schema.mdx | 26 +-- docs/protocol/v1/initialization.mdx | 15 ++ docs/protocol/v1/schema.mdx | 180 +++++++++++++++++- docs/protocol/v1/session-config-options.mdx | 74 ++++++- docs/protocol/v2/draft/schema.mdx | 8 - .../v2/draft/session-config-options.mdx | 6 +- docs/protocol/v2/schema.mdx | 92 ++++++++- docs/protocol/v2/session-config-options.mdx | 62 +++++- docs/rfds/boolean-config-option.mdx | 5 +- docs/rfds/updates.mdx | 7 + schema/v1/schema.json | 142 +++++++++++++- schema/v1/schema.unstable.json | 12 +- schema/v2/schema.json | 126 +++++++++++- schema/v2/schema.unstable.json | 4 +- 21 files changed, 682 insertions(+), 302 deletions(-) diff --git a/agent-client-protocol-schema/Cargo.toml b/agent-client-protocol-schema/Cargo.toml index 16e204b09..c50d7d2ad 100644 --- a/agent-client-protocol-schema/Cargo.toml +++ b/agent-client-protocol-schema/Cargo.toml @@ -31,7 +31,6 @@ unstable = [ "unstable_plan_operations", "unstable_session_fork", "unstable_end_turn_token_usage", - "unstable_boolean_config", ] # Protocol v2 is intentionally NOT part of the `unstable` umbrella. # It introduces a parallel `v2` module and (eventually) a different wire @@ -45,7 +44,6 @@ unstable_nes = [] unstable_plan_operations = [] unstable_session_fork = [] unstable_end_turn_token_usage = [] -unstable_boolean_config = [] # Emit `tracing::warn!` events when `VecSkipError` drops a malformed list # entry during deserialization. When disabled (the default), the inspector diff --git a/agent-client-protocol-schema/src/v1/agent.rs b/agent-client-protocol-schema/src/v1/agent.rs index 4c140007f..3a1bf7929 100644 --- a/agent-client-protocol-schema/src/v1/agent.rs +++ b/agent-client-protocol-schema/src/v1/agent.rs @@ -2448,12 +2448,7 @@ impl SessionConfigSelect { } } -/// **UNSTABLE** -/// -/// This capability is not part of the spec yet, and may be removed or changed at any point. -/// /// A boolean on/off toggle session configuration option payload. -#[cfg(feature = "unstable_boolean_config")] #[skip_serializing_none] #[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)] #[serde(rename_all = "camelCase")] @@ -2463,7 +2458,6 @@ pub struct SessionConfigBoolean { pub current_value: bool, } -#[cfg(feature = "unstable_boolean_config")] impl SessionConfigBoolean { /// Builds [`SessionConfigBoolean`] with the required fields set; optional fields start unset or empty. #[must_use] @@ -2506,12 +2500,7 @@ pub enum SessionConfigOptionCategory { pub enum SessionConfigKind { /// Single-value selector (dropdown). Select(SessionConfigSelect), - /// **UNSTABLE** - /// - /// This capability is not part of the spec yet, and may be removed or changed at any point. - /// /// Boolean on/off toggle. - #[cfg(feature = "unstable_boolean_config")] Boolean(SessionConfigBoolean), } @@ -2584,10 +2573,7 @@ impl SessionConfigOption { ) } - /// **UNSTABLE** - /// - /// This capability is not part of the spec yet, and may be removed or changed at any point. - #[cfg(feature = "unstable_boolean_config")] + /// Builds a boolean-style session configuration option with its current value. #[must_use] pub fn boolean( id: impl Into, @@ -2627,10 +2613,6 @@ impl SessionConfigOption { } } -/// **UNSTABLE** -/// -/// This capability is not part of the spec yet, and may be removed or changed at any point. -/// /// The value to set for a session configuration option. /// /// The `type` field acts as the discriminator in the serialized JSON form. @@ -2641,7 +2623,6 @@ impl SessionConfigOption { /// kind. For example every option kind that picks from a list of ids /// (`select`, `radio`, …) would use [`ValueId`](Self::ValueId), while a /// future freeform text option would get its own variant. -#[cfg(feature = "unstable_boolean_config")] #[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)] #[serde(tag = "type", rename_all = "snake_case")] #[non_exhaustive] @@ -2663,7 +2644,6 @@ pub enum SessionConfigOptionValue { }, } -#[cfg(feature = "unstable_boolean_config")] impl SessionConfigOptionValue { /// Create a value-id option value (used by `select` and other id-based option types). #[must_use] @@ -2697,21 +2677,18 @@ impl SessionConfigOptionValue { } } -#[cfg(feature = "unstable_boolean_config")] impl From for SessionConfigOptionValue { fn from(value: SessionConfigValueId) -> Self { Self::ValueId { value } } } -#[cfg(feature = "unstable_boolean_config")] impl From for SessionConfigOptionValue { fn from(value: bool) -> Self { Self::Boolean { value } } } -#[cfg(feature = "unstable_boolean_config")] impl From<&str> for SessionConfigOptionValue { fn from(value: &str) -> Self { Self::ValueId { @@ -2736,12 +2713,8 @@ pub struct SetSessionConfigOptionRequest { /// /// When `type` is absent on the wire, defaults to treating the value as a /// [`SessionConfigValueId`] for `select` options. - #[cfg(feature = "unstable_boolean_config")] #[serde(flatten)] pub value: SessionConfigOptionValue, - /// The ID of the configuration option value to set. - #[cfg(not(feature = "unstable_boolean_config"))] - pub value: SessionConfigValueId, /// 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. @@ -2756,7 +2729,6 @@ pub struct SetSessionConfigOptionRequest { impl SetSessionConfigOptionRequest { /// Builds [`SetSessionConfigOptionRequest`] with the required request fields set; optional fields start unset or empty. - #[cfg(feature = "unstable_boolean_config")] #[must_use] pub fn new( session_id: impl Into, @@ -2771,23 +2743,6 @@ impl SetSessionConfigOptionRequest { } } - /// Builds a select-value `session/set_config_option` request for crates built - /// without boolean session configuration support. - #[cfg(not(feature = "unstable_boolean_config"))] - #[must_use] - pub fn new( - session_id: impl Into, - config_id: impl Into, - value: impl Into, - ) -> Self { - Self { - session_id: session_id.into(), - config_id: config_id.into(), - value: value.into(), - meta: None, - } - } - /// 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. @@ -5401,12 +5356,10 @@ mod test_serialization { use super::*; use serde_json::json; - #[cfg(feature = "unstable_boolean_config")] fn test_meta() -> Meta { json!({ "source": "test" }).as_object().unwrap().clone() } - #[cfg(feature = "unstable_boolean_config")] fn serialized_meta_key_count(value: &impl serde::Serialize) -> usize { serde_json::to_string(value) .unwrap() @@ -6116,7 +6069,6 @@ mod test_serialization { } } - #[cfg(feature = "unstable_boolean_config")] #[test] fn test_session_config_option_value_id_serialize() { let val = SessionConfigOptionValue::value_id("model-1"); @@ -6126,7 +6078,6 @@ mod test_serialization { assert!(!json.as_object().unwrap().contains_key("type")); } - #[cfg(feature = "unstable_boolean_config")] #[test] fn test_session_config_option_value_boolean_serialize() { let val = SessionConfigOptionValue::boolean(true); @@ -6134,7 +6085,6 @@ mod test_serialization { assert_eq!(json, json!({ "type": "boolean", "value": true })); } - #[cfg(feature = "unstable_boolean_config")] #[test] fn test_session_config_option_value_deserialize_no_type() { // Missing "type" should default to ValueId @@ -6144,7 +6094,6 @@ mod test_serialization { assert_eq!(val.as_value_id().unwrap().to_string(), "model-1"); } - #[cfg(feature = "unstable_boolean_config")] #[test] fn test_session_config_option_value_deserialize_boolean() { let json = json!({ "type": "boolean", "value": true }); @@ -6153,7 +6102,6 @@ mod test_serialization { assert_eq!(val.as_bool(), Some(true)); } - #[cfg(feature = "unstable_boolean_config")] #[test] fn test_session_config_option_value_deserialize_boolean_false() { let json = json!({ "type": "boolean", "value": false }); @@ -6162,7 +6110,6 @@ mod test_serialization { assert_eq!(val.as_bool(), Some(false)); } - #[cfg(feature = "unstable_boolean_config")] #[test] fn test_session_config_option_value_deserialize_unknown_type_with_string_value() { // Unknown type with a string value gracefully falls back to ValueId @@ -6171,7 +6118,6 @@ mod test_serialization { assert_eq!(val.as_value_id().unwrap().to_string(), "freeform input"); } - #[cfg(feature = "unstable_boolean_config")] #[test] fn test_session_config_option_value_roundtrip_value_id() { let original = SessionConfigOptionValue::value_id("option-a"); @@ -6180,7 +6126,6 @@ mod test_serialization { assert_eq!(original, roundtripped); } - #[cfg(feature = "unstable_boolean_config")] #[test] fn test_session_config_option_value_roundtrip_boolean() { let original = SessionConfigOptionValue::boolean(false); @@ -6189,7 +6134,6 @@ mod test_serialization { assert_eq!(original, roundtripped); } - #[cfg(feature = "unstable_boolean_config")] #[test] fn test_session_config_option_value_type_mismatch_boolean_with_string() { // type says "boolean" but value is a string — falls to untagged ValueId @@ -6203,7 +6147,6 @@ mod test_serialization { ); } - #[cfg(feature = "unstable_boolean_config")] #[test] fn test_session_config_option_value_from_impls() { let from_str: SessionConfigOptionValue = "model-1".into(); @@ -6216,7 +6159,6 @@ mod test_serialization { assert_eq!(from_bool.as_bool(), Some(true)); } - #[cfg(feature = "unstable_boolean_config")] #[test] fn test_set_session_config_option_request_value_id() { let req = SetSessionConfigOptionRequest::new("sess_1", "model", "model-1"); @@ -6233,7 +6175,6 @@ mod test_serialization { assert!(!json.as_object().unwrap().contains_key("type")); } - #[cfg(feature = "unstable_boolean_config")] #[test] fn test_set_session_config_option_request_boolean() { let req = SetSessionConfigOptionRequest::new("sess_1", "brave_mode", true); @@ -6249,7 +6190,6 @@ mod test_serialization { ); } - #[cfg(feature = "unstable_boolean_config")] #[test] fn test_set_session_config_option_request_deserialize_no_type() { // Backwards-compatible: no "type" field → value_id @@ -6264,7 +6204,6 @@ mod test_serialization { assert_eq!(req.value.as_value_id().unwrap().to_string(), "model-1"); } - #[cfg(feature = "unstable_boolean_config")] #[test] fn test_set_session_config_option_request_deserialize_boolean() { let json = json!({ @@ -6277,7 +6216,6 @@ mod test_serialization { assert_eq!(req.value.as_bool(), Some(true)); } - #[cfg(feature = "unstable_boolean_config")] #[test] fn test_set_session_config_option_request_roundtrip_value_id() { let original = SetSessionConfigOptionRequest::new("s", "c", "v"); @@ -6286,7 +6224,6 @@ mod test_serialization { assert_eq!(original, roundtripped); } - #[cfg(feature = "unstable_boolean_config")] #[test] fn test_set_session_config_option_request_roundtrip_boolean() { let original = SetSessionConfigOptionRequest::new("s", "c", false); @@ -6295,7 +6232,6 @@ mod test_serialization { assert_eq!(original, roundtripped); } - #[cfg(feature = "unstable_boolean_config")] #[test] fn test_session_config_boolean_serialization() { let cfg = SessionConfigBoolean::new(true); @@ -6306,7 +6242,6 @@ mod test_serialization { assert!(deserialized.current_value); } - #[cfg(feature = "unstable_boolean_config")] #[test] fn test_session_config_option_boolean_variant() { let opt = SessionConfigOption::boolean("brave_mode", "Brave Mode", false) @@ -6338,7 +6273,6 @@ mod test_serialization { } } - #[cfg(feature = "unstable_boolean_config")] #[test] fn test_session_config_option_select_still_works() { // Make sure existing select options are unaffected diff --git a/agent-client-protocol-schema/src/v1/client.rs b/agent-client-protocol-schema/src/v1/client.rs index 2846c3416..a4261d707 100644 --- a/agent-client-protocol-schema/src/v1/client.rs +++ b/agent-client-protocol-schema/src/v1/client.rs @@ -1739,15 +1739,10 @@ pub struct ClientCapabilities { #[schemars(extend("x-deserialize-default-on-error" = true))] #[serde(default)] pub terminal: bool, - /// **UNSTABLE** - /// - /// This capability is not part of the spec yet, and may be removed or changed at any point. - /// /// Session-related capabilities supported by the client. /// /// Optional. Omitted or `null` both mean the client does not advertise any /// session-related extensions. - #[cfg(feature = "unstable_boolean_config")] #[serde_as(deserialize_as = "DefaultOnError")] #[schemars(extend("x-deserialize-default-on-error" = true))] #[serde(default)] @@ -1849,12 +1844,7 @@ impl ClientCapabilities { self } - /// **UNSTABLE** - /// - /// This capability is not part of the spec yet, and may be removed or changed at any point. - /// /// Session-related capabilities supported by the client. - #[cfg(feature = "unstable_boolean_config")] #[must_use] pub fn session(mut self, session: impl IntoOption) -> Self { self.session = session.into_option(); @@ -1935,12 +1925,7 @@ impl ClientCapabilities { } } -/// **UNSTABLE** -/// -/// This capability is not part of the spec yet, and may be removed or changed at any point. -/// /// Session-related capabilities supported by the client. -#[cfg(feature = "unstable_boolean_config")] #[serde_as] #[skip_serializing_none] #[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)] @@ -1967,7 +1952,6 @@ pub struct ClientSessionCapabilities { pub meta: Option, } -#[cfg(feature = "unstable_boolean_config")] impl ClientSessionCapabilities { /// Builds an empty [`ClientSessionCapabilities`]; use builder methods to advertise supported sub-capabilities. #[must_use] @@ -2000,12 +1984,7 @@ impl ClientSessionCapabilities { } } -/// **UNSTABLE** -/// -/// This capability is not part of the spec yet, and may be removed or changed at any point. -/// /// Session configuration option capabilities supported by the client. -#[cfg(feature = "unstable_boolean_config")] #[serde_as] #[skip_serializing_none] #[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)] @@ -2034,7 +2013,6 @@ pub struct SessionConfigOptionsCapabilities { pub meta: Option, } -#[cfg(feature = "unstable_boolean_config")] impl SessionConfigOptionsCapabilities { /// Builds an empty [`SessionConfigOptionsCapabilities`]; use builder methods to advertise supported sub-capabilities. #[must_use] @@ -2066,14 +2044,9 @@ impl SessionConfigOptionsCapabilities { } } -/// **UNSTABLE** -/// -/// This capability is not part of the spec yet, and may be removed or changed at any point. -/// /// Capabilities for boolean session configuration options. /// /// Supplying `{}` means the client supports boolean session configuration options. -#[cfg(feature = "unstable_boolean_config")] #[serde_as] #[skip_serializing_none] #[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)] @@ -2091,7 +2064,6 @@ pub struct BooleanConfigOptionCapabilities { pub meta: Option, } -#[cfg(feature = "unstable_boolean_config")] impl BooleanConfigOptionCapabilities { /// Builds an empty [`BooleanConfigOptionCapabilities`]; use builder methods to advertise supported sub-capabilities. #[must_use] @@ -2797,7 +2769,6 @@ mod tests { assert_eq!(json["positionEncodings"], json!(["utf-32", "utf-16"])); } - #[cfg(feature = "unstable_boolean_config")] #[test] fn test_client_capabilities_boolean_config_options_serialization() { use serde_json::json; diff --git a/agent-client-protocol-schema/src/v2/agent.rs b/agent-client-protocol-schema/src/v2/agent.rs index b3f318da4..f80542219 100644 --- a/agent-client-protocol-schema/src/v2/agent.rs +++ b/agent-client-protocol-schema/src/v2/agent.rs @@ -2286,12 +2286,7 @@ impl SessionConfigSelect { } } -/// **UNSTABLE** -/// -/// This capability is not part of the spec yet, and may be removed or changed at any point. -/// /// A boolean on/off toggle session configuration option payload. -#[cfg(feature = "unstable_boolean_config")] #[skip_serializing_none] #[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)] #[serde(rename_all = "camelCase")] @@ -2301,7 +2296,6 @@ pub struct SessionConfigBoolean { pub current_value: bool, } -#[cfg(feature = "unstable_boolean_config")] impl SessionConfigBoolean { /// Builds [`SessionConfigBoolean`] with the required fields set; optional fields start unset or empty. #[must_use] @@ -2348,12 +2342,7 @@ pub enum SessionConfigOptionCategory { pub enum SessionConfigKind { /// Single-value selector (dropdown). Select(SessionConfigSelect), - /// **UNSTABLE** - /// - /// This capability is not part of the spec yet, and may be removed or changed at any point. - /// /// Boolean on/off toggle. - #[cfg(feature = "unstable_boolean_config")] Boolean(SessionConfigBoolean), /// Custom or future session configuration option payload. /// @@ -2424,24 +2413,11 @@ impl<'de> Deserialize<'de> for OtherSessionConfigKind { } fn is_known_session_config_kind_type(type_: &str) -> bool { - match type_ { - "select" => true, - #[cfg(feature = "unstable_boolean_config")] - "boolean" => true, - _ => false, - } + matches!(type_, "select" | "boolean") } fn other_session_config_kind_schema(schema: &mut Schema) { - super::schema_util::reject_known_string_discriminators( - schema, - "type", - &[ - "select", - #[cfg(feature = "unstable_boolean_config")] - "boolean", - ], - ); + super::schema_util::reject_known_string_discriminators(schema, "type", &["select", "boolean"]); } /// A session configuration option selector and its current state. @@ -2513,10 +2489,7 @@ impl SessionConfigOption { ) } - /// **UNSTABLE** - /// - /// This capability is not part of the spec yet, and may be removed or changed at any point. - #[cfg(feature = "unstable_boolean_config")] + /// Builds a boolean-style session configuration option with its current value. #[must_use] pub fn boolean( config_id: impl Into, @@ -2556,10 +2529,6 @@ impl SessionConfigOption { } } -/// **UNSTABLE** -/// -/// This capability is not part of the spec yet, and may be removed or changed at any point. -/// /// The value to set for a session configuration option. /// /// The `type` field acts as the discriminator in the serialized JSON form. @@ -2568,7 +2537,6 @@ impl SessionConfigOption { /// kind. For example every option kind that picks from a list of ids /// (`select`, `radio`, …) would use [`Id`](Self::Id), while a future freeform /// text option would get its own variant. -#[cfg(feature = "unstable_boolean_config")] #[derive(Debug, Clone, Serialize, JsonSchema, PartialEq, Eq)] #[serde(tag = "type", rename_all = "snake_case")] #[schemars(extend("discriminator" = {"propertyName": "type"}))] @@ -2594,7 +2562,6 @@ pub enum SessionConfigOptionValue { } /// Custom or future session configuration option value payload. -#[cfg(feature = "unstable_boolean_config")] #[derive(Debug, Clone, Serialize, JsonSchema, PartialEq, Eq)] #[schemars(inline)] #[schemars(transform = other_session_config_option_value_schema)] @@ -2615,7 +2582,6 @@ pub struct OtherSessionConfigOptionValue { pub fields: BTreeMap, } -#[cfg(feature = "unstable_boolean_config")] impl OtherSessionConfigOptionValue { /// Builds [`OtherSessionConfigOptionValue`] from an unknown discriminator and preserves the remaining extension fields. #[must_use] @@ -2635,7 +2601,6 @@ impl OtherSessionConfigOptionValue { } } -#[cfg(feature = "unstable_boolean_config")] impl<'de> Deserialize<'de> for OtherSessionConfigOptionValue { fn deserialize(deserializer: D) -> Result where @@ -2667,7 +2632,6 @@ impl<'de> Deserialize<'de> for OtherSessionConfigOptionValue { } } -#[cfg(feature = "unstable_boolean_config")] impl<'de> Deserialize<'de> for SessionConfigOptionValue { fn deserialize(deserializer: D) -> Result where @@ -2711,17 +2675,14 @@ impl<'de> Deserialize<'de> for SessionConfigOptionValue { } } -#[cfg(feature = "unstable_boolean_config")] fn is_known_session_config_option_value_type(type_: &str) -> bool { matches!(type_, "id" | "boolean") } -#[cfg(feature = "unstable_boolean_config")] fn other_session_config_option_value_schema(schema: &mut Schema) { super::schema_util::reject_known_string_discriminators(schema, "type", &["id", "boolean"]); } -#[cfg(feature = "unstable_boolean_config")] impl SessionConfigOptionValue { /// Create an id option value (used by `select` and other id-based option types). #[must_use] @@ -2755,21 +2716,18 @@ impl SessionConfigOptionValue { } } -#[cfg(feature = "unstable_boolean_config")] impl From for SessionConfigOptionValue { fn from(value: SessionConfigValueId) -> Self { Self::Id { value } } } -#[cfg(feature = "unstable_boolean_config")] impl From for SessionConfigOptionValue { fn from(value: bool) -> Self { Self::Boolean { value } } } -#[cfg(feature = "unstable_boolean_config")] impl From<&str> for SessionConfigOptionValue { fn from(value: &str) -> Self { Self::Id { @@ -2793,12 +2751,8 @@ pub struct SetSessionConfigOptionRequest { /// The value to set, including a `type` discriminator and the raw `value`. /// /// Payloads must send `type: "id"` for id-based options. - #[cfg(feature = "unstable_boolean_config")] #[serde(flatten)] pub value: SessionConfigOptionValue, - /// The ID of the configuration option value to set. - #[cfg(not(feature = "unstable_boolean_config"))] - pub value: SessionConfigValueId, /// 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. @@ -2813,7 +2767,6 @@ pub struct SetSessionConfigOptionRequest { impl SetSessionConfigOptionRequest { /// Builds [`SetSessionConfigOptionRequest`] with the required request fields set; optional fields start unset or empty. - #[cfg(feature = "unstable_boolean_config")] #[must_use] pub fn new( session_id: impl Into, @@ -2828,23 +2781,6 @@ impl SetSessionConfigOptionRequest { } } - /// Builds a select-value `session/set_config_option` request for crates built - /// without boolean session configuration support. - #[cfg(not(feature = "unstable_boolean_config"))] - #[must_use] - pub fn new( - session_id: impl Into, - config_id: impl Into, - value: impl Into, - ) -> Self { - Self { - session_id: session_id.into(), - config_id: config_id.into(), - value: value.into(), - meta: None, - } - } - /// 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. @@ -6473,7 +6409,6 @@ mod test_serialization { } } - #[cfg(feature = "unstable_boolean_config")] #[test] fn test_session_config_option_id_serialize() { let val = SessionConfigOptionValue::id("model-1"); @@ -6481,7 +6416,6 @@ mod test_serialization { assert_eq!(json, json!({ "type": "id", "value": "model-1" })); } - #[cfg(feature = "unstable_boolean_config")] #[test] fn test_session_config_option_value_boolean_serialize() { let val = SessionConfigOptionValue::boolean(true); @@ -6489,7 +6423,6 @@ mod test_serialization { assert_eq!(json, json!({ "type": "boolean", "value": true })); } - #[cfg(feature = "unstable_boolean_config")] #[test] fn test_session_config_option_value_deserialize_id() { let json = json!({ "type": "id", "value": "model-1" }); @@ -6498,7 +6431,6 @@ mod test_serialization { assert_eq!(val.as_id().unwrap().to_string(), "model-1"); } - #[cfg(feature = "unstable_boolean_config")] #[test] fn test_session_config_option_value_deserialize_requires_type() { let json = json!({ "value": "model-1" }); @@ -6506,7 +6438,6 @@ mod test_serialization { assert!(result.is_err()); } - #[cfg(feature = "unstable_boolean_config")] #[test] fn test_session_config_option_value_deserialize_boolean() { let json = json!({ "type": "boolean", "value": true }); @@ -6515,7 +6446,6 @@ mod test_serialization { assert_eq!(val.as_bool(), Some(true)); } - #[cfg(feature = "unstable_boolean_config")] #[test] fn test_session_config_option_value_deserialize_boolean_false() { let json = json!({ "type": "boolean", "value": false }); @@ -6524,7 +6454,6 @@ mod test_serialization { assert_eq!(val.as_bool(), Some(false)); } - #[cfg(feature = "unstable_boolean_config")] #[test] fn test_session_config_option_value_deserialize_unknown_type_with_string_value() { let json = json!({ @@ -6541,7 +6470,6 @@ mod test_serialization { assert_eq!(unknown.fields["maxLength"], json!(200)); } - #[cfg(feature = "unstable_boolean_config")] #[test] fn test_session_config_option_value_deserialize_unknown_type_with_object_value() { let json = json!({ @@ -6556,7 +6484,6 @@ mod test_serialization { assert_eq!(unknown.value, json!({ "min": 1, "max": 5 })); } - #[cfg(feature = "unstable_boolean_config")] #[test] fn test_session_config_option_value_roundtrip_id() { let original = SessionConfigOptionValue::id("option-a"); @@ -6565,7 +6492,6 @@ mod test_serialization { assert_eq!(original, roundtripped); } - #[cfg(feature = "unstable_boolean_config")] #[test] fn test_session_config_option_value_roundtrip_boolean() { let original = SessionConfigOptionValue::boolean(false); @@ -6574,7 +6500,6 @@ mod test_serialization { assert_eq!(original, roundtripped); } - #[cfg(feature = "unstable_boolean_config")] #[test] fn test_session_config_option_value_roundtrip_other() { let mut fields = BTreeMap::new(); @@ -6589,7 +6514,6 @@ mod test_serialization { assert_eq!(original, roundtripped); } - #[cfg(feature = "unstable_boolean_config")] #[test] fn test_session_config_option_value_type_mismatch_boolean_with_string() { let json = json!({ "type": "boolean", "value": "not a bool" }); @@ -6597,7 +6521,6 @@ mod test_serialization { assert!(result.is_err()); } - #[cfg(feature = "unstable_boolean_config")] #[test] fn test_session_config_option_value_from_impls() { let from_str: SessionConfigOptionValue = "model-1".into(); @@ -6610,7 +6533,6 @@ mod test_serialization { assert_eq!(from_bool.as_bool(), Some(true)); } - #[cfg(feature = "unstable_boolean_config")] #[test] fn test_set_session_config_option_request_id() { let req = SetSessionConfigOptionRequest::new("sess_1", "model", "model-1"); @@ -6626,7 +6548,6 @@ mod test_serialization { ); } - #[cfg(feature = "unstable_boolean_config")] #[test] fn test_set_session_config_option_request_boolean() { let req = SetSessionConfigOptionRequest::new("sess_1", "brave_mode", true); @@ -6642,7 +6563,6 @@ mod test_serialization { ); } - #[cfg(feature = "unstable_boolean_config")] #[test] fn test_set_session_config_option_request_deserialize_requires_type() { let json = json!({ @@ -6654,7 +6574,6 @@ mod test_serialization { assert!(result.is_err()); } - #[cfg(feature = "unstable_boolean_config")] #[test] fn test_set_session_config_option_request_deserialize_boolean() { let json = json!({ @@ -6667,7 +6586,6 @@ mod test_serialization { assert_eq!(req.value.as_bool(), Some(true)); } - #[cfg(feature = "unstable_boolean_config")] #[test] fn test_set_session_config_option_request_roundtrip_id() { let original = SetSessionConfigOptionRequest::new("s", "c", "v"); @@ -6676,7 +6594,6 @@ mod test_serialization { assert_eq!(original, roundtripped); } - #[cfg(feature = "unstable_boolean_config")] #[test] fn test_set_session_config_option_request_roundtrip_boolean() { let original = SetSessionConfigOptionRequest::new("s", "c", false); @@ -6685,7 +6602,6 @@ mod test_serialization { assert_eq!(original, roundtripped); } - #[cfg(feature = "unstable_boolean_config")] #[test] fn test_session_config_boolean_serialization() { let cfg = SessionConfigBoolean::new(true); @@ -6696,7 +6612,6 @@ mod test_serialization { assert!(deserialized.current_value); } - #[cfg(feature = "unstable_boolean_config")] #[test] fn test_session_config_option_boolean_variant() { let opt = SessionConfigOption::boolean("brave_mode", "Brave Mode", false) @@ -6728,7 +6643,6 @@ mod test_serialization { } } - #[cfg(feature = "unstable_boolean_config")] #[test] fn test_session_config_option_select_still_works() { // Make sure existing select options are unaffected diff --git a/agent-client-protocol-schema/src/v2/conversion.rs b/agent-client-protocol-schema/src/v2/conversion.rs index a64008c0e..bdef9c7ff 100644 --- a/agent-client-protocol-schema/src/v2/conversion.rs +++ b/agent-client-protocol-schema/src/v2/conversion.rs @@ -1945,7 +1945,6 @@ impl IntoV1 for super::ClientCapabilities { Ok(crate::v1::ClientCapabilities { fs: crate::v1::FileSystemCapabilities::default(), terminal: false, - #[cfg(feature = "unstable_boolean_config")] session: Some( crate::v1::ClientSessionCapabilities::new().config_options( crate::v1::SessionConfigOptionsCapabilities::new() @@ -1974,8 +1973,7 @@ impl IntoV2 for crate::v1::ClientCapabilities { let Self { fs: _, terminal: _, - #[cfg(feature = "unstable_boolean_config")] - session: _, + session: _, #[cfg(feature = "unstable_plan_operations")] plan: _, #[cfg(feature = "unstable_auth_methods")] @@ -3968,7 +3966,6 @@ impl IntoV2 for crate::v1::SessionConfigSelect { } } -#[cfg(feature = "unstable_boolean_config")] impl IntoV1 for super::SessionConfigBoolean { type Output = crate::v1::SessionConfigBoolean; @@ -3980,7 +3977,6 @@ impl IntoV1 for super::SessionConfigBoolean { } } -#[cfg(feature = "unstable_boolean_config")] impl IntoV2 for crate::v1::SessionConfigBoolean { type Output = super::SessionConfigBoolean; @@ -4026,7 +4022,6 @@ impl IntoV1 for super::SessionConfigKind { fn into_v1(self) -> Result { Ok(match self { Self::Select(value) => crate::v1::SessionConfigKind::Select(value.into_v1()?), - #[cfg(feature = "unstable_boolean_config")] Self::Boolean(value) => crate::v1::SessionConfigKind::Boolean(value.into_v1()?), Self::Other(value) => { return Err(unknown_v2_enum_variant("SessionConfigKind", &value.type_)); @@ -4041,7 +4036,6 @@ impl IntoV2 for crate::v1::SessionConfigKind { fn into_v2(self) -> Result { Ok(match self { Self::Select(value) => super::SessionConfigKind::Select(value.into_v2()?), - #[cfg(feature = "unstable_boolean_config")] Self::Boolean(value) => super::SessionConfigKind::Boolean(value.into_v2()?), }) } @@ -4093,7 +4087,6 @@ impl IntoV2 for crate::v1::SessionConfigOption { } } -#[cfg(feature = "unstable_boolean_config")] impl IntoV1 for super::SessionConfigOptionValue { type Output = crate::v1::SessionConfigOptionValue; @@ -4115,7 +4108,6 @@ impl IntoV1 for super::SessionConfigOptionValue { } } -#[cfg(feature = "unstable_boolean_config")] impl IntoV2 for crate::v1::SessionConfigOptionValue { type Output = super::SessionConfigOptionValue; @@ -9198,16 +9190,12 @@ mod tests { #[test] fn round_trips_initialize_request() { - let client_capabilities = v1::ClientCapabilities::new(); - #[cfg(feature = "unstable_boolean_config")] - let client_capabilities = { - client_capabilities.session( - v1::ClientSessionCapabilities::new().config_options( - v1::SessionConfigOptionsCapabilities::new() - .boolean(v1::BooleanConfigOptionCapabilities::new()), - ), - ) - }; + let client_capabilities = v1::ClientCapabilities::new().session( + v1::ClientSessionCapabilities::new().config_options( + v1::SessionConfigOptionsCapabilities::new() + .boolean(v1::BooleanConfigOptionCapabilities::new()), + ), + ); let request = v1::InitializeRequest::new(ProtocolVersion::V1) .client_capabilities(client_capabilities) @@ -9467,7 +9455,6 @@ mod tests { assert!(!v1_after.terminal); } - #[cfg(feature = "unstable_boolean_config")] #[test] fn v2_client_capabilities_default_to_v1_boolean_config_option_support() { let v2_capabilities = v2::ClientCapabilities::new(); diff --git a/docs/docs.json b/docs/docs.json index ebcb6c026..d2172b751 100644 --- a/docs/docs.json +++ b/docs/docs.json @@ -218,7 +218,7 @@ }, { "group": "Preview", - "pages": ["rfds/boolean-config-option"] + "pages": [] }, { "group": "Completed", @@ -238,7 +238,8 @@ "rfds/session-delete", "rfds/model-config-category", "rfds/rust-sdk-v1", - "rfds/request-cancellation" + "rfds/request-cancellation", + "rfds/boolean-config-option" ] } ] diff --git a/docs/protocol/v1/draft/initialization.mdx b/docs/protocol/v1/draft/initialization.mdx index ba5d650cb..c0859ccfe 100644 --- a/docs/protocol/v1/draft/initialization.mdx +++ b/docs/protocol/v1/draft/initialization.mdx @@ -152,7 +152,7 @@ The Client **SHOULD** specify whether it supports the following capabilities: diff --git a/docs/protocol/v1/draft/schema.mdx b/docs/protocol/v1/draft/schema.mdx index bb8ccec3c..94c4ace97 100644 --- a/docs/protocol/v1/draft/schema.mdx +++ b/docs/protocol/v1/draft/schema.mdx @@ -3210,10 +3210,6 @@ See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/v1/d ## BooleanConfigOptionCapabilities -**UNSTABLE** - -This capability is not part of the spec yet, and may be removed or changed at any point. - Capabilities for boolean session configuration options. Supplying `\{\}` means the client supports boolean session configuration options. @@ -3340,11 +3336,7 @@ The position encodings supported by the client, in order of preference. ClientSessionCapabilities | null} > - **UNSTABLE** - -This capability is not part of the spec yet, and may be removed or changed at any point. - -Session-related capabilities supported by the client. + Session-related capabilities supported by the client. Optional. Omitted or `null` both mean the client does not advertise any session-related extensions. @@ -3385,10 +3377,6 @@ See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/v1/d ## ClientSessionCapabilities -**UNSTABLE** - -This capability is not part of the spec yet, and may be removed or changed at any point. - Session-related capabilities supported by the client. **Type:** Object @@ -7131,10 +7119,6 @@ See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/v1/d ## SessionConfigBoolean -**UNSTABLE** - -This capability is not part of the spec yet, and may be removed or changed at any point. - A boolean on/off toggle session configuration option payload. **Type:** Object @@ -7215,10 +7199,6 @@ Single-value selector (dropdown). -**UNSTABLE** - -This capability is not part of the spec yet, and may be removed or changed at any point. - Boolean on/off toggle. @@ -7269,10 +7249,6 @@ Category names that do not begin with `_` are reserved for the ACP spec. ## SessionConfigOptionsCapabilities -**UNSTABLE** - -This capability is not part of the spec yet, and may be removed or changed at any point. - Session configuration option capabilities supported by the client. **Type:** Object diff --git a/docs/protocol/v1/initialization.mdx b/docs/protocol/v1/initialization.mdx index 67387cafd..9f6402cea 100644 --- a/docs/protocol/v1/initialization.mdx +++ b/docs/protocol/v1/initialization.mdx @@ -140,6 +140,21 @@ The Client **SHOULD** specify whether it supports the following capabilities: Learn more about Terminals +#### Boolean Config Options + + + The Client supports `boolean` session configuration options. Omitted or `null` + at any level means the Client does not advertise support. Supplying `{}` means + Agents may include `type: "boolean"` options in v1 `configOptions` payloads. + + + + Learn more about Session Config Options + + ### Agent Capabilities The Agent **SHOULD** specify whether it supports the following capabilities: diff --git a/docs/protocol/v1/schema.mdx b/docs/protocol/v1/schema.mdx index 2bf3d5b3a..fbd0a7cbb 100644 --- a/docs/protocol/v1/schema.mdx +++ b/docs/protocol/v1/schema.mdx @@ -728,9 +728,9 @@ Sets the current value for a session configuration option. Request parameters for setting a session configuration option. -**Type:** Object +**Type:** Union -**Properties:** +**Shared properties:** The _meta property is reserved by ACP to allow clients and agents to attach additional @@ -746,8 +746,42 @@ See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/v1/e SessionId} required> The ID of the session to set the configuration option for. -SessionConfigValueId} required> - The ID of the configuration option value to set. + +**Variants:** + + +A boolean value (`type: "boolean"`). + + + + + The discriminator value. Must be `"boolean"`. + + + The boolean value. + + + + + + +A `SessionConfigValueId` string value. + +This is the default when `type` is absent on the wire. Unknown `type` +values with string payloads also gracefully deserialize into this +variant. + + + +SessionConfigValueId} + required +> + The value ID. + + + #### SetSessionConfigOptionResponse @@ -1713,6 +1747,25 @@ See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/v1/e URI associated with this resource or media payload. +## BooleanConfigOptionCapabilities + +Capabilities for boolean session configuration options. + +Supplying `\{\}` means the client supports boolean session configuration options. + +**Type:** Object + +**Properties:** + + + 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. + +See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/v1/extensibility) + + + ## ClientCapabilities Capabilities supported by the client. @@ -1740,6 +1793,13 @@ Determines which file operations the agent can request. - Default: `{"readTextFile":false,"writeTextFile":false}` + +ClientSessionCapabilities | null} > + Session-related capabilities supported by the client. + +Optional. Omitted or `null` both mean the client does not advertise any +session-related extensions. + Whether the Client support all `terminal/*` methods. @@ -1748,6 +1808,30 @@ Determines which file operations the agent can request. +## ClientSessionCapabilities + +Session-related capabilities supported by the client. + +**Type:** Object + +**Properties:** + + + 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. + +See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/v1/extensibility) + + +SessionConfigOptionsCapabilities | null} > + Config option capabilities supported by the client. + +Omitted or `null` both mean the client does not advertise support for any +config option extensions. + + + ## ConfigOptionUpdate Session configuration options have been updated. @@ -3112,6 +3196,18 @@ See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/v1/e +## SessionConfigBoolean + +A boolean on/off toggle session configuration option payload. + +**Type:** Object + +**Properties:** + + + The current value of the boolean option. + + ## SessionConfigGroupId Unique identifier for a session configuration option value group. @@ -3128,11 +3224,37 @@ Unique identifier for a session configuration option. A session configuration option selector and its current state. -Single-value selector (dropdown). +**Type:** Union -**Type:** Object +**Shared properties:** -**Properties:** + + 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. + +See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/v1/extensibility) + + +SessionConfigOptionCategory | null} > + Optional semantic category for this option (UX only). + + + Optional description for the Client to display to the user. + +SessionConfigId} required> + Unique identifier for the configuration option. + + + Human-readable label for the option. + + +**Variants:** + + +Single-value selector (dropdown). + + + + + + +Boolean on/off toggle. + + + + + The current value of the boolean option. + + + The discriminator value. Must be `"boolean"`. + + + + + ## SessionConfigOptionCategory Semantic category for a session configuration option. @@ -3186,6 +3326,32 @@ Category names that do not begin with `_` are reserved for the ACP spec. Unknown / uncategorized selector. +## SessionConfigOptionsCapabilities + +Session configuration option capabilities supported by the client. + +**Type:** Object + +**Properties:** + + + 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. + +See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/v1/extensibility) + + +BooleanConfigOptionCapabilities | null} > + Whether the client supports boolean session configuration options. + +Optional. Omitted or `null` both mean the client does not advertise support. +Supplying `\{\}` means agents may include `type: "boolean"` entries in +`configOptions`, and the client may send `session/set_config_option` +requests with `type: "boolean"` and a boolean `value`. + + + ## SessionConfigSelect A single-value selector (dropdown) session configuration option payload. diff --git a/docs/protocol/v1/session-config-options.mdx b/docs/protocol/v1/session-config-options.mdx index 5be63c0ef..967f4601b 100644 --- a/docs/protocol/v1/session-config-options.mdx +++ b/docs/protocol/v1/session-config-options.mdx @@ -93,15 +93,19 @@ During [Session Setup](/protocol/v1/session-setup) the Agent **MAY** return a li - The type of input control. Currently only `select` is supported. + The type of input control. `select` is supported by default. `boolean` is only + supported when the Client advertises `session.configOptions.boolean: {}` in + `clientCapabilities`. - - The currently selected value for this option + + The current value for this option. For `select` options this is a string value + ID. For `boolean` options this is a boolean. - - The available values for this option + + The available values for a `select` option. Required when `type` is `"select"` + and omitted when `type` is `"boolean"`. ### ConfigOptionValue @@ -118,6 +122,43 @@ During [Session Setup](/protocol/v1/session-setup) the Agent **MAY** return a li Optional description of what this value does +### Boolean Config Options + +Agents **MAY** include boolean config options only after the Client advertises +support during initialization: + +```json +{ + "clientCapabilities": { + "session": { + "configOptions": { + "boolean": {} + } + } + } +} +``` + +Omitting `session`, `configOptions`, or `boolean` means the Client does not +advertise support. + +When support is advertised, a boolean option uses `type: "boolean"` and a +boolean `currentValue`: + +```json +{ + "id": "brave_mode", + "name": "Brave Mode", + "description": "Skip confirmation prompts and act autonomously", + "type": "boolean", + "currentValue": true +} +``` + +Agents **MUST NOT** include `type: "boolean"` options in `configOptions` +payloads unless the Client advertised support. Agents that need to support +older Clients should omit the boolean option or provide a `select` fallback. + ## Option Categories Each config option **MAY** include a `category` field. Categories are semantic metadata intended to help Clients provide consistent UX, such as attaching keyboard shortcuts, choosing icons, or deciding placement. @@ -189,11 +230,28 @@ Clients can change a config option value by calling the `session/set_config_opti The `id` of the configuration option to change - - The new value to set. Must be one of the values listed in the option's - `options` array. + + The new value to set. For `select` options, this must be one of the values + listed in the option's `options` array. For `boolean` options, this must be a + boolean. +For boolean options, Clients send `type: "boolean"` with a boolean `value`: + +```json +{ + "jsonrpc": "2.0", + "id": 3, + "method": "session/set_config_option", + "params": { + "sessionId": "sess_abc123def456", + "configId": "brave_mode", + "type": "boolean", + "value": true + } +} +``` + The Agent **MUST** respond with the complete list of all configuration options and their current values: ```json diff --git a/docs/protocol/v2/draft/schema.mdx b/docs/protocol/v2/draft/schema.mdx index 36232cb61..0b36faea7 100644 --- a/docs/protocol/v2/draft/schema.mdx +++ b/docs/protocol/v2/draft/schema.mdx @@ -7261,10 +7261,6 @@ required by `session/prompt`. ## SessionConfigBoolean -**UNSTABLE** - -This capability is not part of the spec yet, and may be removed or changed at any point. - A boolean on/off toggle session configuration option payload. **Type:** Object @@ -7345,10 +7341,6 @@ Single-value selector (dropdown). -**UNSTABLE** - -This capability is not part of the spec yet, and may be removed or changed at any point. - Boolean on/off toggle. diff --git a/docs/protocol/v2/draft/session-config-options.mdx b/docs/protocol/v2/draft/session-config-options.mdx index 2de43cd90..ab08d2e03 100644 --- a/docs/protocol/v2/draft/session-config-options.mdx +++ b/docs/protocol/v2/draft/session-config-options.mdx @@ -110,8 +110,7 @@ During [Session Setup](/protocol/v2/draft/session-setup) the Agent **MAY** retur - The type of input control. `select` is supported by default. The draft boolean - config option extension also defines `boolean`. + The type of input control. `select` and `boolean` are supported. @@ -140,8 +139,7 @@ During [Session Setup](/protocol/v2/draft/session-setup) the Agent **MAY** retur ### Boolean Config Options -The draft boolean config option extension defines `type: "boolean"` for simple -on/off toggles: +Boolean config options use `type: "boolean"` for simple on/off toggles: ```json { diff --git a/docs/protocol/v2/schema.mdx b/docs/protocol/v2/schema.mdx index a0ceb3df4..f9be4cc2e 100644 --- a/docs/protocol/v2/schema.mdx +++ b/docs/protocol/v2/schema.mdx @@ -631,9 +631,9 @@ Sets the current value for a session configuration option. Request parameters for setting a session configuration option. -**Type:** Object +**Type:** Union -**Properties:** +**Shared properties:** The _meta property is reserved by ACP to allow clients and agents to attach additional @@ -649,8 +649,65 @@ See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/v2/e SessionId} required> The ID of the session to set the configuration option for. -SessionConfigValueId} required> - The ID of the configuration option value to set. + +**Variants:** + + +A `SessionConfigValueId` string value (`type: "id"`). + + + + + The discriminator value. Must be `"id"`. + +SessionConfigValueId} + required +> + The value ID. + + + + + + +A boolean value (`type: "boolean"`). + + + + + The discriminator value. Must be `"boolean"`. + + + The boolean value. + + + + + + +Custom or future session configuration option value payload. + +Values beginning with `_` are reserved for implementation-specific +extensions. Unknown values that do not begin with `_` are reserved for +future ACP variants. + + + + + Custom or future session configuration option value type. + +Values beginning with `_` are reserved for implementation-specific +extensions. Unknown values that do not begin with `_` are reserved for +future ACP variants. + + + + Raw value payload for the custom or future value type. + + + #### SetSessionConfigOptionResponse @@ -3324,6 +3381,18 @@ required by `session/prompt`. +## SessionConfigBoolean + +A boolean on/off toggle session configuration option payload. + +**Type:** Object + +**Properties:** + + + The current value of the boolean option. + + ## SessionConfigGroupId Unique identifier for a session configuration option value group. @@ -3393,6 +3462,21 @@ Single-value selector (dropdown). + +Boolean on/off toggle. + + + + + The current value of the boolean option. + + + The discriminator value. Must be `"boolean"`. + + + + + Custom or future session configuration option payload. diff --git a/docs/protocol/v2/session-config-options.mdx b/docs/protocol/v2/session-config-options.mdx index 878e05b5a..7c2b87c42 100644 --- a/docs/protocol/v2/session-config-options.mdx +++ b/docs/protocol/v2/session-config-options.mdx @@ -54,6 +54,13 @@ During [Session Setup](/protocol/v2/session-setup) the Agent **MAY** return a li "description": "The most powerful model" } ] + }, + { + "configId": "brave_mode", + "name": "Brave Mode", + "description": "Skip confirmation prompts and act autonomously", + "type": "boolean", + "currentValue": false } ] } @@ -86,15 +93,17 @@ During [Session Setup](/protocol/v2/session-setup) the Agent **MAY** return a li - The type of input control. Currently only `select` is supported. + The type of input control. `select` and `boolean` are supported. - - The currently selected value for this option + + The current value for this option. For `select` options this is a string value + ID. For `boolean` options this is a boolean. - - The available values for this option + + The available values for a `select` option. Required when `type` is `"select"` + and omitted when `type` is `"boolean"`. ### ConfigOptionValue @@ -111,6 +120,20 @@ During [Session Setup](/protocol/v2/session-setup) the Agent **MAY** return a li Optional description of what this value does +### Boolean Config Options + +Boolean config options use `type: "boolean"` for simple on/off toggles: + +```json +{ + "configId": "brave_mode", + "name": "Brave Mode", + "description": "Skip confirmation prompts and act autonomously", + "type": "boolean", + "currentValue": true +} +``` + ## Option Categories Each config option **MAY** include a `category` field. Categories are semantic metadata intended to help Clients provide consistent UX, such as attaching keyboard shortcuts, choosing icons, or deciding placement. @@ -169,6 +192,7 @@ Clients can change a config option value by calling the `session/set_config_opti "params": { "sessionId": "sess_abc123def456", "configId": "mode", + "type": "id", "value": "code" } } @@ -182,11 +206,33 @@ Clients can change a config option value by calling the `session/set_config_opti The `configId` of the configuration option to change - - The new value to set. Must be one of the values listed in the option's - `options` array. + + The shape of the value. Use `id` for `select` and other id-based options. Use + `boolean` for boolean options. + + + + The new value to set. For `select` options, this must be one of the values + listed in the option's `options` array. For `boolean` options, this must be a + boolean. +For boolean options, Clients send `type: "boolean"` with a boolean `value`: + +```json +{ + "jsonrpc": "2.0", + "id": 3, + "method": "session/set_config_option", + "params": { + "sessionId": "sess_abc123def456", + "configId": "brave_mode", + "type": "boolean", + "value": true + } +} +``` + The Agent **MUST** respond with the complete list of all configuration options and their current values: ```json diff --git a/docs/rfds/boolean-config-option.mdx b/docs/rfds/boolean-config-option.mdx index 182d774a9..2f1c67653 100644 --- a/docs/rfds/boolean-config-option.mdx +++ b/docs/rfds/boolean-config-option.mdx @@ -56,7 +56,7 @@ Omitting `session`, `configOptions`, or `boolean` means the Client does not adve Agents **MUST NOT** include `type: "boolean"` config options in v1 `configOptions` payloads unless the Client advertised `session.configOptions.boolean: {}`. This applies to `session/new`, `session/load`, `session/update`, and `session/set_config_option` responses. Agents that need to support older Clients should omit the boolean option or provide a `select` fallback. -Protocol v2 does not add an equivalent capability field for this extension. When the unstable boolean config option extension is enabled, v2 peers are boolean-aware by construction; compatibility layers that down-convert v2 client capabilities to v1 advertise `session.configOptions.boolean: {}` by default. +Protocol v2 does not add an equivalent capability field for this extension. v2 peers are boolean-aware by construction; compatibility layers that down-convert v2 client capabilities to v1 advertise `session.configOptions.boolean: {}` by default. ### Wire format: declaring a boolean option @@ -165,7 +165,7 @@ Key changes: - `Boolean { value: bool }` — matched when `type` is `"boolean"` - `Other(OtherSessionConfigOptionValue)` — preserves unrecognized typed value payloads 4. `SessionConfigOptionValue` is flattened (`#[serde(flatten)]`) onto `SetSessionConfigOptionRequest`, producing top-level `type` and `value` fields on the wire -5. The `value` field type change in `SetSessionConfigOptionRequest` is gated behind `#[cfg(feature = "unstable_boolean_config")]` — without the feature the field remains `SessionConfigValueId` +5. The `value` field in `SetSessionConfigOptionRequest` is a `SessionConfigOptionValue`, flattened onto the request 6. The v1 `ClientCapabilities.session.config_options.boolean` field path serializes as `session.configOptions.boolean` 7. v2 requires a `type` field so future value shapes can be captured without ambiguity @@ -189,6 +189,7 @@ While no one would set a value of type boolean that doesn't support it, there is ## Revision history +- 2026-07-06: Moved to Completed and stabilized boolean config options in the protocol artifacts. - 2026-06-30: Moved to Preview. - 2026-06-22: Added the v1 `session.configOptions.boolean` client capability gate so boolean config options are only sent to Clients that explicitly opt in, and made v2-to-v1 compatibility conversion advertise the capability by default - 2026-03-05: Updated to reflect final implementation — `flag` renamed to `boolean`, value type changed from untagged `String | Bool` enum to internally-tagged enum with `type` discriminator and untagged `ValueId` fallback, feature-gated behind `unstable_boolean_config` diff --git a/docs/rfds/updates.mdx b/docs/rfds/updates.mdx index 7e772cfb0..a360ed806 100644 --- a/docs/rfds/updates.mdx +++ b/docs/rfds/updates.mdx @@ -6,6 +6,13 @@ rss: true This page tracks lifecycle changes for ACP Requests for Dialog. For broader ACP announcements, see [Updates](/updates). + +## Boolean Config Option RFD moves to Completed + +The RFD for boolean session configuration options has been stabilized and is now part of the protocol. Agents can expose simple on/off toggles with `type: "boolean"` config options, and Clients opt in on v1 by advertising the `session.configOptions.boolean` capability. Please review the [documentation](/protocol/v1/session-config-options#boolean-config-options) for more information. + + + ## Agent Telemetry Export RFD removed diff --git a/schema/v1/schema.json b/schema/v1/schema.json index 8361e704d..0a8301427 100644 --- a/schema/v1/schema.json +++ b/schema/v1/schema.json @@ -2141,6 +2141,22 @@ "$ref": "#/$defs/SessionConfigSelect" } ] + }, + { + "description": "Boolean on/off toggle.", + "type": "object", + "properties": { + "type": { + "type": "string", + "const": "boolean" + } + }, + "required": ["type"], + "allOf": [ + { + "$ref": "#/$defs/SessionConfigBoolean" + } + ] } ], "discriminator": { @@ -2297,6 +2313,17 @@ }, "required": ["currentValue", "options"] }, + "SessionConfigBoolean": { + "description": "A boolean on/off toggle session configuration option payload.", + "type": "object", + "properties": { + "currentValue": { + "description": "The current value of the boolean option.", + "type": "boolean" + } + }, + "required": ["currentValue"] + }, "LoadSessionResponse": { "description": "Response from loading an existing session.", "type": "object", @@ -3548,6 +3575,18 @@ "default": false, "x-deserialize-default-on-error": true }, + "session": { + "description": "Session-related capabilities supported by the client.\n\nOptional. Omitted or `null` both mean the client does not advertise any\nsession-related extensions.", + "anyOf": [ + { + "$ref": "#/$defs/ClientSessionCapabilities" + }, + { + "type": "null" + } + ], + "x-deserialize-default-on-error": true + }, "_meta": { "description": "The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)", "type": ["object", "null"], @@ -3580,6 +3619,66 @@ } } }, + "ClientSessionCapabilities": { + "description": "Session-related capabilities supported by the client.", + "type": "object", + "properties": { + "configOptions": { + "description": "Config option capabilities supported by the client.\n\nOmitted or `null` both mean the client does not advertise support for any\nconfig option extensions.", + "anyOf": [ + { + "$ref": "#/$defs/SessionConfigOptionsCapabilities" + }, + { + "type": "null" + } + ], + "x-deserialize-default-on-error": true + }, + "_meta": { + "description": "The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)", + "type": ["object", "null"], + "x-deserialize-default-on-error": true, + "additionalProperties": true + } + } + }, + "SessionConfigOptionsCapabilities": { + "description": "Session configuration option capabilities supported by the client.", + "type": "object", + "properties": { + "boolean": { + "description": "Whether the client supports boolean session configuration options.\n\nOptional. Omitted or `null` both mean the client does not advertise support.\nSupplying `{}` means agents may include `type: \"boolean\"` entries in\n`configOptions`, and the client may send `session/set_config_option`\nrequests with `type: \"boolean\"` and a boolean `value`.", + "anyOf": [ + { + "$ref": "#/$defs/BooleanConfigOptionCapabilities" + }, + { + "type": "null" + } + ], + "x-deserialize-default-on-error": true + }, + "_meta": { + "description": "The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)", + "type": ["object", "null"], + "x-deserialize-default-on-error": true, + "additionalProperties": true + } + } + }, + "BooleanConfigOptionCapabilities": { + "description": "Capabilities for boolean session configuration options.\n\nSupplying `{}` means the client supports boolean session configuration options.", + "type": "object", + "properties": { + "_meta": { + "description": "The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)", + "type": ["object", "null"], + "x-deserialize-default-on-error": true, + "additionalProperties": true + } + } + }, "AuthenticateRequest": { "description": "Request parameters for the authenticate method.\n\nSpecifies which authentication method to use.", "type": "object", @@ -4021,14 +4120,6 @@ } ] }, - "value": { - "description": "The ID of the configuration option value to set.", - "allOf": [ - { - "$ref": "#/$defs/SessionConfigValueId" - } - ] - }, "_meta": { "description": "The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)", "type": ["object", "null"], @@ -4036,7 +4127,40 @@ "additionalProperties": true } }, - "required": ["sessionId", "configId", "value"], + "required": ["sessionId", "configId"], + "anyOf": [ + { + "description": "A boolean value (`type: \"boolean\"`).", + "type": "object", + "properties": { + "value": { + "description": "The boolean value.", + "type": "boolean" + }, + "type": { + "type": "string", + "const": "boolean" + } + }, + "required": ["type", "value"] + }, + { + "title": "value_id", + "description": "A [`SessionConfigValueId`] string value.\n\nThis is the default when `type` is absent on the wire. Unknown `type`\nvalues with string payloads also gracefully deserialize into this\nvariant.", + "type": "object", + "properties": { + "value": { + "description": "The value ID.", + "allOf": [ + { + "$ref": "#/$defs/SessionConfigValueId" + } + ] + } + }, + "required": ["value"] + } + ], "x-side": "agent", "x-method": "session/set_config_option" }, diff --git a/schema/v1/schema.unstable.json b/schema/v1/schema.unstable.json index 9bc911ec9..3f15cb948 100644 --- a/schema/v1/schema.unstable.json +++ b/schema/v1/schema.unstable.json @@ -3961,7 +3961,7 @@ ] }, { - "description": "**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nBoolean on/off toggle.", + "description": "Boolean on/off toggle.", "type": "object", "properties": { "type": { @@ -4132,7 +4132,7 @@ "required": ["currentValue", "options"] }, "SessionConfigBoolean": { - "description": "**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nA boolean on/off toggle session configuration option payload.", + "description": "A boolean on/off toggle session configuration option payload.", "type": "object", "properties": { "currentValue": { @@ -6235,7 +6235,7 @@ "x-deserialize-default-on-error": true }, "session": { - "description": "**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nSession-related capabilities supported by the client.\n\nOptional. Omitted or `null` both mean the client does not advertise any\nsession-related extensions.", + "description": "Session-related capabilities supported by the client.\n\nOptional. Omitted or `null` both mean the client does not advertise any\nsession-related extensions.", "anyOf": [ { "$ref": "#/$defs/ClientSessionCapabilities" @@ -6336,7 +6336,7 @@ } }, "ClientSessionCapabilities": { - "description": "**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nSession-related capabilities supported by the client.", + "description": "Session-related capabilities supported by the client.", "type": "object", "properties": { "configOptions": { @@ -6360,7 +6360,7 @@ } }, "SessionConfigOptionsCapabilities": { - "description": "**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nSession configuration option capabilities supported by the client.", + "description": "Session configuration option capabilities supported by the client.", "type": "object", "properties": { "boolean": { @@ -6384,7 +6384,7 @@ } }, "BooleanConfigOptionCapabilities": { - "description": "**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nCapabilities for boolean session configuration options.\n\nSupplying `{}` means the client supports boolean session configuration options.", + "description": "Capabilities for boolean session configuration options.\n\nSupplying `{}` means the client supports boolean session configuration options.", "type": "object", "properties": { "_meta": { diff --git a/schema/v2/schema.json b/schema/v2/schema.json index 7995d302f..3c119be67 100644 --- a/schema/v2/schema.json +++ b/schema/v2/schema.json @@ -2589,6 +2589,22 @@ } ] }, + { + "description": "Boolean on/off toggle.", + "type": "object", + "properties": { + "type": { + "type": "string", + "const": "boolean" + } + }, + "required": ["type"], + "allOf": [ + { + "$ref": "#/$defs/SessionConfigBoolean" + } + ] + }, { "title": "other", "description": "Custom or future session configuration option payload.\n\nValues beginning with `_` are reserved for implementation-specific\nextensions. Unknown values that do not begin with `_` are reserved for\nfuture ACP variants.\n\nClients that do not understand this option type should preserve the raw\npayload when storing, replaying, proxying, or forwarding configuration\ndata, and otherwise ignore the option or display it generically.", @@ -2611,6 +2627,16 @@ } }, "required": ["type"] + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "const": "boolean" + } + }, + "required": ["type"] } ] }, @@ -2771,6 +2797,17 @@ }, "required": ["currentValue", "options"] }, + "SessionConfigBoolean": { + "description": "A boolean on/off toggle session configuration option payload.", + "type": "object", + "properties": { + "currentValue": { + "description": "The current value of the boolean option.", + "type": "boolean" + } + }, + "required": ["currentValue"] + }, "ListSessionsResponse": { "description": "Response from listing sessions.", "type": "object", @@ -4932,14 +4969,6 @@ } ] }, - "value": { - "description": "The ID of the configuration option value to set.", - "allOf": [ - { - "$ref": "#/$defs/SessionConfigValueId" - } - ] - }, "_meta": { "description": "The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/v2/extensibility)", "type": ["object", "null"], @@ -4947,7 +4976,86 @@ "additionalProperties": true } }, - "required": ["sessionId", "configId", "value"], + "required": ["sessionId", "configId"], + "anyOf": [ + { + "description": "A [`SessionConfigValueId`] string value (`type: \"id\"`).", + "type": "object", + "properties": { + "value": { + "description": "The value ID.", + "allOf": [ + { + "$ref": "#/$defs/SessionConfigValueId" + } + ] + }, + "type": { + "type": "string", + "const": "id" + } + }, + "required": ["type", "value"] + }, + { + "description": "A boolean value (`type: \"boolean\"`).", + "type": "object", + "properties": { + "value": { + "description": "The boolean value.", + "type": "boolean" + }, + "type": { + "type": "string", + "const": "boolean" + } + }, + "required": ["type", "value"] + }, + { + "title": "other", + "description": "Custom or future session configuration option value payload.\n\nValues beginning with `_` are reserved for implementation-specific\nextensions. Unknown values that do not begin with `_` are reserved for\nfuture ACP variants.", + "type": "object", + "properties": { + "type": { + "description": "Custom or future session configuration option value type.\n\nValues beginning with `_` are reserved for implementation-specific\nextensions. Unknown values that do not begin with `_` are reserved for\nfuture ACP variants.", + "type": "string" + }, + "value": { + "description": "Raw value payload for the custom or future value type." + } + }, + "required": ["type", "value"], + "not": { + "anyOf": [ + { + "type": "object", + "properties": { + "type": { + "type": "string", + "const": "id" + } + }, + "required": ["type"] + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "const": "boolean" + } + }, + "required": ["type"] + } + ] + }, + "additionalProperties": true + } + ], + "discriminator": { + "propertyName": "type" + }, "x-side": "agent", "x-method": "session/set_config_option" }, diff --git a/schema/v2/schema.unstable.json b/schema/v2/schema.unstable.json index 0fd208ab2..8a31ef090 100644 --- a/schema/v2/schema.unstable.json +++ b/schema/v2/schema.unstable.json @@ -4586,7 +4586,7 @@ ] }, { - "description": "**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nBoolean on/off toggle.", + "description": "Boolean on/off toggle.", "type": "object", "properties": { "type": { @@ -4794,7 +4794,7 @@ "required": ["currentValue", "options"] }, "SessionConfigBoolean": { - "description": "**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nA boolean on/off toggle session configuration option payload.", + "description": "A boolean on/off toggle session configuration option payload.", "type": "object", "properties": { "currentValue": {