An AI agent built to do Ralph loops - plan mode for planning and ralph mode for implementing.
at main 68 lines 2.0 kB view raw
1use std::io::{self, Write}; 2 3pub trait PermissionHandler: Send + Sync { 4 fn request_permission(&self, request: &PermissionRequest) -> PermissionResult; 5} 6 7pub struct PermissionRequest { 8 pub resource_type: ResourceType, 9 pub action: String, 10 pub reason: String, 11} 12 13#[derive(Debug, Clone, Copy)] 14pub enum ResourceType { 15 ShellCommand, 16 FilePath, 17} 18 19#[derive(Debug)] 20pub enum PermissionResult { 21 Allow, 22 Deny, 23 AllowAlways(String), 24 Quit, 25} 26 27pub struct CliPermissionHandler; 28 29impl PermissionHandler for CliPermissionHandler { 30 fn request_permission(&self, request: &PermissionRequest) -> PermissionResult { 31 println!("\n⚠️ Permission Required"); 32 println!("Type: {:?}", request.resource_type); 33 println!("Action: {}", request.action); 34 println!("Reason: {}", request.reason); 35 println!(); 36 print!("Allow? [y]es / [n]o / [a]lways allow / [q]uit: "); 37 io::stdout().flush().unwrap(); 38 39 let mut input = String::new(); 40 io::stdin().read_line(&mut input).unwrap(); 41 42 match input.trim().to_lowercase().as_str() { 43 "y" | "yes" => PermissionResult::Allow, 44 "a" | "always" => { 45 // Extract the resource to remember 46 let resource = match request.resource_type { 47 ResourceType::ShellCommand => { 48 // Extract base command 49 request.action.split_whitespace().next().unwrap_or("") 50 } 51 ResourceType::FilePath => &request.action, 52 }; 53 PermissionResult::AllowAlways(resource.to_string()) 54 } 55 "q" | "quit" => PermissionResult::Quit, 56 _ => PermissionResult::Deny, 57 } 58 } 59} 60 61/// Auto-approve handler for testing 62pub struct AutoApproveHandler; 63 64impl PermissionHandler for AutoApproveHandler { 65 fn request_permission(&self, _request: &PermissionRequest) -> PermissionResult { 66 PermissionResult::Allow 67 } 68}