Skip to content

Commit 015e151

Browse files
authored
feat: Add unstable model config category (#1455)
1 parent 326623a commit 015e151

10 files changed

Lines changed: 171 additions & 12 deletions

File tree

Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ unstable = [
3838
"unstable_session_fork",
3939
"unstable_end_turn_token_usage",
4040
"unstable_boolean_config",
41+
"unstable_model_config_category",
4142
]
4243
# Protocol v2 is intentionally NOT part of the `unstable` umbrella.
4344
# It introduces a parallel `v2` module and (eventually) a different wire
@@ -54,6 +55,7 @@ unstable_plan_operations = []
5455
unstable_session_fork = []
5556
unstable_end_turn_token_usage = []
5657
unstable_boolean_config = []
58+
unstable_model_config_category = []
5759

5860
# Emit `tracing::warn!` events when `VecSkipError` drops a malformed list
5961
# entry during deserialization. When disabled (the default), the inspector

docs/protocol/v1/draft/schema.mdx

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7075,6 +7075,15 @@ Category names that do not begin with `_` are reserved for the ACP spec.
70757075
Model selector.
70767076
</ResponseField>
70777077

7078+
<ResponseField name="model_config" type="string">
7079+
**UNSTABLE**
7080+
7081+
This capability is not part of the spec yet, and may be removed or changed at any point.
7082+
7083+
Model-related configuration parameter.
7084+
7085+
</ResponseField>
7086+
70787087
<ResponseField name="thought_level" type="string">
70797088
Thought/reasoning level selector.
70807089
</ResponseField>

docs/protocol/v1/draft/session-config-options.mdx

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ title: "Session Config Options"
33
description: "Flexible configuration selectors for agent sessions"
44
---
55

6-
Agents can provide an arbitrary list of configuration options for a session, allowing Clients to offer users customizable selectors for things like models, modes, reasoning levels, and more.
6+
Agents can provide an arbitrary list of configuration options for a session, allowing Clients to offer users customizable selectors for things like models, model parameters, modes, reasoning levels, and more.
77

88
<Info>
99
Session Config Options are the preferred way to expose session-level
@@ -61,6 +61,23 @@ During [Session Setup](/protocol/v1/draft/session-setup) the Agent **MAY** retur
6161
"description": "The most powerful model"
6262
}
6363
]
64+
},
65+
{
66+
"id": "context_size",
67+
"name": "Context Size",
68+
"category": "model_config",
69+
"type": "select",
70+
"currentValue": "200k",
71+
"options": [
72+
{
73+
"value": "200k",
74+
"name": "200K"
75+
},
76+
{
77+
"value": "1m",
78+
"name": "1M"
79+
}
80+
]
6481
}
6582
]
6683
}
@@ -129,11 +146,14 @@ Each config option **MAY** include a `category` field. Categories are semantic m
129146

130147
Category names beginning with `_` are free for custom use (e.g., `_my_custom_category`). Category names that do not begin with `_` are reserved for the ACP spec.
131148

132-
| Category | Description |
133-
| --------------- | -------------------------------- |
134-
| `mode` | Session mode selector |
135-
| `model` | Model selector |
136-
| `thought_level` | Thought/reasoning level selector |
149+
| Category | Description |
150+
| --------------- | ------------------------------------------------------------------------ |
151+
| `mode` | Session mode selector |
152+
| `model` | Model selector |
153+
| `model_config` | Model-related parameter, such as context size or speed/quality trade-off |
154+
| `thought_level` | Thought/reasoning level selector |
155+
156+
Clients **SHOULD** render `model_config` options near the `model` selector, such as in the same popover or panel. No capability negotiation is required for category values.
137157

138158
When multiple options share the same category, Clients **SHOULD** use the array ordering to resolve ties, preferring earlier options in the list for prominent placement or keyboard shortcuts.
139159

docs/protocol/v2/draft/schema.mdx

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6912,6 +6912,15 @@ Category names that do not begin with `_` are reserved for the ACP spec.
69126912
Model selector.
69136913
</ResponseField>
69146914

