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.