@ondeinference / onde / commits / 02746fe

Release 1.1.0

Seto Elkahfi committed May 15, 2026 at 01:50 UTC 02746fed377fd03141651c994d191c81efe90f6d
19 files changed +302 -217
.github/scripts/build-swift-xcframework.sh
+7 -3
@@ -13,6 +13,7 @@ CHECKSUM_PATH="$DIST_DIR/OndeFramework.checksum.txt"
13 VERSION_PATH="$DIST_DIR/version.txt"
14 BINDGEN="$ROOT_DIR/uniffi-bindgen/target/release/uniffi-bindgen"
15
16 +rm -rf "$FRAMEWORK_DIR" "$ZIP_PATH" "$CHECKSUM_PATH" "$VERSION_PATH"
17 mkdir -p "$DIST_DIR" "$PACKAGE_DIR/Sources/Onde" "$HEADERS_DIR"
18
19 cargo +1.92.0 build --manifest-path uniffi-bindgen/Cargo.toml --release
@@ -75,9 +76,12 @@ printf '%s
76
77 VERSION=$(python3 - <<'VER'
78 from pathlib import Path
78 -import tomllib
79 -cargo = Path('Cargo.toml').read_text().encode()
80 -print(tomllib.loads(cargo.decode())['package']['version'])
79 +import re
80 +cargo = Path('Cargo.toml').read_text()
81 +match = re.search(r'^version\s*=\s*"([^"]+)"', cargo, re.MULTILINE)
82 +if not match:
83 + raise SystemExit('Could not parse package.version from Cargo.toml')
84 +print(match.group(1))
85 VER
86 )
87 printf '%s
CHANGELOG.md
+17
@@ -1,3 +1,20 @@
1 +## 1.1.0
2 +
3 +### Swift / UniFFI runtime stability
4 +
5 +* Added `#[uniffi::export(async_runtime = "tokio")]` to the Swift/Kotlin FFI export surface so async UniFFI calls consistently run on the Tokio runtime.
6 +* Made pulse telemetry initialization lazy and panic-safe on Apple platforms. The GresIQ client is no longer created from the synchronous UniFFI constructor path, and telemetry now gracefully disables itself instead of crashing if a Tokio reactor is unavailable.
7 +* Added a one-time Rust panic hook so panics are logged through the host logger instead of relying on stderr in iOS/tvOS simulator and device contexts.
8 +
9 +### Telemetry
10 +
11 +* Added `ONDE_DISABLE_PULSE=1` as an explicit runtime kill switch for pulse telemetry during local validation and host-app debugging.
12 +* Hardened `model_loaded` and `inference_event` telemetry writes so they never require a current Tokio handle on the calling thread.
13 +
14 +### Packaging
15 +
16 +* Release metadata is aligned for Rust, Swift, Kotlin, Flutter/Dart, and React Native SDKs under version `1.1.0`.
17 +
18 ## 1.0.0
19
20 Onde has already been running in real Splitfire AB apps on the App Store for months, so keeping it on `0.x` no longer felt accurate.
Cargo.lock
+124 -189
@@ -64,9 +64,9 @@ dependencies = [
64
65 [[package]]
66 name = "annotate-snippets"
67 -version = "0.12.15"
67 +version = "0.12.16"
68 source = "registry+https://github.com/rust-lang/crates.io-index"
69 -checksum = "92570a3f9c98e7e84df84b71d0965ac99b1871fcd75a3773a3bd1bad13f64cf7"
69 +checksum = "f211a51805bc641f3ad5b7664c77d2547af685cc33b4cd8d31964027a46f13f1"
70 dependencies = [
71 "anstyle",
72 "memchr",
@@ -262,9 +262,9 @@ checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"
262
263 [[package]]
264 name = "aws-lc-rs"
265 -version = "1.16.3"
265 +version = "1.17.0"
266 source = "registry+https://github.com/rust-lang/crates.io-index"
267 -checksum = "0ec6fb3fe69024a75fa7e1bfb48aa6cf59706a101658ea01bfd33b2b248a038f"
267 +checksum = "5ec2f1fc3ec205783a5da9a7e6c1509cc69dedf09a1949e412c1e18469326d00"
268 dependencies = [
269 "aws-lc-sys",
270 "zeroize",
@@ -272,9 +272,9 @@ dependencies = [
272
273 [[package]]
274 name = "aws-lc-sys"
275 -version = "0.40.0"
275 +version = "0.41.0"
276 source = "registry+https://github.com/rust-lang/crates.io-index"
277 -checksum = "f50037ee5e1e41e7b8f9d161680a725bd1626cb6f8c7e901f91f942850852fe7"
277 +checksum = "1a2f9779ce85b93ab6170dd940ad0169b5766ff848247aff13bb788b832fe3f4"
278 dependencies = [
279 "cc",
280 "cmake",
@@ -389,6 +389,15 @@ dependencies = [
389 "unicode-segmentation",
390 ]
391
392 +[[package]]
393 +name = "bs58"
394 +version = "0.5.1"
395 +source = "registry+https://github.com/rust-lang/crates.io-index"
396 +checksum = "bf88ba1141d185c399bee5288d850d63b8369520c1eafc32a0430b5b6c287bf4"
397 +dependencies = [
398 + "tinyvec",
399 +]
400 +
401 [[package]]
402 name = "bstr"
403 version = "1.12.1"
@@ -591,9 +600,9 @@ dependencies = [
600
601 [[package]]
602 name = "cc"
594 -version = "1.2.61"
603 +version = "1.2.62"
604 source = "registry+https://github.com/rust-lang/crates.io-index"
596 -checksum = "d16d90359e986641506914ba71350897565610e87ce0ad9e6f28569db3dd5c6d"
605 +checksum = "a1dce859f0832a7d088c4f1119888ab94ef4b5d6795d1ce05afb7fe159d79f98"
606 dependencies = [
607 "find-msvc-tools",
608 "jobserver",
@@ -601,12 +610,6 @@ dependencies = [
610 "shlex",
611 ]
612
604 -[[package]]
605 -name = "cesu8"
606 -version = "1.1.0"
607 -source = "registry+https://github.com/rust-lang/crates.io-index"
608 -checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c"
609 -
613 [[package]]
614 name = "cfg-if"
615 version = "1.0.4"
@@ -621,9 +624,9 @@ checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724"
624
625 [[package]]
626 name = "cfgrammar"
624 -version = "0.14.1"
627 +version = "0.14.2"
628 source = "registry+https://github.com/rust-lang/crates.io-index"
626 -checksum = "3efdd8f0bddcc9e33f4a664d0f28bc4e51cd5367c16284087a95313104371865"
629 +checksum = "b5ef80386dea3cda50570f22e1c6a474f0cc688ae220fc584fef354acaf41f2b"
630 dependencies = [
631 "indexmap 2.14.0",
632 "num-traits",
@@ -1424,23 +1427,9 @@ checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6"
1427
1428 [[package]]
1429 name = "fax"
1427 -version = "0.2.6"
1428 -source = "registry+https://github.com/rust-lang/crates.io-index"
1429 -checksum = "f05de7d48f37cd6730705cbca900770cab77a89f413d23e100ad7fad7795a0ab"
1430 -dependencies = [
1431 - "fax_derive",
1432 -]
1433 -
1434 -[[package]]
1435 -name = "fax_derive"
1436 -version = "0.2.0"
1430 +version = "0.2.7"
1431 source = "registry+https://github.com/rust-lang/crates.io-index"
1438 -checksum = "a0aca10fb742cb43f9e7bb8467c91aa9bcb8e3ffbc6a6f7389bb93ffc920577d"
1439 -dependencies = [
1440 - "proc-macro2",
1441 - "quote",
1442 - "syn 2.0.117",
1443 -]
1432 +checksum = "caf1079563223d5d59d83c85886a56e586cfd5c1a26292e971a0fa266531ac5a"
1433
1434 [[package]]
1435 name = "fdeflate"
@@ -2004,9 +1993,9 @@ dependencies = [
1993
1994 [[package]]
1995 name = "h2"
2007 -version = "0.4.13"
1996 +version = "0.4.14"
1997 source = "registry+https://github.com/rust-lang/crates.io-index"
2009 -checksum = "2f44da3a8150a6703ed5d34e164b875fd14c2cdab9af1252a9a1020bde2bdc54"
1998 +checksum = "171fefbc92fe4a4de27e0698d6a5b392d6a0e333506bc49133760b3bcf948733"
1999 dependencies = [
2000 "atomic-waker",
2001 "bytes",
@@ -2068,9 +2057,9 @@ dependencies = [
2057
2058 [[package]]
2059 name = "hashbrown"
2071 -version = "0.17.0"
2060 +version = "0.17.1"
2061 source = "registry+https://github.com/rust-lang/crates.io-index"
2073 -checksum = "4f467dd6dccf739c208452f8014c75c18bb8301b050ad1cfb27153803edb0f51"
2062 +checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a"
2063
2064 [[package]]
2065 name = "heck"
@@ -2417,9 +2406,9 @@ dependencies = [
2406
2407 [[package]]
2408 name = "idna_adapter"
2420 -version = "1.2.1"
2409 +version = "1.2.2"
2410 source = "registry+https://github.com/rust-lang/crates.io-index"
2422 -checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344"
2411 +checksum = "cb68373c0d6620ef8105e855e7745e18b0d00d3bdb07fb532e434244cdb9a714"
2412 dependencies = [
2413 "icu_normalizer",
2414 "icu_properties",
@@ -2474,7 +2463,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
2463 checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9"
2464 dependencies = [
2465 "equivalent",
2477 - "hashbrown 0.17.0",
2466 + "hashbrown 0.17.1",
2467 "serde",
2468 "serde_core",
2469 ]
@@ -2525,16 +2514,6 @@ version = "2.12.0"
2514 source = "registry+https://github.com/rust-lang/crates.io-index"
2515 checksum = "d98f6fed1fde3f8c21bc40a1abb88dd75e67924f9cffc3ef95607bad8017f8e2"
2516
2528 -[[package]]
2529 -name = "iri-string"
2530 -version = "0.7.12"
2531 -source = "registry+https://github.com/rust-lang/crates.io-index"
2532 -checksum = "25e659a4bb38e810ebc252e53b5814ff908a8c58c2a9ce2fae1bbec24cbf4e20"
2533 -dependencies = [
2534 - "memchr",
2535 - "serde",
2536 -]
2537 -
2517 [[package]]
2518 name = "is_terminal_polyfill"
2519 version = "1.70.2"
@@ -2558,27 +2537,32 @@ checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682"
2537
2538 [[package]]
2539 name = "jni"
2561 -version = "0.21.1"
2540 +version = "0.22.4"
2541 source = "registry+https://github.com/rust-lang/crates.io-index"
2563 -checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97"
2542 +checksum = "5efd9a482cf3a427f00d6b35f14332adc7902ce91efb778580e180ff90fa3498"
2543 dependencies = [
2565 - "cesu8",
2544 "cfg-if",
2545 "combine",
2568 - "jni-sys 0.3.1",
2546 + "jni-macros",
2547 + "jni-sys",
2548 "log",
2570 - "thiserror 1.0.69",
2549 + "simd_cesu8",
2550 + "thiserror 2.0.18",
2551 "walkdir",
2572 - "windows-sys 0.45.0",
2552 + "windows-link 0.2.1",
2553 ]
2554
2555 [[package]]
2576 -name = "jni-sys"
2577 -version = "0.3.1"
2556 +name = "jni-macros"
2557 +version = "0.22.4"
2558 source = "registry+https://github.com/rust-lang/crates.io-index"
2579 -checksum = "41a652e1f9b6e0275df1f15b32661cf0d4b78d4d87ddec5e0c3c20f097433258"
2559 +checksum = "a00109accc170f0bdb141fed3e393c565b6f5e072365c3bd58f5b062591560a3"
2560 dependencies = [
2581 - "jni-sys 0.4.1",
2561 + "proc-macro2",
2562 + "quote",
2563 + "rustc_version",
2564 + "simd_cesu8",
2565 + "syn 2.0.117",
2566 ]
2567
2568 [[package]]
@@ -2612,9 +2596,9 @@ dependencies = [
2596
2597 [[package]]
2598 name = "js-sys"
2615 -version = "0.3.95"
2599 +version = "0.3.98"
2600 source = "registry+https://github.com/rust-lang/crates.io-index"
2617 -checksum = "2964e92d1d9dc3364cae4d718d93f227e3abb088e747d92e0395bfdedf1c12ca"
2601 +checksum = "67df7112613f8bfd9150013a0314e196f4800d3201ae742489d999db2f979f08"
2602 dependencies = [
2603 "cfg-if",
2604 "futures-util",
@@ -2691,9 +2675,9 @@ checksum = "11d3d7f243d5c5a8b9bb5d6dd2b1602c0cb0b9db1621bafc7ed66e35ff9fe092"
2675
2676 [[package]]
2677 name = "llguidance"
2694 -version = "1.7.4"
2678 +version = "1.7.5"
2679 source = "registry+https://github.com/rust-lang/crates.io-index"
2696 -checksum = "8e25b7647bd0b32c374d03fd0c148182ba46262fdd060f8897f638b0a3ff0818"
2680 +checksum = "5baa07a0af9806dc6b051fbaf665362314415c4eaa9471acc47de3a6113b9479"
2681 dependencies = [
2682 "anyhow",
2683 "derivre",
@@ -2736,9 +2720,9 @@ dependencies = [
2720
2721 [[package]]
2722 name = "lrtable"
2739 -version = "0.14.1"
2723 +version = "0.14.2"
2724 source = "registry+https://github.com/rust-lang/crates.io-index"
2741 -checksum = "b15ad6a43e5cff4ac046d51281d2256a36d1440065eab53ccce9362b48db5b42"
2725 +checksum = "bcbe6a005a604615ab7aab7d1f74be563e508f5c6e42f85fbf65c38fe1f5f268"
2726 dependencies = [
2727 "cfgrammar",
2728 "fnv",
@@ -3214,7 +3198,7 @@ checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe"
3198
3199 [[package]]
3200 name = "onde"
3217 -version = "1.0.0"
3201 +version = "1.1.0"
3202 dependencies = [
3203 "anyhow",
3204 "cc",
@@ -3251,7 +3235,7 @@ dependencies = [
3235 "onde-mistralrs-core",
3236 "onde-mistralrs-macros",
3237 "rand 0.9.4",
3254 - "reqwest 0.13.2",
3238 + "reqwest 0.13.3",
3239 "schemars 1.2.1",
3240 "serde",
3241 "serde_json",
@@ -3339,7 +3323,7 @@ dependencies = [
3323 "rayon",
3324 "regex",
3325 "regex-automata",
3342 - "reqwest 0.13.2",
3326 + "reqwest 0.13.3",
3327 "rubato",
3328 "rust-mcp-schema",
3329 "rustc-hash 2.1.2",
@@ -3394,7 +3378,7 @@ dependencies = [
3378 "async-trait",
3379 "futures-util",
3380 "http",
3397 - "reqwest 0.13.2",
3381 + "reqwest 0.13.3",
3382 "rust-mcp-schema",
3383 "serde",
3384 "serde_json",
@@ -3488,9 +3472,9 @@ dependencies = [
3472
3473 [[package]]
3474 name = "onde-tqdm"
3491 -version = "0.8.1"
3475 +version = "0.8.2"
3476 source = "registry+https://github.com/rust-lang/crates.io-index"
3493 -checksum = "f1e0a37af6d7c66eab140590f939d648c2ce095c36e24e2dfddd94133451f3a2"
3477 +checksum = "2d96f4fcb4af06959bf9c9b81ace0502e2be2d11d7e037c94f3f7851bde720ea"
3478 dependencies = [
3479 "anyhow",
3480 "crossterm",
@@ -3499,9 +3483,9 @@ dependencies = [
3483
3484 [[package]]
3485 name = "onig"
3502 -version = "6.5.2"
3486 +version = "6.5.3"
3487 source = "registry+https://github.com/rust-lang/crates.io-index"
3504 -checksum = "e9f0430136375a315630bfaf61d6bca71a048258b312be75f26f910fb4333e44"
3488 +checksum = "0cc3cbf698f9438986c11a880c90a6d04b9de27575afd28bbf45b154b6c709e2"
3489 dependencies = [
3490 "bitflags 2.11.1",
3491 "libc",
@@ -3511,9 +3495,9 @@ dependencies = [
3495
3496 [[package]]
3497 name = "onig_sys"
3514 -version = "69.9.2"
3498 +version = "69.9.3"
3499 source = "registry+https://github.com/rust-lang/crates.io-index"
3516 -checksum = "725f3ee364ae6d02cfca12ef2be392cfee2733c2a01f0ed386fb74fa94a0fd26"
3500 +checksum = "1e68317604e77e53b85896388e1a803c1d21b74c899ec9e5e1112db90735edd7"
3501 dependencies = [
3502 "cc",
3503 "pkg-config",
@@ -4174,9 +4158,9 @@ dependencies = [
4158
4159 [[package]]
4160 name = "reqwest"
4177 -version = "0.13.2"
4161 +version = "0.13.3"
4162 source = "registry+https://github.com/rust-lang/crates.io-index"
4179 -checksum = "ab3f43e3283ab1488b624b44b0e988d0acea0b3214e694730a055cb6b2efa801"
4163 +checksum = "62e0021ea2c22aed41653bc7e1419abb2c97e038ff2c33d0e1309e49a97deec0"
4164 dependencies = [
4165 "base64 0.22.1",
4166 "bytes",
@@ -4312,9 +4296,9 @@ dependencies = [
4296
4297 [[package]]
4298 name = "rustls"
4315 -version = "0.23.39"
4299 +version = "0.23.40"
4300 source = "registry+https://github.com/rust-lang/crates.io-index"
4317 -checksum = "7c2c118cb077cca2822033836dfb1b975355dfb784b5e8da48f7b6c5db74e60e"
4301 +checksum = "ef86cd5876211988985292b91c96a8f2d298df24e75989a43a3c73f2d4d8168b"
4302 dependencies = [
4303 "aws-lc-rs",
4304 "log",
@@ -4350,9 +4334,9 @@ dependencies = [
4334
4335 [[package]]
4336 name = "rustls-platform-verifier"
4353 -version = "0.6.2"
4337 +version = "0.7.0"
4338 source = "registry+https://github.com/rust-lang/crates.io-index"
4355 -checksum = "1d99feebc72bae7ab76ba994bb5e121b8d83d910ca40b36e0921f53becc41784"
4339 +checksum = "26d1e2536ce4f35f4846aa13bff16bd0ff40157cdb14cc056c7b14ba41233ba0"
4340 dependencies = [
4341 "core-foundation 0.10.1",
4342 "core-foundation-sys",
@@ -4727,11 +4711,12 @@ dependencies = [
4711
4712 [[package]]
4713 name = "serde_with"
4730 -version = "3.18.0"
4714 +version = "3.20.0"
4715 source = "registry+https://github.com/rust-lang/crates.io-index"
4732 -checksum = "dd5414fad8e6907dbdd5bc441a50ae8d6e26151a03b1de04d89a5576de61d01f"
4716 +checksum = "e72c1c2cb7b223fafb600a619537a871c2818583d619401b785e7c0b746ccde2"
4717 dependencies = [
4718 "base64 0.22.1",
4719 + "bs58",
4720 "chrono",
4721 "hex",
4722 "indexmap 1.9.3",
@@ -4746,9 +4731,9 @@ dependencies = [
4731
4732 [[package]]
4733 name = "serde_with_macros"
4749 -version = "3.18.0"
4734 +version = "3.20.0"
4735 source = "registry+https://github.com/rust-lang/crates.io-index"
4751 -checksum = "d3db8978e608f1fe7357e211969fd9abdcae80bac1ba7a3369bb7eb6b404eb65"
4736 +checksum = "b90c488738ecb4fb0262f41f43bc40efc5868d9fb744319ddf5f5317f417bfac"
4737 dependencies = [
4738 "darling 0.23.0",
4739 "proc-macro2",
@@ -4852,11 +4837,27 @@ version = "0.3.9"
4837 source = "registry+https://github.com/rust-lang/crates.io-index"
4838 checksum = "703d5c7ef118737c72f1af64ad2f6f8c5e1921f818cdcb97b8fe6fc69bf66214"
4839
4840 +[[package]]
4841 +name = "simd_cesu8"
4842 +version = "1.1.1"
4843 +source = "registry+https://github.com/rust-lang/crates.io-index"
4844 +checksum = "94f90157bb87cddf702797c5dadfa0be7d266cdf49e22da2fcaa32eff75b2c33"
4845 +dependencies = [
4846 + "rustc_version",
4847 + "simdutf8",
4848 +]
4849 +
4850 +[[package]]
4851 +name = "simdutf8"
4852 +version = "0.1.5"
4853 +source = "registry+https://github.com/rust-lang/crates.io-index"
4854 +checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e"
4855 +
4856 [[package]]
4857 name = "siphasher"
4857 -version = "1.0.2"
4858 +version = "1.0.3"
4859 source = "registry+https://github.com/rust-lang/crates.io-index"
4859 -checksum = "b2aa850e253778c88a04c3d7323b043aeda9d3e30d5971937c1855769763678e"
4860 +checksum = "8ee5873ec9cce0195efcb7a4e9507a04cd49aec9c83d0389df45b1ef7ba2e649"
4861
4862 [[package]]
4863 name = "slab"
@@ -4884,9 +4885,9 @@ checksum = "b7c388c1b5e93756d0c740965c41e8822f866621d41acbdf6336a6a168f8840c"
4885
4886 [[package]]
4887 name = "smbcloud-gresiq-sdk"
4887 -version = "0.3.35"
4888 +version = "0.3.41"
4889 source = "registry+https://github.com/rust-lang/crates.io-index"
4889 -checksum = "260fbaeaef9dcfe865159dd4b0980a94ebdd1cf2a09267e8a966b485d643ce21"
4890 +checksum = "02a8c916737a712020c57191bcab728303a3963f3fd1c03bd3ddeaf67c4c0a64"
4891 dependencies = [
4892 "anyhow",
4893 "log",
@@ -4900,9 +4901,9 @@ dependencies = [
4901
4902 [[package]]
4903 name = "smbcloud-model"
4903 -version = "0.3.35"
4904 +version = "0.3.41"
4905 source = "registry+https://github.com/rust-lang/crates.io-index"
4905 -checksum = "eeba5e1371b12e9573e6eba49ea99ea990ec1b6befe7bfcafaf41b43e1cf331d"
4906 +checksum = "507bf4de78f6ee575960dbe153d7b35f8df1160122616381fe7ccd1b73ea214d"
4907 dependencies = [
4908 "chrono",
4909 "log",
@@ -4918,9 +4919,9 @@ dependencies = [
4919
4920 [[package]]
4921 name = "smbcloud-network"
4921 -version = "0.3.35"
4922 +version = "0.3.41"
4923 source = "registry+https://github.com/rust-lang/crates.io-index"
4923 -checksum = "1c236db19d4cea01cf48b584838fcc898745514c8e01c1c0cad0cba976cabefb"
4924 +checksum = "4a82778900d84fa1792fb0a303cc4d0919c1a76af29c9bd60a052c62ace8e462"
4925 dependencies = [
4926 "clap 4.6.1",
4927 "log",
@@ -5623,9 +5624,9 @@ dependencies = [
5624
5625 [[package]]
5626 name = "tokio"
5626 -version = "1.52.1"
5627 +version = "1.52.3"
5628 source = "registry+https://github.com/rust-lang/crates.io-index"
5628 -checksum = "b67dee974fe86fd92cc45b7a95fdd2f99a36a6d7b0d431a231178d3d670bbcc6"
5629 +checksum = "8fc7f01b389ac15039e4dc9531aa973a135d7a4135281b12d7c1bc79fd57fffe"
5630 dependencies = [
5631 "bytes",
5632 "libc",
@@ -5696,9 +5697,9 @@ dependencies = [
5697
5698 [[package]]
5699 name = "toktrie"
5699 -version = "1.7.4"
5700 +version = "1.7.5"
5701 source = "registry+https://github.com/rust-lang/crates.io-index"
5701 -checksum = "1c75b9915426b9b90377db7925ce2423c7d92541285beca96c40b4a82da828f3"
5702 +checksum = "dd0aad1688badacc3a769d7bb38b0f668ef4887bff73aa2d5344d407d8e2f4cb"
5703 dependencies = [
5704 "anyhow",
5705 "bytemuck",
@@ -5709,9 +5710,9 @@ dependencies = [
5710
5711 [[package]]
5712 name = "toktrie_hf_tokenizers"
5712 -version = "1.7.4"
5713 +version = "1.7.5"
5714 source = "registry+https://github.com/rust-lang/crates.io-index"
5714 -checksum = "c4e3a33fa3eee2f38bba2223d9f2f2b346fd2dc675716433d0fc18ff2fcbcbeb"
5715 +checksum = "19b4defe24ccadaf7745a4d4bb30cff91bbad7b175c4906fe8e3716b3465a536"
5716 dependencies = [
5717 "anyhow",
5718 "log",
@@ -5751,7 +5752,7 @@ version = "1.1.2+spec-1.1.0"
5752 source = "registry+https://github.com/rust-lang/crates.io-index"
5753 checksum = "a2abe9b86193656635d2411dc43050282ca48aa31c2451210f4202550afb7526"
5754 dependencies = [
5754 - "winnow 1.0.2",
5755 + "winnow 1.0.3",
5756 ]
5757
5758 [[package]]
@@ -5777,20 +5778,20 @@ dependencies = [
5778
5779 [[package]]
5780 name = "tower-http"
5780 -version = "0.6.8"
5781 +version = "0.6.10"
5782 source = "registry+https://github.com/rust-lang/crates.io-index"
5782 -checksum = "d4e6559d53cc268e5031cd8429d05415bc4cb4aefc4aa5d6cc35fbf5b924a1f8"
5783 +checksum = "68d6fdd9f81c2819c9a8b0e0cd91660e7746a8e6ea2ba7c6b2b057985f6bcb51"
5784 dependencies = [
5785 "bitflags 2.11.1",
5786 "bytes",
5787 "futures-util",
5788 "http",
5789 "http-body",
5789 - "iri-string",
5790 "pin-project-lite",
5791 "tower",
5792 "tower-layer",
5793 "tower-service",
5794 + "url",
5795 ]
5796
5797 [[package]]
@@ -6226,9 +6227,9 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
6227
6228 [[package]]
6229 name = "utoipa"
6229 -version = "5.4.0"
6230 +version = "5.5.0"
6231 source = "registry+https://github.com/rust-lang/crates.io-index"
6231 -checksum = "2fcc29c80c21c31608227e0912b2d7fddba57ad76b606890627ba8ee7964e993"
6232 +checksum = "8bde15df68e80b16c7d16b9616e80770ad158988daa56a27dccd1e55558b0160"
6233 dependencies = [
6234 "indexmap 2.14.0",
6235 "serde",
@@ -6238,9 +6239,9 @@ dependencies = [
6239
6240 [[package]]
6241 name = "utoipa-gen"
6241 -version = "5.4.0"
6242 +version = "5.5.0"
6243 source = "registry+https://github.com/rust-lang/crates.io-index"
6243 -checksum = "6d79d08d92ab8af4c5e8a6da20c47ae3f61a0f1dabc1997cdf2d082b757ca08b"
6244 +checksum = "6ba0b99ee52df3028635d93840c797102da61f8a7bb3cf751032455895b52ef8"
6245 dependencies = [
6246 "proc-macro2",
6247 "quote",
@@ -6354,9 +6355,9 @@ dependencies = [
6355
6356 [[package]]
6357 name = "wasm-bindgen"
6357 -version = "0.2.118"
6358 +version = "0.2.121"
6359 source = "registry+https://github.com/rust-lang/crates.io-index"
6359 -checksum = "0bf938a0bacb0469e83c1e148908bd7d5a6010354cf4fb73279b7447422e3a89"
6360 +checksum = "49ace1d07c165b0864824eee619580c4689389afa9dc9ed3a4c75040d82e6790"
6361 dependencies = [
6362 "cfg-if",
6363 "once_cell",
@@ -6367,9 +6368,9 @@ dependencies = [
6368
6369 [[package]]
6370 name = "wasm-bindgen-futures"
6370 -version = "0.4.68"
6371 +version = "0.4.71"
6372 source = "registry+https://github.com/rust-lang/crates.io-index"
6372 -checksum = "f371d383f2fb139252e0bfac3b81b265689bf45b6874af544ffa4c975ac1ebf8"
6373 +checksum = "96492d0d3ffba25305a7dc88720d250b1401d7edca02cc3bcd50633b424673b8"
6374 dependencies = [
6375 "js-sys",
6376 "wasm-bindgen",
@@ -6377,9 +6378,9 @@ dependencies = [
6378
6379 [[package]]
6380 name = "wasm-bindgen-macro"
6380 -version = "0.2.118"
6381 +version = "0.2.121"
6382 source = "registry+https://github.com/rust-lang/crates.io-index"
6382 -checksum = "eeff24f84126c0ec2db7a449f0c2ec963c6a49efe0698c4242929da037ca28ed"
6383 +checksum = "8e68e6f4afd367a562002c05637acb8578ff2dea1943df76afb9e83d177c8578"
6384 dependencies = [
6385 "quote",
6386 "wasm-bindgen-macro-support",
@@ -6387,9 +6388,9 @@ dependencies = [
6388
6389 [[package]]
6390 name = "wasm-bindgen-macro-support"
6390 -version = "0.2.118"
6391 +version = "0.2.121"
6392 source = "registry+https://github.com/rust-lang/crates.io-index"
6392 -checksum = "9d08065faf983b2b80a79fd87d8254c409281cf7de75fc4b773019824196c904"
6393 +checksum = "d95a9ec35c64b2a7cb35d3fead40c4238d0940c86d107136999567a4703259f2"
6394 dependencies = [
6395 "bumpalo",
6396 "proc-macro2",
@@ -6400,9 +6401,9 @@ dependencies = [
6401
6402 [[package]]
6403 name = "wasm-bindgen-shared"
6403 -version = "0.2.118"
6404 +version = "0.2.121"
6405 source = "registry+https://github.com/rust-lang/crates.io-index"
6405 -checksum = "5fd04d9e306f1907bd13c6361b5c6bfc7b3b3c095ed3f8a9246390f8dbdee129"
6406 +checksum = "c4e0100b01e9f0d03189a92b96772a1fb998639d981193d7dbab487302513441"
6407 dependencies = [
6408 "unicode-ident",
6409 ]
@@ -6469,9 +6470,9 @@ dependencies = [
6470
6471 [[package]]
6472 name = "web-sys"
6472 -version = "0.3.95"
6473 +version = "0.3.98"
6474 source = "registry+https://github.com/rust-lang/crates.io-index"
6474 -checksum = "4f2dfbb17949fa2088e5d39408c48368947b86f7834484e87b73de55bc14d97d"
6475 +checksum = "4b572dff8bcf38bad0fa19729c89bb5748b2b9b1d8be70cf90df697e3a8f32aa"
6476 dependencies = [
6477 "js-sys",
6478 "wasm-bindgen",
@@ -6747,15 +6748,6 @@ dependencies = [
6748 "windows-link 0.2.1",
6749 ]
6750
6750 -[[package]]
6751 -name = "windows-sys"
6752 -version = "0.45.0"
6753 -source = "registry+https://github.com/rust-lang/crates.io-index"
6754 -checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0"
6755 -dependencies = [
6756 - "windows-targets 0.42.2",
6757 -]
6758 -
6751 [[package]]
6752 name = "windows-sys"
6753 version = "0.52.0"
@@ -6792,21 +6784,6 @@ dependencies = [
6784 "windows-link 0.2.1",
6785 ]
6786
6795 -[[package]]
6796 -name = "windows-targets"
6797 -version = "0.42.2"
6798 -source = "registry+https://github.com/rust-lang/crates.io-index"
6799 -checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071"
6800 -dependencies = [
6801 - "windows_aarch64_gnullvm 0.42.2",
6802 - "windows_aarch64_msvc 0.42.2",
6803 - "windows_i686_gnu 0.42.2",
6804 - "windows_i686_msvc 0.42.2",
6805 - "windows_x86_64_gnu 0.42.2",
6806 - "windows_x86_64_gnullvm 0.42.2",
6807 - "windows_x86_64_msvc 0.42.2",
6808 -]
6809 -
6787 [[package]]
6788 name = "windows-targets"
6789 version = "0.48.5"
@@ -6864,12 +6841,6 @@ dependencies = [
6841 "windows-link 0.1.3",
6842 ]
6843
6867 -[[package]]
6868 -name = "windows_aarch64_gnullvm"
6869 -version = "0.42.2"
6870 -source = "registry+https://github.com/rust-lang/crates.io-index"
6871 -checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8"
6872 -
6844 [[package]]
6845 name = "windows_aarch64_gnullvm"
6846 version = "0.48.5"
@@ -6888,12 +6859,6 @@ version = "0.53.1"
6859 source = "registry+https://github.com/rust-lang/crates.io-index"
6860 checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53"
6861
6891 -[[package]]
6892 -name = "windows_aarch64_msvc"
6893 -version = "0.42.2"
6894 -source = "registry+https://github.com/rust-lang/crates.io-index"
6895 -checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43"
6896 -
6862 [[package]]
6863 name = "windows_aarch64_msvc"
6864 version = "0.48.5"
@@ -6912,12 +6877,6 @@ version = "0.53.1"
6877 source = "registry+https://github.com/rust-lang/crates.io-index"
6878 checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006"
6879
6915 -[[package]]
6916 -name = "windows_i686_gnu"
6917 -version = "0.42.2"
6918 -source = "registry+https://github.com/rust-lang/crates.io-index"
6919 -checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f"
6920 -
6880 [[package]]
6881 name = "windows_i686_gnu"
6882 version = "0.48.5"
@@ -6948,12 +6907,6 @@ version = "0.53.1"
6907 source = "registry+https://github.com/rust-lang/crates.io-index"
6908 checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c"
6909
6951 -[[package]]
6952 -name = "windows_i686_msvc"
6953 -version = "0.42.2"
6954 -source = "registry+https://github.com/rust-lang/crates.io-index"
6955 -checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060"
6956 -
6910 [[package]]
6911 name = "windows_i686_msvc"
6912 version = "0.48.5"
@@ -6972,12 +6925,6 @@ version = "0.53.1"
6925 source = "registry+https://github.com/rust-lang/crates.io-index"
6926 checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2"
6927
6975 -[[package]]
6976 -name = "windows_x86_64_gnu"
6977 -version = "0.42.2"
6978 -source = "registry+https://github.com/rust-lang/crates.io-index"
6979 -checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36"
6980 -
6928 [[package]]
6929 name = "windows_x86_64_gnu"
6930 version = "0.48.5"
@@ -6996,12 +6943,6 @@ version = "0.53.1"
6943 source = "registry+https://github.com/rust-lang/crates.io-index"
6944 checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499"
6945
6999 -[[package]]
7000 -name = "windows_x86_64_gnullvm"
7001 -version = "0.42.2"
7002 -source = "registry+https://github.com/rust-lang/crates.io-index"
7003 -checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3"
7004 -
6946 [[package]]
6947 name = "windows_x86_64_gnullvm"
6948 version = "0.48.5"
@@ -7020,12 +6961,6 @@ version = "0.53.1"
6961 source = "registry+https://github.com/rust-lang/crates.io-index"
6962 checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1"
6963
7023 -[[package]]
7024 -name = "windows_x86_64_msvc"
7025 -version = "0.42.2"
7026 -source = "registry+https://github.com/rust-lang/crates.io-index"
7027 -checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0"
7028 -
6964 [[package]]
6965 name = "windows_x86_64_msvc"
6966 version = "0.48.5"
@@ -7055,9 +6990,9 @@ dependencies = [
6990
6991 [[package]]
6992 name = "winnow"
7058 -version = "1.0.2"
6993 +version = "1.0.3"
6994 source = "registry+https://github.com/rust-lang/crates.io-index"
7060 -checksum = "2ee1708bef14716a11bae175f579062d4554d95be2c6829f518df847b7b3fdd0"
6995 +checksum = "0592e1c9d151f854e6fd382574c3a0855250e1d9b2f99d9281c6e6391af352f1"
6996
6997 [[package]]
6998 name = "wit-bindgen"
@@ -7228,9 +7163,9 @@ dependencies = [
7163
7164 [[package]]
7165 name = "zerofrom"
7231 -version = "0.1.7"
7166 +version = "0.1.8"
7167 source = "registry+https://github.com/rust-lang/crates.io-index"
7233 -checksum = "69faa1f2a1ea75661980b013019ed6687ed0e83d069bc1114e2cc74c6c04c4df"
7168 +checksum = "0ec05a11813ea801ff6d75110ad09cd0824ddba17dfe17128ea0d5f68e6c5272"
7169 dependencies = [
7170 "zerofrom-derive",
7171 ]
Cargo.toml
+1 -1
@@ -1,6 +1,6 @@
1 [package]
2 name = "onde"
3 -version = "1.0.0"
3 +version = "1.1.0"
4 edition = "2021"
5 description = "On-device inference engine for Apple silicon."
6 license = "MIT OR Apache-2.0"
sdk/dart/CHANGELOG.md
+6
@@ -1,3 +1,9 @@
1 +## 1.1.0
2 +
3 +* **Swift / UniFFI stability:** Pulls in the Onde Rust core `1.1.0` runtime fixes for Swift/Kotlin/Apple-hosted SDKs, including Tokio runtime annotations and panic-safe pulse telemetry initialization.
4 +* **Telemetry:** Pulse telemetry now gracefully disables itself if a Tokio reactor is unavailable and can be explicitly disabled with `ONDE_DISABLE_PULSE=1` during local validation.
5 +* **Release alignment:** Aligns the Flutter/Dart package version with the Rust, Swift, Kotlin, and React Native SDKs.
6 +
7 ## 1.0.2
8
9 * **pub.dev:** Added Apple plugin Swift Package Manager manifests at `ios/onde_inference/Package.swift` and `macos/onde_inference/Package.swift` so pub.dev recognizes modern iOS and macOS plugin toolchain support.
sdk/dart/example/pubspec.yaml
+1 -1
@@ -1,7 +1,7 @@
1 name: onde_inference_example
2 description: Example Flutter app demonstrating the onde_inference SDK.
3 publish_to: "none"
4 -version: 1.0.2+1
4 +version: 1.1.0+1
5
6 environment:
7 sdk: ">=3.3.0 <4.0.0"
sdk/dart/pubspec.yaml
+1 -1
@@ -2,7 +2,7 @@ name: onde_inference
2 description: >-
3 On-device LLM inference for Flutter & Dart. Run Qwen 2.5 models locally
4 with Metal on iOS and macOS, CPU on Android and desktop. No cloud, no API key.
5 -version: 1.0.2
5 +version: 1.1.0
6 repository: https://github.com/ondeinference/onde
7 homepage: https://ondeinference.com
8 documentation: https://ondeinference.com/sdk/dart
sdk/dart/rust/Cargo.lock
+2 -2
@@ -3399,7 +3399,7 @@ checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe"
3399
3400 [[package]]
3401 name = "onde"
3402 -version = "1.0.0"
3402 +version = "1.1.0"
3403 dependencies = [
3404 "anyhow",
3405 "cc",
@@ -3684,7 +3684,7 @@ dependencies = [
3684
3685 [[package]]
3686 name = "onde_inference_dart"
3687 -version = "0.1.0"
3687 +version = "1.1.0"
3688 dependencies = [
3689 "flutter_rust_bridge",
3690 "log",
sdk/dart/rust/Cargo.toml
+1 -1
@@ -1,6 +1,6 @@
1 [package]
2 name = "onde_inference_dart"
3 -version = "1.0.2"
3 +version = "1.1.0"
4 edition = "2021"
5 publish = false
6
sdk/kotlin/.gitignore
-3
@@ -19,9 +19,6 @@ captures/
19 # macOS
20 .DS_Store
21
22 -# Gradle wrapper binary — too large and platform-specific
23 -gradle/wrapper/gradle-wrapper.jar
24 -
22 # Signing keys — never commit private keys
23 *.jks
24 *.keystore
sdk/kotlin/gradle.properties
+1 -1
@@ -10,7 +10,7 @@ kotlin.code.style=official
10 # Maven publishing coordinates — keep in sync with Cargo.toml [package] version
11 GROUP=com.ondeinference
12 POM_ARTIFACT_ID=onde-inference
13 -VERSION_NAME=1.0.0
13 +VERSION_NAME=1.1.0
14
15
16
sdk/kotlin/gradle/wrapper/gradle-wrapper.jar
Binary files /dev/null and b/sdk/kotlin/gradle/wrapper/gradle-wrapper.jar differ
sdk/react-native/package-lock.json
+2 -2
@@ -1,12 +1,12 @@
1 {
2 "name": "@ondeinference/react-native",
3 - "version": "0.1.3",
3 + "version": "1.1.0",
4 "lockfileVersion": 3,
5 "requires": true,
6 "packages": {
7 "": {
8 "name": "@ondeinference/react-native",
9 - "version": "0.1.3",
9 + "version": "1.1.0",
10 "license": "MIT OR Apache-2.0",
11 "devDependencies": {
12 "expo-modules-core": "^2.0.0",
sdk/react-native/package.json
+1 -1
@@ -1,6 +1,6 @@
1 {
2 "name": "@ondeinference/react-native",
3 - "version": "1.0.0",
3 + "version": "1.1.0",
4 "description": "On-device LLM inference for React Native. Run Qwen 2.5 models locally with Metal on iOS, CPU on Android. No cloud, no API key.",
5 "main": "build/index.js",
6 "types": "build/index.d.ts",
sdk/react-native/rust/Cargo.lock
+2 -2
@@ -3215,7 +3215,7 @@ checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe"
3215
3216 [[package]]
3217 name = "onde"
3218 -version = "1.0.0"
3218 +version = "1.1.0"
3219 dependencies = [
3220 "anyhow",
3221 "cc",
@@ -3489,7 +3489,7 @@ dependencies = [
3489
3490 [[package]]
3491 name = "onde-react-native"
3492 -version = "0.1.7"
3492 +version = "1.1.0"
3493 dependencies = [
3494 "jni",
3495 "log",
sdk/react-native/rust/Cargo.toml
+1 -1
@@ -1,6 +1,6 @@
1 [package]
2 name = "onde-react-native"
3 -version = "0.1.7"
3 +version = "1.1.0"
4 edition = "2021"
5 publish = false
6
src/inference/engine.rs
+4
@@ -260,6 +260,7 @@ impl ChatEngine {
260
261 /// Create a new engine with no model loaded.
262 pub fn new() -> Self {
263 + crate::install_panic_hook_once();
264 Self {
265 inner: Mutex::new(None),
266 pulse: std::sync::OnceLock::new(),
@@ -284,6 +285,9 @@ impl ChatEngine {
285 Some(_) => log::info!(
286 "ChatEngine: pulse telemetry enabled (environment={environment})"
287 ),
288 + None if crate::pulse::PulseClient::disabled_by_env() => {
289 + log::info!("ChatEngine: pulse telemetry disabled by ONDE_DISABLE_PULSE")
290 + }
291 None => log::info!(
292 "ChatEngine: pulse telemetry disabled \
293 (GRESIQ_API_KEY / GRESIQ_API_SECRET not embedded at SDK build time)"
src/lib.rs
+23
@@ -47,6 +47,29 @@ pub mod hf_cache;
47 pub mod inference;
48 pub mod pulse;
49
50 +static PANIC_HOOK_ONCE: std::sync::Once = std::sync::Once::new();
51 +
52 +pub(crate) fn install_panic_hook_once() {
53 + PANIC_HOOK_ONCE.call_once(|| {
54 + std::panic::set_hook(Box::new(|panic_info| {
55 + let location = panic_info
56 + .location()
57 + .map(|loc| format!("{}:{}:{}", loc.file(), loc.line(), loc.column()))
58 + .unwrap_or_else(|| "<unknown>".to_string());
59 +
60 + let message = if let Some(msg) = panic_info.payload().downcast_ref::<&str>() {
61 + (*msg).to_string()
62 + } else if let Some(msg) = panic_info.payload().downcast_ref::<String>() {
63 + msg.clone()
64 + } else {
65 + "<non-string panic payload>".to_string()
66 + };
67 +
68 + log::error!("Rust panic at {}: {}", location, message);
69 + }));
70 + });
71 +}
72 +
73 uniffi::setup_scaffolding!();
74
75 // Re-export mistralrs for every platform that onde supports.
src/pulse/client.rs
+108 -9
@@ -26,6 +26,19 @@ pub struct PulseClient {
26 }
27
28 impl PulseClient {
29 + /// Returns true when pulse telemetry is disabled explicitly by the host app.
30 + pub fn disabled_by_env() -> bool {
31 + matches!(
32 + std::env::var("ONDE_DISABLE_PULSE")
33 + .ok()
34 + .as_deref()
35 + .map(str::trim)
36 + .map(str::to_ascii_lowercase)
37 + .as_deref(),
38 + Some("1") | Some("true") | Some("yes") | Some("on")
39 + )
40 + }
41 +
42 /// Build a pulse client using the GresIQ credentials embedded in the SDK.
43 ///
44 /// Returns `None` if the SDK was compiled without `GRESIQ_API_KEY` /
@@ -35,6 +48,10 @@ impl PulseClient {
48 /// `edge_id` is a stable device identifier (installation UUID).
49 /// Pass an empty string to default to `"onde-unknown"`.
50 pub fn new(environment: Environment, edge_id: String) -> Option<Self> {
51 + if Self::disabled_by_env() {
52 + return None;
53 + }
54 +
55 let (api_key, api_secret) = match environment {
56 Environment::Dev => (EMBEDDED_API_KEY_DEV?, EMBEDDED_API_SECRET_DEV?),
57 Environment::Production => (
@@ -49,12 +66,35 @@ impl PulseClient {
66 edge_id
67 };
68
69 + // reqwest 0.12.x requires a live Tokio runtime (with I/O reactor)
70 + // to construct a Client. GresiqClient::from_credentials calls
71 + // reqwest::Client::new() internally. Guard against panics when
72 + // called from a thread/context that lacks a Tokio reactor.
73 + if tokio::runtime::Handle::try_current().is_err() {
74 + log::warn!(
75 + "pulse: no Tokio runtime available — \
76 + deferring PulseClient creation"
77 + );
78 + return None;
79 + }
80 +
81 let credentials = GresiqCredentials {
82 api_key,
83 api_secret,
84 };
85
57 - let inner = GresiqClient::from_credentials(environment, credentials);
86 + let inner = match std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
87 + GresiqClient::from_credentials(environment, credentials)
88 + })) {
89 + Ok(client) => client,
90 + Err(_) => {
91 + log::warn!(
92 + "pulse: GresiqClient::from_credentials panicked \
93 + (likely missing Tokio reactor) — telemetry disabled"
94 + );
95 + return None;
96 + }
97 + };
98
99 Some(PulseClient { inner, edge_id })
100 }
@@ -77,19 +117,55 @@ impl PulseClient {
117 model_name: String,
118 load_duration_ms: u64,
119 ) {
80 - let event = ModelLoadedEvent {
81 - edge_id: self.edge_id.clone(),
82 - model_id,
83 - model_name,
84 - load_duration_ms,
120 + let client = self.clone();
121 + let send_event = async move {
122 + let event = ModelLoadedEvent {
123 + edge_id: client.edge_id.clone(),
124 + model_id,
125 + model_name,
126 + load_duration_ms,
127 + };
128 + if let Err(error) = client.inner.insert("pulse/model_loaded", &event).await {
129 + log::warn!("pulse: model_loaded failed: {}", error);
130 + }
131 };
86 - if let Err(error) = self.inner.insert("pulse/model_loaded", &event).await {
87 - log::warn!("pulse: model_loaded failed: {}", error);
132 +
133 + if tokio::runtime::Handle::try_current().is_ok() {
134 + send_event.await;
135 + return;
136 + }
137 +
138 + let join = std::thread::spawn(move || {
139 + let runtime = tokio::runtime::Builder::new_current_thread()
140 + .enable_all()
141 + .build();
142 +
143 + match runtime {
144 + Ok(runtime) => {
145 + runtime.block_on(send_event);
146 + }
147 + Err(error) => {
148 + log::warn!(
149 + "pulse: could not create fallback runtime for model_loaded: {}",
150 + error
151 + );
152 + }
153 + }
154 + });
155 +
156 + if join.join().is_err() {
157 + log::warn!("pulse: fallback model_loaded thread panicked");
158 }
159 }
160
161 /// Same fire-and-forget pattern as record_model_loaded but for inference
162 /// completions. Writes to pulse/inference_event. Logs on failure, no retry.
163 + ///
164 + /// Swift / UniFFI consumers may call into the SDK from contexts where
165 + /// `tokio::spawn` does not have a current runtime handle even though the
166 + /// outer API is async. To avoid panicking on Apple platforms, we prefer
167 + /// the current Tokio runtime when available and otherwise fall back to a
168 + /// short-lived current-thread runtime on a native background thread.
169 pub fn record_inference(
170 &self,
171 model_id: String,
@@ -98,7 +174,7 @@ impl PulseClient {
174 status: String,
175 ) {
176 let client = self.clone();
101 - tokio::spawn(async move {
177 + let send_event = async move {
178 let event = InferenceEvent {
179 edge_id: client.edge_id.clone(),
180 model_id,
@@ -109,6 +185,29 @@ impl PulseClient {
185 if let Err(error) = client.inner.insert("pulse/inference_event", &event).await {
186 log::warn!("pulse: inference_event failed: {}", error);
187 }
188 + };
189 +
190 + if let Ok(handle) = tokio::runtime::Handle::try_current() {
191 + handle.spawn(send_event);
192 + return;
193 + }
194 +
195 + std::thread::spawn(move || {
196 + let runtime = tokio::runtime::Builder::new_current_thread()
197 + .enable_all()
198 + .build();
199 +
200 + match runtime {
201 + Ok(runtime) => {
202 + runtime.block_on(send_event);
203 + }
204 + Err(error) => {
205 + log::warn!(
206 + "pulse: could not create fallback runtime for inference_event: {}",
207 + error
208 + );
209 + }
210 + }
211 });
212 }
213 }