You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Replace hand-written PermissionRequestResult with PermissionDecision (.NET, Go)
Python (#1376) drove out its own hand-written ``PermissionRequestResult``
wrapper in favour of the generated discriminated ``PermissionDecision``
union plus a small ``PermissionNoResult`` sentinel. This commit lands the
same refactor for the .NET and Go SDKs.
**.NET**
The old ``PermissionRequestResult`` struct (just ``Kind`` + optional
``Feedback``) collapsed every decision variant into a flat string-tagged
DTO, losing the rich per-variant payloads — ``Feedback`` on rejection,
per-kind ``Approval`` lists on ``ApproveForSession`` /
``ApproveForLocation``, ``Domain`` on ``ApprovePermanently``, etc.
The generated ``PermissionDecision`` (``Rpc.cs:4760``) is already a
proper polymorphic hierarchy with ``[JsonDerivedType]`` wired up for
every variant. Switch ``OnPermissionRequest`` to return
``Task<PermissionDecision>`` and route the variant straight onto the
wire — StreamJsonRpc handles the discriminator via the existing
attributes.
Additions:
- ``PermissionDecisionNoResult`` — hand-written subclass of
``PermissionDecision`` used when the handler declines to respond so
another connected client can answer. The SDK suppresses the wire
response when it sees this variant.
- Static factories on ``PermissionDecision`` for discoverability:
``ApproveOnce()``, ``Reject(feedback)``, ``UserNotAvailable()``,
``NoResult()``. For richer decisions that need an ``Approval``
payload, instantiate the variant class directly.
Deletions:
- ``PermissionRequestResult`` class (``Types.cs``)
- ``PermissionRequestResultKind`` struct + obsolete enum-like wrappers
- ``PermissionRequestResultKindTests.cs``
- ``PermissionRequestResult`` JSON serialization metadata
**Go**
Same shape: drop ``PermissionRequestResult`` + ``PermissionRequestResultKind``
in favour of ``rpc.PermissionDecision`` (already a sealed interface
implemented by every variant). Added ``rpc.PermissionDecisionNoResult``
as a hand-written variant that satisfies the unexported
``permissionDecision()`` method — kept inside the ``rpc`` package since
the sealing method is unexported.
Handler signature changes from ``(PermissionRequestResult, error)`` to
``(rpc.PermissionDecision, error)``. ``PermissionHandler.ApproveAll``
now returns ``&rpc.PermissionDecisionApproveOnce{}``.
Removed the ``rpcPermissionDecisionFromKind`` helper used to convert
the flat kind back to a variant — no longer needed when the handler
already returns the variant directly.
**Tests / scenarios**
All E2E tests and scenarios across .NET and Go updated to construct
``rpc.PermissionDecision*`` variants directly. The Go interface return
type means explicit ``Task.FromResult<PermissionDecision>(...)`` casts
are needed in C# where lambdas previously inferred the wrapper type.
**Doc style**
Per repo convention, public docs do not reference protocol v1/v2 or
internal transport details. The README copy for each SDK describes the
behavioural semantics ("decline to respond so another client can
answer") rather than the wire mechanism.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copy file name to clipboardExpand all lines: dotnet/README.md
+16-30Lines changed: 16 additions & 30 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -749,51 +749,37 @@ var session = await client.CreateSessionAsync(new SessionConfig
749
749
750
750
### Custom Permission Handler
751
751
752
-
Provide your own permission handler (`Func<PermissionRequest, PermissionInvocation, Task<PermissionRequestResult>>`) to inspect each request and apply custom logic:
752
+
Provide your own permission handler (`Func<PermissionRequest, PermissionInvocation, Task<PermissionDecision>>`) to inspect each request and apply custom logic:
The `Kind` property must be one of the canonical `PermissionRequestResultKind` values. Approval decisions are present-tense — they describe the decision to apply, not the past-tense outcome reported back on `permission.completed` session events.
773
+
The handler returns a `PermissionDecision`. Use the static factories for common cases (returned types are the strongly-typed variant classes — full IntelliSense via `PermissionDecision.<dot>`):
|`PermissionRequestResultKind.Approved`|`"approve-once"`|Allow this single request|
792
-
|`PermissionRequestResultKind.Rejected`|`"reject"`|Deny the request|
793
-
|`PermissionRequestResultKind.UserNotAvailable`|`"user-not-available"`|Deny the request because no user is available to confirm it|
794
-
|`PermissionRequestResultKind.NoResult`|`"no-result"`| Leave the permission request unanswered (the SDK returns without calling the RPC). Not allowed for protocol v2 permission requests (will be rejected).|
|`PermissionDecision.ApproveOnce()`|Allow this single request |
778
+
|`PermissionDecision.Reject(feedback)`|Deny the request, optionally forwarding feedback to the LLM|
779
+
|`PermissionDecision.UserNotAvailable()`|Deny the request because no user is available to confirm it |
780
+
|`PermissionDecision.NoResult()`| Decline to respond, allowing another connected client to answer instead |
795
781
796
-
> The past-tense names `PermissionRequestResultKind.DeniedInteractivelyByUser`, `PermissionRequestResultKind.DeniedCouldNotRequestFromUser`, and `PermissionRequestResultKind.DeniedByRules` remain as `[Obsolete]` aliases for backward compatibility — prefer the canonical members above in new code.
782
+
For richer decisions that need an `Approval` payload — `PermissionDecisionApproveForSession`, `PermissionDecisionApproveForLocation`, `PermissionDecisionApprovePermanently` — instantiate the variant class directly.
0 commit comments