@@ -600,4 +600,124 @@ void agentToClientElicitationFormWorks() throws Exception {
600600 }
601601 }
602602
603+ @ Test
604+ void agentToClientElicitationDeclineWorks () throws Exception {
605+ AcpClientTransport clientTransport = createClientTransport ();
606+ AcpAgentTransport agentTransport = createAgentTransport ();
607+
608+ try {
609+ AtomicReference <AcpSchema .CreateElicitationResponse > elicitationResponse = new AtomicReference <>();
610+ CountDownLatch latch = new CountDownLatch (1 );
611+ AtomicReference <AcpAsyncAgent > agentRef = new AtomicReference <>();
612+
613+ AcpAsyncAgent agent = AcpAgent .async (agentTransport )
614+ .requestTimeout (TIMEOUT )
615+ .initializeHandler (request -> Mono
616+ .just (new AcpSchema .InitializeResponse (1 , new AcpSchema .AgentCapabilities (), List .of ())))
617+ .newSessionHandler (
618+ request -> Mono .just (new AcpSchema .NewSessionResponse ("session-decline" , null , null )))
619+ .promptHandler ((request , context ) -> {
620+ var schema = new AcpSchema .ElicitationSchema (
621+ Map .of ("name" , AcpSchema .StringPropertySchema .text ("Name" )), null );
622+ return agentRef .get ()
623+ .createElicitation (AcpSchema .CreateElicitationRequest .form (
624+ "session-decline" , "Enter name:" , schema ))
625+ .doOnNext (response -> {
626+ elicitationResponse .set (response );
627+ latch .countDown ();
628+ })
629+ .then (Mono .just (new AcpSchema .PromptResponse (AcpSchema .StopReason .END_TURN )));
630+ })
631+ .build ();
632+ agentRef .set (agent );
633+
634+ // Client declines the form
635+ AcpAsyncClient client = AcpClient .async (clientTransport )
636+ .requestTimeout (TIMEOUT )
637+ .createElicitationHandler (req ->
638+ Mono .just (AcpSchema .CreateElicitationResponse .decline ()))
639+ .build ();
640+
641+ agent .start ().subscribe ();
642+ Thread .sleep (100 );
643+ var caps = new AcpSchema .ClientCapabilities (
644+ new AcpSchema .FileSystemCapability (), false ,
645+ new AcpSchema .ElicitationCapabilities (), null );
646+ client .initialize (new AcpSchema .InitializeRequest (1 , caps )).block (TIMEOUT );
647+ client .newSession (new AcpSchema .NewSessionRequest ("/workspace" , List .of ())).block (TIMEOUT );
648+ client .prompt (new AcpSchema .PromptRequest ("session-decline" ,
649+ List .of (new AcpSchema .TextContent ("test" )))).block (TIMEOUT );
650+
651+ assertThat (latch .await (5 , TimeUnit .SECONDS )).isTrue ();
652+ assertThat (elicitationResponse .get ().action ()).isEqualTo (AcpSchema .ElicitationAction .DECLINE );
653+ assertThat (elicitationResponse .get ().content ()).isNull ();
654+
655+ client .closeGracefully ().block (TIMEOUT );
656+ agent .closeGracefully ().block (TIMEOUT );
657+ }
658+ finally {
659+ closeTransports ();
660+ }
661+ }
662+
663+ @ Test
664+ void agentToClientElicitationCancelWorks () throws Exception {
665+ AcpClientTransport clientTransport = createClientTransport ();
666+ AcpAgentTransport agentTransport = createAgentTransport ();
667+
668+ try {
669+ AtomicReference <AcpSchema .CreateElicitationResponse > elicitationResponse = new AtomicReference <>();
670+ CountDownLatch latch = new CountDownLatch (1 );
671+ AtomicReference <AcpAsyncAgent > agentRef = new AtomicReference <>();
672+
673+ AcpAsyncAgent agent = AcpAgent .async (agentTransport )
674+ .requestTimeout (TIMEOUT )
675+ .initializeHandler (request -> Mono
676+ .just (new AcpSchema .InitializeResponse (1 , new AcpSchema .AgentCapabilities (), List .of ())))
677+ .newSessionHandler (
678+ request -> Mono .just (new AcpSchema .NewSessionResponse ("session-cancel" , null , null )))
679+ .promptHandler ((request , context ) -> {
680+ var schema = new AcpSchema .ElicitationSchema (
681+ Map .of ("name" , AcpSchema .StringPropertySchema .text ("Name" )), null );
682+ return agentRef .get ()
683+ .createElicitation (AcpSchema .CreateElicitationRequest .form (
684+ "session-cancel" , "Enter name:" , schema ))
685+ .doOnNext (response -> {
686+ elicitationResponse .set (response );
687+ latch .countDown ();
688+ })
689+ .then (Mono .just (new AcpSchema .PromptResponse (AcpSchema .StopReason .END_TURN )));
690+ })
691+ .build ();
692+ agentRef .set (agent );
693+
694+ // Client cancels the form
695+ AcpAsyncClient client = AcpClient .async (clientTransport )
696+ .requestTimeout (TIMEOUT )
697+ .createElicitationHandler (req ->
698+ Mono .just (AcpSchema .CreateElicitationResponse .cancel ()))
699+ .build ();
700+
701+ agent .start ().subscribe ();
702+ Thread .sleep (100 );
703+ var caps = new AcpSchema .ClientCapabilities (
704+ new AcpSchema .FileSystemCapability (), false ,
705+ new AcpSchema .ElicitationCapabilities (), null );
706+ client .initialize (new AcpSchema .InitializeRequest (1 , caps )).block (TIMEOUT );
707+ client .newSession (new AcpSchema .NewSessionRequest ("/workspace" , List .of ())).block (TIMEOUT );
708+ client .prompt (new AcpSchema .PromptRequest ("session-cancel" ,
709+ List .of (new AcpSchema .TextContent ("test" )))).block (TIMEOUT );
710+
711+ assertThat (latch .await (5 , TimeUnit .SECONDS )).isTrue ();
712+ assertThat (elicitationResponse .get ().action ()).isEqualTo (AcpSchema .ElicitationAction .CANCEL );
713+ assertThat (elicitationResponse .get ().content ()).isNull ();
714+
715+ client .closeGracefully ().block (TIMEOUT );
716+ agent .closeGracefully ().block (TIMEOUT );
717+ }
718+ finally {
719+ closeTransports ();
720+ }
721+ }
722+
603723}
0 commit comments