@ondeinference / onde / commits / 878bc4d

no bluff 🤷🏻‍♂️

Seto Elkahfi committed May 3, 2026 at 13:30 UTC 878bc4defdba06c81b066bcade88eae9d797afb6
7 files changed +81 -87
build.rs
+22 -28
@@ -1,8 +1,8 @@
1 fn main() {
2 - // ── SDK credentials ──────────────────────────────────────────────────
3 - // Load .env from the onde crate root so GresIQ credentials are available
4 - // to option_env!() in pulse/client.rs. Consumer apps never set these —
5 - // they're Onde Inference's own infrastructure secrets.
2 + // SDK credentials
3 + // Load .env from the onde crate root so pulse/client.rs can read these
4 + // through option_env!(). Consumer apps do not set them. They belong to
5 + // Onde Inference's own infrastructure.
6 println!("cargo:rerun-if-changed=.env");
7 let _ = dotenvy::from_filename(
8 std::path::Path::new(&std::env::var("CARGO_MANIFEST_DIR").unwrap()).join(".env"),
@@ -22,13 +22,12 @@ fn main() {
22 }
23 }
24
25 - // ── UniFFI scaffolding ───────────────────────────────────────────────
26 - // Not strictly required when using `uniffi::setup_scaffolding!()` in
27 - // lib.rs (the proc-macro approach), but having it here ensures the
28 - // build-dep on `uniffi` with `features = ["build"]` is exercised and
29 - // keeps compatibility if we ever switch to UDL-based generation.
25 + // UniFFI scaffolding
26 + // `uniffi::setup_scaffolding!()` in lib.rs already covers the proc-macro
27 + // path, but keeping this here still exercises the build dependency and
28 + // leaves us room to switch back to UDL-based generation later.
29
31 - // ── Apple: provide missing ___chkstk_darwin symbol ───────────────────
30 + // Apple targets: provide a missing ___chkstk_darwin symbol
31 //
32 // On macOS, `___chkstk_darwin` is exported by libSystem as a stack
33 // probing function. On arm64 the kernel grows the stack via guard
@@ -36,16 +35,15 @@ fn main() {
35 //
36 // tvOS, visionOS, and watchOS do NOT export this symbol at all.
37 //
39 - // iOS exports it in libSystem, but deployment-target mismatches
40 - // between dependencies (e.g. onig_sys built for iOS 26.0 linked
41 - // against a min-target of iOS 10.0) can cause the linker to fail
42 - // to resolve it. Providing the stub on iOS is harmless — if
43 - // libSystem already has the symbol the linker prefers it; if not,
44 - // our stub satisfies the reference.
38 + // iOS does export it in libSystem, but deployment-target mismatches
39 + // between dependencies (for example onig_sys built for iOS 26.0 linked
40 + // against a min-target of iOS 10.0) can still make the linker miss it.
41 + // Shipping the stub on iOS is harmless. If libSystem already provides the
42 + // symbol, the linker uses that. If not, our stub covers the reference.
43 //
46 - // `aws-lc-sys` assembly (transitive via reqwest → rustls → aws-lc-rs)
47 - // references ___chkstk_darwin unconditionally, so we compile a tiny
48 - // `ret` stub for all non-macOS Apple targets.
44 + // `aws-lc-sys` assembly (transitive via reqwest -> rustls -> aws-lc-rs)
45 + // always references ___chkstk_darwin, so we compile a tiny `ret` stub for
46 + // all non-macOS Apple targets.
47 let target_os = std::env::var("CARGO_CFG_TARGET_OS").unwrap_or_default();
48
49 if target_os == "ios"
@@ -57,20 +55,16 @@ fn main() {
55 let asm_path = std::path::Path::new(&manifest_dir).join("scripts/tvos_chkstk.s");
56
57 if asm_path.exists() {
60 - // Use the `cc` crate to assemble the stub into a static library
61 - // that the linker will pick up. If `cc` is not available as a
62 - // build-dependency, fall back to printing a cargo link directive
63 - // that tells the linker to include the object directly.
64 - //
65 - // Since `cc` is already a transitive build-dep (pulled in by
66 - // aws-lc-sys, ring, etc.), we use it directly.
58 + // Use `cc` to assemble the stub into a static library the linker
59 + // can pick up. `cc` is already in the build graph through crates
60 + // like aws-lc-sys and ring, so we just use it directly.
61 cc::Build::new().file(&asm_path).compile("tvos_chkstk");
62
63 println!("cargo:rerun-if-changed=scripts/tvos_chkstk.s");
64 } else {
65 println!(
72 - "cargo:warning=tvos_chkstk.s not found at {} — \
73 - ___chkstk_darwin will be unresolved on tvOS",
66 + "cargo:warning=tvos_chkstk.s not found at {}. \
67 + ___chkstk_darwin will stay unresolved on tvOS",
68 asm_path.display()
69 );
70 }
sdk/dart/example/lib/main.dart
+19 -18
@@ -3,14 +3,15 @@
3 //
4 // example/lib/main.dart
5 //
6 -// Complete Material 3 Flutter chat app demonstrating the onde_inference SDK:
7 -// * Synchronous OndeChatEngine() factory constructor (no await, no null)
8 -// * Platform-aware default model loading via loadDefaultModel() extension
9 -// * Multi-turn streaming chat via streamMessage(message:)
10 -// * EngineInfo display using EngineInfoX.historyLengthInt extension
11 -// * OndeError sealed-class error handling (not OndeException)
12 -// * Sampling preset selector (creative / precise / fast)
13 -// * Unload / reload model flow with live status bar
6 +// A complete Material 3 Flutter chat app that shows the main onde_inference
7 +// pieces in one place:
8 +// * synchronous OndeChatEngine() construction (no await, no null)
9 +// * platform-aware default model loading via loadDefaultModel()
10 +// * multi-turn streaming chat via streamMessage(message:)
11 +// * EngineInfo display through EngineInfoX.historyLengthInt
12 +// * OndeError sealed-class handling (not OndeException)
13 +// * sampling preset selection (creative / precise / fast)
14 +// * unload / reload flow with a live status bar
15
16 import 'dart:async';
17
@@ -23,8 +24,8 @@ import 'package:path_provider/path_provider.dart'
24
25 // ── Onde app credentials ──────────────────────────────────────────────────
26 // Register your app at https://ondeinference.com to get these.
26 -// The dashboard lets you assign a model to your app — the SDK fetches
27 -// it automatically. If no model is assigned, the platform default is used.
27 +// The dashboard lets you assign a model to the app. The SDK fetches it
28 +// automatically. If nothing is assigned, it falls back to the platform default.
29 const String ondeAppId = String.fromEnvironment('ONDE_APP_ID');
30 const String ondeAppSecret = String.fromEnvironment('ONDE_APP_SECRET');
31
@@ -36,16 +37,16 @@ void main() async {
37 WidgetsFlutterBinding.ensureInitialized();
38 await OndeInference.init();
39
39 - // Resolve the model cache directory for sandboxed platforms.
40 + // Pick a cache directory that works inside app sandboxes.
41 //
41 - // On iOS/macOS this tries the App Group shared container first
42 - // (group.com.ondeinference.apps) so all Onde-powered apps share
43 - // downloaded models. If the App Group is unavailable it falls back
44 - // to the app's private Application Support directory.
42 + // On iOS and macOS, try the shared App Group container first
43 + // (group.com.ondeinference.apps) so Onde-powered apps can reuse
44 + // downloaded models. If that is not available, fall back to the app's
45 + // own Application Support directory.
46 //
46 - // On Android there is no App Group — the fallback is always used.
47 + // Android has no App Group, so it always uses the fallback.
48 //
48 - // On desktop Linux/Windows this is a no-op (default ~/.cache works).
49 + // Linux and Windows do nothing special here. The default ~/.cache path works.
50 String? fallback;
51 if (Platform.isIOS || Platform.isAndroid) {
52 final dir = await getApplicationSupportDirectory();
@@ -143,7 +144,7 @@ class ChatScreen extends StatefulWidget {
144 }
145
146 class _ChatScreenState extends State<ChatScreen> {
146 - // OndeChatEngine() is a synchronous factory constructor -- no Future, no null.
147 + // OndeChatEngine() is synchronous. No Future, no null.
148 final OndeChatEngine _engine = OndeChatEngine();
149
150 EngineInfo _engineInfo = EngineInfo(
sdk/dart/example/test/widget_test.dart
+4 -4
@@ -8,10 +8,10 @@ import 'package:onde_inference_example/main.dart';
8 void main() {
9 testWidgets('OndeInferenceApp builds without crashing',
10 (WidgetTester tester) async {
11 - // Verify the root widget can be constructed.
12 - // Full integration tests require the native inference library to be
13 - // compiled first — run `flutter build` or `cargo build` in sdk/dart/rust/
14 - // before running widget tests that exercise the engine.
11 + // Make sure the root widget can be constructed.
12 + // Full integration tests need the native inference library first.
13 + // Run `flutter build` or `cargo build` in sdk/dart/rust/ before running
14 + // widget tests that actually hit the engine.
15 expect(const OndeInferenceApp(), isA<OndeInferenceApp>());
16 });
17 }
sdk/dart/ios/Classes/OndeInferencePlugin.swift
+5 -5
@@ -6,10 +6,10 @@
6 // Native iOS plugin for onde_inference.
7 //
8 // Responsibilities:
9 -// 1. Provides a method channel ("com.ondeinference.onde_inference") so Dart
9 +// 1. Provide a method channel ("com.ondeinference.onde_inference") so Dart
10 // can resolve the App Group shared container path at runtime.
11 -// 2. Acts as the CocoaPods framework host — the Rust static library
12 -// (libonde_inference_dart.a) is force-loaded into this framework via
11 +// 2. Act as the CocoaPods framework host. The Rust static library
12 +// (libonde_inference_dart.a) is force-loaded into this framework through
13 // OTHER_LDFLAGS in the podspec.
14
15 import Flutter
@@ -41,8 +41,8 @@ public class OndeInferencePlugin: NSObject, FlutterPlugin {
41 ) {
42 result(url.path)
43 } else {
44 - // App Group not configured or not entitled — fall back to nil
45 - // so the Dart side can use getApplicationSupportDirectory() instead.
44 + // If the App Group is missing or not entitled, return nil.
45 + // Dart can fall back to getApplicationSupportDirectory() instead.
46 result(nil)
47 }
48 default:
sdk/dart/lib/onde_inference.dart
+5 -5
@@ -5,7 +5,7 @@
5 /// On-device LLM inference SDK for Flutter & Dart.
6 ///
7 /// Runs Qwen 2.5 models locally with Metal (Apple silicon) and CPU
8 -/// acceleration — no cloud, no data leaving the device.
8 +/// acceleration, with no cloud hop and no data leaving the device.
9 /// Powered by the Onde Rust engine and [mistral.rs](https://github.com/EricLBuehler/mistral.rs).
10 ///
11 /// ## Quick start
@@ -90,10 +90,10 @@
90 /// instructions.
91 library;
92
93 -// All core data types (ChatMessage, SamplingConfig, GgufModelConfig, etc.)
94 -// re-exported from the FRB-generated api.dart via types.dart.
93 +// Re-export the core data types (ChatMessage, SamplingConfig,
94 +// GgufModelConfig, and friends) from the FRB-generated api.dart via types.dart.
95 export 'src/types.dart';
96
97 -// Engine API — OndeChatEngineX extension, OndeInference static helpers,
98 -// OndeChatEngine opaque type, OndeError sealed class, and RustLib.
97 +// Engine API: OndeChatEngineX helpers, OndeInference static helpers,
98 +// the OndeChatEngine opaque type, the OndeError sealed class, and RustLib.
99 export 'src/engine.dart';
sdk/dart/lib/src/engine.dart
+20 -20
@@ -34,9 +34,9 @@ export 'frb_generated.dart/api.dart'
34 /// High-level wrapper around the FRB-generated [api.OndeChatEngine] opaque type.
35 ///
36 /// Provides:
37 -/// - [OndeChatEngineX.loadDefaultModel] — convenience method not in generated code
38 -/// - [OndeChatEngineX.clearHistoryCount] — returns `int` instead of `BigInt`
39 -/// - [OndeInference] — static initialisation + config/sampling factory helpers
37 +/// - [OndeChatEngineX.loadDefaultModel]: convenience method not present in generated code
38 +/// - [OndeChatEngineX.clearHistoryCount]: returns `int` instead of `BigInt`
39 +/// - [OndeInference]: static initialisation plus config and sampling helpers
40 ///
41 /// ## Lifecycle
42 ///
@@ -44,7 +44,7 @@ export 'frb_generated.dart/api.dart'
44 /// // 1. Initialise once at app startup (idempotent).
45 /// await OndeInference.init();
46 ///
47 -/// // 2. Create a native engine instance (sync — no Future).
47 +/// // 2. Create a native engine instance (sync, no Future).
48 /// final engine = OndeChatEngine();
49 ///
50 /// // 3a. Load your assigned model (recommended for production).
@@ -80,7 +80,7 @@ export 'frb_generated.dart/api.dart'
80 /// serialised internally.
81 extension OndeChatEngineX on api.OndeChatEngine {
82 // -------------------------------------------------------------------------
83 - // loadDefaultModel — implemented in Dart (not in generated bridge)
83 + // loadDefaultModel: implemented in Dart, not in the generated bridge.
84 // -------------------------------------------------------------------------
85
86 /// Loads the platform-appropriate default model.
@@ -107,7 +107,7 @@ extension OndeChatEngineX on api.OndeChatEngine {
107 );
108
109 // -------------------------------------------------------------------------
110 - // clearHistoryCount — int-typed convenience over clearHistory() → BigInt
110 + // clearHistoryCount: int-typed convenience over clearHistory() -> BigInt.
111 // -------------------------------------------------------------------------
112
113 /// Clears the conversation history and returns the count as a plain [int].
@@ -118,7 +118,7 @@ extension OndeChatEngineX on api.OndeChatEngine {
118 }
119
120 // ---------------------------------------------------------------------------
121 -// OndeInference — static SDK helpers
121 +// OndeInference static SDK helpers
122 // ---------------------------------------------------------------------------
123
124 /// Static helper namespace for Onde SDK initialisation and configuration.
@@ -140,14 +140,14 @@ abstract final class OndeInference {
140
141 /// Initialises the Rust shared library.
142 ///
143 - /// Must be called before creating any [OndeChatEngine]. Subsequent calls
144 - /// are safe no-ops — the library is only initialised once per process.
143 + /// Must be called before creating any [OndeChatEngine]. Subsequent calls
144 + /// are safe no-ops. The library is only initialised once per process.
145 ///
146 /// Call this in `main()` or in a Flutter `initState` override before any
147 /// user interaction that could trigger model loading.
148 ///
149 /// On macOS the Rust static library is force-loaded into the
150 - /// `onde_inference.framework` CocoaPods dynamic framework — we must
150 + /// `onde_inference.framework` CocoaPods dynamic framework, so we must
151 /// `dlopen` that framework by name.
152 ///
153 /// On iOS the pod is statically linked into the Runner executable
@@ -155,17 +155,17 @@ abstract final class OndeInference {
155 /// `DynamicLibrary.process()` (`RTLD_DEFAULT`) which searches the
156 /// main executable and all loaded images.
157 ///
158 - /// On Android / Linux / Windows the default FRB stem-based loader
159 - /// finds the `.so` / `.dll` automatically — no override needed.
158 + /// On Android, Linux, and Windows, the default FRB stem-based loader
159 + /// finds the `.so` or `.dll` automatically. No override needed.
160 static Future<void> init() async {
161 ExternalLibrary? lib;
162 if (Platform.isMacOS) {
163 - // CocoaPods + use_frameworks! → pod is a dynamic framework.
164 - // DynamicLibrary.process() can't resolve symbols inside it.
163 + // With CocoaPods + use_frameworks!, the pod is a dynamic framework.
164 + // DynamicLibrary.process() cannot resolve symbols inside it.
165 lib = ExternalLibrary.open('onde_inference.framework/onde_inference');
166 } else if (Platform.isIOS) {
167 - // CocoaPods on iOS statically links the pod into the Runner
168 - // binary via -force_load. Symbols live in the main executable.
167 + // On iOS, CocoaPods statically links the pod into the Runner binary
168 + // through -force_load, so the symbols live in the main executable.
169 lib = ExternalLibrary.process(iKnowHowToUseIt: true);
170 }
171 await frb.RustLib.init(externalLibrary: lib);
@@ -186,10 +186,10 @@ abstract final class OndeInference {
186 /// unavailable (entitlement missing, group not registered), it falls back
187 /// to [fallbackDir] if provided.
188 ///
189 - /// On **Android** there is no App Group equivalent — pass [fallbackDir]
189 + /// On **Android** there is no App Group equivalent. Pass [fallbackDir]
190 /// (e.g. from `getApplicationSupportDirectory().path`).
191 ///
192 - /// On **desktop Linux / Windows** this is a no-op — the default
192 + /// On **desktop Linux / Windows** this is a no-op. The default
193 /// `~/.cache/huggingface` works without intervention.
194 ///
195 /// Call **once** at startup, after [init] and before any model load:
@@ -202,7 +202,7 @@ abstract final class OndeInference {
202 /// await OndeInference.setupCacheDir(fallbackDir: dir.path);
203 /// ```
204 static Future<void> setupCacheDir({String? fallbackDir}) async {
205 - // 1. Apple platforms — try the shared App Group container.
205 + // 1. On Apple platforms, try the shared App Group container first.
206 if (Platform.isIOS || Platform.isMacOS) {
207 try {
208 final String? groupPath = await _channel.invokeMethod<String>(
@@ -218,7 +218,7 @@ abstract final class OndeInference {
218 }
219 }
220
221 - // 2. Fallback — use the caller-provided directory (app sandbox).
221 + // 2. Otherwise use the caller-provided directory in the app sandbox.
222 if (fallbackDir != null && fallbackDir.isNotEmpty) {
223 api.configureCacheDir(appDataDir: fallbackDir);
224 }
sdk/dart/lib/src/types.dart
+6 -7
@@ -6,14 +6,13 @@
6 /// All core data types ([ChatRole], [ChatMessage], [SamplingConfig],
7 /// [GgufModelConfig], [InferenceResult], [StreamChunk], [EngineStatus],
8 /// [EngineInfo], [OndeError]) are generated by `flutter_rust_bridge_codegen`
9 -/// and live in `frb_generated.dart/api.dart`. This file re-exports them
10 -/// and adds Dart-idiomatic convenience extensions.
9 +/// and live in `frb_generated.dart/api.dart`. This file re-exports them
10 +/// and adds a few Dart-idiomatic convenience extensions.
11 library;
12
13 // Re-export every public type from the FRB-generated API layer.
14 -// After running `flutter_rust_bridge_codegen generate` this file is the
15 -// single import needed by consumers — they never need to reference the
16 -// generated directory directly.
14 +// After `flutter_rust_bridge_codegen generate`, consumers only need this
15 +// import. They never have to reference the generated directory directly.
16 export 'frb_generated.dart/api.dart'
17 show
18 ChatRole,
@@ -79,7 +78,7 @@ class OndeException implements Exception {
78 }
79
80 // ---------------------------------------------------------------------------
82 -// ChatMessage — convenience factory extension
81 +// ChatMessage convenience factory extension
82 // ---------------------------------------------------------------------------
83
84 /// Convenience factory constructors for [ChatMessage].
@@ -109,7 +108,7 @@ extension ChatMessageX on ChatMessage {
108 }
109
110 // ---------------------------------------------------------------------------
112 -// SamplingConfig — preset factory extension
111 +// SamplingConfig preset factory extension
112 // ---------------------------------------------------------------------------
113
114 /// Sampling configuration presets for common use-cases.