Skip to content

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

25 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Bottles plugin guest SDK

bottles-plugin-api supplies the Rust provider traits and WebAssembly component exports for Bottles plugins. Use it in a guest crate built as a cdylib for wasm32-wasip3. Native applications load those components through bottles-plugin-host.

Getting started

Implement Default and a provider trait, then select the capability in export!. This library provider has no installed titles yet:

use bottles_plugin_api::library::{LibraryEntry, LibraryProvider};

#[derive(Default)]
struct Catalog;

impl LibraryProvider for Catalog {
    async fn list_entries(&self) -> Result<Vec<LibraryEntry>, String> {
        Ok(Vec::new())
    }

    async fn launch(&self, id: String) -> Result<(), String> {
        Err(format!("No installed title with ID {id}"))
    }
}

bottles_plugin_api::export!(Catalog: library);

Set the guest's library target in its Cargo.toml:

[lib]
crate-type = ["cdylib"]

Build with the SDK's supported guest toolchain:

cargo +nightly-2026-09-25 build --release --target wasm32-wasip3

A dependency's rust-toolchain.toml does not select the consuming crate's toolchain. Select it explicitly with the command above or the guest crate's own toolchain file. The build produces a component in target/wasm32-wasip3/release/<crate_name>.wasm.

State and capability selection

[export!] implements [Plugin] for the selected type. On first use, it calls [Default::default()] and stores the result in one [std::sync::OnceLock]. Every exported capability uses that same instance for the lifetime of the loaded component. Loading the component again creates a separate guest instance; in-memory state is not persistent storage.

Calls may run concurrently. Use interior mutability, such as a [std::sync::Mutex], for state changed through &self. Release mutex guards before .await so another call can access the state while a request is pending.

The export list chooses the component's capabilities:

bottles_plugin_api::export!(MyPlugin: account, library);

Implementing a provider trait does not export its interface. For example, a type may implement both provider traits while export!(MyPlugin: library) exports only the library interface. Call export! once for the type, listing all selected capabilities together.

Account linking and HTTP

[account::AccountProvider] receives a borrowed [account::Interaction] for requesting user input during that invocation. It returns the account's public identity.

A plugin's working directory is private to it and survives restarts and updates, and is removed when the plugin is uninstalled. Use it with std::fs for anything that must outlast the instance, such as a login session; it is the only directory the plugin can see.

[http_client::send] uses standard WASI HTTP imports. Both the request and response bodies are fully buffered in memory; it does not provide a streaming body API.

Packaging

Place the compiled component at plugin.wasm beside a plugin.toml manifest:

id = "my-plugin"
name = "My Plugin"
version = "0.1.0"

The host reads these filenames when installing or loading a package. Package version is display metadata; exported interface versions come from the SDK's WIT definitions.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages