Fix codegen for discriminated unions nested within other types#736
Fix codegen for discriminated unions nested within other types#736SteveSandersonMS merged 2 commits intomainfrom
Conversation
…sult is strongly-typed APIs for permission requests
…ants Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Cross-SDK Consistency ReviewThis PR improves C# codegen to generate strongly-typed discriminated unions for However, there's a cross-SDK consistency gap: Current State After This PR
ImpactThe Python and Go SDKs currently have the same issue this PR fixes for C#:
ExampleTypeScript (already strong): if (request.kind === "shell") {
console.log(request.fullCommandText); // ✅ TypeScript knows this exists
}C# (strong after this PR): if (request is PermissionRequestShell shell) {
Console.WriteLine(shell.FullCommandText); // ✅ C# knows this exists
}Python (currently weak): if request.kind == PermissionRequestKind.SHELL:
print(request.full_command_text) # ⚠️ Not type-safe, could be NoneGo (currently weak): if request.Kind == KindShell {
fmt.Println(*request.FullCommandText) // ⚠️ Not type-safe, pointer could be nil
}Root Cause
RecommendationTo maintain feature parity across all SDKs, consider either:
This PR is good to merge as-is since it improves C# without breaking anything, but the consistency gap is worth addressing in the roadmap. Note: This is an automated consistency review. I'm not blocking the PR, just surfacing the cross-language gap for the team's awareness.
|
There was a problem hiding this comment.
Pull request overview
Updates the C#/.NET codegen pipeline so discriminated unions nested inside other types are generated as strongly-typed polymorphic classes (instead of weakly-typed object), improving the .NET SDK’s type safety while keeping protocol v2 behavior working.
Changes:
- Add C# codegen support for nested discriminated unions (
anyOfwith a shared const discriminator), plus a rename override to keep the public .NET type name asPermissionRequest. - Switch .NET permission-request handling to deserialize via the generated
SessionEventsJsonContextand pass a strongly typedPermissionRequestthrough the permission handler flow. - Update .NET tests to assert against specific derived permission request types (e.g.,
PermissionRequestCustomTool,PermissionRequestShell).
Reviewed changes
Copilot reviewed 6 out of 7 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| scripts/codegen/csharp.ts | Adds nested-discriminated-union generation and type rename overrides for cleaner public C# type names. |
| dotnet/src/Generated/SessionEvents.cs | Generated output now models permissionRequest as a polymorphic PermissionRequest union with derived variants. |
| dotnet/src/Session.cs | Deserializes permission requests using SessionEventsJsonContext and threads typed requests through broadcast handling. |
| dotnet/src/Types.cs | Removes the prior hand-written PermissionRequest type and its serializer registration. |
| dotnet/test/ToolsTests.cs | Updates assertions to use PermissionRequestCustomTool.ToolName instead of extension data. |
| dotnet/test/PermissionTests.cs | Updates toolCallId assertion to pattern-match the appropriate derived permission request type. |
Cross-SDK Consistency Review ✅I've reviewed this PR for consistency across all four SDK implementations. This change maintains appropriate cross-SDK consistency. Summary of ChangeThis PR improves the C# code generation to handle discriminated unions nested within other types, specifically for Cross-Language Analysis✅ TypeScript - Already uses inline discriminated unions (lines 2178-2374 in ✅ .NET (this PR) - Now generates:
✅ Python - Uses quicktype's standard representation (as noted in PR description):
✅ Go - Uses quicktype's standard representation:
Consistency AssessmentEach language now has a semantically equivalent but idiomatically appropriate representation:
The PR description explicitly acknowledges this:
Recommendation✅ Approved - This is an appropriate language-specific improvement that brings .NET in line with TypeScript's type safety while respecting the idiomatic patterns of each language. The codegen changes are scoped to C# only, and the generated types maintain protocol compatibility across all SDKs.
|
|
Are there plans to properly discriminate the event models for python, too? Or would PRs for this be welcome? currently it is horrible to work with the given models, using datamodel-codegen for example would improve the models significantly. |
Previously we only handled discriminated unions at the top level for C#. This resulted in a weak and loosely typed representation of some of the newer APIs. This PR turns this into strongly typed APIs while retaining protocol v2 backcompat.
Note that other languages aren't changed: