sdk/runanywhere-react-native/Docs/Documentation.md
Updated: 2026-07-30
Public API contract: thoughts/shared/plans/public_api_spec.md (v3)
Architecture source of truth: sdk/runanywhere-swift/ARCHITECTURE.md
The React Native SDK implements the v3 public API spec over native runanywhere-commons. TypeScript marshals options and results; lifecycle, auth, device registration, model registry, downloads, imports, storage, and inference orchestration all live in native code.
import { RunAnywhere, SDKEnvironment } from '@runanywhere/core';
Backend packages such as @runanywhere/llamacpp and @runanywhere/onnx only register backends. They do not own downloads, model registry state, storage, or lifecycle orchestration.
Initialization is a single call; there is no second phase to remember.
await RunAnywhere.initialize({
apiKey: 'your-api-key',
baseUrl: 'https://api.runanywhere.ai',
environment: SDKEnvironment.SDK_ENVIRONMENT_PRODUCTION,
});
initialize registers platform adapters, loads native code, and brings commons up, then returns as soon as local inference is usable. Auth, device registration, the model catalog, and telemetry continue in the background and retry on their own; the first call that needs the network joins that work.
| Member | Meaning |
|---|---|
RunAnywhere.isReady | Local inference is usable |
RunAnywhere.version | SDK version |
RunAnywhere.deviceId | Native persistent device identifier (a promise on RN) |
RunAnywhere.events | AsyncIterable<SdkEvent> of lifecycle, model, and error breadcrumbs |
RunAnywhere.reset() | Unload models, close sessions, clear state |
Every capability hangs off a namespace, with spec-named options and results:
| Namespace | Verbs |
|---|---|
llm | generate, generateStream, generateStructured, tools.register/unregister/list |
vlm | generate, generateStream |
stt | transcribe, transcribeStream, state |
tts | synthesize, synthesizeStream, speak, stop, voices |
vad | detect, detectStream |
embeddings / rerank | embed / rerank |
images / diarization / segmentation | generate, generateStream / diarize / segment |
voice | createSession → VoiceSession (events, start, say, interrupt, close) |
rag | open → RagSession (ingest, search, query, queryStream, stats, clear, close) |
models | list, get, register, download, delete, load, unload, state |
lora | apply, remove, list |
Generation verbs auto-load, and download when the named model is absent, so models.load is for callers who want to control when that cost is paid.
Platform services outside the modality spec stay reachable as their own namespaces: storage, logging, auth, pluginLoader, solutions, plus lora.catalog for adapter registration.
const result = await RunAnywhere.llm.generate('Summarize on-device AI.', {
model: 'smollm2-360m-q8_0',
temperature: 0.7,
});
console.log(result.text, result.tokensPerSecond);
Option defaults are never written in TypeScript. Each option bag merges over the generated *Defaults() helper derived from the rac_default annotations in idl/, so a default has one declaration for all SDKs.
Every *Stream verb returns an AsyncIterable directly, so there is nothing to await before iterating. Events follow one grammar: started, then deltas, then completed, with failures thrown into the consumer.
Hermes cannot iterate the Nitro-backed streams with for await...of. Drive them manually and call return() to cancel:
const iterator = RunAnywhere.llm.generateStream(prompt)[Symbol.asyncIterator]();
try {
let step = await iterator.next();
while (!step.done) {
if (step.value.type === 'token') append(step.value.text);
step = await iterator.next();
}
} finally {
await iterator.return?.();
}
Cancelling one stream cancels that one request. There are no global cancel verbs.
Below the public surface, every bridge call is request/result proto bytes:
const requestBytes = ModelLoadRequest.encode(request).finish();
const resultBytes = await NativeRunAnywhere.modelLifecycleLoadProto(requestBytes);
return ModelLoadResult.decode(resultBytes);
Avoid new JSON bridge methods for SDK-owned flows.
Native commons owns model paths, registry state, downloads, imports, and storage deletion. models.register takes one builder covering a single url, an archive, or a multi-file set; models.download(id) reports progress, extraction, and completion through one stream.
Do not reintroduce a JS-owned DownloadService, a JS-owned ModelRegistry, or react-native-blob-util as a model-management path. Apps may build their own download UI, but artifacts enter the registry through the native download and import completion paths.
Each namespace is a thin projection over the commons proto ABI:
events does not open the microphone; start() does.close() releases it.React Native should not persist duplicate SDK auth/device state in JavaScript. Native owns:
Errors should map native rac_result_t and structured proto errors to the React Native SDKException equivalent. Unsupported hardware or platform features should be explicit typed errors, not silent fallbacks.
These are stale RN-owned paths and should not be documented as SDK architecture:
DownloadService as the SDK model download engine.ModelRegistry as the source of truth for registry/downloaded state.react-native-blob-util as the SDK artifact downloader.getAvailableModels or getDownloadedModels.Documentation-only changes are verified by review. Code alignment PRs should include:
yarn workspace @runanywhere/core typecheck
yarn workspace @runanywhere/llamacpp typecheck
yarn workspace @runanywhere/onnx typecheck
yarn workspace runanywhere-ai-example typecheck
Full validation requires fresh install, continuous logs, model download, model load, real inference for the changed modalities, screenshots, and log review on Android and iOS. Build/install/launch is smoke evidence only.