//! PyO3 bridge — exposes ~50 Rust classes to Python via `openjarvis_rust`. #![allow(clippy::redundant_closure, unused_variables)] use once_cell::sync::Lazy; use pyo3::prelude::*; // Shared tokio runtime for async-to-sync bridge (agents, future async APIs). pub(crate) static RUNTIME: Lazy = Lazy::new(|| { tokio::runtime::Runtime::new().expect("Failed to create tokio runtime") }); pub mod a2a; pub mod agents; pub mod core; pub mod engine; pub mod learning; pub mod mcp; pub mod recipes; pub mod scheduler; pub mod security; pub mod sessions; pub mod skills; pub mod storage; pub mod telemetry; pub mod templates; pub mod tools; pub mod traces; pub mod workflow; // Module-level functions #[pyfunction] #[pyo3(signature = (path=None))] fn load_config(path: Option<&str>) -> PyResult { let p = path.map(std::path::Path::new); let config = openjarvis_core::load_config(p) .map_err(|e| PyErr::new::(e.to_string()))?; Ok(core::PyConfig { inner: config }) } #[pyfunction] fn detect_hardware() -> PyResult { let hw = openjarvis_core::hardware::detect_hardware(); Ok(serde_json::to_string(&hw).unwrap_or_default()) } #[pyfunction] fn check_ssrf(url: &str) -> Option { openjarvis_security::check_ssrf(url) } #[pyfunction] fn is_sensitive_file(path: &str) -> bool { openjarvis_security::is_sensitive_file(std::path::Path::new(path)) } #[pyfunction] fn register_builtin_models() { openjarvis_core::model_catalog::register_builtin_models(); } #[pyfunction] fn classify_query(query: &str) -> &'static str { openjarvis_learning::classify_query(query) } #[pymodule] fn openjarvis_rust(m: &Bound<'_, PyModule>) -> PyResult<()> { // --- Core types --- m.add_class::()?; m.add_class::()?; m.add_class::()?; m.add_class::()?; m.add_class::()?; m.add_class::()?; m.add_class::()?; m.add_class::()?; m.add_class::()?; // --- Engines --- m.add_class::()?; m.add_class::()?; // --- Agents --- m.add_class::()?; m.add_class::()?; m.add_class::()?; m.add_class::()?; m.add_class::()?; m.add_class::()?; // --- Tools --- m.add_class::()?; m.add_class::()?; m.add_class::()?; m.add_class::()?; m.add_class::()?; m.add_class::()?; m.add_class::()?; m.add_class::()?; m.add_class::()?; m.add_class::()?; // --- Storage / Memory --- m.add_class::()?; m.add_class::()?; m.add_class::()?; m.add_class::()?; m.add_class::()?; m.add_class::()?; // --- Security --- m.add_class::()?; m.add_class::()?; m.add_class::()?; m.add_class::()?; m.add_class::()?; m.add_class::()?; m.add_class::()?; m.add_class::()?; // --- Telemetry --- m.add_class::()?; m.add_class::()?; m.add_class::()?; // --- Telemetry (new session/phase/ITL/FLOPs classes) --- m.add_class::()?; m.add_class::()?; m.add_class::()?; m.add_class::()?; m.add_class::()?; // --- Traces --- m.add_class::()?; m.add_class::()?; m.add_class::()?; // --- Learning --- m.add_class::()?; m.add_class::()?; m.add_class::()?; m.add_class::()?; m.add_class::()?; m.add_class::()?; m.add_class::()?; m.add_class::()?; m.add_class::()?; m.add_class::()?; m.add_class::()?; m.add_class::()?; m.add_class::()?; m.add_class::()?; m.add_class::()?; // --- MCP --- m.add_class::()?; // --- Sessions --- m.add_class::()?; // --- Workflow --- m.add_class::()?; m.add_class::()?; // --- Skills --- m.add_class::()?; // --- Recipes --- m.add_class::()?; // --- Templates --- m.add_class::()?; // --- A2A --- m.add_class::()?; m.add_class::()?; // --- Scheduler --- m.add_class::()?; // --- Module-level functions --- m.add_function(wrap_pyfunction!(load_config, m)?)?; m.add_function(wrap_pyfunction!(detect_hardware, m)?)?; m.add_function(wrap_pyfunction!(check_ssrf, m)?)?; m.add_function(wrap_pyfunction!(is_sensitive_file, m)?)?; m.add_function(wrap_pyfunction!(register_builtin_models, m)?)?; m.add_function(wrap_pyfunction!(classify_query, m)?)?; m.add_function(wrap_pyfunction!(skills::load_skill, m)?)?; m.add_function(wrap_pyfunction!(recipes::load_recipe, m)?)?; m.add_function(wrap_pyfunction!(templates::load_template, m)?)?; m.add_function(wrap_pyfunction!(a2a::parse_a2a_request, m)?)?; m.add_function(wrap_pyfunction!(scheduler::parse_cron_next, m)?)?; Ok(()) }