Skip to content

Migrating from v2.3 to v2.4

v2.4 is a purely additive release. It introduces the .NET NuGet family (Phase 3G) and republishes the Phase 3D Android umbrella AAR at 2.4.0 for build-graph alignment.

TL;DR

  • No breaking changes. Existing iOS / Android / Capacitor / React Native / Flutter consumers see no behaviour change.
  • New DVAIBridge NuGet family on NuGet.org — the third public registry in the family, joining the iOS CocoaPod and the Flutter pub.dev package.
  • Phase 3D Android AAR republished as co.deepvoiceai:dvai-bridge:2.4.0 with no source changes — version bumped to keep the .NET binding's build graph internally consistent.

What's new

DVAIBridge NuGet family (Phase 3G)

Six NuGet packages on NuGet.org — the original Phase 3G mobile-only set plus a desktop slice, an ONNX Runtime backend, and an ML.NET backend added in the 3G expansion:

NuGet IDTFMContents
DVAIBridgenet10.0facade DLL + xmldoc; TFM-conditional deps to slices
DVAIBridge.iOSnet10.0-ios26.2; net10.0-maccatalyst26.2Obj-C bindings + bundled DVAIBridgeNetBridge.xcframework (multi-target — iOS device/sim and Mac Catalyst from one NuGet)
DVAIBridge.Androidnet10.0-android36.0Java/Kotlin bindings + transform XML (AAR pulled at consumer build)
DVAIBridge.Desktop ⭐ newnet10.0llama.cpp native slice for Windows / macOS / Linux (runtimes/<rid>/native/)
DVAIBridge.OnnxRuntime ⭐ newnet10.0Cross-platform ONNX Runtime + GenAI backend (opt-in, BackendKind.Onnx)
DVAIBridge.MLNet ⭐ newnet10.0ML.NET / OnnxScoringEstimator backend (opt-in, desktop only, BackendKind.MLNet)

Drop it into a .NET MAUI / Avalonia / WinUI 3 / Xamarin (legacy) app:

bash
dotnet add package DVAIBridge --version 2.4.0

Then use the same idiomatic-C# API across iOS + Android:

csharp
using DVAIBridge;

var server = await DVAIBridge.Shared.StartAsync(new StartOptions
{
    Backend = BackendKind.Auto,
    ModelPath = "/path/to/model.gguf",
});
Console.WriteLine(server.BaseUrl); // http://127.0.0.1:38883/v1

await foreach (var ev in DVAIBridge.Shared.ProgressEvents.WithCancellation(ct))
    Console.WriteLine($"{ev.Kind} {ev.Phase}");

await DVAIBridge.Shared.StopAsync();

Full guide: docs/guide/dotnet-sdk.md.

Distribution table — v2.4

Family memberDistributionPublic/Private
@dvai-bridge/capacitornpm (GitHub Packages)private
@dvai-bridge/iosSwiftPM (GitHub) + CocoaPods (Trunk)public (CocoaPods) / private (GH SPM auth optional)
@dvai-bridge/androidMaven (GitHub Packages)private
@dvai-bridge/react-nativenpm (GitHub Packages)private
dvai_bridge (Flutter)pub.devpublic
DVAIBridge (.NET)NuGet.orgpublic ⭐ new

The .NET package is the third public family member. Its iOS slice bundles the xcframework inside the NuGet — so consumers don't need separate SwiftPM auth. The Android slice still needs a GitHub Packages Maven repo entry in the consumer's csproj — the same friction Flutter consumers see.

What didn't change

  • iOS umbrella DVAIBridge — stays at 2.3.0. No source changes; the .NET Swift @objc wrapper depends on the existing public API.
  • Flutter dvai_bridge — stays at 2.3.0. Phase 3G is .NET-only; Flutter is unaffected.
  • React Native @dvai-bridge/react-native — stays at 2.3.0. Same reasoning as Flutter.
  • Capacitor @dvai-bridge/capacitor — stays at 2.3.0.

What did change at 2.4.0

  • Android umbrella co.deepvoiceai:dvai-bridge — republished at 2.4.0. No source changes. The bump exists for build-graph alignment with the new .NET Android binding's <AndroidLibrary> reference.

Upgrade — existing consumers

If you only use the iOS, Android, RN, or Flutter SDKs — do nothing. v2.4 is byte-identical to v2.3 for those families. You can stay on 2.3.x indefinitely.

To add a .NET MAUI app to a project that already uses the iOS or Android SDKs:

  1. Install .NET 10 SDK (LTS through November 2028).
  2. dotnet workload install ios android maui.
  3. dotnet add package DVAIBridge --version 2.4.0.
  4. Configure GitHub Packages Maven for the Android slice (see docs/guide/dotnet-sdk.md).
  5. Wire the Android Bootstrap.Init(applicationContext) call from your MauiApplication.OnCreate.

NativeAOT

Not supported on the binding slices in v2.4. Consumers can still ship NativeAOT iOS apps with <TrimmerRootDescriptor> overrides — expect Phase 4 to add first-class support. See docs/guide/dotnet-sdk.md#nativeaot.

Desktop slice (Phase 3G expansion — new)

DVAIBridge.Desktop is the new desktop-native slice for Windows 10 1809+, macOS 11+, and Ubuntu 22.04+ / Debian 12+. It ships llama.cpp native binaries via NuGet's runtimes/<rid>/native/ mechanism — so a dotnet publish automatically copies the right binary into the publish output. No CocoaPods / Maven / SwiftPM auth required for desktop consumers.

