Migration: v3.0 → v3.1
TL;DR — for most consumers, no changes are required. v3.1 is a backwards-compatible minor bump. The default new DVAI(config) → dvai.initialize() → OpenAI HTTP wire surface keeps working without code changes. v3.0 mobile SDKs keep pairing with v3.1 targets.
The release combines two work streams:
DVAI Hub — a Tauri desktop utility that implements the strong-peer side of the v3.0 distributed-inference plane as a first-party installable app. Don't run it and your v3.0 code keeps working exactly as before. Run it and every dvai-bridge mobile app on the same network can pair with it and offload to it.
Library finalization — small but real changes to
@dvai-bridge/core's public surface that round out the v3.0 distributed-inference plane. A few wiring gaps fixed, a few new extension points added, a wire-protocol field made optional but recommended. Documented in detail below.
DVAI Hub user guide →Developer-fork guide →
What changed
Added
- DVAI Hub — Tauri-based desktop utility. Standalone repo path
hub/. Distributed via GitHub Releases / Homebrew / winget at v3.1.0. - Multi-tenant pairing isolation — the Hub serves multiple unrelated apps from one machine. Per-app pairings, capability caches, audit logs.
- Strict-by-default substitution policy — when a request doesn't match a cached model exactly, the Hub refuses unless
preferBetterQuantis explicitly enabled per-pairing. - Canonical model-name parser — handles GGUF / MLX / ONNX / MLC / Ollama / raw HuggingFace conventions. Feeds the substitution policy a structured view of every cached model.
- External-engine bridge (Hub-side, opt-in) — surfaces Ollama, LM Studio, vLLM, llama-server, and llamafile as additional backend pools, so paired apps can route through whatever's already cached.
- Per-app audit log with 30-day rolling retention.
hub/DEVELOPER-FORK.md— walkthrough for app developers who want a branded companion (Flavor 2).
Library API additions (@dvai-bridge/core)
All optional. Existing v3.0 code paths keep their behaviour when the new fields are omitted.
DVAIConfig.httpBindHost?: string— network interface to bind the embedded HTTP server. Defaults to"127.0.0.1"— loopback only, unchanged from v3.0. LAN-target deployments (the v3.1 Hub, native SDKs running in target mode) set it to"0.0.0.0"so peers on the same Wi-Fi can reach the server. Phone-as-source / single-device deployments should leave the default. A 0.0.0.0 bind without pairing protection exposes the OpenAI surface.DVAIConfig.chatCompletionInterceptor?— first-chance hook for/v1/chat/completions. Receives(body, ctx, headers?), returnsPromise<Response | null>. Return aResponseto short-circuit. Returnnullto fall through to the default local-backend handler. The Hub uses this to enforce its substitution policy and route requests through external engines — Ollama / LM Studio / vLLM / llama-server / llamafile.OffloadConfig.onPairingRequestreturn type widened fromPromise<boolean>to a tagged union:tsPromise< | boolean | { approved: true; pairingKey: string } | { approved: false } >The object form lets a host with its own pairing state (the v3.1 Hub's
MultiTenantPairing) supply the pairing key directly. PairingPolicy uses that key instead of generating a fresh one — avoiding the "two parallel stores generating divergent keys" bug. v3.0 callers still returningbooleankeep working unchanged.HMAC primitives re-exported from package root—composeSignedMessage,verifyHmac,signHmac,generateNonce,generatePairingKeynow hang off the package root — so consumers (Hub, native SDKs, rendezvous clients) don't have to reach into deep paths.
Wire-protocol additions
/v1/dvai/handshakerequest body gains an optionalappIdfield. When present, multi-tenant targets (Hub) use it as the per-app isolation key. When absent, falls back topeerDeviceId— so v3.0 SDKs that don't sendappIdstill pair correctly. Each device becomes its own tenant./v1/dvai/handshakeresponse body now echoes thepairingKeyandpeerDeviceIdso the requester can HMAC-sign subsequent calls. v3.0's response shape ({paired, pairedAt, via}) is preserved as-is — the new fields are additive. LAN trust model: the response only crosses the same Wi-Fi the handshake itself ran over. Rendezvous-QR pairings use the separate ECDH key-agreement path and don't reach this handler./v1/chat/completionsHMAC headers — the v3.1 wire reserves four request headers for HMAC-signed identity:X-DVAI-Peer-Device-IdX-DVAI-App-IdX-DVAI-NonceX-DVAI-Signature(hex ofHMAC-SHA256(pairingKey, composeSignedMessage(nonce, "POST", "/v1/chat/completions", bodyJson))) When all four are present and verify, the Hub records the audit row under the real (appId,peerDeviceId). When all four are absent, the request runs through the anonymous backwards-compat path. Partial sets — some headers, not all — are rejected with
- Implementing this on the SDK side is a v3.1 finalization task. Existing SDKs continue to use the anonymous path.
Behaviour fixes (still backwards compatible)
These were latent v3.0 bugs that the Hub work surfaced. v3.0 consumers running on Node, or relying on /v1/dvai/* routes, benefit from the fixes too:
TransformersBackenddevice resolution —device: "cpu"used to map to"wasm"for "Transformers.js v3/v4 compat". That works in browsers (onnxruntime-web acceptswasm) — but fails in Node (onnxruntime-node throwsUnsupported device: "wasm"). v3.1 detects the runtime and routes tocpuin Node /wasmin browser. Consumers running DVAI-on-Node (the v3.1 Hub, thenode-langchainexample) needed this. Browser consumers see no behavioural difference./v1/dvai/*routes are now actually dispatched by the HTTP transport. v3.0 hadbuildDvaiRoutes()exported but never called by any transport — every/v1/dvai/health|peers|capability| handshake|...returned{"error":"not found"}. The new wiring uses a late-bound getter onHandlerContextso the transport reads the route map per-request — the routes are built after the transport starts. Pairing actually works now.SubstitutionPolicyrefuses onrequest.family === "unknown"— the parser uses"unknown"as a sentinel for "couldn't classify the model name". Treating sentinel-vs-sentinel as a real match would (and did) silently route fictional model requests to whichever cached backend also failed parsing. The Hub's substitution policy short-circuits to refuse when the request side is sentinel.
Removed
- Nothing.
Deprecated
- Nothing. Every v3.0 API surface remains supported.
Migrating
JavaScript / TypeScript
No changes required. To integrate Hub-aware diagnostics in your mobile app:
const dvai = new DVAI({
backend: "...",
modelId: "...",
offload: {
enabled: true,
discoverLAN: true,
minLocalCapability: 10,
onPairingRequest: async (peer) => {
// Surface a UI prompt — same as v3.0; Hub is just another peer.
return await myAppUiConfirm(peer.deviceName);
},
},
});The Hub announces itself via mDNS as a regular dvai-bridge peer — deviceName="DVAI Hub" by default. Your mobile app handles it identically to a peer-mode laptop running dvai-bridge directly.
iOS / Android / RN / Flutter / Capacitor / .NET
No changes required. The Hub's pairing handshake is wire-compatible with every v3.0 SDK.
To explicitly route through the Hub — rather than any peer that satisfies your minimum capability — filter on peer.deviceName == "DVAI Hub" in your onPairingRequest callback.
Distribution
The Hub ships at v3.1.0. Two flavors:
- Flavor 1 — first-party DVAI Hub. Installable via
brew install deepvoiceai/dvai-hub/dvai-huborwinget install DeepVoiceAI.DVAIHub. Suitable for end users who run any dvai-bridge-powered apps. - Flavor 2 — developer-forked branded companion. Walk through the dev-fork guide. Suitable when you want a branded desktop app paired only with your specific mobile app.
Operational notes
- Pairing data on the Hub lives at:
- macOS:
~/Library/Application Support/dvai-hub/ - Windows:
%LOCALAPPDATA%\dvai-hub\ - Linux:
~/.local/share/dvai-hub/
- macOS:
- Audit logs roll over after 30 days of inactivity. The Hub's Logs tab exports the current window as JSON.
- Auto-update is opt-in in v3.1. Want updates pushed? Toggle it in Settings.
When NOT to upgrade
If your app:
- Doesn't expose any host-app UI for offload (target-side or initiator-side);
- Has no need for a desktop companion;
…then v3.0 keeps working fine. The Hub is a separate utility — not a library upgrade. Your v3.0 dependencies are unchanged.
Reporting issues
The Hub line is new in v3.1. File an issue at https://github.com/dvai-global/dvai-bridge/issues with [hub] in the title and include:
- Hub version (Settings tab → About).
- Hub host OS + version.
- The mobile app's dvai-bridge SDK + version.
- Output of the Hub's Status tab.
- Relevant entries from the per-app audit log (Logs tab → Export JSON).
See also
- DVAI Hub user guide
- Developer fork guide
- Distributed inference — the substrate Hub builds on
- Distributed inference testing