6915+
<ResponseField name="model_config" type="string">
6916+
**UNSTABLE**
6917+
6918+
This capability is not part of the spec yet, and may be removed or changed at any point.
6919+
6920+
Model-related configuration parameter.
6921+
6922+
</ResponseField>
6923+
69156924
<ResponseField name="thought_level" type="string">
69166925
Thought/reasoning level selector.
69176926
</ResponseField>

docs/protocol/v2/draft/session-config-options.mdx

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ title: "Session Config Options"
33
description: "Flexible configuration selectors for agent sessions"
44
---
55

6-
Agents can provide an arbitrary list of configuration options for a session, allowing Clients to offer users customizable selectors for things like modes, models, reasoning levels, and more.
6+
Agents can provide an arbitrary list of configuration options for a session, allowing Clients to offer users customizable selectors for things like modes, models, model parameters, reasoning levels, and more.
77

88
## Initial State
99

@@ -54,6 +54,23 @@ During [Session Setup](/protocol/v2/draft/session-setup) the Agent **MAY** retur
5454
"description": "The most powerful model"
5555
}
5656
]
57+
},
58+
{
59+
"id": "context_size",
60+
"name": "Context Size",
61+
"category": "model_config",
62+
"type": "select",
63+
"currentValue": "200k",
64+
"options": [
65+
{
66+
"value": "200k",
67+
"name": "200K"
68+
},
69+
{
70+
"value": "1m",
71+
"name": "1M"
72+
}
73+
]
5774
}
5875
]
5976
}
@@ -122,11 +139,14 @@ Each config option **MAY** include a `category` field. Categories are semantic m
122139

123140
Category names beginning with `_` are free for custom use (e.g., `_my_custom_category`). Category names that do not begin with `_` are reserved for the ACP spec.
124141

125-
| Category | Description |
126-
| --------------- | -------------------------------- |
127-
| `mode` | Session mode selector |
128-
| `model` | Model selector |
129-
| `thought_level` | Thought/reasoning level selector |
142+
| Category | Description |
143+
| --------------- | ------------------------------------------------------------------------ |
144+
| `mode` | Session mode selector |
145+
| `model` | Model selector |
146+
| `model_config` | Model-related parameter, such as context size or speed/quality trade-off |
147+
| `thought_level` | Thought/reasoning level selector |
148+
149+
Clients **SHOULD** render `model_config` options near the `model` selector, such as in the same popover or panel. No capability negotiation is required for category values.
130150

131151
When multiple options share the same category, Clients **SHOULD** use the array ordering to resolve ties, preferring earlier options in the list for prominent placement or keyboard shortcuts.
132152

