Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion md/protocol-v2.md
Original file line number Diff line number Diff line change
Expand Up @@ -175,11 +175,19 @@ agent:
- If the agent rejects the v2 initialize request, the error is surfaced. A
rejected initialize is not treated as permission to retry with v1.

## Draft schema changes in schema 1.5
## Draft schema changes in schema 1.5 and 1.6

The `unstable_protocol_v2` API follows the moving draft schema. Schema 1.5 adds
semantic newtypes for paths, media types, IDs, and cursors; renames
`DiffPatch.diff` to `DiffPatch.text`; adds terminal state and output update
types; and makes v1/v2 conversions fallible and generic. These are draft API
changes rather than stable v1 wire changes. See [Migrating to
v2.0](./migration_v2.0.md#draft-v2-schema-updates) for concrete source changes.

Schema 1.6 adds `Cancelled` tool-call and plan-entry statuses to draft v2.
Programmatic tool-call names are available in both protocol versions through
the separate `unstable_tool_call_name` feature. Draft v2 users must enable both
`unstable_protocol_v2` and `unstable_tool_call_name`. In v2, an omitted name
leaves the existing value unchanged, `null` clears it, and a string replaces
it. V1 cannot clear an existing name, so converting a v2 `null` name to v1
fails.
5 changes: 5 additions & 0 deletions src/agent-client-protocol/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

## [Unreleased]

### Added

- *(unstable)* Expose programmatic tool-call names through the
`unstable_tool_call_name` feature.

### Fixed

- Allow the portable protocol engine and transport abstractions to build for
Expand Down
4 changes: 3 additions & 1 deletion src/agent-client-protocol/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,21 @@ rustdoc-args = ["--cfg", "docsrs"]
default = []

# Forward unstable features from agent-client-protocol-schema.
# Enable these to get support for the corresponding unstable ACP methods.
# Enable these to get support for the corresponding unstable ACP surfaces.
unstable = [
"unstable_auth_methods",
"unstable_elicitation",
"unstable_end_turn_token_usage",
"unstable_mcp_over_acp",
"unstable_session_fork",
"unstable_tool_call_name",
]
unstable_auth_methods = ["agent-client-protocol-schema/unstable_auth_methods"]
unstable_elicitation = ["agent-client-protocol-schema/unstable_elicitation"]
unstable_end_turn_token_usage = ["agent-client-protocol-schema/unstable_end_turn_token_usage"]
unstable_mcp_over_acp = ["agent-client-protocol-schema/unstable_mcp_over_acp"]
unstable_session_fork = ["agent-client-protocol-schema/unstable_session_fork"]
unstable_tool_call_name = ["agent-client-protocol-schema/unstable_tool_call_name"]
unstable_protocol_v2 = ["agent-client-protocol-schema/unstable_protocol_v2"]

[dependencies]
Expand Down
54 changes: 54 additions & 0 deletions src/agent-client-protocol/tests/schema_tool_call_name.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
#![cfg(feature = "unstable_tool_call_name")]

#[cfg(feature = "unstable_protocol_v2")]
use agent_client_protocol::schema::v1::ToolCallUpdate as V1ToolCallUpdate;
use agent_client_protocol::schema::v1::{ToolCall, ToolCallUpdateFields};
use serde_json::json;

#[test]
fn v1_tool_call_name_serializes_and_updates() {
let mut tool_call = ToolCall::new("call_1", "Read configuration").name("read_file");

assert_eq!(
serde_json::to_value(&tool_call).unwrap()["name"],
json!("read_file")
);

tool_call.update(ToolCallUpdateFields::new().name("write_file"));
assert_eq!(tool_call.name.as_deref(), Some("write_file"));

tool_call.update(ToolCallUpdateFields::new());
assert_eq!(tool_call.name.as_deref(), Some("write_file"));

let null_name: ToolCallUpdateFields = serde_json::from_value(json!({ "name": null })).unwrap();
tool_call.update(null_name);
assert_eq!(tool_call.name.as_deref(), Some("write_file"));
}

#[cfg(feature = "unstable_protocol_v2")]
#[test]
fn tool_call_name_preserves_v2_patch_semantics() {
use agent_client_protocol::schema::{
MaybeUndefined,
v2::{
ToolCallUpdate,
conversion::{try_v1_to_v2, try_v2_to_v1},
},
};

let named: ToolCallUpdate =
try_v1_to_v2(ToolCall::new("call_1", "Read configuration").name("read_file")).unwrap();
assert_eq!(named.name, MaybeUndefined::Value("read_file".to_string()));

let omitted: ToolCallUpdate =
try_v1_to_v2(V1ToolCallUpdate::new("call_1", ToolCallUpdateFields::new())).unwrap();
assert_eq!(omitted.name, MaybeUndefined::Undefined);

let cleared = ToolCallUpdate::new("call_1").name(None::<String>);
assert_eq!(cleared.name, MaybeUndefined::Null);
let error = try_v2_to_v1::<_, V1ToolCallUpdate>(cleared).unwrap_err();
assert_eq!(
error.message(),
"v2 ToolCallUpdate.name with null value cannot be represented in v1"
);
}