JS/TS SDK
Install and use the JavaScript/TypeScript client for QVAC.
Overview
The JS/TS SDK (@qvac/sdk on npm) is the JavaScript/TypeScript client for QVAC.
It drives a Bare worker over bare-rpc, and exposes every
QVAC capability through a unified, type-safe API.
Requirements
For host-level requirements (OS versions, GPU drivers, Vulkan runtime), see System requirements.
Install
npm i @qvac/sdkExpo
Install peer dependencies:
npm i 'react-native-bare-kit@^0.11.5'
npm i -D 'bare-pack@^1.5.1'
npx expo install expo-file-system expo-build-properties expo-deviceTip: use npx expo install for all expo-* packages to ensure compatibility with your project's Expo SDK version.
Configure expo-build-properties and add @qvac/sdk/expo-plugin to the plugins array in your app.json:
{
"expo": {
"plugins": [
["expo-build-properties", {
"android": { "minSdkVersion": 29 }
}],
"@qvac/sdk/expo-plugin"
]
}
}Prebuild your project to generate the native files:
npx expo prebuildBuild and run it on a physical device:
npx expo run:ios --device
# or
npx expo run:android --deviceDue to limitations with llamacpp, QVAC currently does not run on emulators.
You must use a physical device.
Quickstart
Run your first example using the JS/TS SDK.
Create the examples workspace:
mkdir qvac-examples
cd qvac-examples
npm init -y && npm pkg set type=moduleInstall the SDK:
npm i @qvac/sdkSave this config in your workspace to enable client and server logs during the run:
{
"loggerLevel": "info",
"loggerConsoleOutput": true,
"httpDownloadConcurrency": 3,
"httpConnectionTimeoutMs": 10000
}Create the quickstart script:
// The SDK prints no logs by default. To see its client and server logs, run with
// QVAC_CONFIG_PATH pointing at a config that sets "loggerConsoleOutput": true
// (see the Quickstart docs).
import { loadModel, LLAMA_3_2_1B_INST_Q4_0, completion, unloadModel } from '@qvac/sdk';
try {
// Load a model into memory
const modelId = await loadModel({
modelSrc: LLAMA_3_2_1B_INST_Q4_0,
onProgress: (p) => {
const mb = (n) => (n / 1e6).toFixed(1);
const line = `▸ Downloading ${p.percentage.toFixed(0)}% (${mb(p.downloaded)}/${mb(p.total)} MB)`;
process.stderr.write(process.stderr.isTTY ? `\r${line}` : `${line}\n`);
if (p.percentage >= 100)
process.stderr.write('\n');
}
});
// You can use the loaded model multiple times
const history = [
{
role: 'user',
content: 'Explain quantum computing in one sentence'
}
];
const result = completion({ modelId, history, stream: true });
for await (const token of result.tokenStream) {
process.stdout.write(token);
}
// Unload model to free up system resources
await unloadModel({ modelId });
}
catch (error) {
console.error('✖', error);
process.exit(1);
}Run the quickstart script:
QVAC_CONFIG_PATH=./qvac.config.json node quickstart.jsOr on Bare with @qvac/inference — see Running on Bare.
Running examples
Follow these instructions to run any example in this documentation:
- All examples are self-contained, runnable JavaScript scripts. Use the
qvac-examplesworkspace created in this quickstart to store and run them as you explore this documentation. - Run each example with the indicated compatible JavaScript environment. QVAC supports Node.js, Expo, and in-process Bare via
@qvac/inference. The examples are written in Node style and run on Node.js or Bun directly; to run them on Bare, see Running on Bare. - More examples can be found in the SDK examples directory.
- Some examples need companion files — sample audio, an image, or a config — that aren't part of the embedded code. These can be found in the same examples directory.
- Some examples also provide a TypeScript version. If you want to run TS directly, install the required dev dependencies:
npm i -D tsx typescript
Configuration
The SDK reads qvac.config.* from the project root, or from the path in QVAC_CONFIG_PATH:
QVAC_CONFIG_PATH=./qvac.config.json node app.jsSee Configuration for options and schema.
File formats
The qvac.config.* format you can use depends on the JS environment where QVAC runs:
| Format | Node.js | Bare | Expo |
|---|---|---|---|
qvac.config.json | ✅ | ✅ | ✅ |
qvac.config.js | ✅ | ✅ | ❌ |
qvac.config.ts | ✅ | ❌ | ❌ |
qvac.config.ts requires installing tsx as a devDependency.
Supported on Node.js and Bare. Not supported in Expo — use JSON instead.
module.exports = {
plugins: ["<builtin_plugin_1>", "<custom_plugin_2>"],
loggerConsoleOutput: true,
loggerLevel: "info",
swarmRelays: ["<hyperbee_key_1>", "<hyperbee_key_2>"],
cacheDirectory: "</absolute/path/to/.qvac/models>",
httpDownloadConcurrency: 3,
httpConnectionTimeoutMs: 10000,
registryDownloadMaxRetries: 3,
registryStreamTimeoutMs: 60000,
rpcInitTimeoutMs: 30000,
deviceDefaults: [
{
name: "Samsung Galaxy force CPU",
match: { platform: "android", deviceBrand: "samsung" },
defaults: { llm: { device: "cpu" } },
},
],
bareRuntimeVersion: "<x.y.z>",
serve: {
models: {
"<model_alias>": {
model: "<SDK_MODEL_CONSTANT>",
default: true,
preload: true,
config: {},
},
},
},
};Running on Bare
To run an example on Bare:
- Provide a
processglobal. Installbare-processand set it before using@qvac/inference:import process from "bare-process"; globalThis.process = process; - Register the plugins the example uses — Bare runs in-process and nothing auto-registers. See Runtime registration on Bare.
Here is the SDK quickstart adapted for Bare with @qvac/inference:
// The SDK's quickstart, adapted for Bare with @qvac/inference. Three edits: import
// from `@qvac/inference` instead of `@qvac/sdk`, import `process` from bare-process
// (Bare has no `process` global), and register the plugins this example uses
// via `plugins([...])`.
import process from 'bare-process'
import { plugins, LLAMA_3_2_1B_INST_Q4_0 } from '@qvac/inference'
import { llmPlugin } from '@qvac/inference/llamacpp-completion/plugin'
const { loadModel, completion, unloadModel } = plugins([llmPlugin])
// From here it is the same as the SDK's quickstart.
const modelId = await loadModel({ modelSrc: LLAMA_3_2_1B_INST_Q4_0 })
const history = [{ role: 'user', content: 'Explain quantum computing in one sentence' }]
const result = completion({ modelId, history, stream: true })
for await (const token of result.tokenStream) {
process.stdout.write(token)
}
await unloadModel({ modelId, autoClose: true })For running QVAC on Bare in production, use @qvac/inference — the Bare-only in-process engine. Select addons and register plugins explicitly. @qvac/bare-sdk is deprecated; last release is 0.18.2.
API reference
API reference
@qvac/sdk npm package exposes a function-centric, typed JS API.