use std::env; use std::fs; use std::panic; use std::path::Path; use rhai::{Engine, Dynamic}; use actor_osis::OSISActor; fn main() -> Result<(), Box> { // Parse command line arguments for verbosity let args: Vec = env::args().collect(); let verbose = args.contains(&"--verbose".to_string()) || args.contains(&"-v".to_string()); // Set up custom panic hook to suppress panic messages unless verbose if !verbose { panic::set_hook(Box::new(|_| { // Suppress panic output in non-verbose mode })); } // Initialize logging only if verbose if verbose { env_logger::init(); } println!("=== OSIS Engine Direct Execution Example ==="); // Find all Rhai scripts in examples/scripts directory let scripts_dir = Path::new("examples/scripts"); if !scripts_dir.exists() { eprintln!("Scripts directory not found: {}", scripts_dir.display()); return Ok(()); } let mut script_files = Vec::new(); for entry in fs::read_dir(scripts_dir)? { let entry = entry?; let path = entry.path(); if path.extension().and_then(|s| s.to_str()) == Some("rhai") { script_files.push(path); } } script_files.sort(); if verbose { println!("Found {} Rhai scripts in {}", script_files.len(), scripts_dir.display()); } else { println!("Testing {} Rhai scripts:\n", script_files.len()); } // Create temporary database path let db_path = "temp_osis_engine_example_db"; // Clean up previous database if it exists if Path::new(db_path).exists() { fs::remove_dir_all(db_path)?; } if verbose { println!("Created temporary database path: {}", db_path); } // Track results for summary let mut success_count = 0; let mut failure_count = 0; // Execute all scripts with colored output for (i, script_path) in script_files.iter().enumerate() { let script_name = script_path.file_name().unwrap().to_string_lossy(); // Read script content let script_content = match fs::read_to_string(script_path) { Ok(content) => content, Err(e) => { println!("\x1b[31m✗\x1b[0m {} ... \x1b[31mFAILED\x1b[0m (read error: {})", script_name, e); failure_count += 1; continue; } }; if verbose { println!("\n=== Script {}/{}: {} ===", i + 1, script_files.len(), script_name); println!("--- Using Fresh OSIS Engine with Job Context ---"); } // Create a new engine instance and configure it with DSL modules let mut engine_with_context = match create_configured_engine(db_path, i + 1, verbose) { Ok(engine) => engine, Err(e) => { println!("\x1b[31m✗\x1b[0m {} ... \x1b[31mFAILED\x1b[0m (engine setup: {})", script_name, e); failure_count += 1; continue; } }; // Execute the script with graceful error handling (catches both errors and panics) let script_result = panic::catch_unwind(panic::AssertUnwindSafe(|| { engine_with_context.eval::(&script_content) })); match script_result { Ok(Ok(result)) => { println!("\x1b[32m✓\x1b[0m {} ... \x1b[32mSUCCESS\x1b[0m", script_name); if verbose { println!(" Result: {:?}", result); } success_count += 1; } Ok(Err(e)) => { println!("\x1b[31m✗\x1b[0m {} ... \x1b[31mFAILED\x1b[0m", script_name); if verbose { println!(" Error: {}", e); } failure_count += 1; } Err(panic_err) => { let panic_msg = if let Some(s) = panic_err.downcast_ref::() { s.clone() } else if let Some(s) = panic_err.downcast_ref::<&str>() { s.to_string() } else { "Unknown panic".to_string() }; println!("\x1b[31m✗\x1b[0m {} ... \x1b[31mFAILED\x1b[0m", script_name); if verbose { println!(" Panic: {}", panic_msg); } failure_count += 1; } } } // Print summary println!("\n=== Summary ==="); println!("\x1b[32m✓ {} scripts succeeded\x1b[0m", success_count); println!("\x1b[31m✗ {} scripts failed\x1b[0m", failure_count); println!("Total: {} scripts", success_count + failure_count); // Clean up the temporary database if Path::new(db_path).exists() { fs::remove_dir_all(db_path)?; if verbose { println!("\nCleaned up temporary database: {}", db_path); } } if verbose { println!("=== Engine Example Complete ==="); } Ok(()) } /// Create a configured Rhai engine with DSL modules and job context fn create_configured_engine(db_path: &str, script_index: usize, verbose: bool) -> Result { // Create a new engine instance let mut engine = Engine::new(); // Register all DSL modules (same as OSIS engine configuration) actor_osis::register_dsl_modules(&mut engine); // Set up job context tags (similar to execute_job_with_engine) let mut db_config = rhai::Map::new(); db_config.insert("DB_PATH".into(), db_path.to_string().into()); db_config.insert("CALLER_ID".into(), "engine_example".to_string().into()); db_config.insert("CONTEXT_ID".into(), format!("script_{}", script_index).into()); engine.set_default_tag(Dynamic::from(db_config)); if verbose { println!(" Set job context: DB_PATH={}, CALLER_ID=engine_example, CONTEXT_ID=script_{}", db_path, script_index); } Ok(engine) }