New: TranslatePsy-AfriSLM translates directly between 19 African languages, offline.
QVAC Logo
SDKJS/TS SDK
v0.21, the current release

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/sdk

Expo

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-device

Tip: 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:

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 prebuild

Build and run it on a physical device:

npx expo run:ios --device
# or
npx expo run:android --device

Due 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=module

Install the SDK:

npm i @qvac/sdk

Save this config in your workspace to enable client and server logs during the run:

qvac.config.json
{
  "loggerLevel": "info",
  "loggerConsoleOutput": true,
  "httpDownloadConcurrency": 3,
  "httpConnectionTimeoutMs": 10000
}

Create the quickstart script:

quickstart.js
// 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.js

Or 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-examples workspace 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.js

See Configuration for options and schema.

File formats

The qvac.config.* format you can use depends on the JS environment where QVAC runs:

FormatNode.jsBareExpo
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.

qvac.config.js
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:

  1. Provide a process global. Install bare-process and set it before using @qvac/inference:
    import process from "bare-process";
    globalThis.process = process;
  2. 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:

quickstart-adapted.ts
// 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.

On this page

Ask anything about QVAC.