Skip to content

Commit 13b286d

Browse files
authored
Update to agent-client-protocol-schema 0.5 (#8)
* Update to agent-client-protocol-schema 0.5 This moves several of the RPC types down into the schema crate and adapts to the new types. * Prep v0.6.0
1 parent af0d26f commit 13b286d

File tree

8 files changed

+35
-245
lines changed

8 files changed

+35
-245
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
# Changelog
22

3+
## 0.6.0 (2025-10-23)
4+
5+
- Provide missing `_meta` fields on certain enum variants.
6+
- More consistent enum usage. Enums are always either newtype or struct variants within a single enum, not mixed.
7+
38
## 0.5.0 (2025-10-20)
49

510
- Export necessary RPC types. Fixes an issue where certain fields weren't public enough.

Cargo.lock

Lines changed: 3 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: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[package]
22
name = "agent-client-protocol"
33
authors = ["Zed <[email protected]>"]
4-
version = "0.5.0"
4+
version = "0.6.0"
55
edition = "2024"
66
license = "Apache-2.0"
77
description = "A protocol for standardizing communication between code editors and AI coding agents"
@@ -17,7 +17,7 @@ include = ["/src/**/*.rs", "/README.md", "/LICENSE", "/Cargo.toml"]
1717
unstable = ["agent-client-protocol-schema/unstable"]
1818

1919
[dependencies]
20-
agent-client-protocol-schema = { version = "0.4.11" }
20+
agent-client-protocol-schema = { version = "0.5.0" }
2121
anyhow = "1"
2222
async-broadcast = "0.7"
2323
async-trait = "0.1"

examples/agent.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,10 @@ impl acp::Agent for ExampleAgent {
9898
.send((
9999
acp::SessionNotification {
100100
session_id: arguments.session_id.clone(),
101-
update: acp::SessionUpdate::AgentMessageChunk { content },
101+
update: acp::SessionUpdate::AgentMessageChunk(acp::ContentChunk {
102+
content,
103+
meta: None,
104+
}),
102105
meta: None,
103106
},
104107
tx,

examples/client.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ impl acp::Client for ExampleClient {
8080
args: acp::SessionNotification,
8181
) -> acp::Result<(), acp::Error> {
8282
match args.update {
83-
acp::SessionUpdate::AgentMessageChunk { content } => {
83+
acp::SessionUpdate::AgentMessageChunk(acp::ContentChunk { content, .. }) => {
8484
let text = match content {
8585
acp::ContentBlock::Text(text_content) => text_content.text,
8686
acp::ContentBlock::Image(_) => "<image>".into(),

src/rpc.rs

Lines changed: 4 additions & 144 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,9 @@ use std::{
88
},
99
};
1010

11-
use agent_client_protocol_schema::{Error, Result};
12-
use derive_more::Display;
11+
use agent_client_protocol_schema::{
12+
Error, JsonRpcMessage, OutgoingMessage, RequestId, ResponseResult, Result, Side,
13+
};
1314
use futures::{
1415
AsyncBufReadExt as _, AsyncRead, AsyncWrite, AsyncWriteExt as _, FutureExt as _,
1516
StreamExt as _,
@@ -22,7 +23,7 @@ use futures::{
2223
select_biased,
2324
};
2425
use parking_lot::Mutex;
25-
use serde::{Deserialize, Serialize, de::DeserializeOwned};
26+
use serde::{Deserialize, de::DeserializeOwned};
2627
use serde_json::value::RawValue;
2728

2829
use super::stream_broadcast::{StreamBroadcast, StreamReceiver, StreamSender};
@@ -298,17 +299,6 @@ where
298299
}
299300
}
300301

301-
/// JSON RPC Request Id
302-
#[derive(Debug, PartialEq, Clone, Hash, Eq, Deserialize, Serialize, PartialOrd, Ord, Display)]
303-
#[serde(deny_unknown_fields)]
304-
#[serde(untagged)]
305-
pub enum RequestId {
306-
#[display("null")]
307-
Null,
308-
Number(i64),
309-
Str(String),
310-
}
311-
312302
#[derive(Deserialize)]
313303
pub struct RawIncomingMessage<'a> {
314304
id: Option<RequestId>,
@@ -328,82 +318,6 @@ pub enum IncomingMessage<Local: Side> {
328318
},
329319
}
330320

331-
#[derive(Serialize, Deserialize, Clone)]
332-
#[serde(untagged)]
333-
pub enum OutgoingMessage<Local: Side, Remote: Side> {
334-
Request {
335-
id: RequestId,
336-
method: Arc<str>,
337-
#[serde(skip_serializing_if = "Option::is_none")]
338-
params: Option<Remote::InRequest>,
339-
},
340-
Response {
341-
id: RequestId,
342-
#[serde(flatten)]
343-
result: ResponseResult<Local::OutResponse>,
344-
},
345-
Notification {
346-
method: Arc<str>,
347-
#[serde(skip_serializing_if = "Option::is_none")]
348-
params: Option<Remote::InNotification>,
349-
},
350-
}
351-
352-
/// Either [`OutgoingMessage`] or [`IncomingMessage`] with `"jsonrpc": "2.0"` specified as
353-
/// [required by JSON-RPC 2.0 Specification][1].
354-
///
355-
/// [1]: https://www.jsonrpc.org/specification#compatibility
356-
#[derive(Debug, Serialize, Deserialize)]
357-
pub struct JsonRpcMessage<M> {
358-
jsonrpc: &'static str,
359-
#[serde(flatten)]
360-
message: M,
361-
}
362-
363-
impl<M> JsonRpcMessage<M> {
364-
/// Used version of [JSON-RPC protocol].
365-
///
366-
/// [JSON-RPC]: https://www.jsonrpc.org
367-
pub const VERSION: &'static str = "2.0";
368-
369-
/// Wraps the provided [`OutgoingMessage`] or [`IncomingMessage`] into a versioned
370-
/// [`JsonRpcMessage`].
371-
#[must_use]
372-
pub fn wrap(message: M) -> Self {
373-
Self {
374-
jsonrpc: Self::VERSION,
375-
message,
376-
}
377-
}
378-
}
379-
380-
#[derive(Debug, Serialize, Deserialize, Clone)]
381-
#[serde(rename_all = "snake_case")]
382-
pub enum ResponseResult<Res> {
383-
Result(Res),
384-
Error(Error),
385-
}
386-
387-
impl<T> From<Result<T>> for ResponseResult<T> {
388-
fn from(result: Result<T>) -> Self {
389-
match result {
390-
Ok(value) => ResponseResult::Result(value),
391-
Err(error) => ResponseResult::Error(error),
392-
}
393-
}
394-
}
395-
396-
pub trait Side: Clone {
397-
type InRequest: Clone + Serialize + DeserializeOwned + 'static;
398-
type OutResponse: Clone + Serialize + DeserializeOwned + 'static;
399-
type InNotification: Clone + Serialize + DeserializeOwned + 'static;
400-
401-
fn decode_request(method: &str, params: Option<&RawValue>) -> Result<Self::InRequest>;
402-
403-
fn decode_notification(method: &str, params: Option<&RawValue>)
404-
-> Result<Self::InNotification>;
405-
}
406-
407321
pub trait MessageHandler<Local: Side> {
408322
fn handle_request(
409323
&self,
@@ -415,57 +329,3 @@ pub trait MessageHandler<Local: Side> {
415329
notification: Local::InNotification,
416330
) -> impl Future<Output = Result<()>>;
417331
}
418-
419-
#[cfg(test)]
420-
mod tests {
421-
use super::*;
422-
423-
use serde_json::{Number, Value};
424-
425-
#[test]
426-
fn id_deserialization() {
427-
let id = serde_json::from_value::<RequestId>(Value::Null).unwrap();
428-
assert_eq!(id, RequestId::Null);
429-
430-
let id = serde_json::from_value::<RequestId>(Value::Number(Number::from_u128(1).unwrap()))
431-
.unwrap();
432-
assert_eq!(id, RequestId::Number(1));
433-
434-
let id = serde_json::from_value::<RequestId>(Value::Number(Number::from_i128(-1).unwrap()))
435-
.unwrap();
436-
assert_eq!(id, RequestId::Number(-1));
437-
438-
let id = serde_json::from_value::<RequestId>(Value::String("id".to_owned())).unwrap();
439-
assert_eq!(id, RequestId::Str("id".to_owned()));
440-
}
441-
442-
#[test]
443-
fn id_serialization() {
444-
let id = serde_json::to_value(RequestId::Null).unwrap();
445-
assert_eq!(id, Value::Null);
446-
447-
let id = serde_json::to_value(RequestId::Number(1)).unwrap();
448-
assert_eq!(id, Value::Number(Number::from_u128(1).unwrap()));
449-
450-
let id = serde_json::to_value(RequestId::Number(-1)).unwrap();
451-
assert_eq!(id, Value::Number(Number::from_i128(-1).unwrap()));
452-
453-
let id = serde_json::to_value(RequestId::Str("id".to_owned())).unwrap();
454-
assert_eq!(id, Value::String("id".to_owned()));
455-
}
456-
457-
#[test]
458-
fn id_display() {
459-
let id = RequestId::Null;
460-
assert_eq!(id.to_string(), "null");
461-
462-
let id = RequestId::Number(1);
463-
assert_eq!(id.to_string(), "1");
464-
465-
let id = RequestId::Number(-1);
466-
assert_eq!(id.to_string(), "-1");
467-
468-
let id = RequestId::Str("id".to_owned());
469-
assert_eq!(id.to_string(), "id");
470-
}
471-
}

0 commit comments

Comments
 (0)