Supported runtimes/<rid>/native/ slots — v2.4 ships CPU-only Win / Linux with AVX2/NEON SIMD; macOS arm64 ships Metal-enabled:

  • win-x64, win-arm64
  • osx-arm64 (Metal), osx-x64 (CPU)
  • linux-x64, linux-arm64

CUDA / ROCm builds are a Phase 4 candidate — they'll land as opt-in DVAIBridge.Desktop.CUDA / .ROCm NuGets when Phase 4 closes.

Migration: if you previously hit the v2.3-era DVAIBridgeException(BackendUnavailable) on desktop, you now get a real working backend. No code changes required — BackendKind.Auto / BackendKind.Llama Just Work on desktop in v2.4.

Mac Catalyst (Phase 3G expansion — new TFM)

DVAIBridge.iOS is now a multi-target binding NuGet that ships both net10.0-ios26.2 and net10.0-maccatalyst26.2 slices. Consumers targeting Mac Catalyst (net10.0-maccatalyst26.2) no longer need a separate package — the existing DVAIBridge reference picks up the Catalyst slice transitively.

The underlying SwiftPM package already declared .macCatalyst(.v15_1) (Phase 3C), so the same DVAIBridgeNetBridge.xcframework carries the Catalyst slice. PlatformBridgeFactory routes both runtime kinds (OperatingSystem.IsIOS() / OperatingSystem.IsMacCatalyst()) to IOSNativeBridge.

Migration: add net10.0-maccatalyst26.2 to your csproj's <TargetFrameworks>. No NuGet additions required.

iOS / Catalyst TPV bump

The Phase 3G mobile-only commit shipped with net10.0-ios18.0 / net10.0-maccatalyst18.0 TFMs. Those values are valid only on .NET 9 — on .NET 10 the SDK accepts 26.0 and 26.2. v2.4 corrects the TFMs to net10.0-ios26.2 and net10.0-maccatalyst26.2. Consumers building against net10.0 will need to update their <TargetFrameworks> accordingly.

ONNX Runtime backend (Phase 3G expansion — new)

DVAIBridge.OnnxRuntime is a new cross-platform backend slice that adds BackendKind.Onnx (= 7). Works on every platform the family runs on — iOS, Mac Catalyst, Android, Windows desktop, macOS desktop, Linux desktop. The most portable backend in the matrix.

Opt-in: dotnet add package DVAIBridge.OnnxRuntime --version 2.4.0. The facade routes BackendKind.Onnx to OnnxNativeBridge at runtime once the assembly is loaded.

Model format: ONNX Runtime GenAI directory containing model.onnx, genai_config.json, and tokenizer.json. microsoft/Phi-3.5-mini-instruct-onnx is the canonical reference bundle.

Migration: purely additive. Existing BackendKind.Llama / BackendKind.Auto consumers see no behaviour change.

ML.NET backend (Phase 3G expansion — new)

DVAIBridge.MLNet is a new desktop-only backend slice that adds BackendKind.MLNet (= 8). It wraps Microsoft.ML + OnnxScoringEstimator — so apps already running ML.NET pipelines (recommendation, classification, forecasting) can drop LLM inference into the same IDataView flow.

Opt-in: dotnet add package DVAIBridge.MLNet --version 2.4.0.

Greenfield consumers

Pick BackendKind.Onnx instead. The MLNet slice rides the same ORT natives but adds ~1.4× per-token overhead from the ML.NET pipeline shape. The MLNet slice exists for "I'm already in ML.NET" use cases — it's a compatibility bridge, not a performance choice.

BackendKind.MLNet is rejected on iOS / Mac Catalyst / Android with a BackendUnavailable error pointing consumers at BackendKind.Onnx.

Migration: purely additive. Mobile consumers don't see this backend.

ProgressBroadcaster cancellation fix (bugfix)

In v2.3.x, the IAsyncEnumerable<ProgressEvent> returned by DVAIBridge.Shared.ProgressEvents.WithCancellation(ct) would propagate OperationCanceledException out of the consuming await foreach block when the caller cancelled. The canonical .NET pattern treats consumer-side cancellation as an iterator yield-break — not a thrown exception. v2.4 fixes the broadcaster to match.

Behavioural change: consumers that previously caught OperationCanceledException around await foreach (var ev in bridge.ProgressEvents.WithCancellation(ct)) will find that catch-block no longer fires when the cancellation is the consumer's own. The loop exits cleanly via yield-break instead.

csharp
// v2.3 — OCE propagated out of `await foreach`:
try
{
    await foreach (var ev in bridge.ProgressEvents.WithCancellation(ct)) { … }
}
catch (OperationCanceledException) { /* ran on consumer cancel */ }

// v2.4 — yield-break, no OCE:
await foreach (var ev in bridge.ProgressEvents.WithCancellation(ct)) { … }
// loop exits cleanly when ct fires

The change is safe for consumers who don't catch OCE — they see no difference. Consumers who relied on the OCE for cleanup logic should move that logic into a finally / await using block, or check ct.IsCancellationRequested after the loop.

Desktop (WinUI 3 / Avalonia / desktop .NET)

See the desktop slice section above. The v2.3-era BackendUnavailable fail-fast is gone — desktop now has a real working BackendKind.Llama backend out of the box.

Reference