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
- Node.js
>= v22.17 - npm
>= v10.9 - Bare
>= v1.30.3(if targeting Bare) - Expo
>= v54(if targeting mobile)
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"
]
}
}QVAC ships part of its Android and iOS binaries as separate packages that your app needs. Pass installMissingPrebuilds to the plugin to have npx expo prebuild add them, or add them yourself. See Install QVAC in the Expo tutorial.
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.