@@ -121,10 +121,11 @@ export namespace PermissionNext {
121121 const s = await state ( )
122122 const { ruleset, ...request } = input
123123 for ( const pattern of request . patterns ?? [ ] ) {
124- const action = evaluate ( request . permission , pattern , ruleset , s . approved )
125- log . info ( "evaluated" , { permission : request . permission , pattern, action } )
126- if ( action === "deny" ) throw new RejectedError ( )
127- if ( action === "ask" ) {
124+ const rule = evaluate ( request . permission , pattern , ruleset , s . approved )
125+ log . info ( "evaluated" , { permission : request . permission , pattern, action : rule } )
126+ if ( rule . action === "deny" )
127+ throw new AutoRejectedError ( ruleset . filter ( ( r ) => Wildcard . match ( request . permission , r . permission ) ) )
128+ if ( rule . action === "ask" ) {
128129 const id = input . id ?? Identifier . ascending ( "permission" )
129130 return new Promise < void > ( ( resolve , reject ) => {
130131 const info : Request = {
@@ -139,7 +140,7 @@ export namespace PermissionNext {
139140 Bus . publish ( Event . Asked , info )
140141 } )
141142 }
142- if ( action === "allow" ) continue
143+ if ( rule . action === "allow" ) continue
143144 }
144145 } ,
145146 )
@@ -195,7 +196,7 @@ export namespace PermissionNext {
195196 for ( const [ id , pending ] of Object . entries ( s . pending ) ) {
196197 if ( pending . info . sessionID !== sessionID ) continue
197198 const ok = pending . info . patterns . every (
198- ( pattern ) => evaluate ( pending . info . permission , pattern , s . approved ) === "allow" ,
199+ ( pattern ) => evaluate ( pending . info . permission , pattern , s . approved ) . action === "allow" ,
199200 )
200201 if ( ! ok ) continue
201202 delete s . pending [ id ]
@@ -215,13 +216,13 @@ export namespace PermissionNext {
215216 } ,
216217 )
217218
218- export function evaluate ( permission : string , pattern : string , ...rulesets : Ruleset [ ] ) : Action {
219+ export function evaluate ( permission : string , pattern : string , ...rulesets : Ruleset [ ] ) : Rule {
219220 const merged = merge ( ...rulesets )
220221 log . info ( "evaluate" , { permission, pattern, ruleset : merged } )
221222 const match = merged . findLast (
222223 ( rule ) => Wildcard . match ( permission , rule . permission ) && Wildcard . match ( pattern , rule . pattern ) ,
223224 )
224- return match ?. action ?? "ask"
225+ return match ?? { action : "allow" , permission , pattern : "*" }
225226 }
226227
227228 const EDIT_TOOLS = [ "edit" , "write" , "patch" , "multiedit" ]
@@ -230,19 +231,23 @@ export namespace PermissionNext {
230231 const result = new Set < string > ( )
231232 for ( const tool of tools ) {
232233 const permission = EDIT_TOOLS . includes ( tool ) ? "edit" : tool
233- if ( evaluate ( permission , "*" , ruleset ) === "deny" ) {
234+ if ( evaluate ( permission , "*" , ruleset ) . action === "deny" ) {
234235 result . add ( tool )
235236 }
236237 }
237238 return result
238239 }
239240
240241 export class RejectedError extends Error {
241- constructor ( public readonly reason ?: string ) {
242+ constructor ( ) {
243+ super ( `The user rejected permission to use this specific tool call. You may try again with different parameters.` )
244+ }
245+ }
246+
247+ export class AutoRejectedError extends Error {
248+ constructor ( public readonly ruleset : Ruleset ) {
242249 super (
243- reason !== undefined
244- ? reason
245- : `The user rejected permission to use this specific tool call. You may try again with different parameters.` ,
250+ `The user has specified a rule which prevents you from using this specific tool call. Here are some of the relevant rules ${ JSON . stringify ( ruleset ) } ` ,
246251 )
247252 }
248253 }
0 commit comments