@@ -231,6 +231,49 @@ describe("tool.bash permissions", () => {
231231 } ,
232232 } )
233233 } )
234+
235+ test ( "matches redirects in permission pattern" , async ( ) => {
236+ await using tmp = await tmpdir ( { git : true } )
237+ await Instance . provide ( {
238+ directory : tmp . path ,
239+ fn : async ( ) => {
240+ const bash = await BashTool . init ( )
241+ const requests : Array < Omit < PermissionNext . Request , "id" | "sessionID" | "tool" > > = [ ]
242+ const testCtx = {
243+ ...ctx ,
244+ ask : async ( req : Omit < PermissionNext . Request , "id" | "sessionID" | "tool" > ) => {
245+ requests . push ( req )
246+ } ,
247+ }
248+ await bash . execute ( { command : "cat > /tmp/output.txt" , description : "Redirect ls output" } , testCtx )
249+ const bashReq = requests . find ( ( r ) => r . permission === "bash" )
250+ expect ( bashReq ) . toBeDefined ( )
251+ expect ( bashReq ! . patterns ) . toContain ( "cat > /tmp/output.txt" )
252+ } ,
253+ } )
254+ } )
255+
256+ test ( "always pattern has space before wildcard to not include different commands" , async ( ) => {
257+ await using tmp = await tmpdir ( { git : true } )
258+ await Instance . provide ( {
259+ directory : tmp . path ,
260+ fn : async ( ) => {
261+ const bash = await BashTool . init ( )
262+ const requests : Array < Omit < PermissionNext . Request , "id" | "sessionID" | "tool" > > = [ ]
263+ const testCtx = {
264+ ...ctx ,
265+ ask : async ( req : Omit < PermissionNext . Request , "id" | "sessionID" | "tool" > ) => {
266+ requests . push ( req )
267+ } ,
268+ }
269+ await bash . execute ( { command : "ls -la" , description : "List" } , testCtx )
270+ const bashReq = requests . find ( ( r ) => r . permission === "bash" )
271+ expect ( bashReq ) . toBeDefined ( )
272+ const pattern = bashReq ! . always [ 0 ]
273+ expect ( pattern ) . toBe ( "ls *" )
274+ } ,
275+ } )
276+ } )
234277} )
235278
236279describe ( "tool.bash truncation" , ( ) => {
0 commit comments