Skip to content

Commit 81507b3

Browse files
authored
refactor(acp): Replace jsonrpcmsg crate with shared schema types (#205)
1 parent 53ade8e commit 81507b3

17 files changed

Lines changed: 586 additions & 347 deletions

File tree

Cargo.lock

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

Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,6 @@ blocking = "1"
6969
chrono = "0.4"
7070
futures = "0.3.32"
7171
futures-concurrency = "7.6.3"
72-
jsonrpcmsg = "0.1.2"
7372
open = "5"
7473
rustc-hash = "2.1.1"
7574
shell-words = "1.1"

md/transport-architecture.md

Lines changed: 27 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -32,21 +32,24 @@ This separation enables:
3232
- **Testability**: Mock transports for unit testing
3333
- **Clarity**: Clear boundaries between protocol and I/O concerns
3434

35-
### The `jsonrpcmsg::Message` Boundary
35+
### The `RawJsonRpcMessage` Boundary
3636

37-
The key insight is that `jsonrpcmsg::Message` provides a natural, transport-neutral boundary:
37+
The key insight is that `agent_client_protocol::RawJsonRpcMessage` provides a natural,
38+
transport-neutral boundary backed by the JSON-RPC envelope types from
39+
`agent-client-protocol-schema`:
3840

3941
```rust
40-
enum jsonrpcmsg::Message {
41-
Request { method, params, id },
42-
Response { result, error, id },
42+
enum RawJsonRpcMessage {
43+
Request(Request<RawJsonRpcParams>),
44+
Notification(Notification<RawJsonRpcParams>),
45+
Response(Response<serde_json::Value>),
4346
}
4447
```
4548

4649
This type sits between the protocol and transport layers:
4750

4851
- **Above**: Protocol layer works with application types (`OutgoingMessage`, `UntypedMessage`)
49-
- **Below**: Transport layer works with `jsonrpcmsg::Message`
52+
- **Below**: Transport layer works with `RawJsonRpcMessage`
5053
- **Boundary**: Clean, well-defined interface
5154

5255
## Actor Architecture
@@ -59,27 +62,27 @@ These actors live in `JrConnection` and understand JSON-RPC semantics:
5962

6063
```
6164
Input: mpsc::UnboundedReceiver<OutgoingMessage>
62-
Output: mpsc::UnboundedSender<jsonrpcmsg::Message>
65+
Output: mpsc::UnboundedSender<RawJsonRpcMessage>
6366
```
6467

6568
Responsibilities:
6669

6770
- Assign unique IDs to outgoing requests
6871
- Subscribe to reply_actor for response correlation
69-
- Convert application-level `OutgoingMessage` to protocol-level `jsonrpcmsg::Message`
72+
- Convert application-level `OutgoingMessage` to protocol-level `RawJsonRpcMessage`
7073

7174
#### Incoming Protocol Actor
7275

7376
```
74-
Input: mpsc::UnboundedReceiver<jsonrpcmsg::Message>
77+
Input: mpsc::UnboundedReceiver<RawJsonRpcMessage>
7578
Output: Routes to reply_actor or registered handlers
7679
```
7780

7881
Responsibilities:
7982

8083
- Route responses to reply_actor (matches by ID)
8184
- Route requests/notifications to registered handlers
82-
- Convert `jsonrpcmsg::Request` to `UntypedMessage` for handlers
85+
- Convert schema request/notification envelopes to `UntypedMessage` for handlers
8386

8487
#### Reply Actor
8588

@@ -100,35 +103,35 @@ These actors are spawned by `IntoJrConnectionTransport` implementations and have
100103
#### Transport Outgoing Actor
101104

102105
```
103-
Input: mpsc::UnboundedReceiver<jsonrpcmsg::Message>
106+
Input: mpsc::UnboundedReceiver<RawJsonRpcMessage>
104107
Output: Writes to I/O (byte stream, channel, socket, etc.)
105108
```
106109

107110
For byte streams:
108111

109-
- Serialize `jsonrpcmsg::Message` to JSON
112+
- Serialize `RawJsonRpcMessage` to JSON
110113
- Write newline-delimited JSON to stream
111114

112115
For in-process channels:
113116

114-
- Directly forward `jsonrpcmsg::Message` to channel
117+
- Directly forward `RawJsonRpcMessage` to channel
115118

116119
#### Transport Incoming Actor
117120

118121
```
119122
Input: Reads from I/O (byte stream, channel, socket, etc.)
120-
Output: mpsc::UnboundedSender<jsonrpcmsg::Message>
123+
Output: mpsc::UnboundedSender<RawJsonRpcMessage>
121124
```
122125

123126
For byte streams:
124127

125128
- Read newline-delimited JSON from stream
126-
- Parse to `jsonrpcmsg::Message`
129+
- Parse to `RawJsonRpcMessage`
127130
- Send to incoming protocol actor
128131

129132
For in-process channels:
130133

131-
- Directly forward `jsonrpcmsg::Message` from channel
134+
- Directly forward `RawJsonRpcMessage` from channel
132135

133136
## Message Flow
134137

@@ -142,9 +145,9 @@ User Handler
142145
Outgoing Protocol Actor
143146
| - Assign ID (for requests)
144147
| - Subscribe to replies
145-
| - Convert to jsonrpcmsg::Message
148+
| - Convert to RawJsonRpcMessage
146149
v
147-
| jsonrpcmsg::Message
150+
| RawJsonRpcMessage
148151
|
149152
Transport Outgoing Actor
150153
| - Serialize (byte streams)
@@ -162,7 +165,7 @@ Transport Incoming Actor
162165
| - Parse (byte streams)
163166
| - Or forward directly (channels)
164167
v
165-
| jsonrpcmsg::Message
168+
| RawJsonRpcMessage
166169
|
167170
Incoming Protocol Actor
168171
| - Route responses → reply_actor
@@ -188,8 +191,8 @@ pub trait IntoJrConnectionTransport {
188191
fn setup_transport(
189192
self,
190193
cx: &JrConnectionCx,
191-
outgoing_rx: mpsc::UnboundedReceiver<jsonrpcmsg::Message>,
192-
incoming_tx: mpsc::UnboundedSender<jsonrpcmsg::Message>,
194+
outgoing_rx: mpsc::UnboundedReceiver<RawJsonRpcMessage>,
195+
incoming_tx: mpsc::UnboundedSender<RawJsonRpcMessage>,
193196
) -> Result<(), Error>;
194197
}
195198
```
@@ -216,7 +219,7 @@ impl<OB: AsyncWrite, IB: AsyncRead> IntoJrConnectionTransport for (OB, IB) {
216219
cx.spawn(async move {
217220
let mut lines = BufReader::new(incoming_bytes).lines();
218221
while let Some(line) = lines.next().await {
219-
let message: jsonrpcmsg::Message = serde_json::from_str(&line?)?;
222+
let message: RawJsonRpcMessage = serde_json::from_str(&line?)?;
220223
incoming_tx.unbounded_send(message)?;
221224
}
222225
Ok(())
@@ -250,8 +253,8 @@ For components in the same process, skip serialization entirely:
250253

251254
```rust
252255
pub struct ChannelTransport {
253-
outgoing: mpsc::UnboundedSender<jsonrpcmsg::Message>,
254-
incoming: mpsc::UnboundedReceiver<jsonrpcmsg::Message>,
256+
outgoing: mpsc::UnboundedSender<RawJsonRpcMessage>,
257+
incoming: mpsc::UnboundedReceiver<RawJsonRpcMessage>,
255258
}
256259

257260
impl IntoJrConnectionTransport for ChannelTransport {

src/agent-client-protocol-conductor/src/snoop.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,25 @@
1-
use agent_client_protocol::{Channel, ConnectTo, DynConnectTo, Role, jsonrpcmsg};
1+
use agent_client_protocol::{Channel, ConnectTo, DynConnectTo, RawJsonRpcMessage, Role};
22
use futures::StreamExt;
33
use futures_concurrency::future::TryJoin;
44

55
pub struct SnooperComponent<R: Role> {
66
base_component: DynConnectTo<R>,
77
incoming_message: Box<
8-
dyn FnMut(&jsonrpcmsg::Message) -> Result<(), agent_client_protocol::Error> + Send + Sync,
8+
dyn FnMut(&RawJsonRpcMessage) -> Result<(), agent_client_protocol::Error> + Send + Sync,
99
>,
1010
outgoing_message: Box<
11-
dyn FnMut(&jsonrpcmsg::Message) -> Result<(), agent_client_protocol::Error> + Send + Sync,
11+
dyn FnMut(&RawJsonRpcMessage) -> Result<(), agent_client_protocol::Error> + Send + Sync,
1212
>,
1313
}
1414

1515
impl<R: Role> SnooperComponent<R> {
1616
pub fn new(
1717
base_component: impl ConnectTo<R>,
18-
incoming_message: impl FnMut(&jsonrpcmsg::Message) -> Result<(), agent_client_protocol::Error>
18+
incoming_message: impl FnMut(&RawJsonRpcMessage) -> Result<(), agent_client_protocol::Error>
1919
+ Send
2020
+ Sync
2121
+ 'static,
22-
outgoing_message: impl FnMut(&jsonrpcmsg::Message) -> Result<(), agent_client_protocol::Error>
22+
outgoing_message: impl FnMut(&RawJsonRpcMessage) -> Result<(), agent_client_protocol::Error>
2323
+ Send
2424
+ Sync
2525
+ 'static,

0 commit comments

Comments
 (0)