Skip to content

Comments

Add E2E scenario tests/examples for all SDK languages#512

Merged
patniko merged 19 commits intomainfrom
add-test-scenarios
Feb 19, 2026
Merged

Add E2E scenario tests/examples for all SDK languages#512
patniko merged 19 commits intomainfrom
add-test-scenarios

Conversation

@patniko
Copy link
Contributor

@patniko patniko commented Feb 19, 2026

Summary

Adds 34 E2E scenario tests under test/scenarios/ with full language parity across TypeScript, Python, Go, and C# (136 total scenario×language combinations).

What's included

Scenarios (34 across 8 categories)

Category Scenarios What they test
auth (6) byok-anthropic, byok-azure, byok-ollama, byok-openai, gh-app, token-sources BYOK providers, GitHub App auth, token source priority
bundling (4) fully-bundled, app-direct-server, app-backend-to-server, container-proxy stdio, TCP, HTTP backend, Docker deployment
callbacks (3) hooks, permissions, user-input Lifecycle hooks, permission handlers, user input
modes (3) cli-preset, filesystem-preset, minimal-preset Preset configurations
prompts (3) attachments, reasoning-effort, system-message File attachments, reasoning effort, system prompts
sessions (6) streaming, concurrent, infinite, resume, multi-user-long, multi-user-short Session lifecycle patterns
tools (6) custom-agents, mcp-servers, no-tools, skills, tool-filtering, virtual-filesystem Tool configuration and MCP
transport (3) stdio, tcp, reconnect Wire protocols

CI & Developer Experience

  • GitHub Actions workflow (scenario-builds.yml) — runs build verification on PRs as 4 parallel jobs with dependency caching
  • justfile targetsjust scenario-build, just scenario-verify, just scenario-build-lang <lang>
  • Per-scenario verify.sh — builds + E2E for all languages in one script

Build verification

All 136 builds pass locally:

  • ✅ 34 TypeScript (npm install)
  • ✅ 34 Python (AST syntax check)
  • ✅ 34 Go (go build)
  • ✅ 34 C# (dotnet build)

patniko and others added 7 commits February 18, 2026 13:15
Add csharp/ subdirectories with Program.cs and csproj for:
- transport/stdio, transport/tcp
- bundling/fully-bundled
- tools/no-tools, tools/custom-agents
- sessions/streaming
- callbacks/permissions
- prompts/system-message

All samples reference the local .NET SDK via ProjectReference.
Each verify.sh updated with dotnet build/run steps.
Added C# build artifacts to .gitignore.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
All 30 go.mod files had incorrect relative paths to the SDK Go
module. Scenarios live at test/scenarios/<cat>/<scenario>/go/
(5 levels deep), so the replace directive needs ../../../../../go
instead of ../../../../go.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
copilot-core is not a product name. Updated 63 files to use the
correct terminology:
- Prose/comments: "Copilot CLI"
- Binary name in code/commands: copilot
- COPILOT_CLI_PATH env var: unchanged (already correct)
- Dockerfile ENTRYPOINT/COPY: copilot
- docker-compose service name: copilot-cli

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Runs build verification for all test/scenarios across 4 languages
(TypeScript, Python, Go, C#) as parallel jobs. Triggered on PRs
that touch scenarios or SDK source, and on push to main.

Build-only — no E2E execution (no API keys or Copilot CLI needed).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Every scenario now has TypeScript, Python, Go, and C# implementations.

New additions:
- C# for 26 scenarios (auth, bundling, callbacks, modes, prompts,
  sessions, tools, transport)
- Python + Go + C# for 3 BYOK scenarios (anthropic, azure, ollama)
- Python + Go + C# stubs for multi-user scenarios (SKIP pattern)

All 136 scenario builds verified: 34 TS, 34 PY, 34 GO, 34 CS.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Add npm, Go module, and NuGet caching to scenario-builds.yml
- Add just scenario-build, scenario-verify, scenario-build-lang targets

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings February 19, 2026 04:15
@patniko patniko requested a review from a team as a code owner February 19, 2026 04:15
@patniko patniko changed the title Add E2E scenario tests for all SDK languages Add E2E scenario tests/examples for all SDK languages Feb 19, 2026
Copy link
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

Adds a large suite of end-to-end “scenario” samples under test/scenarios/ to verify SDK behavior consistently across TypeScript, Python, Go, and C#.

Changes:

  • Introduces many new per-scenario, per-language runnable samples (client/session/tools/callback flows).
  • Adds per-scenario docs plus supporting build metadata (e.g., package.json, go.mod, *.csproj, tsconfig.json).
  • Adds scenario-level ignore rules for build/run artifacts.

Reviewed changes

Copilot reviewed 274 out of 385 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
test/scenarios/tools/mcp-servers/go/main.go Go sample demonstrating MCP server configuration in session config
test/scenarios/tools/mcp-servers/go/go.mod Go module setup wiring scenario to local Go SDK via replace
test/scenarios/tools/mcp-servers/csharp/csharp.csproj C# project for MCP servers scenario referencing .NET SDK project
test/scenarios/tools/mcp-servers/csharp/Program.cs C# sample demonstrating MCP servers session config
test/scenarios/tools/mcp-servers/README.md Scenario documentation for MCP servers configuration
test/scenarios/tools/custom-agents/typescript/src/index.ts TypeScript sample demonstrating customAgents session config
test/scenarios/tools/custom-agents/typescript/package.json TypeScript build/run config for custom-agents sample
test/scenarios/tools/custom-agents/python/requirements.txt Python sample dependency wiring to local Python SDK
test/scenarios/tools/custom-agents/python/main.py Python sample demonstrating custom_agents session config
test/scenarios/tools/custom-agents/go/main.go Go sample demonstrating CustomAgents session config
test/scenarios/tools/custom-agents/go/go.mod Go module setup for custom-agents scenario
test/scenarios/tools/custom-agents/csharp/csharp.csproj C# project for custom-agents scenario
test/scenarios/tools/custom-agents/csharp/Program.cs C# sample demonstrating CustomAgents session config
test/scenarios/tools/custom-agents/README.md Scenario documentation for custom agents
test/scenarios/sessions/streaming/typescript/src/index.ts TypeScript sample enabling streaming and counting stream events
test/scenarios/sessions/streaming/typescript/package.json TypeScript build/run config for streaming scenario
test/scenarios/sessions/streaming/python/requirements.txt Python dependency wiring for streaming scenario
test/scenarios/sessions/streaming/python/main.py Python sample enabling streaming and counting stream events
test/scenarios/sessions/streaming/go/main.go Go sample enabling streaming and counting stream events
test/scenarios/sessions/streaming/go/go.mod Go module setup for streaming scenario
test/scenarios/sessions/streaming/csharp/csharp.csproj C# project for streaming scenario
test/scenarios/sessions/streaming/csharp/Program.cs C# sample enabling streaming and counting delta events
test/scenarios/sessions/streaming/README.md Scenario documentation for streaming behavior
test/scenarios/sessions/session-resume/typescript/src/index.ts TypeScript sample for session persistence/resume flow
test/scenarios/sessions/session-resume/typescript/package.json TypeScript build/run config for session-resume scenario
test/scenarios/sessions/session-resume/python/requirements.txt Python dependency wiring for session-resume scenario
test/scenarios/sessions/session-resume/python/main.py Python sample for session persistence/resume flow
test/scenarios/sessions/session-resume/go/main.go Go sample for session persistence/resume flow
test/scenarios/sessions/session-resume/go/go.mod Go module setup for session-resume scenario
test/scenarios/sessions/session-resume/csharp/csharp.csproj C# project for session-resume scenario
test/scenarios/sessions/session-resume/csharp/Program.cs C# sample for session persistence/resume flow
test/scenarios/sessions/session-resume/README.md Scenario documentation for session resume
test/scenarios/sessions/multi-user-short-lived/typescript/src/index.ts TypeScript placeholder marking scenario as skipped
test/scenarios/sessions/multi-user-short-lived/typescript/package.json TypeScript setup for multi-user-short-lived scenario
test/scenarios/sessions/multi-user-short-lived/python/requirements.txt Python dependency wiring for multi-user-short-lived scenario
test/scenarios/sessions/multi-user-short-lived/python/main.py Python placeholder marking scenario as skipped
test/scenarios/sessions/multi-user-short-lived/go/main.go Go placeholder marking scenario as skipped
test/scenarios/sessions/multi-user-short-lived/go/go.mod Go module metadata for skipped multi-user-short-lived
test/scenarios/sessions/multi-user-short-lived/csharp/csharp.csproj C# project for multi-user-short-lived scenario
test/scenarios/sessions/multi-user-short-lived/csharp/Program.cs C# placeholder marking scenario as skipped
test/scenarios/sessions/multi-user-short-lived/README.md Scenario documentation for multi-user short-lived pattern
test/scenarios/sessions/multi-user-long-lived/typescript/src/index.ts TypeScript placeholder marking scenario as skipped
test/scenarios/sessions/multi-user-long-lived/typescript/package.json TypeScript setup for multi-user-long-lived scenario
test/scenarios/sessions/multi-user-long-lived/python/requirements.txt Python dependency wiring for multi-user-long-lived scenario
test/scenarios/sessions/multi-user-long-lived/python/main.py Python placeholder marking scenario as skipped
test/scenarios/sessions/multi-user-long-lived/go/main.go Go placeholder marking scenario as skipped
test/scenarios/sessions/multi-user-long-lived/go/go.mod Go module metadata for skipped multi-user-long-lived
test/scenarios/sessions/multi-user-long-lived/csharp/csharp.csproj C# project for multi-user-long-lived scenario
test/scenarios/sessions/multi-user-long-lived/csharp/Program.cs C# placeholder marking scenario as skipped
test/scenarios/sessions/multi-user-long-lived/README.md Scenario documentation for multi-user long-lived pattern
test/scenarios/sessions/infinite-sessions/typescript/src/index.ts TypeScript placeholder marking scenario as skipped
test/scenarios/sessions/infinite-sessions/typescript/package.json TypeScript setup for infinite-sessions scenario
test/scenarios/sessions/infinite-sessions/python/requirements.txt Python dependency wiring for infinite-sessions scenario
test/scenarios/sessions/infinite-sessions/python/main.py Python sample enabling infinite sessions config
test/scenarios/sessions/infinite-sessions/go/main.go Go sample enabling infinite sessions config
test/scenarios/sessions/infinite-sessions/go/go.mod Go module setup for infinite-sessions scenario
test/scenarios/sessions/infinite-sessions/csharp/csharp.csproj C# project for infinite-sessions scenario
test/scenarios/sessions/infinite-sessions/csharp/Program.cs C# sample enabling infinite sessions config
test/scenarios/sessions/infinite-sessions/README.md Scenario documentation for infinite sessions
test/scenarios/sessions/concurrent-sessions/typescript/src/index.ts TypeScript sample creating sessions concurrently to validate isolation
test/scenarios/sessions/concurrent-sessions/typescript/package.json TypeScript build/run config for concurrent-sessions scenario
test/scenarios/sessions/concurrent-sessions/python/requirements.txt Python dependency wiring for concurrent-sessions scenario
test/scenarios/sessions/concurrent-sessions/python/main.py Python sample for concurrent sessions isolation
test/scenarios/sessions/concurrent-sessions/go/main.go Go sample for concurrent sessions isolation
test/scenarios/sessions/concurrent-sessions/go/go.mod Go module setup for concurrent-sessions scenario
test/scenarios/sessions/concurrent-sessions/csharp/csharp.csproj C# project for concurrent-sessions scenario
test/scenarios/sessions/concurrent-sessions/csharp/Program.cs C# sample for concurrent sessions isolation
test/scenarios/sessions/concurrent-sessions/README.md Scenario documentation for concurrent sessions
test/scenarios/prompts/system-message/typescript/src/index.ts TypeScript sample demonstrating systemMessage replace
test/scenarios/prompts/system-message/typescript/package.json TypeScript setup for system-message scenario
test/scenarios/prompts/system-message/python/requirements.txt Python dependency wiring for system-message scenario
test/scenarios/prompts/system-message/python/main.py Python sample demonstrating system_message replace
test/scenarios/prompts/system-message/go/main.go Go sample demonstrating SystemMessage replace
test/scenarios/prompts/system-message/go/go.mod Go module setup for system-message scenario
test/scenarios/prompts/system-message/csharp/csharp.csproj C# project for system-message scenario
test/scenarios/prompts/system-message/csharp/Program.cs C# sample demonstrating SystemMessage replace
test/scenarios/prompts/system-message/README.md Scenario documentation for system messages
test/scenarios/prompts/reasoning-effort/typescript/src/index.ts TypeScript sample setting reasoningEffort
test/scenarios/prompts/reasoning-effort/typescript/package.json TypeScript setup for reasoning-effort scenario
test/scenarios/prompts/reasoning-effort/python/requirements.txt Python dependency wiring for reasoning-effort scenario
test/scenarios/prompts/reasoning-effort/python/main.py Python sample setting reasoning_effort
test/scenarios/prompts/reasoning-effort/go/main.go Go sample setting ReasoningEffort
test/scenarios/prompts/reasoning-effort/go/go.mod Go module setup for reasoning-effort scenario
test/scenarios/prompts/reasoning-effort/csharp/csharp.csproj C# project for reasoning-effort scenario
test/scenarios/prompts/reasoning-effort/csharp/Program.cs C# sample setting ReasoningEffort
test/scenarios/prompts/reasoning-effort/README.md Scenario documentation for reasoning effort
test/scenarios/prompts/attachments/typescript/src/index.ts TypeScript sample sending file attachments
test/scenarios/prompts/attachments/typescript/package.json TypeScript setup for attachments scenario
test/scenarios/prompts/attachments/sample-data.txt Sample data file used as attachment
test/scenarios/prompts/attachments/python/requirements.txt Python dependency wiring for attachments scenario
test/scenarios/prompts/attachments/python/main.py Python sample sending file attachments
test/scenarios/prompts/attachments/go/main.go Go sample sending file attachments
test/scenarios/prompts/attachments/go/go.mod Go module setup for attachments scenario
test/scenarios/prompts/attachments/csharp/csharp.csproj C# project for attachments scenario
test/scenarios/prompts/attachments/csharp/Program.cs C# sample sending file attachments
test/scenarios/prompts/attachments/README.md Scenario documentation for file attachments
test/scenarios/modes/minimal-preset/typescript/src/index.ts TypeScript placeholder marking scenario as skipped
test/scenarios/modes/minimal-preset/typescript/package.json TypeScript setup for minimal-preset scenario
test/scenarios/modes/minimal-preset/python/requirements.txt Python dependency wiring for minimal-preset scenario
test/scenarios/modes/minimal-preset/python/main.py Python placeholder marking scenario as skipped
test/scenarios/modes/minimal-preset/go/main.go Go placeholder marking scenario as skipped
test/scenarios/modes/minimal-preset/go/go.mod Go module setup for minimal-preset scenario
test/scenarios/modes/minimal-preset/csharp/csharp.csproj C# project for minimal-preset scenario
test/scenarios/modes/minimal-preset/csharp/Program.cs C# placeholder marking scenario as skipped
test/scenarios/modes/filesystem-preset/typescript/src/index.ts TypeScript placeholder marking scenario as skipped
test/scenarios/modes/filesystem-preset/typescript/package.json TypeScript setup for filesystem-preset scenario
test/scenarios/modes/filesystem-preset/python/requirements.txt Python dependency wiring for filesystem-preset scenario
test/scenarios/modes/filesystem-preset/python/main.py Python placeholder marking scenario as skipped
test/scenarios/modes/filesystem-preset/go/main.go Go placeholder marking scenario as skipped
test/scenarios/modes/filesystem-preset/go/go.mod Go module setup for filesystem-preset scenario
test/scenarios/modes/filesystem-preset/csharp/csharp.csproj C# project for filesystem-preset scenario
test/scenarios/modes/filesystem-preset/csharp/Program.cs C# placeholder marking scenario as skipped
test/scenarios/modes/cli-preset/typescript/src/index.ts TypeScript placeholder marking scenario as skipped
test/scenarios/modes/cli-preset/typescript/package.json TypeScript setup for cli-preset scenario
test/scenarios/modes/cli-preset/python/requirements.txt Python dependency wiring for cli-preset scenario
test/scenarios/modes/cli-preset/python/main.py Python placeholder marking scenario as skipped
test/scenarios/modes/cli-preset/go/main.go Go placeholder marking scenario as skipped
test/scenarios/modes/cli-preset/go/go.mod Go module setup for cli-preset scenario
test/scenarios/modes/cli-preset/csharp/csharp.csproj C# project for cli-preset scenario
test/scenarios/modes/cli-preset/csharp/Program.cs C# placeholder marking scenario as skipped
test/scenarios/callbacks/user-input/typescript/src/index.ts TypeScript sample exercising ask_user callback flow
test/scenarios/callbacks/user-input/typescript/package.json TypeScript setup for user-input scenario
test/scenarios/callbacks/user-input/python/requirements.txt Python dependency wiring for user-input scenario
test/scenarios/callbacks/user-input/python/main.py Python sample exercising ask_user callback flow
test/scenarios/callbacks/user-input/go/main.go Go sample exercising ask_user callback flow
test/scenarios/callbacks/user-input/go/go.mod Go module setup for user-input scenario
test/scenarios/callbacks/user-input/csharp/csharp.csproj C# project for user-input scenario
test/scenarios/callbacks/user-input/csharp/Program.cs C# sample exercising ask_user callback flow
test/scenarios/callbacks/user-input/README.md Scenario documentation for user input callback
test/scenarios/callbacks/permissions/typescript/src/index.ts TypeScript sample exercising onPermissionRequest hook
test/scenarios/callbacks/permissions/typescript/package.json TypeScript setup for permissions scenario
test/scenarios/callbacks/permissions/python/requirements.txt Python dependency wiring for permissions scenario
test/scenarios/callbacks/permissions/python/main.py Python sample exercising on_permission_request hook
test/scenarios/callbacks/permissions/go/main.go Go sample exercising OnPermissionRequest hook
test/scenarios/callbacks/permissions/go/go.mod Go module setup for permissions scenario
test/scenarios/callbacks/permissions/csharp/csharp.csproj C# project for permissions scenario
test/scenarios/callbacks/permissions/csharp/Program.cs C# sample exercising permission request flow
test/scenarios/callbacks/permissions/README.md Scenario documentation for permission request flow
test/scenarios/callbacks/hooks/typescript/src/index.ts TypeScript sample exercising lifecycle hooks
test/scenarios/callbacks/hooks/typescript/package.json TypeScript setup for hooks scenario
test/scenarios/callbacks/hooks/python/requirements.txt Python dependency wiring for hooks scenario
test/scenarios/callbacks/hooks/python/main.py Python sample exercising lifecycle hooks
test/scenarios/callbacks/hooks/go/main.go Go sample exercising lifecycle hooks
test/scenarios/callbacks/hooks/go/go.mod Go module setup for hooks scenario
test/scenarios/callbacks/hooks/csharp/csharp.csproj C# project for hooks scenario
test/scenarios/callbacks/hooks/csharp/Program.cs C# sample exercising lifecycle hooks
test/scenarios/callbacks/hooks/README.md Scenario documentation for lifecycle hooks
test/scenarios/bundling/fully-bundled/typescript/tsconfig.json TS compiler config for fully-bundled sample
test/scenarios/bundling/fully-bundled/typescript/src/index.ts TypeScript fully-bundled sample code
test/scenarios/bundling/fully-bundled/typescript/package.json TypeScript setup for fully-bundled sample
test/scenarios/bundling/fully-bundled/python/requirements.txt Python dependency wiring for fully-bundled sample
test/scenarios/bundling/fully-bundled/python/main.py Python fully-bundled sample code
test/scenarios/bundling/fully-bundled/go/main.go Go fully-bundled sample code
test/scenarios/bundling/fully-bundled/go/go.mod Go module setup for fully-bundled sample
test/scenarios/bundling/fully-bundled/csharp/csharp.csproj C# project for fully-bundled sample
test/scenarios/bundling/fully-bundled/csharp/Program.cs C# fully-bundled sample code
test/scenarios/bundling/fully-bundled/README.md Documentation for fully-bundled deployment pattern
test/scenarios/bundling/container-proxy/typescript/tsconfig.json TS compiler config for container-proxy sample
test/scenarios/bundling/container-proxy/typescript/src/index.ts TypeScript client sample for container-proxy pattern
test/scenarios/bundling/container-proxy/typescript/package.json TypeScript setup for container-proxy sample
test/scenarios/bundling/container-proxy/python/requirements.txt Python dependency wiring for container-proxy sample
test/scenarios/bundling/container-proxy/python/main.py Python client sample for container-proxy pattern
test/scenarios/bundling/container-proxy/go/main.go Go client sample for container-proxy pattern
test/scenarios/bundling/container-proxy/go/go.mod Go module setup for container-proxy sample
test/scenarios/bundling/container-proxy/docker-compose.yml Docker compose to run Copilot CLI in container
test/scenarios/bundling/container-proxy/csharp/csharp.csproj C# project for container-proxy sample
test/scenarios/bundling/container-proxy/csharp/Program.cs C# client sample for container-proxy pattern
test/scenarios/bundling/container-proxy/Dockerfile Container image definition for running Copilot CLI
test/scenarios/bundling/container-proxy/.dockerignore Docker build context filtering for container-proxy
test/scenarios/bundling/app-direct-server/typescript/tsconfig.json TS compiler config for app-direct-server sample
test/scenarios/bundling/app-direct-server/typescript/src/index.ts TypeScript client connecting to pre-running CLI server
test/scenarios/bundling/app-direct-server/typescript/package.json TypeScript setup for app-direct-server sample
test/scenarios/bundling/app-direct-server/python/requirements.txt Python dependency wiring for app-direct-server sample
test/scenarios/bundling/app-direct-server/python/main.py Python client connecting to pre-running CLI server
test/scenarios/bundling/app-direct-server/go/main.go Go client connecting to pre-running CLI server
test/scenarios/bundling/app-direct-server/go/go.mod Go module setup for app-direct-server sample
test/scenarios/bundling/app-direct-server/csharp/csharp.csproj C# project for app-direct-server sample
test/scenarios/bundling/app-direct-server/csharp/Program.cs C# client connecting to pre-running CLI server
test/scenarios/bundling/app-direct-server/README.md Documentation for app-direct-server deployment pattern
test/scenarios/bundling/app-backend-to-server/typescript/src/index.ts TypeScript Express backend proxying to Copilot CLI server
test/scenarios/bundling/app-backend-to-server/typescript/package.json TypeScript deps/scripts for Express backend sample
test/scenarios/bundling/app-backend-to-server/python/requirements.txt Python deps for Flask backend sample
test/scenarios/bundling/app-backend-to-server/python/main.py Python Flask backend proxying to Copilot CLI server
test/scenarios/bundling/app-backend-to-server/go/go.mod Go module placeholder for app-backend-to-server scenario
test/scenarios/bundling/app-backend-to-server/csharp/csharp.csproj C# project for app-backend-to-server scenario
test/scenarios/bundling/app-backend-to-server/csharp/Program.cs C# sample connecting to Copilot CLI server
test/scenarios/auth/token-sources/typescript/src/index.ts TypeScript sample demonstrating token source resolution
test/scenarios/auth/token-sources/typescript/package.json TypeScript setup for token-sources scenario
test/scenarios/auth/token-sources/python/requirements.txt Python dependency wiring for token-sources scenario
test/scenarios/auth/token-sources/python/main.py Python sample demonstrating token source resolution
test/scenarios/auth/token-sources/go/main.go Go sample demonstrating token source resolution
test/scenarios/auth/token-sources/go/go.mod Go module setup for token-sources scenario
test/scenarios/auth/token-sources/csharp/csharp.csproj C# project for token-sources scenario
test/scenarios/auth/token-sources/csharp/Program.cs C# sample demonstrating token source resolution
test/scenarios/auth/token-sources/README.md Documentation for token source priority chain
test/scenarios/auth/gh-app/typescript/package.json TypeScript setup for GitHub OAuth device flow scenario
test/scenarios/auth/gh-app/python/requirements.txt Python dependency wiring for gh-app scenario
test/scenarios/auth/gh-app/python/main.py Python interactive OAuth device flow sample
test/scenarios/auth/gh-app/go/go.mod Go module setup for gh-app scenario
test/scenarios/auth/gh-app/csharp/csharp.csproj C# project for gh-app scenario
test/scenarios/auth/gh-app/csharp/Program.cs C# interactive OAuth device flow sample
test/scenarios/auth/gh-app/README.md Documentation for GitHub OAuth device flow scenario
test/scenarios/auth/byok-openai/typescript/src/index.ts TypeScript BYOK OpenAI provider sample
test/scenarios/auth/byok-openai/typescript/package.json TypeScript setup for byok-openai scenario
test/scenarios/auth/byok-openai/python/requirements.txt Python dependency wiring for byok-openai scenario
test/scenarios/auth/byok-openai/python/main.py Python BYOK OpenAI provider sample
test/scenarios/auth/byok-openai/go/main.go Go BYOK OpenAI provider sample
test/scenarios/auth/byok-openai/go/go.mod Go module setup for byok-openai scenario
test/scenarios/auth/byok-openai/csharp/csharp.csproj C# project for byok-openai scenario
test/scenarios/auth/byok-openai/csharp/Program.cs C# BYOK OpenAI provider sample
test/scenarios/auth/byok-openai/README.md Documentation for BYOK OpenAI scenario
test/scenarios/auth/byok-ollama/verify.sh Per-scenario verification script for Ollama BYOK
test/scenarios/auth/byok-ollama/typescript/src/index.ts TypeScript BYOK Ollama provider sample
test/scenarios/auth/byok-ollama/typescript/package.json TypeScript setup for byok-ollama scenario
test/scenarios/auth/byok-ollama/python/requirements.txt Python dependency wiring for byok-ollama scenario
test/scenarios/auth/byok-ollama/python/main.py Python BYOK Ollama provider sample
test/scenarios/auth/byok-ollama/go/main.go Go BYOK Ollama provider sample
test/scenarios/auth/byok-ollama/go/go.mod Go module setup for byok-ollama scenario
test/scenarios/auth/byok-ollama/csharp/csharp.csproj C# project for byok-ollama scenario
test/scenarios/auth/byok-ollama/csharp/Program.cs C# BYOK Ollama provider sample
test/scenarios/auth/byok-ollama/README.md Documentation for BYOK Ollama scenario
test/scenarios/auth/byok-azure/verify.sh Per-scenario verification script for Azure BYOK
test/scenarios/auth/byok-azure/typescript/src/index.ts TypeScript BYOK Azure OpenAI provider sample
test/scenarios/auth/byok-azure/typescript/package.json TypeScript setup for byok-azure scenario
test/scenarios/auth/byok-azure/python/requirements.txt Python dependency wiring for byok-azure scenario
test/scenarios/auth/byok-azure/python/main.py Python BYOK Azure OpenAI provider sample
test/scenarios/auth/byok-azure/go/main.go Go BYOK Azure OpenAI provider sample
test/scenarios/auth/byok-azure/go/go.mod Go module setup for byok-azure scenario
test/scenarios/auth/byok-azure/csharp/csharp.csproj C# project for byok-azure scenario
test/scenarios/auth/byok-azure/csharp/Program.cs C# BYOK Azure OpenAI provider sample
test/scenarios/auth/byok-azure/README.md Documentation for BYOK Azure OpenAI scenario
test/scenarios/auth/byok-anthropic/verify.sh Per-scenario verification script for Anthropic BYOK
test/scenarios/auth/byok-anthropic/typescript/src/index.ts TypeScript BYOK Anthropic provider sample
test/scenarios/auth/byok-anthropic/typescript/package.json TypeScript setup for byok-anthropic scenario
test/scenarios/auth/byok-anthropic/python/requirements.txt Python dependency wiring for byok-anthropic scenario
test/scenarios/auth/byok-anthropic/python/main.py Python BYOK Anthropic provider sample
test/scenarios/auth/byok-anthropic/go/main.go Go BYOK Anthropic provider sample
test/scenarios/auth/byok-anthropic/go/go.mod Go module setup for byok-anthropic scenario
test/scenarios/auth/byok-anthropic/csharp/csharp.csproj C# project for byok-anthropic scenario
test/scenarios/auth/byok-anthropic/csharp/Program.cs C# BYOK Anthropic provider sample
test/scenarios/auth/byok-anthropic/README.md Documentation for BYOK Anthropic scenario
test/scenarios/README.md Top-level documentation for scenario suite
test/scenarios/.gitignore Ignores scenario build outputs and run artifacts

