Skip to content

Commit 4e8bb15

Browse files
author
Mark Pollack
committed
Add elicitation decline and cancel integration tests
Tests the full agent-to-client elicitation flow for all three response types: accept (existing), decline, and cancel. Verifies the action enum and null content for non-accept responses.
1 parent 970d4fd commit 4e8bb15

1 file changed

Lines changed: 120 additions & 0 deletions

File tree

acp-core/src/test/java/com/agentclientprotocol/sdk/integration/AbstractAcpClientAgentIT.java

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)