From b9599521be5c114d5e502b7ba3d895beb19db89f Mon Sep 17 00:00:00 2001 From: TestUser Date: Fri, 17 Jul 2026 08:06:20 -0400 Subject: [PATCH 1/2] Update SDK E2E tests for canonical exit_plan_mode action order The runtime now canonicalizes the exit_plan_mode action menu to [autopilot, interactive, exit_only] regardless of the order the model passes in the tool call. Update the mode_handlers E2E assertions in all five SDK suites (C#, Go, Node, Python, Rust) to expect the canonical order so the shared snapshot test passes against the current runtime. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 9e36340e-3d37-46ed-ac6f-3989fea57dc7 --- dotnet/test/E2E/ModeHandlersE2ETests.cs | 2 +- go/internal/e2e/mode_handlers_e2e_test.go | 2 +- nodejs/test/e2e/mode_handlers.e2e.test.ts | 2 +- python/e2e/test_mode_handlers_e2e.py | 2 +- rust/tests/e2e/mode_handlers.rs | 4 ++-- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/dotnet/test/E2E/ModeHandlersE2ETests.cs b/dotnet/test/E2E/ModeHandlersE2ETests.cs index a397999f73..1e8fa49f9f 100644 --- a/dotnet/test/E2E/ModeHandlersE2ETests.cs +++ b/dotnet/test/E2E/ModeHandlersE2ETests.cs @@ -60,7 +60,7 @@ public async Task Should_Invoke_Exit_Plan_Mode_Handler_When_Model_Uses_Tool() var (request, invocation) = await handlerTask.Task.WaitAsync(TimeSpan.FromSeconds(30)); Assert.Equal(session.SessionId, invocation.SessionId); Assert.Equal(summary, request.Summary); - Assert.Equal(["interactive", "autopilot", "exit_only"], request.Actions); + Assert.Equal(["autopilot", "interactive", "exit_only"], request.Actions); Assert.Equal("interactive", request.RecommendedAction); Assert.NotNull(request.PlanContent); diff --git a/go/internal/e2e/mode_handlers_e2e_test.go b/go/internal/e2e/mode_handlers_e2e_test.go index 15800bf858..e7471fbd06 100644 --- a/go/internal/e2e/mode_handlers_e2e_test.go +++ b/go/internal/e2e/mode_handlers_e2e_test.go @@ -101,7 +101,7 @@ func TestModeHandlersE2E(t *testing.T) { if request.Summary != planSummary { t.Fatalf("Expected summary %q, got %q", planSummary, request.Summary) } - if len(request.Actions) != 3 || request.Actions[0] != "interactive" || request.Actions[1] != "autopilot" || request.Actions[2] != "exit_only" { + if len(request.Actions) != 3 || request.Actions[0] != "autopilot" || request.Actions[1] != "interactive" || request.Actions[2] != "exit_only" { t.Fatalf("Unexpected actions: %#v", request.Actions) } if request.RecommendedAction != "interactive" { diff --git a/nodejs/test/e2e/mode_handlers.e2e.test.ts b/nodejs/test/e2e/mode_handlers.e2e.test.ts index 8e2b8aed67..71c4b08963 100644 --- a/nodejs/test/e2e/mode_handlers.e2e.test.ts +++ b/nodejs/test/e2e/mode_handlers.e2e.test.ts @@ -110,7 +110,7 @@ describe("Mode handlers", async () => { expect(exitPlanModeRequests).toHaveLength(1); expect(exitPlanModeRequests[0]).toMatchObject({ summary: PLAN_SUMMARY, - actions: ["interactive", "autopilot", "exit_only"], + actions: ["autopilot", "interactive", "exit_only"], recommendedAction: "interactive", }); expect(exitPlanModeRequests[0].planContent).toBeDefined(); diff --git a/python/e2e/test_mode_handlers_e2e.py b/python/e2e/test_mode_handlers_e2e.py index a53064e744..f6173a4a5e 100644 --- a/python/e2e/test_mode_handlers_e2e.py +++ b/python/e2e/test_mode_handlers_e2e.py @@ -119,7 +119,7 @@ async def on_exit_plan_mode_request(request, invocation): assert len(exit_plan_mode_requests) == 1 request = exit_plan_mode_requests[0] assert request["summary"] == PLAN_SUMMARY - assert request["actions"] == ["interactive", "autopilot", "exit_only"] + assert request["actions"] == ["autopilot", "interactive", "exit_only"] assert request["recommendedAction"] == "interactive" assert request.get("planContent") is not None diff --git a/rust/tests/e2e/mode_handlers.rs b/rust/tests/e2e/mode_handlers.rs index fbaaf5158d..b4089ca28a 100644 --- a/rust/tests/e2e/mode_handlers.rs +++ b/rust/tests/e2e/mode_handlers.rs @@ -134,7 +134,7 @@ async fn should_invoke_exit_plan_mode_handler_when_model_uses_tool() { assert_eq!(request.summary, PLAN_SUMMARY); assert_eq!( request.actions, - ["interactive", "autopilot", "exit_only"].map(str::to_string) + ["autopilot", "interactive", "exit_only"].map(str::to_string) ); assert_eq!(request.recommended_action, "interactive"); @@ -146,8 +146,8 @@ async fn should_invoke_exit_plan_mode_handler_when_model_uses_tool() { assert_eq!( requested_data.actions, [ - ExitPlanModeAction::Interactive, ExitPlanModeAction::Autopilot, + ExitPlanModeAction::Interactive, ExitPlanModeAction::ExitOnly, ] ); From c65e8da82d89e66407f8d2aaaf7d7d9cdd2744d0 Mon Sep 17 00:00:00 2001 From: Stephen Toub Date: Fri, 17 Jul 2026 08:57:53 -0400 Subject: [PATCH 2/2] Update mode_handlers snapshot to canonical exit_plan_mode action order The E2E tests were updated to expect the canonical action order [autopilot, interactive, exit_only], but the replay snapshot still supplied [interactive, autopilot, exit_only] as the model's exit_plan_mode tool-call arguments, which the CLI forwards verbatim to the SDK handler. Align the snapshot with the tests so request.actions matches across all language SDKs. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 446b10a1-29f6-4155-bf3a-ac1241c742f3 --- ...ould_invoke_exit_plan_mode_handler_when_model_uses_tool.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/snapshots/mode_handlers/should_invoke_exit_plan_mode_handler_when_model_uses_tool.yaml b/test/snapshots/mode_handlers/should_invoke_exit_plan_mode_handler_when_model_uses_tool.yaml index d3e915f6d4..078ba05483 100644 --- a/test/snapshots/mode_handlers/should_invoke_exit_plan_mode_handler_when_model_uses_tool.yaml +++ b/test/snapshots/mode_handlers/should_invoke_exit_plan_mode_handler_when_model_uses_tool.yaml @@ -13,7 +13,7 @@ conversations: function: name: exit_plan_mode arguments: '{"summary":"Greeting file implementation - plan","actions":["interactive","autopilot","exit_only"],"recommendedAction":"interactive"}' + plan","actions":["autopilot","interactive","exit_only"],"recommendedAction":"interactive"}' - role: tool tool_call_id: toolcall_0 content: >-