Comment on lines +34 to +36
"type": "stdio",
"command": cmd,
"args": args,
Copy link

Copilot AI Feb 19, 2026

Choose a reason for hiding this comment

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

copilot.MCPServerConfig{ "type": ... } is not valid Go syntax for a struct composite literal (keys must be identifiers like Type, not quoted strings). This will not compile; update the literal to use the actual exported field names of copilot.MCPServerConfig (e.g., Type:, Command:, Args:) or change the map type to map[string]any if the SDK expects untyped config.

Suggested change
"type": "stdio",
"command": cmd,
"args": args,
Type: "stdio",
Command: cmd,
Args: args,

Copilot uses AI. Check for mistakes.
@@ -0,0 +1,3 @@
*
Copy link

Copilot AI Feb 19, 2026

Choose a reason for hiding this comment

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

This .dockerignore excludes the copilot binary from the Docker build context, but the Dockerfile does ARG COPILOT_CLI_PATH=copilot and COPY ${COPILOT_CLI_PATH} .... With the current ignore rules, docker build will fail unless the binary happens to be under the only unignored paths. Add an exception to include the expected binary path (e.g., !copilot and/or !path/to/copilot-binary) or adjust the Dockerfile/docs to copy from the allowed directory.

Suggested change
*
*
!copilot

Copilot uses AI. Check for mistakes.
Comment on lines +39 to +47
exe, err := os.Executable()
if err != nil {
log.Fatal(err)
}
sampleFile := filepath.Join(filepath.Dir(exe), "..", "sample-data.txt")
sampleFile, err = filepath.Abs(sampleFile)
if err != nil {
log.Fatal(err)
}
Copy link

Copilot AI Feb 19, 2026

Choose a reason for hiding this comment

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

Resolving sample-data.txt relative to os.Executable() will usually break when the scenario is run via go run (the executable lives in a temporary build directory, not alongside the repo files). Prefer resolving relative to the current working directory (the verify scripts typically cd into the scenario’s go/ directory) or use runtime.Caller / go:embed to locate the file reliably.

Copilot uses AI. Check for mistakes.
Comment on lines +3 to +9
Demonstrates session persistence and resume with the Copilot SDK. This validates that a destroyed session can be resumed by its ID, retaining full conversation history.

## What Each Sample Does

1. Creates a session with `availableTools: []` and model `gpt-4.1`
2. Sends: _"Remember this: the secret word is PINEAPPLE."_
3. Captures the session ID and destroys the session
Copy link

Copilot AI Feb 19, 2026

Choose a reason for hiding this comment

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

The README states the original session is destroyed before resuming, but the implementations shown in this PR explicitly do not destroy the original session prior to calling resumeSession(...) (they keep it alive so it can be resumed). Please update the README to match the actual behavior (either “do not destroy before resuming” or adjust the code to destroy and then resume if that’s truly what’s being validated).

Suggested change
Demonstrates session persistence and resume with the Copilot SDK. This validates that a destroyed session can be resumed by its ID, retaining full conversation history.
## What Each Sample Does
1. Creates a session with `availableTools: []` and model `gpt-4.1`
2. Sends: _"Remember this: the secret word is PINEAPPLE."_
3. Captures the session ID and destroys the session
Demonstrates session persistence and resume with the Copilot SDK. This validates that a persisted session can be resumed by its ID, retaining full conversation history.
## What Each Sample Does
1. Creates a session with `availableTools: []` and model `gpt-4.1`
2. Sends: _"Remember this: the secret word is PINEAPPLE."_
3. Captures the session ID so it can be resumed later

Copilot uses AI. Check for mistakes.
Comment on lines +3 to +9
Demonstrates session persistence and resume with the Copilot SDK. This validates that a destroyed session can be resumed by its ID, retaining full conversation history.

## What Each Sample Does

1. Creates a session with `availableTools: []` and model `gpt-4.1`
2. Sends: _"Remember this: the secret word is PINEAPPLE."_
3. Captures the session ID and destroys the session
Copy link

Copilot AI Feb 19, 2026

Choose a reason for hiding this comment

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

The README states the original session is destroyed before resuming, but the implementations shown in this PR explicitly do not destroy the original session prior to calling resumeSession(...) (they keep it alive so it can be resumed). Please update the README to match the actual behavior (either “do not destroy before resuming” or adjust the code to destroy and then resume if that’s truly what’s being validated).

Suggested change
Demonstrates session persistence and resume with the Copilot SDK. This validates that a destroyed session can be resumed by its ID, retaining full conversation history.
## What Each Sample Does
1. Creates a session with `availableTools: []` and model `gpt-4.1`
2. Sends: _"Remember this: the secret word is PINEAPPLE."_
3. Captures the session ID and destroys the session
Demonstrates session persistence and resume with the Copilot SDK. This validates that a session can be resumed by its ID, retaining full conversation history.
## What Each Sample Does
1. Creates a session with `availableTools: []` and model `gpt-4.1`
2. Sends: _"Remember this: the secret word is PINEAPPLE."_
3. Captures the session ID for later resumption

Copilot uses AI. Check for mistakes.
|-----------|---------------|----------|
| `typescript/` | `@github/copilot-sdk` | TypeScript (Node.js) |
| `python/` | `github-copilot-sdk` | Python |
| `go/` | `github.com/github/copilot-sdk/go` | Go |
Copy link

Copilot AI Feb 19, 2026

Choose a reason for hiding this comment

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

This scenario has a csharp/ implementation in the diff, but the “Languages” table omits it. Add the C# row so the docs accurately reflect the language parity introduced by this PR.

Suggested change
| `go/` | `github.com/github/copilot-sdk/go` | Go |
| `go/` | `github.com/github/copilot-sdk/go` | Go |
| `csharp/` | `GitHub.Copilot.SDK` | C# |

