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            requests: [$first_request:literal $(, $request:literal)* $(,)?] $(,)?
64        }
65    ) => {
66        type __LensoExportedPlugin = $plugin;
67
68        #[cfg(target_arch = "wasm32")]
69        mod __lenso_wasm_export {
70            struct Component;
71
72            const DESCRIPTOR: &str = $crate::__private::lenso_guest_sdk::__request_plugin_descriptor!(
73                $capability_id,
74                $descriptor_version,
75                $first_request $(, $request)*
76            );
77
78            #[used]
79            #[unsafe(link_section = "lenso.plugin-descriptor.v1")]
80            static DESCRIPTOR_SECTION: [u8; DESCRIPTOR.len()] =
81                $crate::__private::lenso_guest_sdk::__descriptor_bytes(DESCRIPTOR);
82
83            impl $crate::__private::wasm::Guest for Component {
84                fn describe() -> ::std::string::String {
85                    DESCRIPTOR.to_owned()
86                }
87
88                fn invoke(
89                    capability: ::std::string::String,
90                    operation: ::std::string::String,
91                    request_json: ::std::string::String,
92                ) -> ::std::result::Result<::std::string::String, ::std::string::String> {
93                    let request = $crate::__private::serde_json::from_str(&request_json)
94                        .map_err(|_| "\"invalid_arguments\"".to_owned())?;
95                    match <super::__LensoExportedPlugin as $crate::JsonRequestHandler>::invoke(
96                        &<super::__LensoExportedPlugin as ::std::default::Default>::default(),
97                        &capability,
98                        &operation,
99                        request,
100                    ) {
101                        $crate::InvocationOutcome::Success(value) =>
102                            $crate::__private::serde_json::to_string(&value)
103                                .map_err(|error| error.to_string()),
104                        $crate::InvocationOutcome::DomainError(value) =>
105                            ::std::result::Result::Err(
106                                $crate::__private::serde_json::to_string(&value)
107                                    .unwrap_or_else(|_| "\"execution_failed\"".to_owned()),
108                            ),
109                        $crate::InvocationOutcome::Failure(detail) =>
110                            ::std::result::Result::Err(
111                                $crate::__private::serde_json::to_string(&detail)
112                                    .unwrap_or_else(|_| "\"execution_failed\"".to_owned()),
113                            ),
114                    }
115                }
116            }
117
118            $crate::__private::wasm::export_lenso_plugin!(Component);
119        }
120
121        #[cfg(not(target_arch = "wasm32"))]
122        mod __lenso_process_export {
123            struct Component(super::__LensoExportedPlugin);
124
125            impl $crate::__private::lenso_process_sdk::ProcessPlugin for Component {
126                fn descriptor(&self) -> $crate::__private::serde_json::Value {
127                    $crate::__private::serde_json::json!({
128                        "abi": "lenso.json-request@1",
129                        "capabilities": [{
130                            "capability_id": $capability_id,
131                            "descriptor_version": $descriptor_version,
132                            "request_operations": [$first_request $(, $request)*],
133                        }],
134                    })
135                }
136
137                fn invoke(
138                    &self,
139                    capability: &str,
140                    operation: &str,
141                    request: $crate::__private::serde_json::Value,
142                ) -> $crate::__private::lenso_process_sdk::ProcessOutcome {
143                    match <super::__LensoExportedPlugin as $crate::JsonRequestHandler>::invoke(
144                        &self.0,
145                        capability,
146                        operation,
147                        request,
148                    ) {
149                        $crate::InvocationOutcome::Success(value) =>
150                            $crate::__private::lenso_process_sdk::ProcessOutcome::Success(value),
151                        $crate::InvocationOutcome::DomainError(value) =>
152                            $crate::__private::lenso_process_sdk::ProcessOutcome::DomainError(value),
153                        $crate::InvocationOutcome::Failure(detail) =>
154                            $crate::__private::lenso_process_sdk::ProcessOutcome::Failure(detail),
155                    }
156                }
157            }
158
159            pub fn serve() {
160                $crate::__private::lenso_process_sdk::serve(&Component(
161                    <super::__LensoExportedPlugin as ::std::default::Default>::default(),
162                ))
163                .expect("serve Lenso Process Plugin");
164            }
165        }
166
167        #[cfg(not(target_arch = "wasm32"))]
168        fn main() {
169            __lenso_process_export::serve();
170        }
171    };
172}
173
174#[doc(hidden)]
175pub mod __private {
176    pub use serde_json;
177
178    #[cfg(target_arch = "wasm32")]
179    pub use crate::__wasm as wasm;
180    #[cfg(target_arch = "wasm32")]
181    pub use lenso_guest_sdk;
182    #[cfg(not(target_arch = "wasm32"))]
183    pub use lenso_process_sdk;
184}