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
DVAIBridgeNuGet 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.0with 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 ID | TFM | Contents |
|---|---|---|
DVAIBridge | net10.0 | facade DLL + xmldoc; TFM-conditional deps to slices |
DVAIBridge.iOS | net10.0-ios26.2; net10.0-maccatalyst26.2 | Obj-C bindings + bundled DVAIBridgeNetBridge.xcframework (multi-target — iOS device/sim and Mac Catalyst from one NuGet) |
DVAIBridge.Android | net10.0-android36.0 | Java/Kotlin bindings + transform XML (AAR pulled at consumer build) |
DVAIBridge.Desktop ⭐ new | net10.0 | llama.cpp native slice for Windows / macOS / Linux (runtimes/<rid>/native/) |
DVAIBridge.OnnxRuntime ⭐ new | net10.0 | Cross-platform ONNX Runtime + GenAI backend (opt-in, BackendKind.Onnx) |
DVAIBridge.MLNet ⭐ new | net10.0 | ML.NET / OnnxScoringEstimator backend (opt-in, desktop only, BackendKind.MLNet) |
Drop it into a .NET MAUI / Avalonia / WinUI 3 / Xamarin (legacy) app:
dotnet add package DVAIBridge --version 2.4.0Then use the same idiomatic-C# API across iOS + Android:
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 member | Distribution | Public/Private |
|---|---|---|
@dvai-bridge/capacitor | npm (GitHub Packages) | private |
@dvai-bridge/ios | SwiftPM (GitHub) + CocoaPods (Trunk) | public (CocoaPods) / private (GH SPM auth optional) |
@dvai-bridge/android | Maven (GitHub Packages) | private |
@dvai-bridge/react-native | npm (GitHub Packages) | private |
dvai_bridge (Flutter) | pub.dev | public |
DVAIBridge (.NET) | NuGet.org | public ⭐ 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.NETSwift@objcwrapper 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:
- Install .NET 10 SDK (LTS through November 2028).
dotnet workload install ios android maui.dotnet add package DVAIBridge --version 2.4.0.- Configure GitHub Packages Maven for the Android slice (see
docs/guide/dotnet-sdk.md). - Wire the Android
Bootstrap.Init(applicationContext)call from yourMauiApplication.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-arm64osx-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.
// 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 firesThe 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
- .NET SDK guide — full setup + API.
- API reference —
DVAIConfigfield-by-field. - Migration v2.2 → v2.3 — Flutter family addition.
- Migration v2.4 → v3.0 — distributed inference.