Copilot uses AI. Check for mistakes.
@@ -0,0 +1,38 @@
# SDK E2E Scenario Tests

End-to-end scenario tests for the Copilot SDK. Each scenario demonstrates a specific SDK capability with implementations in TypeScript, Python, and Go.
Copy link

Copilot AI Feb 19, 2026

Choose a reason for hiding this comment

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

The scenario suite in this PR includes C# (csharp/) implementations, but the top-level README claims only TypeScript/Python/Go. Update this sentence (and any related structure docs, if applicable) to include C# so it matches the repo contents.

Copilot uses AI. Check for mistakes.
Model: "gpt-4.1",
OnPermissionRequest: func(req copilot.PermissionRequest, inv copilot.PermissionInvocation) (copilot.PermissionRequestResult, error) {
permissionLogMu.Lock()
permissionLog = append(permissionLog, fmt.Sprintf("approved:%s", req.Kind))
Copy link

Copilot AI Feb 19, 2026

Choose a reason for hiding this comment

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

The log entry uses req.Kind, which is unlikely to be the tool identifier (other language samples log toolName). If the goal is “which tools were invoked”, this should record the tool name field from the permission request (e.g., req.ToolName if that’s the SDK type) rather than the request “kind”.

Suggested change
permissionLog = append(permissionLog, fmt.Sprintf("approved:%s", req.Kind))
permissionLog = append(permissionLog, fmt.Sprintf("approved:%s", req.ToolName))

Copilot uses AI. Check for mistakes.
@@ -0,0 +1,46 @@
import asyncio
import os
import sys
patniko and others added 6 commits February 18, 2026 20:29
- Add C# build/run steps to all 26 verify.sh scripts that were missing them
- Replace infinite-sessions TS stub with real implementation
- Rework modes: remove filesystem-preset, rename cli-preset→default and
  minimal-preset→minimal with real implementations in all 4 languages
- Fix C# patterns across all 33 scenarios: consistent await using,
  StartAsync/StopAsync, proper disposal

33 scenarios × 4 languages = 132 builds, all passing.
2 multi-user scenarios remain as stubs (require memory FS features).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Install the Python SDK and use py_compile for proper compilation
checking, plus verify the copilot module is importable.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Replace else/elif fallback branches that always passed with proper
failure reporting. Previously, when the expected grep pattern wasn't
found, the test would emit a warning but still count as passed. Now
these cases correctly report failure and increment the FAIL counter.

Changed 18 files with 21 soft-pass fixes across:
- 10 standard else-branch fallbacks (modes, prompts, tools, sessions)
- 3 elif-branch fallbacks (callbacks, streaming, virtual-filesystem)
- 3 multi-branch fixes with both 'partial' and 'got response' fallbacks
  (concurrent-sessions, multi-user-long-lived, multi-user-short-lived)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- tool-filtering: use word-boundary grep (-w) for blacklisted tools to
  avoid false positives on substrings like 'bashing'
- no-tools: change question to directly request bash tool usage; update
  verify grep to check for inability patterns (can't, cannot, unable)
- virtual-filesystem: require both 'Virtual filesystem contents' AND
  'plan.md' in output; fix dead elif branch
- custom-agents: tighten grep to only match 'researcher' or 'Research'
  instead of also matching generic tool names
- skills: add lowercase 'skill' to grep pattern for broader matching
- mcp-servers: replace soft-pass (non-empty output) with meaningful
  content grep; add separate failure message for pattern mismatch

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actions
Copy link

Cross-SDK Consistency Review

This PR adds comprehensive E2E scenario tests with excellent language parity (34 scenarios × 4 languages). I've reviewed the SDK source changes for consistency across all implementations.

✅ Consistent Changes

1. .NET CliUrl validation logic (dotnet/src/Client.cs)
The .NET SDK now automatically disables UseStdio when CliUrl is provided, matching the behavior already present in other SDKs:

  • Node.js (line 212): useStdio: options.cliUrl ? false : (options.useStdio ?? true)
  • Python (line 182): "use_stdio": False if opts.get("cli_url") else opts.get("use_stdio", True)
  • Go (line 147): client.useStdio = false when CLIUrl != ""
  • .NET (NEW): Now sets _options.UseStdio = false when CliUrl is provided

This change brings the .NET SDK into alignment with the other three SDKs. 👍

⚠️ Inconsistency Detected

2. Go PermissionRequest.ToolName field (go/types.go)
The Go SDK adds a ToolName field to PermissionRequest, but this field is missing from the other three SDKs:

  • Go (NEW): Has ToolName string field
  • TypeScript (nodejs/src/types.ts:213-217): Missing toolName field (only has kind and toolCallId)
  • Python (python/copilot/types.py:169-175): Missing toolName field (only has kind and toolCallId)
  • .NET (dotnet/src/Types.cs:143-153): Missing ToolName field (only has Kind and ToolCallId)

Impact: The test scenario at test/scenarios/callbacks/permissions/go/main.go (mentioned in existing review comment) appears to use req.ToolName for logging, which would only work in the Go SDK. If similar permission logging is needed in TypeScript, Python, or .NET scenarios, those SDKs won't have access to the tool name.

Recommendation: Consider adding the toolName field to the PermissionRequest type in all SDKs to maintain feature parity:

  • TypeScript: Add optional toolName?: string to the PermissionRequest interface
  • Python: Add toolName: str to the PermissionRequest TypedDict (with total=False)
  • .NET: Add [JsonPropertyName("toolName")] public string? ToolName { get; set; } to the PermissionRequest class

Alternatively, if toolName is only needed for Go-specific scenarios and not a general SDK feature, this inconsistency is acceptable—but it should be documented.


Overall: The PR maintains excellent cross-language consistency for the test scenarios themselves. The .NET validation fix is a positive consistency improvement. The only inconsistency is the new ToolName field in Go that hasn't been mirrored to other SDKs yet.

AI generated by SDK Consistency Review Agent

patniko and others added 3 commits February 18, 2026 22:03
…cution

- Fix relative paths in TS package.json (43 files) and Python requirements.txt (33 files)
- Add RollForward to C# csproj files for .NET 8/10 compat
- Remove soft-pass fallbacks in verify.sh — tests now hard-fail on missing patterns
- Fix Go permissions bug (req.Kind → req.ToolName) and add ToolName to SDK type
- Fix Python/Go availableTools: empty list was omitted instead of sent as []
- Fix streaming event names (assistant.message.chunk → assistant.message_delta)
- Fix TS streaming subscription (session.on('event') → typed subscription)
- Fix Python streaming enum comparison (event.type.value)
- Add permission handlers to Go skills scenario
- Switch scenarios to claude-haiku-4.5 for faster execution
- Parallelize verify.sh with live progress bar and per-SDK status icons
- Fix parallel pip install race with pre-install and import check
- Remove go.sum files from tracking
- Remove hardcoded OAuth client ID from C# gh-app scenario

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>


async def log_permission(request, invocation):
permission_log.append(f"approved:{request.tool_name}")

Choose a reason for hiding this comment

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

Cross-SDK consistency issue: The Python SDK's PermissionRequest TypedDict (in python/copilot/types.py) doesn't explicitly define a tool_name field.

While this code works at runtime (the field exists in the JSON from the CLI), it's not reflected in the type definition, making the API inconsistent with:

  • Go SDK: Has explicit ToolName field in the struct
  • TypeScript SDK: Has [key: string]: unknown index signature (allowing toolName but not explicitly typed)

Suggestion: Add tool_name: str field to the PermissionRequest TypedDict in python/copilot/types.py to match the Go SDK's explicit typing and improve type safety.

AI generated by SDK Consistency Review Agent for #512

Model = "claude-haiku-4.5",
OnPermissionRequest = (request, invocation) =>
{
var toolName = request.ExtensionData?.TryGetValue("toolName", out var value) == true

Choose a reason for hiding this comment

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

Cross-SDK consistency issue: The .NET SDK's PermissionRequest class doesn't have a ToolName property, requiring this ExtensionData workaround.

Compare with other SDKs:

  • Go SDK: Has explicit ToolName property on the struct
  • TypeScript: Accesses request.toolName directly (via index signature)
  • Python: Accesses request.tool_name directly (though the type doesn't define it either)

Suggestion: Add a ToolName property to the PermissionRequest class in dotnet/src/Types.cs to provide first-class access and match the other SDK implementations.

AI generated by SDK Consistency Review Agent for #512

@github-actions
Copy link

Cross-SDK Consistency Review ✅ (with 1 type issue)

Great work on achieving full language parity across all 34 scenarios! The implementations are remarkably consistent in structure and behavior across TypeScript, Python, Go, and C#.

🎯 What's Consistent

I reviewed scenarios across multiple categories (auth, sessions, tools, callbacks) and found excellent consistency:

  • ✅ API method names follow language conventions correctly (createSessioncreate_sessionCreateSession)
  • ✅ Configuration objects use parallel structure across languages
  • ✅ Event handling patterns are semantically equivalent
  • ✅ Authentication and provider configurations match across SDKs
  • ✅ All scenarios use appropriate language idioms (camelCase/snake_case/PascalCase)

⚠️ Type Inconsistency Found

Issue: PermissionRequest.toolName field handling is inconsistent across SDKs:

SDK Implementation Issue
Go ToolName string field in struct Correct - explicit field
TypeScript ⚠️ Accesses request.toolName via index signature Works, but not explicitly typed
Python ❌ Accesses request.tool_name but type doesn't define it Type doesn't reflect runtime structure
.NET ❌ Workaround via ExtensionData dictionary Requires boilerplate instead of property access

Impact: The scenario code works at runtime (the field exists in the JSON from the CLI), but the type definitions don't consistently expose it, leading to:

  • Python: No type safety or IDE autocomplete for this field
  • .NET: Verbose dictionary lookup instead of property access
  • TypeScript: Field access works but isn't documented in the type

Recommendation: Update the SDK type definitions to explicitly include the toolName/tool_name/ToolName field (following each language's naming convention) in the PermissionRequest type. I've added inline comments on the specific scenario files showing where this affects the code.


Overall, this PR demonstrates excellent consistency engineering! The single type definition gap I found is minor and doesn't block the scenarios from working correctly.

AI generated by SDK Consistency Review Agent

const session = await client.createSession({
model: "claude-haiku-4.5",
onPermissionRequest: async (request) => {
permissionLog.push(`approved:${request.toolName}`);

Choose a reason for hiding this comment

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

Minor type definition inconsistency: While this code works (thanks to the [key: string]: unknown index signature in PermissionRequest), the toolName field isn't explicitly defined in the TypeScript interface.

Suggestion: Consider adding toolName?: string; to the PermissionRequest interface in nodejs/src/types.ts to match the Go SDK's explicit typing and improve IDE autocomplete/type safety.

AI generated by SDK Consistency Review Agent for #512

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actions
Copy link

Cross-SDK Consistency Review

I've reviewed this PR for consistency across all four SDK implementations. Overall, this is an excellent contribution that maintains strong feature parity across languages! 🎉

✅ Consistent Changes

The following changes were properly implemented across all SDKs:

  1. clientName parameter: Added to both SessionConfig and ResumeSessionConfig in all 4 SDKs ✅
  2. requestPermission: true: Changed from conditional (!!config.onPermissionRequest) to always true in all SDKs ✅
  3. Empty availableTools handling: Python and Go fixed to send [] instead of omitting; Node.js and .NET already handle this correctly ✅
  4. Permission handler documentation improvements: Enhanced docs across SDKs to clarify deny-by-default behavior ✅

⚠️ Inconsistencies Found

1. PermissionRequest.toolName field - Missing in Node.js, Python, and .NET

Go SDK (this PR):

type PermissionRequest struct {
    Kind       string         `json:"kind"`
    ToolCallID string         `json:"toolCallId,omitempty"`
    ToolName   string         `json:"toolName,omitempty"`  // ← Added
    Extra      map[string]any `json:"-"`
}

Node.js, Python, .NET: This field is missing from the PermissionRequest type.

Recommendation: Add toolName?: string / toolName: str / ToolName to the PermissionRequest type in the other SDKs for consistency. This field appears to be useful for identifying which tool triggered a permission request.


2. Permission handler type naming - Inconsistent across SDKs

  • Node.js: PermissionHandler (unchanged) ✅
  • Python: _PermissionHandlerFn (renamed from PermissionHandler, underscore prefix suggests internal)
  • Go: PermissionHandlerFunc (renamed from PermissionHandler)
  • .NET: PermissionRequestHandler (renamed from PermissionHandler)

Recommendation: While the function signatures are equivalent, the naming divergence could confuse users. Consider standardizing on one name (e.g., PermissionRequestHandler or PermissionHandler) across all SDKs.


3. approveAll helper - Missing in Go and .NET

Node.js (this PR):

export const approveAll: PermissionHandler = () => ({ kind: "approved" });

Python (this PR):

class PermissionHandler:
    `@staticmethod`
    def approve_all(request: Any, invocation: Any) -> dict:
        return {"kind": "approved"}

Go and .NET: No equivalent helper provided.

Recommendation: Add an ApproveAll / approve_all helper function to Go and .NET for consistency. This is a common pattern in samples and makes it easier for developers to quickly approve all permissions during development/testing.


4. cliUrl + useStdio validation - Inconsistent behavior

  • .NET (this PR): Automatically disables UseStdio when CliUrl is provided ✅
  • Node.js: Still throws error if both are provided ❌
  • Python: Throws error if both provided, but auto-disables internally (contradictory)
  • Go: Still throws error if both are provided ❌

Recommendation: Follow .NET's approach across all SDKs - automatically disable useStdio when cliUrl is provided instead of throwing an error. This is more user-friendly and the behavior is unambiguous (external server = no stdio spawning).


📊 Summary

  • 4 major changes: All implemented consistently ✅
  • 4 inconsistencies identified: 1 new field, 1 naming divergence, 1 missing helper, 1 validation behavior difference

This PR makes significant progress toward full language parity with the 136 scenario examples. The inconsistencies above are relatively minor and could be addressed in follow-up PRs without blocking this one, given its scope and value.

Great work on the comprehensive E2E test coverage! 🚀

AI generated by SDK Consistency Review Agent

@patniko patniko enabled auto-merge February 19, 2026 16:35
The ToolName field doesn't exist on PermissionRequest in other SDKs.
The scenario test now reads toolName from the Extra map to stay
consistent without modifying SDK types.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@patniko patniko disabled auto-merge February 19, 2026 16:50
claude-haiku-4.5 does not support the reasoningEffort configuration,
causing all 4 SDK scenario tests to fail. Switch to o4-mini which
supports reasoning effort.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@@ -105,9 +105,15 @@ public CopilotClient(CopilotClientOptions? options = null)
_options = options ?? new();

Choose a reason for hiding this comment

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

Cross-SDK consistency issue: The validation logic change here is not reflected in the other SDKs.

The .NET SDK now only validates that CliUrl is mutually exclusive with CliPath (not UseStdio), and explicitly sets UseStdio = false when CliUrl is provided.

However, the other three SDKs still have the stricter validation:

  • Node.js (client.ts:195-196): if (options.cliUrl && (options.useStdio === true || options.cliPath))
  • Python (client.py:134-135): if opts.get("cli_url") and (opts.get("use_stdio") or opts.get("cli_path"))
  • Go (client.go:132-133): if options.CLIUrl != "" && ((options.UseStdio != nil) || options.CLIPath != "")

Recommendation: Either:

  1. Apply the same validation change to Node.js, Python, and Go (remove UseStdio from the mutual exclusivity check and set useStdio = false when URL is provided), OR
  2. Revert this .NET change to keep the validation consistent across all SDKs

The current state creates an inconsistency where .NET users can set both CliUrl and UseStdio=true (though it gets overridden), while users of other SDKs would get an immediate error.

AI generated by SDK Consistency Review Agent for #512

@github-actions
Copy link

Cross-SDK Consistency Review

I've reviewed this PR for consistency across the TypeScript, Python, Go, and .NET SDK implementations. Here are my findings:

✅ Consistent Changes

Tool filtering (availableTools handling):

  • Python ✅ Fixed to handle empty array: Changed if available_tools: to if available_tools is not None:
  • Go ✅ Fixed to handle empty array: Removed omitempty from AvailableTools field
  • Node.js ✅ Already correct: Unconditionally sends availableTools: config.availableTools
  • .NET ✅ Already correct: Uses JsonIgnoreCondition.WhenWritingNull which correctly distinguishes null from empty lists

This ensures all SDKs can properly send an empty array [] to disable all tools, which is different from not sending the field at all (which means "use defaults").

⚠️ Inconsistency Found

.NET validation logic diverges from other SDKs:

The .NET SDK now allows CliUrl and UseStdio to be set together (though it silently overrides UseStdio), while the other three SDKs throw an error if both are provided. See inline comment for details and recommendations.

📝 Test Scenarios

The 136 new scenario tests provide excellent coverage for testing these configurations across all languages. Great work ensuring language parity in the test suite!

AI generated by SDK Consistency Review Agent

@github-actions
Copy link

Cross-SDK Consistency Review

I've reviewed this PR for consistency across all four SDK implementations (Node.js, Python, Go, .NET). The PR contains two separate changes to SDK client code:


✅ 1. availableTools Empty Array Handling (Python & Go)

Changes:

  • Python (client.py): Changed if available_tools:if available_tools is not None: (lines 484, 655)
  • Go (types.go): Removed omitempty from AvailableTools field (lines 643, 674)

Status:Consistent — This fix brings Python and Go into alignment with Node.js and .NET.

Why this matters: The scenario tests use availableTools: [] (empty array) to disable all tools. Before this fix:

  • Python's if available_tools: would evaluate to False for empty lists, omitting the field
  • Go's omitempty JSON tag would omit empty arrays from serialization
  • Node.js and .NET already correctly include availableTools: [] in the JSON-RPC request

After this fix: All four SDKs now properly send availableTools: [] when explicitly set, enabling the "no tools" use case tested in test/scenarios/tools/no-tools/.


⚠️ 2. .NET CliUrl Validation Logic Change

Changes:

  • .NET (Client.cs lines 108-117): Modified validation to remove UseStdio from mutual exclusivity check and instead automatically set UseStdio = false when CliUrl is provided

Status: ⚠️ Creates cross-SDK inconsistency

Current behavior in all SDKs (including .NET before this PR):

// All SDKs reject this combination:
new CopilotClient({ cliUrl: "...", useStdio: true }) // ❌ Throws error

// All SDKs allow cliUrl alone and auto-set useStdio=false internally:
new CopilotClient({ cliUrl: "..." }) // ✅ Works, uses TCP

After this PR (.NET only):

// .NET NOW allows this and silently overrides UseStdio:
new CopilotClient(new CopilotClientOptions { 
    CliUrl = "...", 
    UseStdio = true  // ⚠️ Silently changed to false
}) // Now accepted (no error), UseStdio overridden

Validation logic comparison:

  • Node.js (line 195): if (options.cliUrl && options.useStdio === true) → throws error
  • Python (line ~165): if opts.get("cli_url") and opts.get("use_stdio") → raises ValueError
  • Go (line 132): if options.CLIUrl != "" && options.UseStdio != nil → panics
  • .NET before PR: if (!string.IsNullOrEmpty(_options.CliUrl) && _options.UseStdio) → throws ArgumentException
  • .NET after PR: Removes validation, silently overrides UseStdio = false

💡 Recommendation

Option 1 (Maintain consistency): Keep the validation error and use the same pattern as other SDKs:

// In NewClient constructor validation
if (!string.IsNullOrEmpty(_options.CliUrl) && _options.UseStdio)
{
    throw new ArgumentException("CliUrl is mutually exclusive with UseStdio and CliPath");
}

// Later, during connection setup (if not already done elsewhere):
if (!string.IsNullOrEmpty(_options.CliUrl))
{
    // Only set UseStdio=false if not explicitly set by user
    // This prevents the explicit true case from passing validation
}

Option 2 (Document the divergence): If the silent override behavior is intentional for .NET's API ergonomics, document this as a known language-specific difference and update the other SDKs' documentation to note that .NET handles this case differently.

The current change makes .NET behave differently from the other three SDKs when users explicitly pass conflicting options, which could cause confusion for developers working across multiple languages.

AI generated by SDK Consistency Review Agent

@patniko patniko merged commit c263dfc into main Feb 19, 2026
35 checks passed
@patniko patniko deleted the add-test-scenarios branch February 19, 2026 17:07
if [ "$FAIL" -gt 0 ]; then
echo -e "Failures:$FAILURES"
exit 1
fi
Copy link
Contributor

Choose a reason for hiding this comment

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

This seems a bit odd - is it really doing a build? Looks like it just does npm install

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