# Blockless Rust SDK
The SDK allows your Rust-based WebAssembly (WASM) modules to interact with the `bls-runtime` and `b7s-browser` WASM execution environments/runtimes.
It provides convenient wrappers around the host functions exposed by the runtime, enabling capabilities like HTTP requests, CGI script execution, LLM interactions, and more.
## Installation
Add the `blockless-sdk` to your `Cargo.toml`:
```sh
cargo add blockless-sdk
```
### Features
The SDK has an optional `serde` feature, enabled by default, which derives `Serialize` and `Deserialize` for some of its types. If you don't need this, you can disable default features:
```toml
blockless-sdk = { version = "0.1.10", default-features = false }
```
## Core Concepts
### Permissions
The `bls-runtime` operates on a permission-based model.
For your WASM module to access resources (like making an HTTP request or accessing a specific CGI script), the runtime must be configured with the appropriate permissions.
If a required permission is missing, SDK calls will likely fail.
Permissions are typically defined in the runtime's JSON configuration file:
```json
{
"permissions": [
"http://api.example.com/data", // Allow HTTP GET to this specific URL
"file:///scripts/my_script.sh", // Example for CGI if it needs file access
"cgi://my_cgi_alias" // Hypothetical permission for a specific CGI alias
]
}
```
Refer to the `bls-runtime` documentation for details on configuring permissions.
### Compiling Your Rust Code to WASM
To use this SDK, your Rust code needs to be compiled to the `wasm32-wasip1` target:
```bash
cargo build --target wasm32-wasip1 --release
```
This will typically produce a `.wasm` file in `target/wasm32-wasip1/release/your_crate_name.wasm`.
## Blockless Rust SDK: Architectural Overview
The Blockless Rust SDK acts as a bridge between your Rust application code and the wasm runtime. It simplifies interaction with the host functions exposed by the runtime, abstracting away the low-level details of WebAssembly System Interface (WASI) calls and custom Blockless host function ABIs.
### High-Level System Architecture
This diagram shows the main components and their relationships when building and running a WASM application with the Blockless Rust SDK on `bls-runtime`.
```mermaid
graph LR
subgraph "Development Phase"
A["Rust Application Code (.rs)"] -- "Uses" --> B{Blockless Rust SDK Crate};
B -- "Compiled with App Code" --> C["WASM Module (.wasm)"];
end
subgraph "Runtime Execution Phase (bls-runtime)"
D{bls-runtime Engine} -- "Loads & Executes" --> C;
C -- "Calls (via SDK)" --> E["Host Function Interface (ABI)"];
E -- "Handled by" --> D;
D -- "Routes to" --> F[Blockless Driver Modules];
F -- "Interact with" --> G[External Resources];
end
subgraph "Blockless Driver Modules (Host Plugins)"
direction LR
HTTP_Driver[HTTP Driver]
LLM_Driver[LLM Driver]
CGI_Driver[CGI Driver]
IPFS_Driver[IPFS Driver]
S3_Driver[S3 Driver]
Memory_Driver["Memory Driver (Stdin/Env)"]
TCP_Driver[TCP Driver]
WASI_Support[WASI Support]
F -.-> HTTP_Driver;
F -.-> LLM_Driver;
F -.-> CGI_Driver;
F -.-> IPFS_Driver;
F -.-> S3_Driver;
F -.-> Memory_Driver;
F -.-> TCP_Driver;
F -.-> WASI_Support;
end
subgraph "External Resources"
direction LR
Internet["Internet Services (APIs, IPFS, S3)"]
LocalFS["Local Filesystem (if permitted)"]
LLM_Services[External LLM Services]
CGI_Exec[CGI Scripts/Executables]
G -.-> Internet;
G -.-> LocalFS;
G -.-> LLM_Services;
G -.-> CGI_Exec;
end
style A fill:#D2E0FB,stroke:#333,stroke-width:2px
style B fill:#B0C4DE,stroke:#333,stroke-width:2px
style C fill:#98FB98,stroke:#333,stroke-width:2px
style D fill:#87CEFA,stroke:#333,stroke-width:2px
style E fill:#F0E68C,stroke:#333,stroke-width:2px
style F fill:#F4A460,stroke:#333,stroke-width:2px
style G fill:#FFB6C1,stroke:#333,stroke-width:2px
```
**Explanation:**
1. **Development Phase:**
* You write your application logic in Rust (`.rs` files).
* You include and use the `blockless-sdk` crate to access extended functionalities.
* The Rust compiler, targeting `wasm32-wasip1`, bundles your application code and the necessary parts of the SDK into a single `.wasm` module.
2. **Runtime Execution Phase:**
* The `bls-runtime` (which uses Wasmtime as its core engine) loads your compiled `.wasm` module.
* When your WASM code (through an SDK function call) needs to interact with the host (e.g., make an HTTP request):
* It calls a function defined in the Host Function Interface (ABI). These are the `extern "C"` functions you see in the SDK's source (e.g., `http_open`, `llm_prompt_request`).
* The `bls-runtime` intercepts this call.
* Based on the called function (e.g., from the `blockless_http` or `blockless_llm` Wasm import module), the runtime routes the request to the corresponding **Blockless Driver Module** (plugin).
* The Driver Module (e.g., HTTP Driver, LLM Driver) then performs the actual operation, potentially interacting with **External Resources** like the internet, local filesystem (if permitted by the runtime configuration), or specific LLM services.
* Results are passed back through the same chain to your WASM module.
### Development and Execution Flow
This diagram shows the typical lifecycle from writing code to running your Blockless-enabled WASM application.
```mermaid
graph TD
A["Write Rust Code - using blockless-sdk"] --> B(2. Compile to WASM <br/> `cargo build --target wasm32-wasip1`);
B --> C{app.wasm};
D["Create/Edit Runtime Config - config.json"] --> E{config.json};
E --> F["Run with bls-runtime - `bls-runtime config.json`"];
C --> F;
subgraph "During Execution (Step 4)"
direction LR
F --> G{WASM App Logic};
G -- "Calls SDK Function <br/> e.g., BlocklessLlm::new()" --> H{SDK Abstraction};
H -- "Calls Host ABI <br/> e.g., llm_set_model_request()" --> I[bls-runtime];
I -- "Checks Permissions <br/> (from config.json)" --> J{Permission Check};
J -- "Granted" --> K[Invokes LLM Driver];
J -- "Denied" --> L[Error to WASM];
K -- "Interacts with <br/> External LLM Service" --> M[LLM Service];
M -- "Response" --> K;
K -- "Result" --> I;
I -- "Result" --> H;
H -- "Result (e.g., LLM Handle)" --> G;
G -- "Produces Output / <br/> Further Interactions" --> N[Application Output/Effects];
end
style A fill:#D2E0FB
style B fill:#B0C4DE
style C fill:#98FB98
style D fill:#FFE4B5
style E fill:#FFDAB9
style F fill:#87CEFA
style G fill:#E6E6FA
style H fill:#D8BFD8
style I fill:#ADD8E6
style J fill:#F08080
style K fill:#F4A460
style L fill:#CD5C5C
style M fill:#FFB6C1
style N fill:#90EE90
```
**Explanation:**
1. **Develop:** You write your application in Rust, leveraging the `blockless-sdk` for functionalities like HTTP, LLM, etc.
2. **Compile:** You compile your Rust project to the `wasm32-wasip1` target. This produces a `.wasm` file containing your application logic and the SDK's glue code.
3. **Configure:** You prepare a JSON configuration file for the `bls-runtime`. This file specifies:
* The path to your `.wasm` file(s).
* **Permissions:** Crucially, you must grant permissions for any host functions your WASM module will use (e.g., allowed HTTP endpoints, CGI script aliases).
* Resource limits (fuel, memory), entry points, etc.
4. **Execute:** You start the `bls-runtime` with your configuration file.
5. **Runtime Interoperation (as shown in the subgraph):**
* Your WASM application logic makes a call to an SDK function (e.g., `BlocklessLlm::new()`).
* The SDK function translates this into a specific low-level host function call (e.g., `llm_set_model_request()`).
* The `bls-runtime` intercepts this call.
* **Permission Check:** The runtime verifies if the operation is allowed based on the `config.json`. If not, an error is returned to the WASM module.
* If permitted, the runtime invokes the appropriate driver module (e.g., LLM Driver).
* The driver performs the action (e.g., initializes an LLM model, potentially downloading it or interacting with an external service).
* The result (e.g., a handle to the LLM session, or data) is passed back through the runtime and SDK to your application code.
* Your application then continues, potentially making more host calls or producing output.
## SDK Modules
The SDK provides modules to interact with different host functionalities:
### 1. HTTP Client (`BlocklessHttp`)
Make HTTP requests from your WASM module.
**Host Function Namespace:** `blockless_http`
### 2. Memory Access (Stdin & Environment Variables)
Access standard input and environment variables provided by the runtime.
**Host Function Namespace:** `blockless_memory`
#### Reading from Stdin
* `read_stdin(buf: &mut [u8]) -> std::io::Result<u32>`: Reads data from stdin into `buf`. Returns the number of bytes read.
#### Reading Environment Variables
Environment variables are passed as a single string, typically JSON formatted or newline-separated key-value pairs, as determined by the runtime.
* `read_env_vars(buf: &mut [u8]) -> std::io::Result<u32>`: Reads environment variables string into `buf`. Returns number of bytes read.
### 3. CGI (Common Gateway Interface)
Execute external scripts/programs as CGI extensions.
**Host Function Namespace:** `blockless_cgi`
Error Type: `CGIErrorKind`
### 4. Sockets (`blockless_socket`)
Primarily for creating TCP listener sockets within your WASM module, allowing it to act as a server.
**Host Function Namespace:** `blockless_socket`
* `create_tcp_bind_socket(addr: &str) -> Result<u32, SocketErrorKind>`: Creates a TCP socket, binds it to the given address (e.g., "0.0.0.0:8080"), and prepares it for listening. Returns a file descriptor.
Error Type: `SocketErrorKind`
### 5. LLM (Large Language Model) (`BlocklessLlm`)
Interact with Large Language Models supported by the runtime.
**Host Function Namespace:** `blockless_llm`
#### `Models` Enum
Specifies which LLM to use.
Common variants:
* `Llama321BInstruct(Option<String>)`
* `Llama323BInstruct(Option<String>)`
* `Mistral7BInstructV03(Option<String>)`
* `Mixtral8x7BInstructV01(Option<String>)`
* `Gemma22BInstruct(Option<String>)`
* `Gemma27BInstruct(Option<String>)`
* `Gemma29BInstruct(Option<String>)`
* `Custom(String)`: For models identified by a string not covered by specific enum variants. The string inside `Option<String>` usually refers to a quantization format like "Q6_K" or "q4f16_1".
#### `LlmOptions`
Configuration options for LLM interactions.
Fields/Methods:
* `system_message: Option<String>`: A system prompt to guide the LLM's behavior.
* `tools_sse_urls: Option<Vec<String>>`: A list of URLs for Model Control Protocol (MCP) tool servers (SSE endpoints).
* `temperature: Option<f32>`: Sampling temperature.
* `top_p: Option<f32>`: Nucleus sampling probability.
* `.with_system_message(String) -> Self`: Builder method.
* `.with_tools_sse_urls(Vec<String>) -> Self`: Builder method.
Error Type: `LlmErrorKind` (covers model issues, UTF-8 errors, MCP errors, etc.)
## Error Handling
Each module in the SDK has its own `ErrorKind` enum (e.g., `HttpErrorKind`, `LlmErrorKind`). These enums provide specific error details for operations within that module. Always check the `Result` returned by SDK functions.
## Examples
You can find more complete, runnable examples in the [`examples`](https://github.com/blocklessnetwork/sdk-rust/tree/main/examples) directory of the SDK repository.