Skip to content

Commit d8fef2b

Browse files
feat(acp): route session/setTitle to the new schema types
Wires the SetSessionTitleRequest / SetSessionTitleResponse types into the agent-side JSON-RPC dispatch tables. Companion to agentclientprotocol/agent-client-protocol#1199, which adds the schema definitions for session/setTitle. This PR is the Rust SDK half of the round trip: once the schema crate ships a release with the new types, ACP-backed agents can implement Agent::set_session_title and have it dispatched here.
1 parent a9affa6 commit d8fef2b

9 files changed

Lines changed: 118 additions & 45 deletions

File tree

Cargo.lock

Lines changed: 2 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ agent-client-protocol-trace-viewer = { path = "src/agent-client-protocol-trace-v
3737
yopo = { package = "agent-client-protocol-yopo", path = "src/yopo" }
3838

3939
# Protocol
40-
agent-client-protocol-schema = { version = "=1.1.0", features = ["tracing"] }
40+
agent-client-protocol-schema = { version = "=1.2.0", features = ["tracing"] }
4141

4242
# Core async runtime
4343
tokio = { version = "1.52", default-features = false }
@@ -113,3 +113,7 @@ struct_field_names = "allow"
113113
too_many_lines = "allow"
114114
type_complexity = "allow"
115115
wildcard_imports = "allow"
116+
117+
[patch.crates-io]
118+
# Temporary: consume session/setTitle schema types before they are released.
119+
agent-client-protocol-schema = { git = "https://github.com/daniel-agentee/agent-client-protocol", rev = "a19eb3b2cf8092e03a22ec7aad64cdccc132a9d3" }

src/agent-client-protocol/src/capabilities.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ mod tests {
142142

143143
#[test]
144144
fn test_add_capability_to_request() {
145-
let request = InitializeRequest::new(ProtocolVersion::LATEST);
145+
let request = InitializeRequest::new(ProtocolVersion::V1);
146146

147147
let request = request.add_meta_capability(TestCapability);
148148

@@ -165,8 +165,8 @@ mod tests {
165165
);
166166
let client_capabilities = ClientCapabilities::new().meta(meta);
167167

168-
let request = InitializeRequest::new(ProtocolVersion::LATEST)
169-
.client_capabilities(client_capabilities);
168+
let request =
169+
InitializeRequest::new(ProtocolVersion::V1).client_capabilities(client_capabilities);
170170

171171
let request = request.remove_meta_capability(TestCapability);
172172

@@ -175,7 +175,7 @@ mod tests {
175175

176176
#[test]
177177
fn test_add_capability_to_response() {
178-
let response = InitializeResponse::new(ProtocolVersion::LATEST);
178+
let response = InitializeResponse::new(ProtocolVersion::V1);
179179

180180
let response = response.add_meta_capability(TestCapability);
181181

@@ -198,8 +198,8 @@ mod tests {
198198
);
199199
let client_capabilities = ClientCapabilities::new().meta(meta);
200200

201-
let request = InitializeRequest::new(ProtocolVersion::LATEST)
202-
.client_capabilities(client_capabilities);
201+
let request =
202+
InitializeRequest::new(ProtocolVersion::V1).client_capabilities(client_capabilities);
203203

204204
assert!(!request.has_meta_capability(TestCapability));
205205
}
@@ -216,8 +216,8 @@ mod tests {
216216
);
217217
let client_capabilities = ClientCapabilities::new().meta(meta);
218218

219-
let request = InitializeRequest::new(ProtocolVersion::LATEST)
220-
.client_capabilities(client_capabilities);
219+
let request =
220+
InitializeRequest::new(ProtocolVersion::V1).client_capabilities(client_capabilities);
221221

222222
assert!(!request.has_meta_capability(TestCapability));
223223
}

src/agent-client-protocol/src/jsonrpc/protocol_compat.rs

Lines changed: 42 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -536,7 +536,11 @@ mod imp {
536536
}
537537

538538
fn public_to_v2_message(message: UntypedMessage) -> Result<UntypedMessage, crate::Error> {
539-
let UntypedMessage { method, params } = message;
539+
let UntypedMessage { method, mut params } = message;
540+
541+
if method == "initialize" {
542+
ensure_legacy_initialize_info(&mut params, "clientInfo");
543+
}
540544

541545
if let Some(message) = try_convert_message_to_v2::<ClientRequest>(&method, &params)? {
542546
return Ok(message);
@@ -573,8 +577,12 @@ mod imp {
573577

574578
fn public_to_v2_response(
575579
method: &str,
576-
value: serde_json::Value,
580+
mut value: serde_json::Value,
577581
) -> Result<serde_json::Value, crate::Error> {
582+
if method == "initialize" {
583+
ensure_legacy_initialize_info(&mut value, "agentInfo");
584+
}
585+
578586
if let Some(value) = try_convert_response_to_v2::<AgentResponse>(method, &value)? {
579587
return Ok(value);
580588
}
@@ -585,6 +593,27 @@ mod imp {
585593
Ok(value)
586594
}
587595

596+
fn ensure_legacy_initialize_info(value: &mut serde_json::Value, field: &str) {
597+
let serde_json::Value::Object(object) = value else {
598+
return;
599+
};
600+
601+
let needs_default = match object.get(field) {
602+
Some(value) => value.is_null(),
603+
None => true,
604+
};
605+
606+
if needs_default {
607+
object.insert(
608+
field.into(),
609+
serde_json::json!({
610+
"name": "legacy-acp-peer",
611+
"version": "unknown",
612+
}),
613+
);
614+
}
615+
}
616+
588617
fn v2_to_public_response(
589618
method: &str,
590619
value: serde_json::Value,
@@ -728,6 +757,10 @@ mod imp {
728757
.negotiated
729758
}
730759

760+
fn v2_implementation() -> v2::Implementation {
761+
v2::Implementation::new("rust-sdk-test", "0.0.0")
762+
}
763+
731764
#[test]
732765
fn initialize_request_sets_active_wire_version_before_response() -> Result<(), crate::Error>
733766
{
@@ -736,7 +769,7 @@ mod imp {
736769

737770
compat.incoming_message(UntypedMessage::new(
738771
"initialize",
739-
v2::InitializeRequest::new(ProtocolVersion::V2),
772+
v2::InitializeRequest::new(ProtocolVersion::V2, v2_implementation()),
740773
)?)?;
741774

742775
assert_eq!(negotiated(&compat), ProtocolVersionKind::V1);
@@ -746,6 +779,7 @@ mod imp {
746779
"initialize",
747780
Ok(serde_json::to_value(v2::InitializeResponse::new(
748781
ProtocolVersion::V2,
782+
v2_implementation(),
749783
))?),
750784
)?;
751785

@@ -762,7 +796,7 @@ mod imp {
762796

763797
compat.outgoing_message(UntypedMessage::new(
764798
"initialize",
765-
v2::InitializeRequest::new(ProtocolVersion::V1),
799+
v2::InitializeRequest::new(ProtocolVersion::V1, v2_implementation()),
766800
)?)?;
767801

768802
assert_eq!(negotiated(&compat), ProtocolVersionKind::V1);
@@ -772,6 +806,7 @@ mod imp {
772806
"initialize",
773807
Ok(serde_json::to_value(v2::InitializeResponse::new(
774808
ProtocolVersion::V2,
809+
v2_implementation(),
775810
))?),
776811
)?;
777812

@@ -788,7 +823,7 @@ mod imp {
788823

789824
compat.outgoing_message(UntypedMessage::new(
790825
"initialize",
791-
v2::InitializeRequest::new(ProtocolVersion::V1),
826+
v2::InitializeRequest::new(ProtocolVersion::V1, v2_implementation()),
792827
)?)?;
793828

794829
assert_eq!(negotiated(&compat), ProtocolVersionKind::V1);
@@ -814,7 +849,7 @@ mod imp {
814849
let compat = ProtocolCompat::new(ProtocolMode::v2_client());
815850
compat.outgoing_message(UntypedMessage::new(
816851
"initialize",
817-
v2::InitializeRequest::new(ProtocolVersion::V1),
852+
v2::InitializeRequest::new(ProtocolVersion::V1, v2_implementation()),
818853
)?)?;
819854

820855
let error = compat
@@ -838,7 +873,7 @@ mod imp {
838873
let compat = ProtocolCompat::new(ProtocolMode::v2_agent());
839874
let messages = compat.outgoing_notification(UntypedMessage::new(
840875
"session/update",
841-
v2::SessionNotification::new(
876+
v2::UpdateSessionNotification::new(
842877
"sess",
843878
v2::SessionUpdate::AgentMessage(v2::AgentMessage::new("msg_agent").content(
844879
vec![

src/agent-client-protocol/src/schema/client_to_agent/requests.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use crate::schema::v1::{
55
LogoutRequest, LogoutResponse, NewSessionRequest, NewSessionResponse, PromptRequest,
66
PromptResponse, ResumeSessionRequest, ResumeSessionResponse, SetSessionConfigOptionRequest,
77
SetSessionConfigOptionResponse, SetSessionModeRequest, SetSessionModeResponse,
8+
SetSessionTitleRequest, SetSessionTitleResponse,
89
};
910
#[cfg(feature = "unstable_session_fork")]
1011
use crate::schema::v1::{ForkSessionRequest, ForkSessionResponse};
@@ -31,6 +32,11 @@ impl_jsonrpc_request!(
3132
SetSessionConfigOptionResponse,
3233
"session/set_config_option"
3334
);
35+
impl_jsonrpc_request!(
36+
SetSessionTitleRequest,
37+
SetSessionTitleResponse,
38+
"session/setTitle"
39+
);
3440

3541
#[cfg(feature = "unstable_session_fork")]
3642
impl_jsonrpc_request!(ForkSessionRequest, ForkSessionResponse, "session/fork");

src/agent-client-protocol/src/schema/enum_impls.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ impl_jsonrpc_request_enum!(ClientRequest {
2424
CloseSessionRequest => "session/close",
2525
SetSessionModeRequest => "session/set_mode",
2626
SetSessionConfigOptionRequest => "session/set_config_option",
27+
SetSessionTitleRequest => "session/setTitle",
2728
PromptRequest => "session/prompt",
2829
#[cfg(feature = "unstable_mcp_over_acp")]
2930
MessageMcpRequest => "mcp/message",

src/agent-client-protocol/src/schema/v2_impls.rs

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -107,10 +107,10 @@ macro_rules! impl_v2_jsonrpc_request_enum {
107107
if method.starts_with('_') {
108108
crate::util::json_cast_params(params).map(
109109
|ext_req: v2::ExtRequest| {
110-
Self::$ext_variant(v2::ExtRequest::new(
110+
Self::$ext_variant(Box::new(v2::ExtRequest::new(
111111
method.to_string(),
112112
ext_req.params,
113-
))
113+
)))
114114
},
115115
)
116116
} else {
@@ -159,10 +159,10 @@ macro_rules! impl_v2_jsonrpc_notification_enum {
159159
if method.starts_with('_') {
160160
crate::util::json_cast_params(params).map(
161161
|ext_notif: v2::ExtNotification| {
162-
Self::$ext_variant(v2::ExtNotification::new(
162+
Self::$ext_variant(Box::new(v2::ExtNotification::new(
163163
method.to_string(),
164164
ext_notif.params,
165-
))
165+
)))
166166
},
167167
)
168168
} else {
@@ -210,12 +210,8 @@ macro_rules! impl_v2_jsonrpc_response_enum {
210210
}
211211

212212
impl_v2_jsonrpc_request!(v2::InitializeRequest, v2::InitializeResponse, "initialize");
213-
impl_v2_jsonrpc_request!(
214-
v2::AuthenticateRequest,
215-
v2::AuthenticateResponse,
216-
"authenticate"
217-
);
218-
impl_v2_jsonrpc_request!(v2::LogoutRequest, v2::LogoutResponse, "logout");
213+
impl_v2_jsonrpc_request!(v2::LoginAuthRequest, v2::LoginAuthResponse, "auth/login");
214+
impl_v2_jsonrpc_request!(v2::LogoutAuthRequest, v2::LogoutAuthResponse, "auth/logout");
219215
impl_v2_jsonrpc_request!(v2::NewSessionRequest, v2::NewSessionResponse, "session/new");
220216
impl_v2_jsonrpc_request!(
221217
v2::LoadSessionRequest,
@@ -248,6 +244,11 @@ impl_v2_jsonrpc_request!(
248244
v2::CloseSessionResponse,
249245
"session/close"
250246
);
247+
impl_v2_jsonrpc_request!(
248+
v2::SetSessionTitleRequest,
249+
v2::SetSessionTitleResponse,
250+
"session/setTitle"
251+
);
251252
impl_v2_jsonrpc_request!(
252253
v2::SetSessionConfigOptionRequest,
253254
v2::SetSessionConfigOptionResponse,
@@ -259,7 +260,7 @@ impl_v2_jsonrpc_request!(v2::MessageMcpRequest, v2::MessageMcpResponse, "mcp/mes
259260

260261
#[cfg(feature = "unstable_cancel_request")]
261262
impl_v2_jsonrpc_notification!(v2::CancelRequestNotification, "$/cancel_request");
262-
impl_v2_jsonrpc_notification!(v2::CancelNotification, "session/cancel");
263+
impl_v2_jsonrpc_notification!(v2::CancelSessionNotification, "session/cancel");
263264
#[cfg(feature = "unstable_mcp_over_acp")]
264265
impl_v2_jsonrpc_notification!(v2::MessageMcpNotification, "mcp/message");
265266

@@ -283,7 +284,7 @@ impl_v2_jsonrpc_request!(
283284
"mcp/disconnect"
284285
);
285286

286-
impl_v2_jsonrpc_notification!(v2::SessionNotification, "session/update");
287+
impl_v2_jsonrpc_notification!(v2::UpdateSessionNotification, "session/update");
287288
#[cfg(feature = "unstable_elicitation")]
288289
impl_v2_jsonrpc_notification!(v2::CompleteElicitationNotification, "elicitation/complete");
289290

@@ -294,8 +295,8 @@ impl_jsonrpc_protocol_level_notification_enum!(v2::ProtocolLevelNotification {
294295

295296
impl_v2_jsonrpc_request_enum!(v2::ClientRequest {
296297
InitializeRequest => "initialize",
297-
AuthenticateRequest => "authenticate",
298-
LogoutRequest => "logout",
298+
LoginAuthRequest => "auth/login",
299+
LogoutAuthRequest => "auth/logout",
299300
NewSessionRequest => "session/new",
300301
LoadSessionRequest => "session/load",
301302
ListSessionsRequest => "session/list",
@@ -304,6 +305,7 @@ impl_v2_jsonrpc_request_enum!(v2::ClientRequest {
304305
ForkSessionRequest => "session/fork",
305306
ResumeSessionRequest => "session/resume",
306307
CloseSessionRequest => "session/close",
308+
SetSessionTitleRequest => "session/setTitle",
307309
SetSessionConfigOptionRequest => "session/set_config_option",
308310
PromptRequest => "session/prompt",
309311
#[cfg(feature = "unstable_mcp_over_acp")]
@@ -313,8 +315,8 @@ impl_v2_jsonrpc_request_enum!(v2::ClientRequest {
313315

314316
impl_v2_jsonrpc_response_enum!(v2::AgentResponse {
315317
InitializeResponse => "initialize",
316-
AuthenticateResponse => "authenticate",
317-
LogoutResponse => "logout",
318+
LoginAuthResponse => "auth/login",
319+
LogoutAuthResponse => "auth/logout",
318320
NewSessionResponse => "session/new",
319321
LoadSessionResponse => "session/load",
320322
ListSessionsResponse => "session/list",
@@ -323,6 +325,7 @@ impl_v2_jsonrpc_response_enum!(v2::AgentResponse {
323325
ForkSessionResponse => "session/fork",
324326
ResumeSessionResponse => "session/resume",
325327
CloseSessionResponse => "session/close",
328+
SetSessionTitleResponse => "session/setTitle",
326329
SetSessionConfigOptionResponse => "session/set_config_option",
327330
PromptResponse => "session/prompt",
328331
#[cfg(feature = "unstable_mcp_over_acp")]
@@ -331,7 +334,7 @@ impl_v2_jsonrpc_response_enum!(v2::AgentResponse {
331334
});
332335

333336
impl_v2_jsonrpc_notification_enum!(v2::ClientNotification {
334-
CancelNotification => "session/cancel",
337+
CancelSessionNotification => "session/cancel",
335338
#[cfg(feature = "unstable_mcp_over_acp")]
336339
MessageMcpNotification => "mcp/message",
337340
[ext] ExtNotification,
@@ -364,7 +367,7 @@ impl_v2_jsonrpc_response_enum!(v2::ClientResponse {
364367
});
365368

366369
impl_v2_jsonrpc_notification_enum!(v2::AgentNotification {
367-
SessionNotification => "session/update",
370+
UpdateSessionNotification => "session/update",
368371
#[cfg(feature = "unstable_elicitation")]
369372
CompleteElicitationNotification => "elicitation/complete",
370373
#[cfg(feature = "unstable_mcp_over_acp")]

0 commit comments

Comments
 (0)