Aiden Cline il y a 7 mois
Parent
commit
1e2ac94a91
1 fichiers modifiés avec 45 ajouts et 26 suppressions
  1. 45 26
      packages/opencode/src/permission/next.ts

+ 45 - 26
packages/opencode/src/permission/next.ts

@@ -2,7 +2,6 @@ import { Bus } from "@/bus"
 import { BusEvent } from "@/bus/bus-event"
 import { Config } from "@/config/config"
 import { Identifier } from "@/id/id"
-import { Plugin } from "@/plugin"
 import { Instance } from "@/project/instance"
 import { Storage } from "@/storage/storage"
 import { fn } from "@/util/fn"
@@ -121,37 +120,57 @@ export namespace PermissionNext {
     async (input) => {
       const s = await state()
       const { ruleset, ...request } = input
-      for (const pattern of request.patterns ?? []) {
+      const ask = (request.patterns ?? []).reduce((ask, pattern) => {
         const rule = evaluate(request.permission, pattern, ruleset, s.approved)
         log.info("evaluated", { permission: request.permission, pattern, action: rule })
-        if (rule.action === "deny")
+        if (rule.action === "deny") {
           throw new DeniedError(ruleset.filter((r) => Wildcard.match(request.permission, r.permission)))
-        if (rule.action === "ask") {
-          const id = input.id ?? Identifier.ascending("permission")
-          const info: Request = {
-            id,
-            ...request,
-          }
-          const pluginResult = await Plugin.trigger("permission.ask", info, {
-            status: "ask" as "ask" | "allow" | "deny",
-          })
-          if (pluginResult.status === "deny") {
-            throw new RejectedError()
-          }
-          if (pluginResult.status === "allow") {
-            continue
-          }
-          return new Promise<void>((resolve, reject) => {
-            s.pending[id] = {
-              info,
-              resolve,
-              reject,
+        }
+        return ask || rule.action === "ask"
+      }, false)
+
+      if (!ask) return
+
+      const id = input.id ?? Identifier.ascending("permission")
+      const info: Request = {
+        id,
+        ...request,
+      }
+
+      return new Promise<void>((resolve, reject) => {
+        s.pending[id] = {
+          info,
+          resolve,
+          reject,
+        }
+
+        void import("@/plugin")
+          .then((plugin) =>
+            plugin.Plugin.trigger("permission.ask", info, {
+              status: "ask" as "ask" | "allow" | "deny",
+            }),
+          )
+          .then((result) => {
+            const existing = s.pending[id]
+            if (!existing) return
+            if (result.status === "deny") {
+              delete s.pending[id]
+              existing.reject(new RejectedError())
+              return
+            }
+            if (result.status === "allow") {
+              delete s.pending[id]
+              existing.resolve()
+              return
             }
             Bus.publish(Event.Asked, info)
           })
-        }
-        if (rule.action === "allow") continue
-      }
+          .catch((error) => {
+            log.error("permission.ask plugin failed", { error })
+            if (!s.pending[id]) return
+            Bus.publish(Event.Asked, info)
+          })
+      })
     },
   )