Skip to content

Commit 4e06a18

Browse files
committed
feat(acp-nats): add request_permission client handler (#24)
1 parent c53444d commit 4e06a18

5 files changed

Lines changed: 571 additions & 1 deletion

File tree

rsworkspace/crates/acp-nats/src/client/mod.rs

Lines changed: 86 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
pub(crate) mod fs_read_text_file;
2+
pub(crate) mod request_permission;
23
pub(crate) mod session_update;
34

45
use crate::agent::Bridge;
@@ -206,6 +207,17 @@ async fn dispatch_client_method<
206207
)
207208
.await;
208209
}
210+
ClientMethod::SessionRequestPermission => {
211+
request_permission::handle(
212+
&payload,
213+
ctx.client,
214+
reply.as_deref(),
215+
ctx.nats,
216+
parsed.session_id.as_str(),
217+
ctx.serializer,
218+
)
219+
.await;
220+
}
209221
ClientMethod::SessionUpdate => {
210222
session_update::handle(&payload, ctx.client, &parsed.session_id).await;
211223
}
@@ -218,7 +230,8 @@ mod tests {
218230
use crate::session_id::AcpSessionId;
219231
use agent_client_protocol::{
220232
ContentBlock, ContentChunk, ReadTextFileRequest, ReadTextFileResponse, Request, RequestId,
221-
RequestPermissionRequest, RequestPermissionResponse, SessionNotification, SessionUpdate,
233+
RequestPermissionOutcome, RequestPermissionRequest, RequestPermissionResponse,
234+
SessionNotification, SessionUpdate,
222235
};
223236
use async_trait::async_trait;
224237
use std::cell::RefCell;
@@ -499,6 +512,78 @@ mod tests {
499512
assert_eq!(nats.published_messages(), vec!["_INBOX.reply"]);
500513
}
501514

515+
#[derive(Debug)]
516+
struct RpcMockClient;
517+
518+
#[async_trait(?Send)]
519+
impl Client for RpcMockClient {
520+
async fn session_notification(
521+
&self,
522+
_: SessionNotification,
523+
) -> agent_client_protocol::Result<()> {
524+
Ok(())
525+
}
526+
527+
async fn request_permission(
528+
&self,
529+
_: RequestPermissionRequest,
530+
) -> agent_client_protocol::Result<RequestPermissionResponse> {
531+
Ok(RequestPermissionResponse::new(
532+
RequestPermissionOutcome::Cancelled,
533+
))
534+
}
535+
536+
async fn read_text_file(
537+
&self,
538+
_: ReadTextFileRequest,
539+
) -> agent_client_protocol::Result<ReadTextFileResponse> {
540+
Ok(ReadTextFileResponse::new("file contents".to_string()))
541+
}
542+
}
543+
544+
#[tokio::test]
545+
async fn dispatch_client_method_dispatches_request_permission() {
546+
let nats = MockNatsClient::new();
547+
let client = RpcMockClient;
548+
let session_id = AcpSessionId::new("sess-1").unwrap();
549+
550+
let request = RequestPermissionRequest::new(
551+
"sess-1",
552+
agent_client_protocol::ToolCallUpdate::new(
553+
"call-1",
554+
agent_client_protocol::ToolCallUpdateFields::new(),
555+
),
556+
vec![],
557+
);
558+
let envelope = Request {
559+
id: RequestId::Number(1),
560+
method: std::sync::Arc::from("session/request_permission"),
561+
params: Some(request),
562+
};
563+
let payload = bytes::Bytes::from(serde_json::to_vec(&envelope).unwrap());
564+
565+
let parsed = crate::nats::ParsedClientSubject {
566+
session_id,
567+
method: ClientMethod::SessionRequestPermission,
568+
};
569+
570+
let ctx = DispatchContext {
571+
nats: &nats,
572+
client: &client,
573+
serializer: &StdJsonSerialize,
574+
};
575+
dispatch_client_method(
576+
"acp.sess-1.client.session.request_permission",
577+
parsed,
578+
payload,
579+
Some("_INBOX.reply".to_string()),
580+
&ctx,
581+
)
582+
.await;
583+
584+
assert_eq!(nats.published_messages(), vec!["_INBOX.reply"]);
585+
}
586+
502587
#[tokio::test]
503588
async fn process_message_invalid_subject_no_reply_does_not_publish() {
504589
let nats = MockNatsClient::new();

0 commit comments

Comments
 (0)