el-ffi — host bindings (React Native, Flutter, Web)
One Rust API surface exported three ways, so mobile and web apps can call the SDK in their native idiom (ADR-001, ADR-009, ADR-010):
| Surface | Tool | Output |
|---|---|---|
| React Native | uniffi-bindgen-react-native |
TypeScript + JSI C++ + Turbo Module |
| Flutter | flutter_rust_bridge v2 |
Dart opaque handle, Future/Stream |
| Web / npm | wasm-bindgen |
ESM TypeScript package via wasm-pack |
No unsafe (#![forbid(unsafe_code)]). The crate is cdylib + staticlib +
lib so each toolchain can link the form it needs.
What it provides
EdgeLlm— the flat, FFI-friendly facade, annotated for all three surfaces at once:EdgeLlm::local(model_uri)— local Candle engine, air-gapped (ADR-002/004). An emptymodel_uriuses a deterministic toy model for development; a path loads a consumer-supplied GGUF.EdgeLlm::cloud(model, api_key)— frontier cloud backend (opt-in, ADR-010). Native only — see the web limitation below.api_keymust come from the platform keystore, never embedded.ask(prompt) -> Result<String, SdkError>— blocking chat.ask_stream(prompt, |token| …)— closure streaming (Flutter / FRB v2).ask_stream_cb(prompt, handler)—StreamHandlercallback streaming (React Native; UniFFI cannot exportimpl FnMut).reset().
SdkError— a thin, FFI-safe projection ofel_core::EdgeError(el-core'sBox<str>/Rust-specific variants are not FFI-safe). Projects to the host language's exception type, or a JS exception on wasm.StreamHandler— the React Native streaming callback interface.
Usage (Rust side)
use EdgeLlm;
// Empty path → deterministic toy model; exercises the full binding layer.
let sdk = local?;
let reply = sdk.ask?;
assert!;
// Streaming (Flutter / closure form):
sdk.ask_stream?;
# Ok::
Building the bindings
The Rust binding surfaces compile on the host; the cross-target builds and
codegen run via the Makefile:
Prerequisites (rustup targets, NDK linker, wasm-pack,
uniffi-bindgen-react-native, flutter_rust_bridge_codegen) are documented in
the Makefile header.
Web limitations
On wasm32 the local path currently uses a dev-stage echo placeholder until
Candle-on-wasm is wired, and the cloud backend is not available on web
(ADR-010 amendment): el-cloud's blocking HTTP transport has no wasm
implementation, so EdgeLlm.cloud throws an explicit error there instead of
silently degrading. Use a native binding (React Native / Flutter) for cloud
access.
Status
Implemented and tested (native + wasm32 compile). As a workspace member, the
host-target Rust surfaces build and test with the rest of the workspace
(cargo test --workspace); the Android / iOS / wasm cross-builds and binding
codegen run separately via the Makefile because those toolchains are installed
out-of-band.
Part of the Edge Intelligence workspace. Realizes ADR-001, ADR-009, and ADR-010.