Commit 581abad
Phase L: emit discriminated unions in Python codegen + drop hand-written PermissionRequestResult
Brings Python in line with TS/Rust/.NET/Go which all emit per-variant types
for �nyOf-of-\ discriminated unions in the schemas (PermissionRequest,
PermissionDecision, AuthInfo, SendAttachment, ToolExecutionCompleteContent,
TaskInfo, SystemNotification, etc.). Previously the Python codegen merged
each one into a single flat dataclass with every variant's fields collapsed
to Optional — see `scripts/codegen/python.ts:897-901` for the old remap
table that fronted the merged blob as `PermissionRequest`.
Codegen changes (`scripts/codegen/python.ts`)
* `tryEmitPyRefBasedDiscriminatedUnion` in the hand-written session-events
pipeline emits each variant as its own `@dataclass`, plus a
`Name = VariantA | VariantB | ...` union alias and a `_load_Name(obj)`
dispatcher that switches on the discriminator (matches `findPyDiscriminator`).
* `postProcessRefBasedDiscriminatedUnionsForPython` does the equivalent on
the quicktype-emitted RPC types: detects each `\`-based discriminated
union, deletes the merged flat class quicktype produced, emits the union
alias and dispatcher, and rewrites every `Name.from_dict(x)` / `to_class(Name, x)`
call (including in RPC method wrappers generated later) to route through
the dispatcher.
* Acronym resolution table (`Api → API`, `Mcp → MCP`, `Cli → CLI`, etc.)
to map schema names to the actual class names quicktype emits.
* `postProcessDiscriminatorDefaultsForPython` replaces the dataclass-level
`kind` field on each variant with a class-level `ClassVar[str]` constant.
Users construct variants with no discriminator arg required:
`PermissionDecisionApproveOnce()` instead of
`PermissionDecisionApproveOnce(kind=PermissionDecisionApproveOnceKind.APPROVE_ONCE)`.
`from_dict` / `to_dict` are rewritten in lock-step.
Hand-written SDK changes
* `copilot.session.PermissionRequestResult` becomes a type alias for
`PermissionDecision | PermissionNoResult` (mirrors TS
`nodejs/src/types.ts:883`). The hand-written `PermissionRequestResult`
dataclass and the `_decision_from_result` mapper are gone — handlers now
return the generated variant directly. `PermissionNoResult` is a tiny
hand-written sentinel for the v1-protocol case.
* `PermissionHandler.approve_all` returns `PermissionDecisionApproveOnce()`.
* `CopilotSession._execute_permission_and_respond` passes the returned
decision straight through to the RPC; v2 servers reject `PermissionNoResult`
with a clear `ValueError`.
* `CopilotClient._handle_permission_request_v2` uses `_load_PermissionRequest`
and serialises the variant result with `.to_dict()`.
Tests and scenarios updated in lock-step.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>1 parent f4d22d7 commit 581abad
18 files changed
Lines changed: 3141 additions & 2701 deletions
File tree
- python
- copilot
- generated
- e2e
- scripts/codegen
- test/scenarios
- callbacks
- hooks/python
- permissions/python
- user-input/python
- tools
- skills/python
- virtual-filesystem/python
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
39 | 39 | | |
40 | 40 | | |
41 | 41 | | |
| 42 | + | |
42 | 43 | | |
43 | 44 | | |
44 | 45 | | |
45 | 46 | | |
46 | 47 | | |
47 | 48 | | |
48 | 49 | | |
49 | | - | |
50 | 50 | | |
| 51 | + | |
51 | 52 | | |
52 | 53 | | |
53 | 54 | | |
| |||
61 | 62 | | |
62 | 63 | | |
63 | 64 | | |
| 65 | + | |
64 | 66 | | |
65 | 67 | | |
66 | 68 | | |
| |||
3193 | 3195 | | |
3194 | 3196 | | |
3195 | 3197 | | |
3196 | | - | |
| 3198 | + | |
3197 | 3199 | | |
3198 | | - | |
| 3200 | + | |
3199 | 3201 | | |
3200 | | - | |
| 3202 | + | |
3201 | 3203 | | |
3202 | 3204 | | |
3203 | 3205 | | |
3204 | | - | |
3205 | | - | |
3206 | | - | |
3207 | | - | |
3208 | | - | |
| 3206 | + | |
3209 | 3207 | | |
3210 | | - | |
3211 | | - | |
3212 | | - | |
3213 | | - | |
3214 | | - | |
| 3208 | + | |
0 commit comments