diff --git a/packages/opencode/src/permission/index.ts b/packages/opencode/src/permission/index.ts index f486eb43b1..cb4d9eef69 100644 --- a/packages/opencode/src/permission/index.ts +++ b/packages/opencode/src/permission/index.ts @@ -29,7 +29,11 @@ export type Rule = Schema.Schema.Type export const Ruleset = Schema.Array(Rule).annotate({ identifier: "PermissionRuleset" }) export type Ruleset = Schema.Schema.Type -export class Request extends Schema.Class("PermissionRequest")({ +// Pure data; nothing checks class identity. As `Schema.Struct` + type alias, +// `Permission.ask` can trust its already-typed input and skip the inner +// `decodeUnknownSync` that would otherwise throw uncaught on any structural +// mismatch. Same pattern as `Question.Request` in PR #28570. +export const Request = Schema.Struct({ id: PermissionID, sessionID: SessionID, permission: Schema.String, @@ -42,7 +46,8 @@ export class Request extends Schema.Class("PermissionRequest")({ callID: Schema.String, }), ), -}) {} +}).annotate({ identifier: "PermissionRequest" }) +export type Request = Schema.Schema.Type export const Reply = Schema.Literals(["once", "always", "reject"]) export type Reply = Schema.Schema.Type @@ -55,10 +60,11 @@ const reply = { export const ReplyBody = Schema.Struct(reply).annotate({ identifier: "PermissionReplyBody" }) export type ReplyBody = Schema.Schema.Type -export class Approval extends Schema.Class("PermissionApproval")({ +export const Approval = Schema.Struct({ projectID: ProjectID, patterns: Schema.Array(Schema.String), -}) {} +}).annotate({ identifier: "PermissionApproval" }) +export type Approval = Schema.Schema.Type export const Event = { Asked: BusEvent.define("permission.asked", Request), @@ -178,10 +184,15 @@ export const layer = Layer.effect( if (!needsAsk) return const id = request.id ?? PermissionID.ascending() - const info = Schema.decodeUnknownSync(Request)({ + const info: Request = { id, - ...request, - }) + sessionID: request.sessionID, + permission: request.permission, + patterns: request.patterns, + metadata: request.metadata, + always: request.always, + tool: request.tool, + } log.info("asking", { id, permission: info.permission, patterns: info.patterns }) const deferred = yield* Deferred.make()