Build a plugin
The initial SDK targets Rust and WASI 0.2 components. Install the component target:
rustup target add wasm32-wasip2
The reference implementation uses Rust 1.98. Plugin source can use compatible Rust releases, but its generated component must satisfy the supported WIT API. Native subprocess, OS-specific and unrestricted networking crates are not automatically available inside a component.
Start with the SDK
The SDK lives at plugin_system/sdk in the
Memona repository. Until a crates.io
release is published, use a checked-out, pinned Memona revision and a path
dependency:
[package]
name = "my-memona-plugin"
version = "0.1.0"
edition = "2024"
[lib]
crate-type = ["cdylib"]
[dependencies]
memona-plugin-sdk = { path = "../memona/plugin_system/sdk" }
The path is relative to your own Cargo.toml; adjust it to your checkout. Pin
the checkout revision so your build does not silently pick up an API change.
The SDK includes the canonical WIT and generated Rust types. Implement its
Guest trait and invoke its export! macro for your implementation type. You
do not need wasm-bindgen, wasm-pack, or WIT copies in your plugin repository.
cargo doc also exposes the generated Rust API.
struct MyProvider;
// Implement every method of memona_plugin_sdk::Guest for MyProvider.
// Unsupported optional operations return ErrorCode::Unsupported.
memona_plugin_sdk::export!(MyProvider);
This short excerpt shows registration, not a complete implementation. The full
buildable example is plugin_system/test-component/src/lib.rs. It is a test
fixture, not a WebDAV or IPFS client. From a Memona checkout, build it with:
cargo build --manifest-path plugin_system/Cargo.toml \
-p memona-plugin-test-component --target wasm32-wasip2 --release
Build your own plugin with:
cargo build --release --target wasm32-wasip2
Call the host
Use the SDK’s generated host interface for network requests. For example, this helper retrieves a bounded HTTP response through the connection’s permissions:
use memona_plugin_sdk::memona::filesystem::host;
pub fn get_bytes(url: &str) -> Result<Vec<u8>, host::HostError> {
let response = host::http(&host::Request {
method: "GET".into(),
url: url.into(),
headers: Vec::new(),
body: Vec::new(),
})?;
if !(200..300).contains(&response.status) {
return Err(host::HostError::Unavailable);
}
Ok(response.body)
}
Map HTTP statuses to appropriate filesystem errors in a real provider. Supply authentication through request headers using connection configuration; do not hard-code tokens. The host checks exact destinations and private-network permission and limits request/response bodies to 4 MiB. Reads exported by the filesystem provider have the smaller 1 MiB transfer limit.
Prepare a release
Copy the resulting .wasm component to plugin.wasm, write
manifest.json, and ZIP the files at the archive root. Name the
archive with a .memona-plugin suffix. A directory wrapping the files inside
the ZIP is not accepted.
Use the filesystem behavior guide to handle revisions, unsupported operations and mutation failures correctly. Before publishing, exercise your provider against its real service and test lost connections.