From db4c4980e76641da3da9dd6b93bcb2a992846719 Mon Sep 17 00:00:00 2001 From: Shushakov Daniil 84373458 Date: Tue, 9 Jun 2026 18:35:25 +0300 Subject: [PATCH] Add descriptions to elicitation enum options --- docs/protocol/v1/draft/schema.mdx | 5 ++- docs/protocol/v2/draft/schema.mdx | 5 ++- docs/rfds/elicitation.mdx | 66 +++++++++++++++++++++++++------ schema/v1/schema.unstable.json | 6 ++- schema/v2/schema.unstable.json | 6 ++- src/v1/elicitation.rs | 25 ++++++++++-- src/v2/conversion.rs | 14 ++++++- src/v2/elicitation.rs | 25 ++++++++++-- 8 files changed, 128 insertions(+), 24 deletions(-) diff --git a/docs/protocol/v1/draft/schema.mdx b/docs/protocol/v1/draft/schema.mdx index eb4d43dd7..1656b0ace 100644 --- a/docs/protocol/v1/draft/schema.mdx +++ b/docs/protocol/v1/draft/schema.mdx @@ -4185,7 +4185,7 @@ See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/v1/d ## EnumOption -A titled enum option with a const value and human-readable title. +A titled enum option with a const value, human-readable title, and optional description. **Type:** Object @@ -4194,6 +4194,9 @@ A titled enum option with a const value and human-readable title. The constant value for this option. + + Optional description for this option value. + Human-readable title for this option. diff --git a/docs/protocol/v2/draft/schema.mdx b/docs/protocol/v2/draft/schema.mdx index 3f2db2fdc..79954ed2a 100644 --- a/docs/protocol/v2/draft/schema.mdx +++ b/docs/protocol/v2/draft/schema.mdx @@ -3784,7 +3784,7 @@ See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/v2/d ## EnumOption -A titled enum option with a const value and human-readable title. +A titled enum option with a const value, human-readable title, and optional description. **Type:** Object @@ -3793,6 +3793,9 @@ A titled enum option with a const value and human-readable title. The constant value for this option. + + Optional description for this option value. + Human-readable title for this option. diff --git a/docs/rfds/elicitation.mdx b/docs/rfds/elicitation.mdx index ab69c1082..72f3d6929 100644 --- a/docs/rfds/elicitation.mdx +++ b/docs/rfds/elicitation.mdx @@ -99,12 +99,18 @@ Agents send elicitation requests when they need information from the user. This "oneOf": [ { "const": "conservative", - "title": "Conservative - Minimal changes" + "title": "Conservative - Minimal changes", + "description": "Make minimal changes and avoid broad cleanup." + }, + { + "const": "balanced", + "title": "Balanced (Recommended)", + "description": "Fix the issue and clean nearby code when it lowers risk." }, - { "const": "balanced", "title": "Balanced (Recommended)" }, { "const": "aggressive", - "title": "Aggressive - Maximum optimization" + "title": "Aggressive - Maximum optimization", + "description": "Refactor more broadly to optimize the affected area." } ], "default": "balanced" @@ -269,9 +275,21 @@ Single-select enum (with titles): "title": "Color Selection", "description": "Choose your favorite color", "oneOf": [ - { "const": "#FF0000", "title": "Red" }, - { "const": "#00FF00", "title": "Green" }, - { "const": "#0000FF", "title": "Blue" } + { + "const": "#FF0000", + "title": "Red", + "description": "High emphasis and warning-oriented." + }, + { + "const": "#00FF00", + "title": "Green", + "description": "Positive status and success-oriented." + }, + { + "const": "#0000FF", + "title": "Blue", + "description": "Neutral and informational." + } ], "default": "#FF0000" } @@ -305,9 +323,21 @@ Multi-select enum (with titles): "maxItems": 2, "items": { "anyOf": [ - { "const": "#FF0000", "title": "Red" }, - { "const": "#00FF00", "title": "Green" }, - { "const": "#0000FF", "title": "Blue" } + { + "const": "#FF0000", + "title": "Red", + "description": "High emphasis and warning-oriented." + }, + { + "const": "#00FF00", + "title": "Green", + "description": "Positive status and success-oriented." + }, + { + "const": "#0000FF", + "title": "Blue", + "description": "Neutral and informational." + } ] }, "default": ["#FF0000", "#00FF00"] @@ -368,9 +398,21 @@ The agent sends an `elicitation/create` request when it needs information from t "type": "string", "title": "Refactoring Strategy", "oneOf": [ - { "const": "conservative", "title": "Conservative" }, - { "const": "balanced", "title": "Balanced (Recommended)" }, - { "const": "aggressive", "title": "Aggressive" } + { + "const": "conservative", + "title": "Conservative", + "description": "Make minimal changes and avoid broad cleanup." + }, + { + "const": "balanced", + "title": "Balanced (Recommended)", + "description": "Fix the issue and clean nearby code when it lowers risk." + }, + { + "const": "aggressive", + "title": "Aggressive", + "description": "Refactor more broadly to optimize the affected area." + } ], "default": "balanced" } diff --git a/schema/v1/schema.unstable.json b/schema/v1/schema.unstable.json index 8a748875e..710b9d581 100644 --- a/schema/v1/schema.unstable.json +++ b/schema/v1/schema.unstable.json @@ -1509,7 +1509,7 @@ ] }, "EnumOption": { - "description": "A titled enum option with a const value and human-readable title.", + "description": "A titled enum option with a const value, human-readable title, and optional description.", "type": "object", "properties": { "const": { @@ -1519,6 +1519,10 @@ "title": { "description": "Human-readable title for this option.", "type": "string" + }, + "description": { + "description": "Optional description for this option value.", + "type": ["string", "null"] } }, "required": ["const", "title"] diff --git a/schema/v2/schema.unstable.json b/schema/v2/schema.unstable.json index a153590bc..551a1f56a 100644 --- a/schema/v2/schema.unstable.json +++ b/schema/v2/schema.unstable.json @@ -1694,7 +1694,7 @@ ] }, "EnumOption": { - "description": "A titled enum option with a const value and human-readable title.", + "description": "A titled enum option with a const value, human-readable title, and optional description.", "type": "object", "properties": { "const": { @@ -1704,6 +1704,10 @@ "title": { "description": "Human-readable title for this option.", "type": "string" + }, + "description": { + "description": "Optional description for this option value.", + "type": ["string", "null"] } }, "required": ["const", "title"] diff --git a/src/v1/elicitation.rs b/src/v1/elicitation.rs index 6ba41946a..9975dea58 100644 --- a/src/v1/elicitation.rs +++ b/src/v1/elicitation.rs @@ -60,7 +60,8 @@ pub enum ElicitationSchemaType { Object, } -/// A titled enum option with a const value and human-readable title. +/// A titled enum option with a const value, human-readable title, and optional description. +#[skip_serializing_none] #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)] #[non_exhaustive] pub struct EnumOption { @@ -69,6 +70,8 @@ pub struct EnumOption { pub value: String, /// Human-readable title for this option. pub title: String, + /// Optional description for this option value. + pub description: Option, } impl EnumOption { @@ -78,8 +81,16 @@ impl EnumOption { Self { value: value.into(), title: title.into(), + description: None, } } + + /// Optional description for this option value. + #[must_use] + pub fn description(mut self, description: impl IntoOption) -> Self { + self.description = description.into_option(); + self + } } /// Schema for string properties in an elicitation form. @@ -1763,7 +1774,7 @@ mod tests { let schema = ElicitationSchema::new().property( "country", StringPropertySchema::new().one_of(vec![ - EnumOption::new("us", "United States"), + EnumOption::new("us", "United States").description("Use US English spelling."), EnumOption::new("uk", "United Kingdom"), ]), true, @@ -1775,12 +1786,20 @@ mod tests { assert_eq!(one_of.len(), 2); assert_eq!(one_of[0]["const"], "us"); assert_eq!(one_of[0]["title"], "United States"); + assert_eq!(one_of[0]["description"], "Use US English spelling."); + assert!(one_of[1].get("description").is_none()); let roundtripped: ElicitationSchema = serde_json::from_value(json).unwrap(); if let ElicitationPropertySchema::String(s) = roundtripped.properties.get("country").unwrap() { - assert_eq!(s.one_of.as_ref().unwrap().len(), 2); + let one_of = s.one_of.as_ref().unwrap(); + assert_eq!(one_of.len(), 2); + assert_eq!( + one_of[0].description.as_deref(), + Some("Use US English spelling.") + ); + assert!(one_of[1].description.is_none()); } else { panic!("expected String variant"); } diff --git a/src/v2/conversion.rs b/src/v2/conversion.rs index f72a87921..3417269ef 100644 --- a/src/v2/conversion.rs +++ b/src/v2/conversion.rs @@ -7347,10 +7347,15 @@ impl IntoV1 for super::EnumOption { type Output = crate::v1::EnumOption; fn into_v1(self) -> Result { - let Self { value, title } = self; + let Self { + value, + title, + description, + } = self; Ok(crate::v1::EnumOption { value: value.into_v1()?, title: title.into_v1()?, + description: description.into_v1()?, }) } } @@ -7360,10 +7365,15 @@ impl IntoV2 for crate::v1::EnumOption { type Output = super::EnumOption; fn into_v2(self) -> Result { - let Self { value, title } = self; + let Self { + value, + title, + description, + } = self; Ok(super::EnumOption { value: value.into_v2()?, title: title.into_v2()?, + description: description.into_v2()?, }) } } diff --git a/src/v2/elicitation.rs b/src/v2/elicitation.rs index 69f5cd5da..0051c1347 100644 --- a/src/v2/elicitation.rs +++ b/src/v2/elicitation.rs @@ -67,7 +67,8 @@ pub enum ElicitationSchemaType { Object, } -/// A titled enum option with a const value and human-readable title. +/// A titled enum option with a const value, human-readable title, and optional description. +#[skip_serializing_none] #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)] #[non_exhaustive] pub struct EnumOption { @@ -76,6 +77,8 @@ pub struct EnumOption { pub value: String, /// Human-readable title for this option. pub title: String, + /// Optional description for this option value. + pub description: Option, } impl EnumOption { @@ -85,8 +88,16 @@ impl EnumOption { Self { value: value.into(), title: title.into(), + description: None, } } + + /// Optional description for this option value. + #[must_use] + pub fn description(mut self, description: impl IntoOption) -> Self { + self.description = description.into_option(); + self + } } /// Schema for string properties in an elicitation form. @@ -1767,7 +1778,7 @@ mod tests { let schema = ElicitationSchema::new().property( "country", StringPropertySchema::new().one_of(vec![ - EnumOption::new("us", "United States"), + EnumOption::new("us", "United States").description("Use US English spelling."), EnumOption::new("uk", "United Kingdom"), ]), true, @@ -1779,12 +1790,20 @@ mod tests { assert_eq!(one_of.len(), 2); assert_eq!(one_of[0]["const"], "us"); assert_eq!(one_of[0]["title"], "United States"); + assert_eq!(one_of[0]["description"], "Use US English spelling."); + assert!(one_of[1].get("description").is_none()); let roundtripped: ElicitationSchema = serde_json::from_value(json).unwrap(); if let ElicitationPropertySchema::String(s) = roundtripped.properties.get("country").unwrap() { - assert_eq!(s.one_of.as_ref().unwrap().len(), 2); + let one_of = s.one_of.as_ref().unwrap(); + assert_eq!(one_of.len(), 2); + assert_eq!( + one_of[0].description.as_deref(), + Some("Use US English spelling.") + ); + assert!(one_of[1].description.is_none()); } else { panic!("expected String variant"); }