schema/v1/schema.unstable.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3696,6 +3696,11 @@
36963696
"type": "string",
36973697
"const": "model"
36983698
},
3699+
{
3700+
"description": "**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nModel-related configuration parameter.",
3701+
"type": "string",
3702+
"const": "model_config"
3703+
},
36993704
{
37003705
"description": "Thought/reasoning level selector.",
37013706
"type": "string",

schema/v2/schema.unstable.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4057,6 +4057,11 @@
40574057
"type": "string",
40584058
"const": "model"
40594059
},
4060+
{
4061+
"description": "**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nModel-related configuration parameter.",
4062+
"type": "string",
4063+
"const": "model_config"
4064+
},
40604065
{
40614066
"description": "Thought/reasoning level selector.",
40624067
"type": "string",

src/v1/agent.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2298,6 +2298,13 @@ pub enum SessionConfigOptionCategory {
22982298
Mode,
22992299
/// Model selector.
23002300
Model,
2301+
/// **UNSTABLE**
2302+
///
2303+
/// This capability is not part of the spec yet, and may be removed or changed at any point.
2304+
///
2305+
/// Model-related configuration parameter.
2306+
#[cfg(feature = "unstable_model_config_category")]
2307+
ModelConfig,
23012308
/// Thought/reasoning level selector.
23022309
ThoughtLevel,
23032310
/// Unknown / uncategorized selector.
@@ -5248,6 +5255,11 @@ mod test_serialization {
52485255
serde_json::to_value(&SessionConfigOptionCategory::Model).unwrap(),
52495256
json!("model")
52505257
);
5258+
#[cfg(feature = "unstable_model_config_category")]
5259+
assert_eq!(
5260+
serde_json::to_value(&SessionConfigOptionCategory::ModelConfig).unwrap(),
5261+
json!("model_config")
5262+
);
52515263
assert_eq!(
52525264
serde_json::to_value(&SessionConfigOptionCategory::ThoughtLevel).unwrap(),
52535265
json!("thought_level")
@@ -5262,6 +5274,11 @@ mod test_serialization {
52625274
serde_json::from_str::<SessionConfigOptionCategory>("\"model\"").unwrap(),
52635275
SessionConfigOptionCategory::Model
52645276
);
5277+
#[cfg(feature = "unstable_model_config_category")]
5278+
assert_eq!(
5279+
serde_json::from_str::<SessionConfigOptionCategory>("\"model_config\"").unwrap(),
5280+
SessionConfigOptionCategory::ModelConfig
5281+
);
52655282
assert_eq!(
52665283
serde_json::from_str::<SessionConfigOptionCategory>("\"thought_level\"").unwrap(),
52675284
SessionConfigOptionCategory::ThoughtLevel
@@ -5283,6 +5300,17 @@ mod test_serialization {
52835300
assert_eq!(json, json!("some_future_category"));
52845301
}
52855302

5303+
#[cfg(not(feature = "unstable_model_config_category"))]
5304+
#[test]
5305+
fn test_session_config_option_model_config_is_unknown_without_feature() {
5306+
let unknown: SessionConfigOptionCategory =
5307+
serde_json::from_str("\"model_config\"").unwrap();
5308+
assert_eq!(
5309+
unknown,
5310+
SessionConfigOptionCategory::Other("model_config".to_string())
5311+
);
5312+
}
5313+
52865314
#[test]
52875315
fn test_session_config_option_category_custom_categories() {
52885316
// Category names beginning with `_` are free for custom use

src/v2/agent.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2188,6 +2188,13 @@ pub enum SessionConfigOptionCategory {
21882188
Mode,
21892189
/// Model selector.
21902190
Model,
2191+
/// **UNSTABLE**
2192+
///
2193+
/// This capability is not part of the spec yet, and may be removed or changed at any point.
2194+
///
2195+
/// Model-related configuration parameter.
2196+
#[cfg(feature = "unstable_model_config_category")]
2197+
ModelConfig,
21912198
/// Thought/reasoning level selector.
21922199
ThoughtLevel,
21932200
/// Custom or future category.
@@ -5490,6 +5497,11 @@ mod test_serialization {
54905497
serde_json::to_value(&SessionConfigOptionCategory::Model).unwrap(),
54915498
json!("model")
54925499
);
5500+
#[cfg(feature = "unstable_model_config_category")]
5501+
assert_eq!(
5502+
serde_json::to_value(&SessionConfigOptionCategory::ModelConfig).unwrap(),
5503+
json!("model_config")
5504+
);
54935505
assert_eq!(
54945506
serde_json::to_value(&SessionConfigOptionCategory::ThoughtLevel).unwrap(),
54955507
json!("thought_level")
@@ -5504,6 +5516,11 @@ mod test_serialization {
55045516
serde_json::from_str::<SessionConfigOptionCategory>("\"model\"").unwrap(),
55055517
SessionConfigOptionCategory::Model
55065518
);
5519+
#[cfg(feature = "unstable_model_config_category")]
5520+
assert_eq!(
5521+
serde_json::from_str::<SessionConfigOptionCategory>("\"model_config\"").unwrap(),
5522+
SessionConfigOptionCategory::ModelConfig
5523+
);
55075524
assert_eq!(
55085525
serde_json::from_str::<SessionConfigOptionCategory>("\"thought_level\"").unwrap(),
55095526
SessionConfigOptionCategory::ThoughtLevel
@@ -5525,6 +5542,17 @@ mod test_serialization {
55255542
assert_eq!(json, json!("some_future_category"));
55265543
}
55275544

5545+
#[cfg(not(feature = "unstable_model_config_category"))]
5546+
#[test]
5547+
fn test_session_config_option_model_config_is_unknown_without_feature() {
5548+
let unknown: SessionConfigOptionCategory =
5549+
serde_json::from_str("\"model_config\"").unwrap();
5550+
assert_eq!(
5551+
unknown,
5552+
SessionConfigOptionCategory::Other("model_config".to_string())
5553+
);
5554+
}
5555+
55285556
#[test]
55295557
fn test_session_config_option_category_custom_categories() {
55305558
// Category names beginning with `_` are free for custom use

src/v2/conversion.rs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3875,6 +3875,8 @@ impl IntoV1 for super::SessionConfigOptionCategory {
38753875
Ok(match self {
38763876
Self::Mode => crate::v1::SessionConfigOptionCategory::Mode,
38773877
Self::Model => crate::v1::SessionConfigOptionCategory::Model,
3878+
#[cfg(feature = "unstable_model_config_category")]
3879+
Self::ModelConfig => crate::v1::SessionConfigOptionCategory::ModelConfig,
38783880
Self::ThoughtLevel => crate::v1::SessionConfigOptionCategory::ThoughtLevel,
38793881
Self::Other(value) => crate::v1::SessionConfigOptionCategory::Other(value.into_v1()?),
38803882
})
@@ -3888,6 +3890,8 @@ impl IntoV2 for crate::v1::SessionConfigOptionCategory {
38883890
Ok(match self {
38893891
Self::Mode => super::SessionConfigOptionCategory::Mode,
38903892
Self::Model => super::SessionConfigOptionCategory::Model,
3893+
#[cfg(feature = "unstable_model_config_category")]
3894+
Self::ModelConfig => super::SessionConfigOptionCategory::ModelConfig,
38913895
Self::ThoughtLevel => super::SessionConfigOptionCategory::ThoughtLevel,
38923896
Self::Other(value) => super::SessionConfigOptionCategory::Other(value.into_v2()?),
38933897
})
@@ -9009,6 +9013,35 @@ mod tests {
90099013
assert_eq!(error.message(), expected);
90109014
}
90119015

9016+
#[test]
9017+
fn round_trips_session_config_option_categories() {
9018+
for category in [
9019+
v1::SessionConfigOptionCategory::Mode,
9020+
v1::SessionConfigOptionCategory::Model,
9021+
#[cfg(feature = "unstable_model_config_category")]
9022+
v1::SessionConfigOptionCategory::ModelConfig,
9023+
v1::SessionConfigOptionCategory::ThoughtLevel,
9024+
v1::SessionConfigOptionCategory::Other("_custom_category".to_string()),
9025+
] {
9026+
assert_v1_round_trip::<v1::SessionConfigOptionCategory, v2::SessionConfigOptionCategory>(
9027+
category,
9028+
);
9029+
}
9030+
9031+
for category in [
9032+
v2::SessionConfigOptionCategory::Mode,
9033+
v2::SessionConfigOptionCategory::Model,
9034+
#[cfg(feature = "unstable_model_config_category")]
9035+
v2::SessionConfigOptionCategory::ModelConfig,
9036+
v2::SessionConfigOptionCategory::ThoughtLevel,
9037+
v2::SessionConfigOptionCategory::Other("_custom_category".to_string()),
9038+
] {
9039+
assert_v2_round_trip::<v2::SessionConfigOptionCategory, v1::SessionConfigOptionCategory>(
9040+
category,
9041+
);
9042+
}
9043+
}
9044+
90129045
#[test]
90139046
fn converts_v2_initialize_request_to_v1_without_serde() {
90149047
let request = v2::InitializeRequest::new(ProtocolVersion::V2);

0 commit comments

Comments
 (0)