| 464 | } |
| 465 | |
| 466 | pub fn eval_perm(&self, os: &Os, agent: &Agent) -> PermissionEvalResult { |
| 467 | #[derive(Debug, Deserialize)] |
| 468 | #[serde(rename_all = "camelCase")] |
| 469 | struct Settings { |
| 470 | #[serde(default)] |
| 471 | allowed_paths: Vec<String>, |
| 472 | #[serde(default)] |
| 473 | denied_paths: Vec<String>, |
| 474 | } |
| 475 | |
| 476 | let is_in_allowlist = is_tool_in_allowlist(&agent.allowed_tools, "fs_write", None); |
| 477 | match agent.tools_settings.get("fs_write") { |
| 478 | Some(settings) => { |
| 479 | let Settings { |
| 480 | allowed_paths, |
| 481 | denied_paths, |
| 482 | } = match serde_json::from_value::<Settings>(settings.clone()) { |
| 483 | Ok(settings) => settings, |
| 484 | Err(e) => { |
| 485 | error!("Failed to deserialize tool settings for fs_write: {:?}", e); |
| 486 | return PermissionEvalResult::Ask; |
| 487 | }, |
| 488 | }; |
| 489 | let allow_set = { |
| 490 | let mut builder = GlobSetBuilder::new(); |
| 491 | for path in &allowed_paths { |
| 492 | let Ok(path) = paths::canonicalizes_path(os, path) else { |
| 493 | continue; |
| 494 | }; |
| 495 | if let Err(e) = paths::add_gitignore_globs(&mut builder, path.as_str()) { |
| 496 | warn!("Failed to create glob from path given: {path}: {e}. Ignoring."); |
| 497 | } |
| 498 | } |
| 499 | builder.build() |
| 500 | }; |
| 501 | |
| 502 | let mut sanitized_deny_list = Vec::<&String>::new(); |
| 503 | let deny_set = { |
| 504 | let mut builder = GlobSetBuilder::new(); |
| 505 | for path in &denied_paths { |
| 506 | let Ok(processed_path) = paths::canonicalizes_path(os, path) else { |
| 507 | continue; |
| 508 | }; |
| 509 | match paths::add_gitignore_globs(&mut builder, processed_path.as_str()) { |
| 510 | Ok(_) => { |
| 511 | // Note that we need to push twice here because for each rule we |
| 512 | // are creating two globs (one for file and one for directory) |
| 513 | sanitized_deny_list.push(path); |
| 514 | sanitized_deny_list.push(path); |
| 515 | }, |
| 516 | Err(e) => warn!("Failed to create glob from path given: {path}: {e}. Ignoring."), |
| 517 | } |
| 518 | } |
| 519 | builder.build() |
| 520 | }; |
| 521 | |
| 522 | match (allow_set, deny_set) { |
| 523 | (Ok(allow_set), Ok(deny_set)) => { |