From a75f744b8ff1e7c2b592be599abe1cb45c9a2efc Mon Sep 17 00:00:00 2001 From: arimu1 Date: Sun, 19 Jul 2026 21:40:01 +0700 Subject: [PATCH 1/2] test(java): re-enable ModeHandlers exit_plan_mode E2E assertions Remove the CLI 1.0.57 @Disabled workaround and assert the canonical action order (autopilot, interactive, exit_only) plus recommendedAction, matching the other language SDKs after snapshot updates. Fixes #1547 Co-authored-by: Cursor --- .../test/java/com/github/copilot/ModeHandlersTest.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/java/src/test/java/com/github/copilot/ModeHandlersTest.java b/java/src/test/java/com/github/copilot/ModeHandlersTest.java index 5128a31ace..5dd62d11d4 100644 --- a/java/src/test/java/com/github/copilot/ModeHandlersTest.java +++ b/java/src/test/java/com/github/copilot/ModeHandlersTest.java @@ -7,13 +7,13 @@ import static org.junit.jupiter.api.Assertions.*; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.concurrent.CompletableFuture; import java.util.concurrent.TimeUnit; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import com.github.copilot.generated.ExitPlanModeAction; @@ -68,7 +68,6 @@ private void configureAuthenticatedUser(String testName) throws Exception { } @Test - @Disabled("Snapshot needs re-recording for CLI 1.0.57: https://github.com/github/copilot-sdk/issues/1547") void shouldInvokeExitPlanModeHandlerWhenModelUsesTool() throws Exception { final String summary = "Greeting file implementation plan"; configureAuthenticatedUser("should_invoke_exit_plan_mode_handler_when_model_uses_tool"); @@ -103,16 +102,19 @@ void shouldInvokeExitPlanModeHandlerWhenModelUsesTool() throws Exception { var request = handlerCalled.get(10, TimeUnit.SECONDS); assertEquals(summary, request.getSummary()); - assertNotNull(request.getActions()); - assertTrue(request.getActions().contains("interactive")); + // Canonical action order after CLI 1.0.57+ (aligned with #2023 / other SDKs). + assertEquals(List.of("autopilot", "interactive", "exit_only"), request.getActions()); + assertEquals("interactive", request.getRecommendedAction()); assertNotNull(request.getPlanContent()); var reqEvent = requestedEvent.get(10, TimeUnit.SECONDS); assertEquals(request.getSummary(), reqEvent.getData().summary()); + assertEquals(ExitPlanModeAction.INTERACTIVE, reqEvent.getData().recommendedAction()); var compEvent = completedEvent.get(10, TimeUnit.SECONDS); assertTrue(compEvent.getData().approved()); assertEquals(ExitPlanModeAction.INTERACTIVE, compEvent.getData().selectedAction()); + assertEquals("Approved by the Java E2E test", compEvent.getData().feedback()); assertNotNull(response); From a222a017cd3cacb3da874a085fbf495758881403 Mon Sep 17 00:00:00 2001 From: Steve Sanderson Date: Fri, 31 Jul 2026 13:50:26 +0000 Subject: [PATCH 2/2] fix(java): use agentMode instead of mode for exit_plan_mode E2E test The test was using MessageOptions.setMode("plan") which sets the wire-protocol 'mode' field (prompt formatting only, e.g. the [[PLAN]] prefix). The field that actually switches the CLI's active agent mode and exposes the exit_plan_mode tool to the model is 'agentMode', set via MessageOptions.setAgentMode(AgentMode.PLAN) - matching how the Node.js and .NET reference E2E tests invoke this same scenario. This was root-caused by capturing the Node SDK's actual outgoing session.send payload and comparing it against Java's: Node sends agentMode: "plan", Java was only sending mode: "plan". Without agentMode set, the CLI never enters plan UI mode, so exit_plan_mode is not registered as an available tool and the model's tool call is rejected by the real (non-replayed) CLI, causing the replay-proxy snapshot mismatch failure seen in CI. Reproduced the original failure locally, confirmed this fix resolves it, and validated on both JDK 25 and JDK 17 per java/README.md's two-step build/test process. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- java/src/test/java/com/github/copilot/ModeHandlersTest.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/java/src/test/java/com/github/copilot/ModeHandlersTest.java b/java/src/test/java/com/github/copilot/ModeHandlersTest.java index 5dd62d11d4..942b2efe6d 100644 --- a/java/src/test/java/com/github/copilot/ModeHandlersTest.java +++ b/java/src/test/java/com/github/copilot/ModeHandlersTest.java @@ -19,6 +19,7 @@ import com.github.copilot.generated.ExitPlanModeAction; import com.github.copilot.generated.ExitPlanModeCompletedEvent; import com.github.copilot.generated.ExitPlanModeRequestedEvent; +import com.github.copilot.rpc.AgentMode; import com.github.copilot.rpc.AutoModeSwitchRequest; import com.github.copilot.rpc.AutoModeSwitchResponse; import com.github.copilot.rpc.CopilotClientOptions; @@ -98,7 +99,7 @@ void shouldInvokeExitPlanModeHandlerWhenModelUsesTool() throws Exception { var response = session.sendAndWait(new MessageOptions().setPrompt( "Create a brief implementation plan for adding a greeting.txt file, then request approval with exit_plan_mode.") - .setMode("plan")).get(120, TimeUnit.SECONDS); + .setAgentMode(AgentMode.PLAN)).get(120, TimeUnit.SECONDS); var request = handlerCalled.get(10, TimeUnit.SECONDS); assertEquals(summary, request.getSummary());