Skip to content

Commit cb6e027

Browse files
authored
fix(unstable): Fix plan capability key (#1369)
Should match the rest of the fields in the object
1 parent 51d8f0a commit cb6e027

7 files changed

Lines changed: 21 additions & 24 deletions

File tree

docs/protocol/v1/draft/agent-plan.mdx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ Plans are execution strategies for complex tasks that require multiple steps.
77

88
Agents may share plans with Clients through [`session/update`](/protocol/v1/draft/prompt-turn#3-agent-reports-output) notifications, providing real-time visibility into their thinking and progress.
99

10-
The existing `plan` update is the baseline format. Clients that advertise `planCapabilities` during [initialization](/protocol/v1/draft/initialization#client-capabilities) can also receive identified plan operations through `plan_update` and `plan_removed`.
10+
The existing `plan` update is the baseline format. Clients that advertise `plan` during [initialization](/protocol/v1/draft/initialization#client-capabilities) can also receive identified plan operations through `plan_update` and `plan_removed`.
1111

1212
## Creating Plans
1313

@@ -50,7 +50,7 @@ When the language model creates an execution plan, the Agent **SHOULD** report i
5050

5151
## Plan Operations
5252

53-
Agents **MUST NOT** send `plan_update` or `plan_removed` unless the Client advertised `planCapabilities`. If the Client omits `planCapabilities`, the Agent **MUST** fall back to the existing `plan` update.
53+
Agents **MUST NOT** send `plan_update` or `plan_removed` unless the Client advertised `plan`. If the Client omits `plan`, the Agent **MUST** fall back to the existing `plan` update.
5454

5555
`plan_update` carries a `plan` object with a `type` discriminator. Every plan format includes a required `id` so Clients can track multiple plans independently.
5656

docs/protocol/v1/draft/schema.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3232,7 +3232,7 @@ This capability is not part of the spec yet, and may be removed or changed at an
32323232
NES (Next Edit Suggestions) capabilities supported by the client.
32333233

32343234
</ResponseField>
3235-
<ResponseField name="planCapabilities" type={<><span><a href="#plancapabilities">PlanCapabilities</a></span><span> | null</span></>} >
3235+
<ResponseField name="plan" type={<><span><a href="#plancapabilities">PlanCapabilities</a></span><span> | null</span></>} >
32363236
**UNSTABLE**
32373237

32383238
This capability is not part of the spec yet, and may be removed or changed at any point.

docs/rfds/plan-operations.mdx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,14 +36,14 @@ All variants carry a required `id: string` that identifies the plan, and an opti
3636

3737
Additionally, introduce a `plan_removed` session update type that carries only a plan `id` to signal dismissal. This keeps `plan_update` focused purely on content updates and makes removal a distinct, self-describing event.
3838

39-
The existing `plan` session update type is **not modified** and continues to work as before. Agents that want multi-plan support, new plan formats, or removal capabilities use `plan_update` and `plan_removed` only when the client advertises `planCapabilities`; otherwise they fall back to the existing `plan` session update type.
39+
The existing `plan` session update type is **not modified** and continues to work as before. Agents that want multi-plan support, new plan formats, or removal capabilities use `plan_update` and `plan_removed` only when the client advertises `plan`; otherwise they fall back to the existing `plan` session update type.
4040

4141
### Client Capabilities
4242

4343
Add to `ClientCapabilities`:
4444

4545
```
46-
planCapabilities?: PlanCapabilities
46+
plan?: PlanCapabilities
4747
```
4848

4949
This field is optional. When present as `{}`, it signals the client supports the `plan_update` and `plan_removed` session update types. When omitted, the client does not advertise support, and the agent must fall back to the existing `plan` session update type.
@@ -64,7 +64,7 @@ Agent sends a `plan_removed` session update with the plan's `id` to dismiss it.
6464

6565
> How will things will play out once this feature exists?
6666
67-
Agents will be able to present plans in the format most natural to them — structured checklists for step-by-step execution, markdown for free-form design docs, or file URIs for large plans generated externally. Clients that support `plan_update` can show multiple concurrent plans (e.g., a high-level strategy and a detailed implementation checklist), and dismiss plans that are no longer relevant. Clients that don't advertise `planCapabilities` continue to receive the existing `plan` updates with no changes.
67+
Agents will be able to present plans in the format most natural to them — structured checklists for step-by-step execution, markdown for free-form design docs, or file URIs for large plans generated externally. Clients that support `plan_update` can show multiple concurrent plans (e.g., a high-level strategy and a detailed implementation checklist), and dismiss plans that are no longer relevant. Clients that don't advertise `plan` continue to receive the existing `plan` updates with no changes.
6868

6969
## Implementation details and plan
7070

@@ -137,7 +137,7 @@ Removal:
137137
138138
### Why a new session update type instead of extending the existing `plan`?
139139

140-
The existing `plan` variant flattens `Plan`'s `entries` field directly into the `SessionUpdate` discriminated union object. Adding a nested `plan` field, optional `id`, and polymorphic types to the same variant would require breaking the existing format or complex dual-deserialization logic. A new `plan_update` variant avoids this, but agents must only send it to clients that advertised `planCapabilities`; clients that do not advertise support can continue to receive the existing `plan` update.
140+
The existing `plan` variant flattens `Plan`'s `entries` field directly into the `SessionUpdate` discriminated union object. Adding a nested `plan` field, optional `id`, and polymorphic types to the same variant would require breaking the existing format or complex dual-deserialization logic. A new `plan_update` variant avoids this, but agents must only send it to clients that advertised `plan`; clients that do not advertise support can continue to receive the existing `plan` update.
141141

142142
### Why a separate `plan_removed` session update type instead of a removal variant inside `plan_update`?
143143

docs/rfds/v2/plan-variants.mdx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ For now, v2 should stabilize only the item-based plan content variant:
2525
}
2626
```
2727

28-
The markdown, file, and removal pieces from [Plan Operations Support](/rfds/plan-operations) remain behind the unstable plan-operations feature while that RFD continues. V2 does not need a separate `planCapabilities` runtime handshake for those unstable operations.
28+
The markdown, file, and removal pieces from [Plan Operations Support](/rfds/plan-operations) remain behind the unstable plan-operations feature while that RFD continues. V2 does not need a separate `plan` runtime handshake for those unstable operations.
2929

3030
## Status quo
3131

@@ -55,10 +55,10 @@ ACP v2 should:
5555
- Stabilize only the `plan.type: "items"` content variant for now.
5656
- Keep unknown plan content variants parseable and preservable using the [v2 enum variant extension](/rfds/v2/enum-variant-extension) rules.
5757
- Require every plan content variant, including unknown future/custom variants, to carry a plan `id`.
58-
- Remove `ClientCapabilities.planCapabilities` from v2.
58+
- Remove `ClientCapabilities.plan` from v2.
5959
- Keep `markdown`, `file`, and `plan_removed` behind `unstable_plan_operations` until the Plan Operations RFD settles.
6060

61-
The stable v2 `plan_update` shape does not require a capability. The unstable plan operations remain gated by the draft unstable protocol surface, not by a v2 `planCapabilities` field.
61+
The stable v2 `plan_update` shape does not require a capability. The unstable plan operations remain gated by the draft unstable protocol surface, not by a v2 `plan` field.
6262

6363
### Compatibility
6464

@@ -93,7 +93,7 @@ Clients that only understand item-based plans can still preserve or display unkn
9393
9494
### Why not wait for the Plan Operations RFD to complete?
9595

96-
The item-based tagged shape is enough to make v2 extensible and remove the old flattened plan variant. The rest of the Plan Operations RFD can continue behind the unstable feature flag. V2 does not need `planCapabilities` because those operations are either part of the draft unstable protocol surface or absent from the stable schema.
96+
The item-based tagged shape is enough to make v2 extensible and remove the old flattened plan variant. The rest of the Plan Operations RFD can continue behind the unstable feature flag. V2 does not need `plan` because those operations are either part of the draft unstable protocol surface or absent from the stable schema.
9797

9898
### Why use `main` for v1 conversion?
9999

schema/schema.unstable.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1025,7 +1025,7 @@
10251025
"description": "**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nNES (Next Edit Suggestions) capabilities supported by the client.",
10261026
"x-deserialize-default-on-error": true
10271027
},
1028-
"planCapabilities": {
1028+
"plan": {
10291029
"anyOf": [
10301030
{
10311031
"$ref": "#/$defs/PlanCapabilities"

src/v1/client.rs

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1579,7 +1579,7 @@ pub struct ClientCapabilities {
15791579
#[serde_as(deserialize_as = "DefaultOnError")]
15801580
#[schemars(extend("x-deserialize-default-on-error" = true))]
15811581
#[serde(default)]
1582-
pub plan_capabilities: Option<PlanCapabilities>,
1582+
pub plan: Option<PlanCapabilities>,
15831583
/// **UNSTABLE**
15841584
///
15851585
/// This capability is not part of the spec yet, and may be removed or changed at any point.
@@ -1662,11 +1662,8 @@ impl ClientCapabilities {
16621662
/// Supplying `{}` means the client can receive both update types.
16631663
#[cfg(feature = "unstable_plan_operations")]
16641664
#[must_use]
1665-
pub fn plan_capabilities(
1666-
mut self,
1667-
plan_capabilities: impl IntoOption<PlanCapabilities>,
1668-
) -> Self {
1669-
self.plan_capabilities = plan_capabilities.into_option();
1665+
pub fn plan(mut self, plan: impl IntoOption<PlanCapabilities>) -> Self {
1666+
self.plan = plan.into_option();
16701667
self
16711668
}
16721669

@@ -2293,14 +2290,14 @@ mod tests {
22932290
})
22942291
);
22952292

2296-
let capabilities = ClientCapabilities::new().plan_capabilities(PlanCapabilities::new());
2293+
let capabilities = ClientCapabilities::new().plan(PlanCapabilities::new());
22972294
let json = serde_json::to_value(&capabilities).unwrap();
2298-
assert_eq!(json["planCapabilities"], json!({}));
2295+
assert_eq!(json["plan"], json!({}));
22992296

23002297
assert_eq!(
2301-
serde_json::from_value::<ClientCapabilities>(json!({ "planCapabilities": null }))
2298+
serde_json::from_value::<ClientCapabilities>(json!({ "plan": null }))
23022299
.unwrap()
2303-
.plan_capabilities,
2300+
.plan,
23042301
None
23052302
);
23062303
}

src/v2/conversion.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1665,7 +1665,7 @@ impl IntoV1 for super::ClientCapabilities {
16651665
fs: crate::v1::FileSystemCapabilities::default(),
16661666
terminal: false,
16671667
#[cfg(feature = "unstable_plan_operations")]
1668-
plan_capabilities: None,
1668+
plan: None,
16691669
#[cfg(feature = "unstable_auth_methods")]
16701670
auth: auth.into_v1()?,
16711671
#[cfg(feature = "unstable_elicitation")]
@@ -1687,7 +1687,7 @@ impl IntoV2 for crate::v1::ClientCapabilities {
16871687
fs: _,
16881688
terminal: _,
16891689
#[cfg(feature = "unstable_plan_operations")]
1690-
plan_capabilities: _,
1690+
plan: _,
16911691
#[cfg(feature = "unstable_auth_methods")]
16921692
auth,
16931693
#[cfg(feature = "unstable_elicitation")]

0 commit comments

Comments
 (0)