diff --git a/agent-client-protocol-schema/src/v2/conversion.rs b/agent-client-protocol-schema/src/v2/conversion.rs index 070a0c87..a33a07b3 100644 --- a/agent-client-protocol-schema/src/v2/conversion.rs +++ b/agent-client-protocol-schema/src/v2/conversion.rs @@ -1603,6 +1603,9 @@ impl TryToV1 for super::PlanEntryStatus { Self::Pending => crate::v1::PlanEntryStatus::Pending, Self::InProgress => crate::v1::PlanEntryStatus::InProgress, Self::Completed => crate::v1::PlanEntryStatus::Completed, + Self::Cancelled => { + return Err(unknown_v2_enum_variant("PlanEntryStatus", "cancelled")); + } Self::Other(value) => return Err(unknown_v2_enum_variant("PlanEntryStatus", &value)), }) } @@ -3189,6 +3192,9 @@ impl TryToV1 for super::ToolCallStatus { Self::InProgress => crate::v1::ToolCallStatus::InProgress, Self::Completed => crate::v1::ToolCallStatus::Completed, Self::Failed => crate::v1::ToolCallStatus::Failed, + Self::Cancelled => { + return Err(unknown_v2_enum_variant("ToolCallStatus", "cancelled")); + } Self::Other(value) => return Err(unknown_v2_enum_variant("ToolCallStatus", &value)), }) } @@ -10648,6 +10654,18 @@ mod tests { ); } + #[test] + fn v2_cancelled_statuses_do_not_convert_to_v1() { + assert_v2_to_v1_error( + v2::ToolCallStatus::Cancelled, + "v2 ToolCallStatus variant `cancelled` cannot be represented in v1", + ); + assert_v2_to_v1_error( + v2::PlanEntryStatus::Cancelled, + "v2 PlanEntryStatus variant `cancelled` cannot be represented in v1", + ); + } + #[test] fn v2_collection_conversion_fails_on_unrepresentable_items() { let response = v2::InitializeResponse::new( diff --git a/agent-client-protocol-schema/src/v2/plan.rs b/agent-client-protocol-schema/src/v2/plan.rs index de51ff78..6ec1c499 100644 --- a/agent-client-protocol-schema/src/v2/plan.rs +++ b/agent-client-protocol-schema/src/v2/plan.rs @@ -514,6 +514,8 @@ pub enum PlanEntryStatus { InProgress, /// The task has been successfully completed. Completed, + /// The task was cancelled before it completed. + Cancelled, /// Custom or future plan entry status. /// /// Values beginning with `_` are reserved for implementation-specific @@ -541,6 +543,13 @@ mod tests { assert_eq!(serde_json::to_value(&status).unwrap(), "blocked"); } + #[test] + fn plan_entry_status_recognizes_cancelled_variant() { + let status: PlanEntryStatus = serde_json::from_str("\"cancelled\"").unwrap(); + assert_eq!(status, PlanEntryStatus::Cancelled); + assert_eq!(serde_json::to_value(&status).unwrap(), "cancelled"); + } + #[test] fn plan_update_content_preserves_unknown_variant() { let content: PlanUpdateContent = serde_json::from_value(serde_json::json!({ diff --git a/agent-client-protocol-schema/src/v2/tool_call.rs b/agent-client-protocol-schema/src/v2/tool_call.rs index 34f8b516..45dbf0fb 100644 --- a/agent-client-protocol-schema/src/v2/tool_call.rs +++ b/agent-client-protocol-schema/src/v2/tool_call.rs @@ -330,6 +330,8 @@ pub enum ToolCallStatus { Completed, /// The tool call failed with an error. Failed, + /// The tool call was cancelled before it completed. + Cancelled, /// Custom or future tool call status. /// /// Values beginning with `_` are reserved for implementation-specific @@ -1244,6 +1246,13 @@ mod tests { assert_eq!(serde_json::to_value(&status).unwrap(), "deferred"); } + #[test] + fn tool_call_status_recognizes_cancelled_variant() { + let status: ToolCallStatus = serde_json::from_str("\"cancelled\"").unwrap(); + assert_eq!(status, ToolCallStatus::Cancelled); + assert_eq!(serde_json::to_value(&status).unwrap(), "cancelled"); + } + #[test] fn tool_call_content_preserves_unknown_variant() { let content: ToolCallContent = serde_json::from_value(serde_json::json!({ diff --git a/docs/protocol/v2/agent-plan.mdx b/docs/protocol/v2/agent-plan.mdx index 8e7da726..960828db 100644 --- a/docs/protocol/v2/agent-plan.mdx +++ b/docs/protocol/v2/agent-plan.mdx @@ -95,6 +95,7 @@ Custom or future priority values can be used for display hints. Custom prioritie - `pending` - `in_progress` - `completed` +- `cancelled` Custom or future status values can be used when Clients can preserve or display a generic plan-entry state. Custom statuses **MUST** begin with `_`; unknown non-underscore statuses are reserved for future ACP variants. diff --git a/docs/protocol/v2/draft/agent-plan.mdx b/docs/protocol/v2/draft/agent-plan.mdx index 4f46ec47..26ece2e4 100644 --- a/docs/protocol/v2/draft/agent-plan.mdx +++ b/docs/protocol/v2/draft/agent-plan.mdx @@ -161,6 +161,7 @@ Custom or future priority values can be used for display hints. Custom prioritie - `pending` - `in_progress` - `completed` +- `cancelled` Custom or future status values can be used when Clients can preserve or display a generic plan-entry state. Custom statuses **MUST** begin with `_`; unknown non-underscore statuses are reserved for future ACP variants. diff --git a/docs/protocol/v2/draft/schema.mdx b/docs/protocol/v2/draft/schema.mdx index 86af8b06..64d440ec 100644 --- a/docs/protocol/v2/draft/schema.mdx +++ b/docs/protocol/v2/draft/schema.mdx @@ -6482,6 +6482,10 @@ See protocol docs: [Plan Entries](https://agentclientprotocol.com/protocol/v2/dr The task has been successfully completed. + + The task was cancelled before it completed. + + Custom or future plan entry status. @@ -9225,6 +9229,10 @@ See protocol docs: [Status](https://agentclientprotocol.com/protocol/v2/draft/to The tool call failed with an error. + + The tool call was cancelled before it completed. + + Custom or future tool call status. diff --git a/docs/protocol/v2/draft/tool-calls.mdx b/docs/protocol/v2/draft/tool-calls.mdx index e6d9acae..86209370 100644 --- a/docs/protocol/v2/draft/tool-calls.mdx +++ b/docs/protocol/v2/draft/tool-calls.mdx @@ -339,6 +339,10 @@ Tool calls progress through different statuses during their lifecycle: The tool call failed with an error + + The tool call was cancelled before it completed + + Custom or future status values can be used when Clients can display a generic progress state. Custom status values **MUST** begin with `_`; unknown non-underscore statuses are reserved for future ACP variants. ## Content diff --git a/docs/protocol/v2/migration.mdx b/docs/protocol/v2/migration.mdx index 9efdb304..dfc2577e 100644 --- a/docs/protocol/v2/migration.mdx +++ b/docs/protocol/v2/migration.mdx @@ -348,7 +348,7 @@ v1 had `tool_call` (create) and `tool_call_update` (modify). In practice the spl } ``` -The patch semantics are the same three-state model as messages: omitted fields stay unchanged, `null` explicitly clears a field, and concrete values replace. Array fields such as `content` and `locations` are replaced wholesale when present. The field set (`title`, `kind`, `status`, `content`, `locations`, `rawInput`, `rawOutput`) and the `kind`/`status` values are unchanged from v1, though the enums are now extensible. +The patch semantics are the same three-state model as messages: omitted fields stay unchanged, `null` explicitly clears a field, and concrete values replace. Array fields such as `content` and `locations` are replaced wholesale when present. The field set (`title`, `kind`, `status`, `content`, `locations`, `rawInput`, `rawOutput`) and `kind` values are unchanged from v1. The `status` enum adds `cancelled`, and both enums are now extensible. ### Streaming tool-call content @@ -550,7 +550,7 @@ The v1 `plan` update was a flat entries list with no identity and no room to gro -Stable v2 defines the `items` plan type. The entry shape (`content`, `priority`, `status`, all required) is unchanged from v1, and entry priorities and statuses are now extensible enums. Each `plan_update` for a given `planId` replaces that plan's entries, and the `planId` allows multiple plans per session and future plan content types (such as markdown or file-backed plans, which remain unstable) without another breaking change. +Stable v2 defines the `items` plan type. The entry shape (`content`, `priority`, `status`, all required) is unchanged from v1. Entry priorities and statuses are now extensible enums, and `status` adds `cancelled`. Each `plan_update` for a given `planId` replaces that plan's entries, and the `planId` allows multiple plans per session and future plan content types (such as markdown or file-backed plans, which remain unstable) without another breaking change. ## Session setup and lifecycle diff --git a/docs/protocol/v2/schema.mdx b/docs/protocol/v2/schema.mdx index af57e9f2..89bed140 100644 --- a/docs/protocol/v2/schema.mdx +++ b/docs/protocol/v2/schema.mdx @@ -2846,6 +2846,10 @@ See protocol docs: [Plan Entries](https://agentclientprotocol.com/protocol/v2/ag The task has been successfully completed. + + The task was cancelled before it completed. + + Custom or future plan entry status. @@ -5010,6 +5014,10 @@ See protocol docs: [Status](https://agentclientprotocol.com/protocol/v2/tool-cal The tool call failed with an error. + + The tool call was cancelled before it completed. + + Custom or future tool call status. diff --git a/docs/protocol/v2/tool-calls.mdx b/docs/protocol/v2/tool-calls.mdx index e9512f6c..6495353f 100644 --- a/docs/protocol/v2/tool-calls.mdx +++ b/docs/protocol/v2/tool-calls.mdx @@ -339,6 +339,10 @@ Tool calls progress through different statuses during their lifecycle: The tool call failed with an error + + The tool call was cancelled before it completed + + Custom or future status values can be used when Clients can display a generic progress state. Custom status values **MUST** begin with `_`; unknown non-underscore statuses are reserved for future ACP variants. ## Content diff --git a/docs/rfds/v2/plan-variants.mdx b/docs/rfds/v2/plan-variants.mdx index f4dd76e7..64ec07d7 100644 --- a/docs/rfds/v2/plan-variants.mdx +++ b/docs/rfds/v2/plan-variants.mdx @@ -64,7 +64,7 @@ The stable v2 `plan_update` shape does not require a capability. The unstable pl When converting a v1 single-plan update to v2, implementations should use the item-based `plan_update` shape with a stable synthetic plan ID of `main`. -When converting v2 back to a v1 surface that does not support unstable plan operations, an item-based `plan_update` can be represented as the old v1 `plan` update by dropping the plan ID. Other plan content variants cannot be represented without the unstable v1 plan operations surface. +When converting v2 back to a v1 surface that does not support unstable plan operations, an item-based `plan_update` whose entries use v1-representable priorities and statuses can be represented as the old v1 `plan` update by dropping the plan ID. Other plan content variants cannot be represented without the unstable v1 plan operations surface. ## Shiny future diff --git a/docs/rfds/v2/tool-call-updates.mdx b/docs/rfds/v2/tool-call-updates.mdx index 13630da6..fcae5ff1 100644 --- a/docs/rfds/v2/tool-call-updates.mdx +++ b/docs/rfds/v2/tool-call-updates.mdx @@ -94,7 +94,7 @@ There is a single way to update a tool call, removing lots of confusion from how When converting v1 to v2, both v1 `tool_call` and v1 `tool_call_update` should map to v2 `tool_call_update`. -When converting v2 back to v1, adapters can represent a v2 update as a v1 `ToolCallUpdate`. This is lossy for some explicit clear operations because v1 update fields cannot represent every distinction between omitted and `null`. Collection clears can be represented as empty arrays, but scalar/raw-field clears may have to be omitted when targeting v1. This will be a best-effort conversion. +When converting v2 back to v1, adapters can represent compatible v2 updates as a v1 `ToolCallUpdate`. Conversion is also lossy for some explicit clear operations because v1 update fields cannot represent every distinction between omitted and `null`. Collection clears can be represented as empty arrays, but scalar/raw-field clears may have to be omitted when targeting v1. This will be a best-effort conversion. `tool_call_content_chunk` cannot be represented by the stateless v2-to-v1 conversion helper because v1 tool-call content updates replace the whole content array rather than appending one item. A stateful bridge can choose to accumulate chunks and emit replacement arrays to v1 clients. diff --git a/schema/v2/schema.json b/schema/v2/schema.json index 5f7242a5..a987af0c 100644 --- a/schema/v2/schema.json +++ b/schema/v2/schema.json @@ -816,6 +816,11 @@ "type": "string", "const": "failed" }, + { + "description": "The tool call was cancelled before it completed.", + "type": "string", + "const": "cancelled" + }, { "title": "other", "description": "Custom or future tool call status.\n\nValues beginning with `_` are reserved for implementation-specific\nextensions. Unknown values that do not begin with `_` are reserved for\nfuture ACP variants.", @@ -4390,6 +4395,11 @@ "type": "string", "const": "completed" }, + { + "description": "The task was cancelled before it completed.", + "type": "string", + "const": "cancelled" + }, { "title": "other", "description": "Custom or future plan entry status.\n\nValues beginning with `_` are reserved for implementation-specific\nextensions. Unknown values that do not begin with `_` are reserved for\nfuture ACP variants.", diff --git a/schema/v2/schema.unstable.json b/schema/v2/schema.unstable.json index 82ebe9d8..a8110a82 100644 --- a/schema/v2/schema.unstable.json +++ b/schema/v2/schema.unstable.json @@ -960,6 +960,11 @@ "type": "string", "const": "failed" }, + { + "description": "The tool call was cancelled before it completed.", + "type": "string", + "const": "cancelled" + }, { "title": "other", "description": "Custom or future tool call status.\n\nValues beginning with `_` are reserved for implementation-specific\nextensions. Unknown values that do not begin with `_` are reserved for\nfuture ACP variants.", @@ -6991,6 +6996,11 @@ "type": "string", "const": "completed" }, + { + "description": "The task was cancelled before it completed.", + "type": "string", + "const": "cancelled" + }, { "title": "other", "description": "Custom or future plan entry status.\n\nValues beginning with `_` are reserved for implementation-specific\nextensions. Unknown values that do not begin with `_` are reserved for\nfuture ACP variants.",