You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat(unstable): Add config option type for boolean on/off toggles (#576)
* Add flag config option type for boolean on/off toggles
* Update to make this less breaking
---------
Co-authored-by: Ben Brandt <benjamin.j.brandt@gmail.com>
Copy file name to clipboardExpand all lines: docs/rfds/boolean-config-option.mdx
+32-11Lines changed: 32 additions & 11 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -19,7 +19,7 @@ However, there is no native way to represent a simple boolean on/off toggle. To
19
19
20
20
- Add a `SessionConfigBoolean` struct with a `current_value: bool` field
21
21
- Add a `Boolean(SessionConfigBoolean)` variant to the `SessionConfigKind` enum, discriminated by `"type": "boolean"`
22
-
- Add a `SessionConfigOptionValue` enum (untagged: `String` | `Bool`) so that `SetSessionConfigOptionRequest.value` can accept both string values (for `select`) and boolean values (for `flag`)
22
+
- Add a `SessionConfigOptionValue`internally-tagged enum so that `SetSessionConfigOptionRequest` can carry both string values (for `select`) and boolean values (for `boolean`) with an explicit `type` discriminator
23
23
- Provide convenience constructors and `From` impls for ergonomic usage
24
24
- Update documentation and regenerate schema files
25
25
@@ -65,7 +65,9 @@ In a `session/new` response (or any response containing `configOptions`):
65
65
66
66
### Wire format: setting a boolean option
67
67
68
-
The `session/set_config_option` request uses a string value, consistent with `select` options:
68
+
The `session/set_config_option` request carries a `type` discriminator alongside the `value`. The `type` field describes the _shape_ of the value, not the option kind.
69
+
70
+
When `type` is absent the value is treated as a `SessionConfigValueId` string, preserving backwards compatibility with existing clients:
69
71
70
72
```json
71
73
{
@@ -75,11 +77,27 @@ The `session/set_config_option` request uses a string value, consistent with `se
75
77
"params": {
76
78
"sessionId": "sess_abc123",
77
79
"configId": "brave_mode",
80
+
"type": "boolean",
78
81
"value": true
79
82
}
80
83
}
81
84
```
82
85
86
+
For select options the `type` field can be omitted (defaults to `value_id`):
87
+
88
+
```json
89
+
{
90
+
"jsonrpc": "2.0",
91
+
"id": 3,
92
+
"method": "session/set_config_option",
93
+
"params": {
94
+
"sessionId": "sess_abc123",
95
+
"configId": "mode",
96
+
"value": "code"
97
+
}
98
+
}
99
+
```
100
+
83
101
The response returns the full set of config options with current values, as with `select`:
84
102
85
103
```json
@@ -108,15 +126,17 @@ The response returns the full set of config options with current values, as with
108
126
}
109
127
```
110
128
111
-
A working implementation is available at: https://github.com/fscarponi/agent-client-protocol/tree/fabrizio.scarponi/flag-config-option
112
-
113
129
Key changes:
114
130
115
-
1.`SessionConfigFlag` struct with `current_value: bool`
116
-
2.`Flag` variant in `SessionConfigKind` (tagged via `"type": "flag"`)
117
-
3.`SessionConfigOptionValue` untagged enum (`String` | `Bool`) replacing `SessionConfigValueId` in `SetSessionConfigOptionRequest.value`
1.`SessionConfigBoolean` struct with `current_value: bool`
132
+
2.`Boolean(SessionConfigBoolean)` variant in `SessionConfigKind` (tagged via `"type": "boolean"`)
133
+
3.`SessionConfigOptionValue` enum using `#[serde(tag = "type")]` with a `#[serde(untagged)]` fallback variant — the same pattern as `AuthMethod`:
134
+
-`Boolean { value: bool }` — matched when `type` is `"boolean"`
135
+
-`ValueId { value: SessionConfigValueId }` — untagged fallback when `type` is absent or unrecognised
136
+
4.`SessionConfigOptionValue` is flattened (`#[serde(flatten)]`) onto `SetSessionConfigOptionRequest`, producing top-level `type` and `value` fields on the wire
137
+
5. The `value` field type change in `SetSessionConfigOptionRequest` is gated behind `#[cfg(feature = "unstable_boolean_config")]` — without the feature the field remains `SessionConfigValueId`
138
+
6.`From` impls (`&str`, `SessionConfigValueId`, `bool`) ensure ergonomic construction
139
+
7. Wire-level backward compatible: existing JSON payloads without a `type` field remain valid via the untagged fallback
120
140
121
141
### Client capabilities
122
142
@@ -126,12 +146,13 @@ Per the existing protocol design, clients that receive a config option with an u
126
146
127
147
### What alternative approaches did you consider, and why did you settle on this one?
128
148
129
-
We considered reusing the existing `select` type with a convention (e.g., options named "on"/"off"), but this would require clients to implement non-agnostic detection logic, which contradicts the goal of a standardized protocol. A dedicated `flag` type is cleaner and lets clients render the appropriate UI control without guessing.
149
+
We considered reusing the existing `select` type with a convention (e.g., options named "on"/"off"), but this would require clients to implement non-agnostic detection logic, which contradicts the goal of a standardized protocol. A dedicated `boolean` type is cleaner and lets clients render the appropriate UI control without guessing.
130
150
131
151
### Is this a breaking change?
132
152
133
-
On the wire/JSON level: no. `SessionConfigOptionValue` uses `#[serde(untagged)]`, so existing string payloads deserialize correctly. On the Rust API level: the type of `SetSessionConfigOptionRequest.value`changed, but `From` impls ensure source compatibility for users of the `new()` constructor.
153
+
On the wire/JSON level: no. When `type` is absent the value is treated as a `SessionConfigValueId`, so existing payloads deserialize correctly. On the Rust API level: the type of `SetSessionConfigOptionRequest.value`changes, but this is gated behind `unstable_boolean_config`. Without the feature flag the stable API is unchanged. With the feature flag,`From` impls ensure source compatibility for users of the `new()` constructor.
134
154
135
155
## Revision history
136
156
137
157
- 2026-02-24: Initial proposal
158
+
- 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`
Copy file name to clipboardExpand all lines: schema/schema.unstable.json
+61-9Lines changed: 61 additions & 9 deletions
Original file line number
Diff line number
Diff line change
@@ -2882,6 +2882,17 @@
2882
2882
},
2883
2883
"type": "object"
2884
2884
},
2885
+
"SessionConfigBoolean": {
2886
+
"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.",
2887
+
"properties": {
2888
+
"currentValue": {
2889
+
"description": "The current value of the boolean option.",
2890
+
"type": "boolean"
2891
+
}
2892
+
},
2893
+
"required": ["currentValue"],
2894
+
"type": "object"
2895
+
},
2885
2896
"SessionConfigGroupId": {
2886
2897
"description": "Unique identifier for a session configuration option value group.",
2887
2898
"type": "string"
@@ -2911,6 +2922,22 @@
2911
2922
},
2912
2923
"required": ["type"],
2913
2924
"type": "object"
2925
+
},
2926
+
{
2927
+
"allOf": [
2928
+
{
2929
+
"$ref": "#/$defs/SessionConfigBoolean"
2930
+
}
2931
+
],
2932
+
"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.",
2933
+
"properties": {
2934
+
"type": {
2935
+
"const": "boolean",
2936
+
"type": "string"
2937
+
}
2938
+
},
2939
+
"required": ["type"],
2940
+
"type": "object"
2914
2941
}
2915
2942
],
2916
2943
"properties": {
@@ -3475,6 +3502,39 @@
3475
3502
]
3476
3503
},
3477
3504
"SetSessionConfigOptionRequest": {
3505
+
"anyOf": [
3506
+
{
3507
+
"description": "A boolean value (`type: \"boolean\"`).",
3508
+
"properties": {
3509
+
"type": {
3510
+
"const": "boolean",
3511
+
"type": "string"
3512
+
},
3513
+
"value": {
3514
+
"description": "The boolean value.",
3515
+
"type": "boolean"
3516
+
}
3517
+
},
3518
+
"required": ["type", "value"],
3519
+
"type": "object"
3520
+
},
3521
+
{
3522
+
"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.",
3523
+
"properties": {
3524
+
"value": {
3525
+
"allOf": [
3526
+
{
3527
+
"$ref": "#/$defs/SessionConfigValueId"
3528
+
}
3529
+
],
3530
+
"description": "The value ID."
3531
+
}
3532
+
},
3533
+
"required": ["value"],
3534
+
"title": "value_id",
3535
+
"type": "object"
3536
+
}
3537
+
],
3478
3538
"description": "Request parameters for setting a session configuration option.",
3479
3539
"properties": {
3480
3540
"_meta": {
@@ -3497,17 +3557,9 @@
3497
3557
}
3498
3558
],
3499
3559
"description": "The ID of the session to set the configuration option for."
3500
-
},
3501
-
"value": {
3502
-
"allOf": [
3503
-
{
3504
-
"$ref": "#/$defs/SessionConfigValueId"
3505
-
}
3506
-
],
3507
-
"description": "The ID of the configuration option value to set."
0 commit comments