Skip to content

Restore mode handler APIs across SDKs#1228

Merged
stephentoub merged 4 commits into
mainfrom
stephentoub/restore-mode-apis
May 8, 2026
Merged

Restore mode handler APIs across SDKs#1228
stephentoub merged 4 commits into
mainfrom
stephentoub/restore-mode-apis

Conversation

@stephentoub
Copy link
Copy Markdown
Collaborator

Restores the mode-handler surface area removed from the Rust SDK and brings exitPlanMode and autoModeSwitch parity to .NET, Go, Python, and TypeScript. This keeps every SDK consistent with the CLI callbacks for plan approval and rate-limit recovery.

Summary

  • Restores Rust session handler/config support for exitPlanMode and autoModeSwitch, including request/result types and JSON-RPC dispatch.
  • Adds equivalent handler APIs, create/resume request flags, serialization, clone, and dispatch coverage across .NET, Go, Python, and TypeScript.
  • Extends the replay harness so snapshots can return chat completion errors, enabling real CLI-driven auto-mode-switch tests from a replayed 429 response.
  • Adds real CLI E2E coverage for both mode handlers across all SDKs using shared snapshots.

Validation

  • dotnet test dotnet\test\GitHub.Copilot.SDK.Test.csproj --filter FullyQualifiedName~ModeHandlersE2ETests --nologo --verbosity minimal
  • cd nodejs; npm test -- --run test\e2e\mode_handlers.e2e.test.ts
  • cd python; python -m pytest e2e\test_mode_handlers_e2e.py -q
  • cd go; go test .\internal\e2e -run TestModeHandlersE2E -count=1
  • cd rust; cargo test --test mode_handlers_e2e_test -- --ignored --nocapture
  • cd rust; cargo +nightly-2026-04-14 fmt --check; cargo clippy --all-features --all-targets -- -D warnings
  • cd test\harness; npm test

Copilot AI review requested due to automatic review settings May 8, 2026 02:34
@stephentoub stephentoub requested a review from a team as a code owner May 8, 2026 02:34
Comment thread python/e2e/test_mode_handlers_e2e.py Fixed
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR restores and standardizes “mode handler” callback APIs across the Rust, .NET, Go, Python, and TypeScript SDKs, aligning them with Copilot CLI JSON-RPC callbacks for plan approval (exitPlanMode.request) and rate-limit recovery (autoModeSwitch.request). It also extends the replaying CAPI proxy + snapshots to simulate chat completion errors (e.g., 429) to enable cross-SDK E2E coverage.

Changes:

  • Add/restore exitPlanMode + autoModeSwitch handler types, request flags (create/resume), and JSON-RPC dispatch across all SDKs.
  • Extend the replay harness + snapshots to replay chat-completion error responses (e.g., 429 with Retry-After), enabling realistic auto-mode-switch tests.
  • Add unit + E2E tests across SDKs to validate flag forwarding, callback dispatch, and event emission parity.
