Refactor Rhai integration with context-based execution and type registry

Major Changes:
- Moved Rhai support from rhai_support/ to rhai/ module
- Implemented context-based execution with signatory access control
- Added TypeRegistry for dynamic type registration and object creation
- Refactored engine to use context (Vec<String>) instead of instance
- Removed old runner binary (moved to runner_rust crate)

Rhai Module:
- engine.rs: Core Rhai engine with context-based get_context()
- functions.rs: Rhai function bindings (create_note, create_event, etc.)
- mod.rs: Module exports and organization

Store Improvements:
- TypeRegistry for registering object types and creators
- Generic store uses type registry for dynamic object creation
- Improved error handling and type safety

Documentation:
- RHAI_REFACTOR_COMPLETE.md: Refactoring details
- SIGNATORY_ACCESS_CONTROL.md: Context-based access control
- TYPE_REGISTRY_DESIGN.md: Type registry architecture
- REFACTORING_COMPLETE.md: Overall refactoring summary
- TESTS_COMPLETE.md: Testing documentation

Build Status:  Compiles successfully with minor warnings
This commit is contained in:
Timur Gordon
2025-10-28 03:33:39 +01:00
parent 097360ad12
commit e04012c8c0
24 changed files with 1810 additions and 249 deletions

View File

@@ -6,19 +6,14 @@
/// Usage:
/// ```bash
/// # Script mode
/// cargo run --bin runner --features rhai-support -- runner1 --script "let note = note('test').title('Hi'); put_note(note);"
/// cargo run --bin runner -- runner1 --script "let note = note('test').title('Hi'); put_note(note);"
///
/// # Daemon mode (requires runner_rust infrastructure)
/// cargo run --bin runner --features rhai-support -- runner1 --redis-url redis://localhost:6379
/// cargo run --bin runner -- runner1 --redis-url redis://localhost:6379
/// ```
use clap::Parser;
#[cfg(feature = "rhai-support")]
mod engine;
#[cfg(feature = "rhai-support")]
use engine::create_osiris_engine;
use osiris::rhai::{OsirisEngineConfig, create_osiris_engine_with_config};
#[derive(Parser, Debug)]
#[command(author, version, about = "OSIRIS Rhai Script Runner", long_about = None)]
@@ -48,14 +43,6 @@ struct Args {
instances: Vec<String>,
}
#[cfg(not(feature = "rhai-support"))]
fn main() -> Result<(), Box<dyn std::error::Error>> {
eprintln!("❌ Error: OSIRIS runner requires the 'rhai-support' feature");
eprintln!("Run with: cargo run --bin runner --features rhai-support");
std::process::exit(1);
}
#[cfg(feature = "rhai-support")]
fn main() -> Result<(), Box<dyn std::error::Error>> {
// Initialize logging
env_logger::init();
@@ -67,11 +54,11 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("HeroDB: {} (DB {})", args.redis_url, args.db_id);
// Parse predefined instances
let mut config = engine::OsirisConfig::new();
let mut config = OsirisEngineConfig::new();
if args.instances.is_empty() {
// No predefined instances, use default
config.add_instance("default", &args.redis_url, args.db_id);
// No predefined instances, use default with runner_id as owner
config.add_context("default", &args.runner_id, &args.redis_url, args.db_id);
} else {
// Parse instance definitions (format: name:url:db_id)
// We need to split carefully since URL contains colons
@@ -93,8 +80,8 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
let db_id: u16 = db_id_str.parse()
.map_err(|_| format!("Invalid db_id in instance '{}': {}", instance_def, db_id_str))?;
config.add_instance(name, url, db_id);
println!(" Instance: {}{} (DB {})", name, url, db_id);
config.add_context(name, &args.runner_id, url, db_id);
println!(" Context: {}{} (DB {})", name, url, db_id);
}
}
@@ -113,8 +100,8 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("📝 Executing script...\n");
println!("─────────────────────────────────────");
// Create engine with predefined instances
let (engine, mut scope) = engine::create_osiris_engine_with_config(config)?;
// Create engine with predefined contexts
let (engine, mut scope) = create_osiris_engine_with_config(config)?;
match engine.eval_with_scope::<rhai::Dynamic>(&mut scope, &script_content) {
Ok(result) => {

View File

@@ -1,73 +0,0 @@
/// OSIRIS Engine Factory
///
/// Creates a Rhai engine configured with OSIRIS objects and methods.
use osiris::rhai_support::{register_note_api, register_event_api, OsirisInstance};
use rhai::Engine;
use std::collections::HashMap;
#[allow(dead_code)]
/// Configuration for multiple OSIRIS instances
pub struct OsirisConfig {
pub instances: HashMap<String, (String, u16)>, // name -> (url, db_id)
}
impl OsirisConfig {
pub fn new() -> Self {
Self {
instances: HashMap::new(),
}
}
pub fn add_instance(&mut self, name: impl ToString, url: impl ToString, db_id: u16) {
self.instances.insert(name.to_string(), (url.to_string(), db_id));
}
pub fn single(url: impl ToString, db_id: u16) -> Self {
let mut config = Self::new();
config.add_instance("default", url, db_id);
config
}
}
/// Create a new Rhai engine with OSIRIS support
pub fn create_osiris_engine(
herodb_url: &str,
db_id: u16,
) -> Result<(Engine, rhai::Scope<'static>), Box<dyn std::error::Error>> {
let config = OsirisConfig::single(herodb_url, db_id);
create_osiris_engine_with_config(config)
}
/// Create a new Rhai engine with multiple OSIRIS instances
/// Returns (Engine, Scope) where Scope contains predefined instances
pub fn create_osiris_engine_with_config(
config: OsirisConfig,
) -> Result<(Engine, rhai::Scope<'static>), Box<dyn std::error::Error>> {
let mut engine = Engine::new();
// Register Note API
register_note_api(&mut engine);
// Register Event API
register_event_api(&mut engine);
// Register OsirisInstance type
engine.build_type::<OsirisInstance>();
// Register osiris() constructor function for dynamic creation
engine.register_fn("osiris", |name: &str, url: &str, db_id: rhai::INT| -> Result<OsirisInstance, Box<rhai::EvalAltResult>> {
OsirisInstance::new(name, url, db_id as u16)
.map_err(|e| format!("Failed to create OSIRIS instance: {}", e).into())
});
// Create predefined instances and inject them as global constants in scope
let mut scope = rhai::Scope::new();
for (name, (url, db_id)) in config.instances {
let instance = OsirisInstance::new(&name, &url, db_id)?;
scope.push_constant(&name, instance);
}
Ok((engine, scope))
}