Skip to main content

lenso_plugin_sdk/
lib.rs

1//! Execution-target lowering for portable Rust Plugins.
2//!
3//! Product SDKs own Capability semantics and typed authoring. This crate owns
4//! only the final JSON request seam and lowers it to Wasm Component or Process
5//! transport glue. Plugin authors normally use a product SDK instead of this
6//! interface directly.
7
8use serde_json::Value;
9
10pub use lenso_plugin_sdk_macros::plugin;
11
12#[cfg(target_arch = "wasm32")]
13#[doc(hidden)]
14pub mod __wasm {
15    wit_bindgen::generate!({
16        inline: r#"
17            package lenso:runtime@1.0.0;
18
19            world plugin {
20              export describe: func() -> string;
21              export invoke: func(capability: string, operation: string, request-json: string) -> result<string, string>;
22            }
23        "#,
24        world: "plugin",
25        export_macro_name: "export_lenso_plugin",
26        pub_export_macro: true,
27        default_bindings_module: "::lenso::__wasm",
28    });
29}
30
31/// Transport-neutral result produced by a product SDK's generated dispatcher.
32#[doc(hidden)]
33#[derive(Clone, Debug)]
34pub enum InvocationOutcome {
35    /// A successful Capability response.
36    Success(Value),
37    /// A domain error defined by the Capability contract.
38    DomainError(Value),
39    /// An adapter-safe implementation failure.
40    Failure(String),
41}
42
43/// JSON request seam implemented by generated product SDK glue.
44///
45/// This interface deliberately has no knowledge of Agent Tools, Ingress,
46/// authentication, or any other product Capability.
47#[doc(hidden)]
48pub trait JsonRequestHandler: Default {
49    /// Handles one validated Capability request.
50    fn invoke(&self, capability: &str, operation: &str, request: Value) -> InvocationOutcome;
51}
52
53/// Lowers a generated JSON request handler to Wasm Component or Process.
54///
55/// Product SDK macros call this macro; Plugin business code should not need to.
56#[doc(hidden)]
57#[macro_export]
58macro_rules! __export_json_request_handler {
59    (
60        $plugin:ty {
61            capability_id: $capability_id:literal,
62            descriptor_version: $descriptor_version:literal,
63            descriptor_digest: $descriptor_digest:literal,
64            requests: [$first_request:literal $(, $request:literal)* $(,)?] $(,)?
65        }
66    ) => {
67        type __LensoExportedPlugin = $plugin;
68
69        #[cfg(target_arch = "wasm32")]
70        mod __lenso_wasm_export {
71            struct Component;
72
73            const DESCRIPTOR: &str = $crate::__private::lenso_guest_sdk::__request_plugin_descriptor!(
74                $capability_id,
75                $descriptor_version,
76                digest: $descriptor_digest,
77                $first_request $(, $request)*
78            );
79
80            #[used]
81            #[unsafe(link_section = "lenso.plugin-descriptor.v1")]
82            static DESCRIPTOR_SECTION: [u8; DESCRIPTOR.len()] =
83                $crate::__private::lenso_guest_sdk::__descriptor_bytes(DESCRIPTOR);
84
85            impl $crate::__private::wasm::Guest for Component {
86                fn describe() -> ::std::string::String {
87                    DESCRIPTOR.to_owned()
88                }
89
90                fn invoke(
91                    capability: ::std::string::String,
92                    operation: ::std::string::String,
93                    request_json: ::std::string::String,
94                ) -> ::std::result::Result<::std::string::String, ::std::string::String> {
95                    let request = $crate::__private::serde_json::from_str(&request_json)
96                        .map_err(|_| "\"invalid_arguments\"".to_owned())?;
97                    match <super::__LensoExportedPlugin as $crate::JsonRequestHandler>::invoke(
98                        &<super::__LensoExportedPlugin as ::std::default::Default>::default(),
99                        &capability,
100                        &operation,
101                        request,
102                    ) {
103                        $crate::InvocationOutcome::Success(value) =>
104                            $crate::__private::serde_json::to_string(&value)
105                                .map_err(|error| error.to_string()),
106                        $crate::InvocationOutcome::DomainError(value) =>
107                            ::std::result::Result::Err(
108                                $crate::__private::serde_json::to_string(&value)
109                                    .unwrap_or_else(|_| "\"execution_failed\"".to_owned()),
110                            ),
111                        $crate::InvocationOutcome::Failure(detail) =>
112                            ::std::result::Result::Err(
113                                $crate::__private::serde_json::to_string(&detail)
114                                    .unwrap_or_else(|_| "\"execution_failed\"".to_owned()),
115                            ),
116                    }
117                }
118            }
119
120            $crate::__private::wasm::export_lenso_plugin!(Component);
121        }
122
123        #[cfg(not(target_arch = "wasm32"))]
124        mod __lenso_process_export {
125            struct Component;
126
127            const DESCRIPTOR: &str =
128                $crate::__private::lenso_guest_sdk::__request_plugin_descriptor!(
129                    $capability_id,
130                    $descriptor_version,
131                    digest: $descriptor_digest,
132                    $first_request $(, $request)*
133                );
134
135            impl $crate::__private::lenso_process_sdk::ProcessPluginV2 for Component {
136                type Instance = super::__LensoExportedPlugin;
137
138                fn construct(
139                    &self,
140                    _params: &$crate::__private::lenso_process_sdk::authoring::ConstructParams,
141                    _context: $crate::__private::lenso_process_sdk::ProcessLifecycleContext,
142                ) -> ::std::result::Result<Self::Instance, ::std::string::String> {
143                    Ok(<super::__LensoExportedPlugin as ::std::default::Default>::default())
144                }
145
146                fn invoke(
147                    &self,
148                    instance: &Self::Instance,
149                    params: $crate::__private::lenso_process_sdk::authoring::InvokeParams,
150                    _context: $crate::__private::lenso_process_sdk::ProcessInvocationContext,
151                ) -> $crate::__private::lenso_process_sdk::authoring::InvocationOutcome {
152                    match <super::__LensoExportedPlugin as $crate::JsonRequestHandler>::invoke(
153                        instance,
154                        &params.capability_id,
155                        &params.operation,
156                        params.payload,
157                    ) {
158                        $crate::InvocationOutcome::Success(value) =>
159                            $crate::__private::lenso_process_sdk::authoring::InvocationOutcome::Success {
160                                value,
161                            },
162                        $crate::InvocationOutcome::DomainError(value) =>
163                            $crate::__private::lenso_process_sdk::authoring::InvocationOutcome::Domain {
164                                error: value,
165                            },
166                        $crate::InvocationOutcome::Failure(detail) =>
167                            $crate::__private::lenso_process_sdk::authoring::InvocationOutcome::Runtime {
168                                failure: $crate::__private::lenso_process_sdk::authoring::RuntimeFailure::PluginFailure {
169                                    detail,
170                                },
171                            },
172                    }
173                }
174            }
175
176            pub fn serve() {
177                if ::std::env::args_os().nth(1).as_deref()
178                    == Some(::std::ffi::OsStr::new("--lenso-describe"))
179                {
180                    println!("{DESCRIPTOR}");
181                    return;
182                }
183                $crate::__private::lenso_process_sdk::serve_v2(Component)
184                .expect("serve Lenso Process V2 Plugin");
185            }
186        }
187
188        #[cfg(not(target_arch = "wasm32"))]
189        fn main() {
190            __lenso_process_export::serve();
191        }
192    };
193}
194
195#[doc(hidden)]
196pub mod __private {
197    pub use serde_json;
198
199    #[cfg(target_arch = "wasm32")]
200    pub use crate::__wasm as wasm;
201    pub use lenso_guest_sdk;
202    #[cfg(not(target_arch = "wasm32"))]
203    pub use lenso_process_sdk;
204}