Show a summary per file
File Description
test/snapshots/mode_handlers/should_invoke_exit_plan_mode_handler_when_model_uses_tool.yaml Adds a replay snapshot that triggers exit_plan_mode tool usage.
test/snapshots/mode_handlers/should_invoke_auto_mode_switch_handler_when_rate_limited.yaml Adds a replay snapshot that simulates a 429 + recovery to validate auto-mode switching.
test/harness/replayingCapiProxy.ts Adds support for replaying stored chat completion errors (status/Retry-After/body) and preserving error entries when writing captures.
rust/tests/session_test.rs Adds unit coverage for new Rust handler dispatch paths and request flags in session.create.
rust/tests/mode_handlers_e2e_test.rs Adds Rust E2E tests (ignored by default) that run the CLI against the shared replay proxy to validate both mode handlers.
rust/src/types.rs Adds request flags to session config/resume config and introduces ExitPlanModeData.
rust/src/session.rs Adds JSON-RPC request dispatch for exitPlanMode.request and autoModeSwitch.request.
rust/src/handler.rs Extends Rust handler event/response surface area with exit-plan-mode + auto-mode-switch types and default behaviors.
rust/CHANGELOG.md Updates Rust changelog notes about auto-mode-switch retry-after representation.
python/test_commands_and_elicitation.py Adds unit tests verifying flag forwarding and handler dispatch for the new Python callbacks.
python/e2e/test_mode_handlers_e2e.py Adds Python E2E coverage for both mode handlers with replay snapshots.
python/copilot/session.py Adds request/result TypedDicts and handler plumbing for exit-plan-mode and auto-mode-switch callbacks.
python/copilot/client.py Adds create/resume flags and request routing for the new callback methods.
python/copilot/init.py Re-exports new public Python types/handlers.
nodejs/test/e2e/mode_handlers.e2e.test.ts Adds TS E2E tests validating both callbacks and related session events.
nodejs/test/client.test.ts Adds unit coverage for request flag forwarding and handler dispatch for the new callbacks.
nodejs/src/types.ts Adds new TS request/result/handler types and wires them into session config types.
nodejs/src/session.ts Adds handler registration + request dispatch helpers for the new callbacks; clears them on disconnect.
nodejs/src/index.ts Re-exports new TS public types.
nodejs/src/client.ts Forwards create/resume request flags and registers new handlers; adds JSON-RPC request handlers.
go/types.go Adds Go request/result/handler types and request flag fields to create/resume request payloads.
go/session.go Adds handler registration + dispatch methods for the new callbacks.
go/internal/e2e/mode_handlers_e2e_test.go Adds Go E2E coverage for both callbacks using replay snapshots.
go/client.go Forwards mode callback flags and registers JSON-RPC request handlers for the new methods.
go/client_test.go Adds unit tests for flag serialization and JSON-RPC handler dispatch.
dotnet/test/Unit/SerializationTests.cs Adds .NET unit tests for request flag serialization and enum serialization.
dotnet/test/Unit/CloneTests.cs Ensures config cloning copies the new handler delegates.
dotnet/test/E2E/ModeHandlersE2ETests.cs Adds .NET E2E coverage for both mode handlers using replay snapshots.
dotnet/src/Types.cs Adds .NET public request/result/handler types and updates source-gen serialization context.
dotnet/src/Session.cs Adds handler registration, dispatch, timing logs, and cleanup for the new callbacks.
dotnet/src/Client.cs Wires new flags into create/resume, registers RPC endpoints, and adds handler implementations for the new JSON-RPC methods.

Copilot's findings

  • Files reviewed: 31/31 changed files
  • Comments generated: 2

Comment thread go/client.go
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@stephentoub stephentoub force-pushed the stephentoub/restore-mode-apis branch from 2623337 to 075a005 Compare May 8, 2026 02:55
stephentoub and others added 3 commits May 7, 2026 22:58
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 8, 2026

Cross-SDK Consistency Review ✅

This PR adds exitPlanMode and autoModeSwitch handler support across all five SDK implementations (Node.js, Python, Go, .NET, Rust). The changes are highly consistent across SDKs. Here's the summary:

What was checked

Aspect Verdict
Types added to all 5 SDKs
Handlers in SessionConfig + ResumeSessionConfig ✅ All SDKs
Default behavior (no handler) approved: true / "no" everywhere
Default recommendedAction = "autopilot" ✅ All SDKs
Shared E2E snapshot files ✅ Both scenarios
E2E tests added ✅ All 5 SDKs
Wire field names (exitPlanMode.request, autoModeSwitch.request) ✅ Consistent
AutoModeSwitchResponse values (yes/yes_always/no) ✅ All SDKs

Language-idiomatic differences (expected, not issues)

  • Rust uses ExitPlanModeData instead of ExitPlanModeRequest — intentional; Rust's event-based model wraps data in HandlerEvent::ExitPlanMode { data: ExitPlanModeData }, where the Data suffix correctly distinguishes the inbound payload from user-facing request types.
  • Rust defaults request_exit_plan_mode: Some(true) always — intentional; Rust's SessionHandler trait handles all events, so there's no per-event opt-in; the flag is exposed as a builder knob (with_request_exit_plan_mode(false)) for callers who want to opt out.
  • Node.js/Python send requestExitPlanMode: false when no handler — consistent with how those SDKs already handle other flags (e.g., requestElicitation: !!config.onElicitationRequest). .NET/Go omit the field entirely when null/nil. Both are functionally equivalent to the CLI.
  • Python invocation dict uses session_id (snake_case) — consistent with all other Python handler invocation dicts in the SDK.

No cross-SDK inconsistencies found. The implementation is well-coordinated.

Generated by SDK Consistency Review Agent for issue #1228 · ● 1M ·

@stephentoub stephentoub merged commit 671b50a into main May 8, 2026
43 checks passed
@stephentoub stephentoub deleted the stephentoub/restore-mode-apis branch May 8, 2026 03:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants