Преглед изворни кода

add flag wildcard parsing support for bash tool (#3390)

Aiden Cline пре 5 месеци
родитељ
комит
9b5fe10df6
2 измењених фајлова са 27 додато и 1 уклоњено
  1. 1 1
      packages/opencode/src/tool/bash.ts
  2. 26 0
      packages/opencode/src/util/wildcard.ts

+ 1 - 1
packages/opencode/src/tool/bash.ts

@@ -97,7 +97,7 @@ export const BashTool = Tool.define("bash", {
 
 
       // always allow cd if it passes above check
       // always allow cd if it passes above check
       if (command[0] !== "cd") {
       if (command[0] !== "cd") {
-        const action = Wildcard.all(node.text, permissions)
+        const action = Wildcard.allStructured({ head: command[0], tail: command.slice(1) }, permissions)
         if (action === "deny") {
         if (action === "deny") {
           throw new Error(
           throw new Error(
             `The user has specifically restricted access to this command, you are not allowed to execute it. Here is the configuration: ${JSON.stringify(permissions)}`,
             `The user has specifically restricted access to this command, you are not allowed to execute it. Here is the configuration: ${JSON.stringify(permissions)}`,

+ 26 - 0
packages/opencode/src/util/wildcard.ts

@@ -25,4 +25,30 @@ export namespace Wildcard {
     }
     }
     return result
     return result
   }
   }
+
+  export function allStructured(input: { head: string; tail: string[] }, patterns: Record<string, any>) {
+    const sorted = pipe(patterns, Object.entries, sortBy([([key]) => key.length, "asc"], [([key]) => key, "asc"]))
+    let result = undefined
+    for (const [pattern, value] of sorted) {
+      const parts = pattern.split(/\s+/)
+      if (!match(input.head, parts[0])) continue
+      if (parts.length === 1 || matchSequence(input.tail, parts.slice(1))) {
+        result = value
+        continue
+      }
+    }
+    return result
+  }
+
+  function matchSequence(items: string[], patterns: string[]): boolean {
+    if (patterns.length === 0) return true
+    const [pattern, ...rest] = patterns
+    if (pattern === "*") return matchSequence(items, rest)
+    for (let i = 0; i < items.length; i++) {
+      if (match(items[i], pattern) && matchSequence(items.slice(i + 1), rest)) {
+        return true
+      }
+    }
+    return false
+  }
 }
 }