11pub ( crate ) mod fs_read_text_file;
2+ pub ( crate ) mod request_permission;
23pub ( crate ) mod session_update;
34
45use 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