@@ -99,6 +99,121 @@ impl FsRead {
99
99
}
100
100
}
101
101
102
+ pub fn eval_perm ( & self , agent : & Agent ) -> PermissionEvalResult {
103
+ #[ derive( Debug , Deserialize ) ]
104
+ #[ serde( rename_all = "camelCase" ) ]
105
+ struct Settings {
106
+ #[ serde( default ) ]
107
+ allowed_paths : Vec < String > ,
108
+ #[ serde( default ) ]
109
+ denied_paths : Vec < String > ,
110
+ #[ serde( default = "default_allow_read_only" ) ]
111
+ allow_read_only : bool ,
112
+ }
113
+
114
+ fn default_allow_read_only ( ) -> bool {
115
+ true
116
+ }
117
+
118
+ let is_in_allowlist = agent. allowed_tools . contains ( "fs_read" ) ;
119
+ match agent. tools_settings . get ( "fs_read" ) {
120
+ Some ( settings) if is_in_allowlist => {
121
+ let Settings {
122
+ allowed_paths,
123
+ denied_paths,
124
+ allow_read_only,
125
+ } = match serde_json:: from_value :: < Settings > ( settings. clone ( ) ) {
126
+ Ok ( settings) => settings,
127
+ Err ( e) => {
128
+ error ! ( "Failed to deserialize tool settings for fs_read: {:?}" , e) ;
129
+ return PermissionEvalResult :: Ask ;
130
+ } ,
131
+ } ;
132
+ let allow_set = {
133
+ let mut builder = GlobSetBuilder :: new ( ) ;
134
+ for path in & allowed_paths {
135
+ if let Ok ( glob) = Glob :: new ( path) {
136
+ builder. add ( glob) ;
137
+ } else {
138
+ warn ! ( "Failed to create glob from path given: {path}. Ignoring." ) ;
139
+ }
140
+ }
141
+ builder. build ( )
142
+ } ;
143
+
144
+ let deny_set = {
145
+ let mut builder = GlobSetBuilder :: new ( ) ;
146
+ for path in & denied_paths {
147
+ if let Ok ( glob) = Glob :: new ( path) {
148
+ builder. add ( glob) ;
149
+ } else {
150
+ warn ! ( "Failed to create glob from path given: {path}. Ignoring." ) ;
151
+ }
152
+ }
153
+ builder. build ( )
154
+ } ;
155
+
156
+ match ( allow_set, deny_set) {
157
+ ( Ok ( allow_set) , Ok ( deny_set) ) => {
158
+ let eval_res = self
159
+ . operations
160
+ . iter ( )
161
+ . map ( |op| {
162
+ match op {
163
+ FsReadOperation :: Line ( FsLine { path, .. } )
164
+ | FsReadOperation :: Directory ( FsDirectory { path, .. } )
165
+ | FsReadOperation :: Search ( FsSearch { path, .. } ) => {
166
+ if deny_set. is_match ( path) {
167
+ return PermissionEvalResult :: Deny ;
168
+ }
169
+ if allow_set. is_match ( path) {
170
+ return PermissionEvalResult :: Allow ;
171
+ }
172
+ } ,
173
+ FsReadOperation :: Image ( fs_image) => {
174
+ let paths = & fs_image. image_paths ;
175
+ if paths. iter ( ) . any ( |path| deny_set. is_match ( path) ) {
176
+ return PermissionEvalResult :: Deny ;
177
+ }
178
+ if paths. iter ( ) . all ( |path| allow_set. is_match ( path) ) {
179
+ return PermissionEvalResult :: Allow ;
180
+ }
181
+ } ,
182
+ }
183
+
184
+ if allow_read_only {
185
+ PermissionEvalResult :: Allow
186
+ } else {
187
+ PermissionEvalResult :: Ask
188
+ }
189
+ } )
190
+ . collect :: < Vec < _ > > ( ) ;
191
+
192
+ if eval_res. contains ( & PermissionEvalResult :: Deny ) {
193
+ PermissionEvalResult :: Deny
194
+ } else if eval_res. contains ( & PermissionEvalResult :: Ask ) {
195
+ PermissionEvalResult :: Ask
196
+ } else {
197
+ PermissionEvalResult :: Allow
198
+ }
199
+ } ,
200
+ ( allow_res, deny_res) => {
201
+ if let Err ( e) = allow_res {
202
+ warn ! ( "fs_read failed to build allow set: {:?}" , e) ;
203
+ }
204
+ if let Err ( e) = deny_res {
205
+ warn ! ( "fs_read failed to build deny set: {:?}" , e) ;
206
+ }
207
+ warn ! ( "One or more detailed args failed to parse, falling back to ask" ) ;
208
+ PermissionEvalResult :: Ask
209
+ } ,
210
+ }
211
+ } ,
212
+ None if is_in_allowlist => PermissionEvalResult :: Allow ,
213
+ _ => PermissionEvalResult :: Ask ,
214
+ }
215
+ }
216
+
102
217
pub async fn invoke ( & self , os : & Os , updates : & mut impl Write ) -> Result < InvokeOutput > {
103
218
if self . operations . len ( ) == 1 {
104
219
// Single operation - return result directly
@@ -218,106 +333,6 @@ impl FsReadOperation {
218
333
FsReadOperation :: Image ( fs_image) => fs_image. invoke ( updates) . await ,
219
334
}
220
335
}
221
-
222
- pub fn eval_perm ( & self , agent : & Agent ) -> PermissionEvalResult {
223
- #[ derive( Debug , Deserialize ) ]
224
- #[ serde( rename_all = "camelCase" ) ]
225
- struct Settings {
226
- #[ serde( default ) ]
227
- allowed_paths : Vec < String > ,
228
- #[ serde( default ) ]
229
- denied_paths : Vec < String > ,
230
- #[ serde( default = "default_allow_read_only" ) ]
231
- allow_read_only : bool ,
232
- }
233
-
234
- fn default_allow_read_only ( ) -> bool {
235
- true
236
- }
237
-
238
- let is_in_allowlist = agent. allowed_tools . contains ( "fs_read" ) ;
239
- match agent. tools_settings . get ( "fs_read" ) {
240
- Some ( settings) if is_in_allowlist => {
241
- let Settings {
242
- allowed_paths,
243
- denied_paths,
244
- allow_read_only,
245
- } = match serde_json:: from_value :: < Settings > ( settings. clone ( ) ) {
246
- Ok ( settings) => settings,
247
- Err ( e) => {
248
- error ! ( "Failed to deserialize tool settings for fs_read: {:?}" , e) ;
249
- return PermissionEvalResult :: Ask ;
250
- } ,
251
- } ;
252
- let allow_set = {
253
- let mut builder = GlobSetBuilder :: new ( ) ;
254
- for path in & allowed_paths {
255
- if let Ok ( glob) = Glob :: new ( path) {
256
- builder. add ( glob) ;
257
- } else {
258
- warn ! ( "Failed to create glob from path given: {path}. Ignoring." ) ;
259
- }
260
- }
261
- builder. build ( )
262
- } ;
263
-
264
- let deny_set = {
265
- let mut builder = GlobSetBuilder :: new ( ) ;
266
- for path in & denied_paths {
267
- if let Ok ( glob) = Glob :: new ( path) {
268
- builder. add ( glob) ;
269
- } else {
270
- warn ! ( "Failed to create glob from path given: {path}. Ignoring." ) ;
271
- }
272
- }
273
- builder. build ( )
274
- } ;
275
-
276
- match ( allow_set, deny_set) {
277
- ( Ok ( allow_set) , Ok ( deny_set) ) => {
278
- match self {
279
- Self :: Line ( FsLine { path, .. } )
280
- | Self :: Directory ( FsDirectory { path, .. } )
281
- | Self :: Search ( FsSearch { path, .. } ) => {
282
- if deny_set. is_match ( path) {
283
- return PermissionEvalResult :: Deny ;
284
- }
285
- if allow_set. is_match ( path) {
286
- return PermissionEvalResult :: Allow ;
287
- }
288
- } ,
289
- Self :: Image ( fs_image) => {
290
- let paths = & fs_image. image_paths ;
291
- if paths. iter ( ) . any ( |path| deny_set. is_match ( path) ) {
292
- return PermissionEvalResult :: Deny ;
293
- }
294
- if paths. iter ( ) . all ( |path| allow_set. is_match ( path) ) {
295
- return PermissionEvalResult :: Allow ;
296
- }
297
- } ,
298
- }
299
- if allow_read_only {
300
- PermissionEvalResult :: Allow
301
- } else {
302
- PermissionEvalResult :: Ask
303
- }
304
- } ,
305
- ( allow_res, deny_res) => {
306
- if let Err ( e) = allow_res {
307
- warn ! ( "fs_read failed to build allow set: {:?}" , e) ;
308
- }
309
- if let Err ( e) = deny_res {
310
- warn ! ( "fs_read failed to build deny set: {:?}" , e) ;
311
- }
312
- warn ! ( "One or more detailed args failed to parse, falling back to ask" ) ;
313
- PermissionEvalResult :: Ask
314
- } ,
315
- }
316
- } ,
317
- None if is_in_allowlist => PermissionEvalResult :: Allow ,
318
- _ => PermissionEvalResult :: Ask ,
319
- }
320
- }
321
336
}
322
337
323
338
/// Read images from given paths.
0 commit comments