r2x_python/plugin_invoker/
mod.rs

1//! Plugin invocation and execution
2
3use crate::errors::BridgeError;
4use pyo3::prelude::*;
5use r2x_logger as logger;
6use r2x_manifest::{
7    runtime::{build_runtime_bindings, RuntimeBindings},
8    DiscoveryPlugin,
9};
10use std::time::Duration;
11
12mod kwargs;
13mod regular;
14mod upgrader;
15
16/// Timings for a plugin invocation phase
17pub struct PluginInvocationTimings {
18    pub python_invocation: Duration,
19    pub serialization: Duration,
20}
21
22/// Result of running a plugin through the Python bridge
23pub struct PluginInvocationResult {
24    /// JSON text emitted by the plugin (may be `"null"`)
25    pub output: String,
26    /// Optional per-phase timings for diagnostics
27    pub timings: Option<PluginInvocationTimings>,
28}
29
30impl super::Bridge {
31    pub fn invoke_plugin(
32        &self,
33        target: &str,
34        config_json: &str,
35        stdin_json: Option<&str>,
36        plugin_metadata: Option<&DiscoveryPlugin>,
37    ) -> Result<PluginInvocationResult, BridgeError> {
38        let runtime_bindings = match plugin_metadata {
39            Some(meta) => Some(
40                build_runtime_bindings(meta)
41                    .map_err(|e| BridgeError::Python(format!("Invalid plugin metadata: {}", e)))?,
42            ),
43            None => None,
44        };
45
46        if let Some(plugin) = plugin_metadata {
47            if plugin.plugin_type == "UpgraderPlugin" {
48                logger::debug("Routing to upgrader plugin handler");
49                return self.invoke_upgrader_plugin(
50                    target,
51                    config_json,
52                    runtime_bindings.as_ref(),
53                    plugin_metadata,
54                );
55            }
56        }
57
58        self.invoke_plugin_regular(target, config_json, stdin_json, runtime_bindings.as_ref())
59    }
60}
61
62#[cfg(test)]
63mod tests {
64    #[test]
65    fn test_plugin_invocation_placeholder() {
66        assert!(true);
67    }
68}