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    PluginKind, PluginSpec,
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<&PluginSpec>,
37    ) -> Result<PluginInvocationResult, BridgeError> {
38        let runtime_bindings = match plugin_metadata {
39            Some(meta) => Some(build_runtime_bindings(meta)),
40            None => None,
41        };
42
43        if let Some(plugin) = plugin_metadata {
44            if plugin.kind == PluginKind::Upgrader {
45                logger::debug("Routing to upgrader plugin handler");
46                return self.invoke_upgrader_plugin(
47                    target,
48                    config_json,
49                    runtime_bindings.as_ref(),
50                    plugin_metadata,
51                );
52            }
53        }
54
55        self.invoke_plugin_regular(target, config_json, stdin_json, runtime_bindings.as_ref())
56    }
57}
58
59#[cfg(test)]
60mod tests {
61    #[test]
62    fn test_plugin_invocation_placeholder() {
63        assert!(true);
64    }
65}