Initial commit
Seto Elkahfi committed
Apr 3, 2026 at 08:52 UTC
0ae8bebe6a6de8c0065ec2a0440ccbea416d1d29
3 files changed
+2624
.gitignore
new
+8
@@ -0,0 +1,8 @@
1
+.DS_Store
2
+.local/
3
+.build/
4
+.swiftpm/
5
+OndeFramework.xcframework/
6
+OndeFramework.xcframework.zip
7
+
8
+.zed
Package.swift
new
+26
@@ -0,0 +1,26 @@
1
+// swift-tools-version:5.5
2
+import Foundation
3
+import PackageDescription
4
+
5
+let package = Package(
6
+ name: "Onde",
7
+ platforms: [
8
+ .iOS(.v15),
9
+ .macOS(.v11),
10
+ .tvOS(.v15),
11
+ ],
12
+ products: [
13
+ .library(name: "Onde", targets: ["Onde"])
14
+ ],
15
+ targets: [
16
+ .binaryTarget(
17
+ name: "OndeFramework",
18
+ path: "./../onde/sdk/Onde/OndeFramework.xcframework",
19
+ ),
20
+ .target(
21
+ name: "Onde",
22
+ dependencies: [.target(name: "OndeFramework")],
23
+ path: "Sources/Onde"
24
+ ),
25
+ ]
26
+)
Sources/Onde/onde.swift
new
+2590
@@ -0,0 +1,2590 @@
1
+// This file was autogenerated by some hot garbage in the `uniffi` crate.
2
+// Trust me, you don't want to mess with it!
3
+
4
+// swiftlint:disable all
5
+import Foundation
6
+
7
+// Depending on the consumer's build setup, the low-level FFI code
8
+// might be in a separate module, or it might be compiled inline into
9
+// this module. This is a bit of light hackery to work with both.
10
+#if canImport(ondeFFI)
11
+ import ondeFFI
12
+#endif
13
+
14
+extension RustBuffer {
15
+ // Allocate a new buffer, copying the contents of a `UInt8` array.
16
+ fileprivate init(bytes: [UInt8]) {
17
+ let rbuf = bytes.withUnsafeBufferPointer { ptr in
18
+ RustBuffer.from(ptr)
19
+ }
20
+ self.init(capacity: rbuf.capacity, len: rbuf.len, data: rbuf.data)
21
+ }
22
+
23
+ fileprivate static func empty() -> RustBuffer {
24
+ RustBuffer(capacity: 0, len: 0, data: nil)
25
+ }
26
+
27
+ fileprivate static func from(_ ptr: UnsafeBufferPointer<UInt8>) -> RustBuffer {
28
+ try! rustCall { ffi_onde_rustbuffer_from_bytes(ForeignBytes(bufferPointer: ptr), $0) }
29
+ }
30
+
31
+ // Frees the buffer in place.
32
+ // The buffer must not be used after this is called.
33
+ fileprivate func deallocate() {
34
+ try! rustCall { ffi_onde_rustbuffer_free(self, $0) }
35
+ }
36
+}
37
+
38
+extension ForeignBytes {
39
+ fileprivate init(bufferPointer: UnsafeBufferPointer<UInt8>) {
40
+ self.init(len: Int32(bufferPointer.count), data: bufferPointer.baseAddress)
41
+ }
42
+}
43
+
44
+// For every type used in the interface, we provide helper methods for conveniently
45
+// lifting and lowering that type from C-compatible data, and for reading and writing
46
+// values of that type in a buffer.
47
+
48
+// Helper classes/extensions that don't change.
49
+// Someday, this will be in a library of its own.
50
+
51
+extension Data {
52
+ fileprivate init(rustBuffer: RustBuffer) {
53
+ self.init(
54
+ bytesNoCopy: rustBuffer.data!,
55
+ count: Int(rustBuffer.len),
56
+ deallocator: .none
57
+ )
58
+ }
59
+}
60
+
61
+// Define reader functionality. Normally this would be defined in a class or
62
+// struct, but we use standalone functions instead in order to make external
63
+// types work.
64
+//
65
+// With external types, one swift source file needs to be able to call the read
66
+// method on another source file's FfiConverter, but then what visibility
67
+// should Reader have?
68
+// - If Reader is fileprivate, then this means the read() must also
69
+// be fileprivate, which doesn't work with external types.
70
+// - If Reader is internal/public, we'll get compile errors since both source
71
+// files will try define the same type.
72
+//
73
+// Instead, the read() method and these helper functions input a tuple of data
74
+
75
+private func createReader(data: Data) -> (data: Data, offset: Data.Index) {
76
+ (data: data, offset: 0)
77
+}
78
+
79
+// Reads an integer at the current offset, in big-endian order, and advances
80
+// the offset on success. Throws if reading the integer would move the
81
+// offset past the end of the buffer.
82
+private func readInt<T: FixedWidthInteger>(_ reader: inout (data: Data, offset: Data.Index)) throws
83
+ -> T
84
+{
85
+ let range = reader.offset..<reader.offset + MemoryLayout<T>.size
86
+ guard reader.data.count >= range.upperBound else {
87
+ throw UniffiInternalError.bufferOverflow
88
+ }
89
+ if T.self == UInt8.self {
90
+ let value = reader.data[reader.offset]
91
+ reader.offset += 1
92
+ return value as! T
93
+ }
94
+ var value: T = 0
95
+ let _ = withUnsafeMutableBytes(of: &value, { reader.data.copyBytes(to: $0, from: range) })
96
+ reader.offset = range.upperBound
97
+ return value.bigEndian
98
+}
99
+
100
+// Reads an arbitrary number of bytes, to be used to read
101
+// raw bytes, this is useful when lifting strings
102
+private func readBytes(_ reader: inout (data: Data, offset: Data.Index), count: Int) throws
103
+ -> [UInt8]
104
+{
105
+ let range = reader.offset..<(reader.offset + count)
106
+ guard reader.data.count >= range.upperBound else {
107
+ throw UniffiInternalError.bufferOverflow
108
+ }
109
+ var value = [UInt8](repeating: 0, count: count)
110
+ value.withUnsafeMutableBufferPointer({ buffer in
111
+ reader.data.copyBytes(to: buffer, from: range)
112
+ })
113
+ reader.offset = range.upperBound
114
+ return value
115
+}
116
+
117
+// Reads a float at the current offset.
118
+private func readFloat(_ reader: inout (data: Data, offset: Data.Index)) throws -> Float {
119
+ return Float(bitPattern: try readInt(&reader))
120
+}
121
+
122
+// Reads a float at the current offset.
123
+private func readDouble(_ reader: inout (data: Data, offset: Data.Index)) throws -> Double {
124
+ return Double(bitPattern: try readInt(&reader))
125
+}
126
+
127
+// Indicates if the offset has reached the end of the buffer.
128
+private func hasRemaining(_ reader: (data: Data, offset: Data.Index)) -> Bool {
129
+ return reader.offset < reader.data.count
130
+}
131
+
132
+// Define writer functionality. Normally this would be defined in a class or
133
+// struct, but we use standalone functions instead in order to make external
134
+// types work. See the above discussion on Readers for details.
135
+
136
+private func createWriter() -> [UInt8] {
137
+ return []
138
+}
139
+
140
+private func writeBytes<S>(_ writer: inout [UInt8], _ byteArr: S)
141
+where S: Sequence, S.Element == UInt8 {
142
+ writer.append(contentsOf: byteArr)
143
+}
144
+
145
+// Writes an integer in big-endian order.
146
+//
147
+// Warning: make sure what you are trying to write
148
+// is in the correct type!
149
+private func writeInt<T: FixedWidthInteger>(_ writer: inout [UInt8], _ value: T) {
150
+ var value = value.bigEndian
151
+ withUnsafeBytes(of: &value) { writer.append(contentsOf: $0) }
152
+}
153
+
154
+private func writeFloat(_ writer: inout [UInt8], _ value: Float) {
155
+ writeInt(&writer, value.bitPattern)
156
+}
157
+
158
+private func writeDouble(_ writer: inout [UInt8], _ value: Double) {
159
+ writeInt(&writer, value.bitPattern)
160
+}
161
+
162
+// Protocol for types that transfer other types across the FFI. This is
163
+// analogous to the Rust trait of the same name.
164
+private protocol FfiConverter {
165
+ associatedtype FfiType
166
+ associatedtype SwiftType
167
+
168
+ static func lift(_ value: FfiType) throws -> SwiftType
169
+ static func lower(_ value: SwiftType) -> FfiType
170
+ static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> SwiftType
171
+ static func write(_ value: SwiftType, into buf: inout [UInt8])
172
+}
173
+
174
+// Types conforming to `Primitive` pass themselves directly over the FFI.
175
+private protocol FfiConverterPrimitive: FfiConverter where FfiType == SwiftType {}
176
+
177
+extension FfiConverterPrimitive {
178
+ #if swift(>=5.8)
179
+ @_documentation(visibility: private)
180
+ #endif
181
+ public static func lift(_ value: FfiType) throws -> SwiftType {
182
+ return value
183
+ }
184
+
185
+ #if swift(>=5.8)
186
+ @_documentation(visibility: private)
187
+ #endif
188
+ public static func lower(_ value: SwiftType) -> FfiType {
189
+ return value
190
+ }
191
+}
192
+
193
+// Types conforming to `FfiConverterRustBuffer` lift and lower into a `RustBuffer`.
194
+// Used for complex types where it's hard to write a custom lift/lower.
195
+private protocol FfiConverterRustBuffer: FfiConverter where FfiType == RustBuffer {}
196
+
197
+extension FfiConverterRustBuffer {
198
+ #if swift(>=5.8)
199
+ @_documentation(visibility: private)
200
+ #endif
201
+ public static func lift(_ buf: RustBuffer) throws -> SwiftType {
202
+ var reader = createReader(data: Data(rustBuffer: buf))
203
+ let value = try read(from: &reader)
204
+ if hasRemaining(reader) {
205
+ throw UniffiInternalError.incompleteData
206
+ }
207
+ buf.deallocate()
208
+ return value
209
+ }
210
+
211
+ #if swift(>=5.8)
212
+ @_documentation(visibility: private)
213
+ #endif
214
+ public static func lower(_ value: SwiftType) -> RustBuffer {
215
+ var writer = createWriter()
216
+ write(value, into: &writer)
217
+ return RustBuffer(bytes: writer)
218
+ }
219
+}
220
+// An error type for FFI errors. These errors occur at the UniFFI level, not
221
+// the library level.
222
+private enum UniffiInternalError: LocalizedError {
223
+ case bufferOverflow
224
+ case incompleteData
225
+ case unexpectedOptionalTag
226
+ case unexpectedEnumCase
227
+ case unexpectedNullPointer
228
+ case unexpectedRustCallStatusCode
229
+ case unexpectedRustCallError
230
+ case unexpectedStaleHandle
231
+ case rustPanic(_ message: String)
232
+
233
+ public var errorDescription: String? {
234
+ switch self {
235
+ case .bufferOverflow:
236
+ return "Reading the requested value would read past the end of the buffer"
237
+ case .incompleteData: return "The buffer still has data after lifting its containing value"
238
+ case .unexpectedOptionalTag: return "Unexpected optional tag; should be 0 or 1"
239
+ case .unexpectedEnumCase: return "Raw enum value doesn't match any cases"
240
+ case .unexpectedNullPointer: return "Raw pointer value was null"
241
+ case .unexpectedRustCallStatusCode: return "Unexpected RustCallStatus code"
242
+ case .unexpectedRustCallError: return "CALL_ERROR but no errorClass specified"
243
+ case .unexpectedStaleHandle: return "The object in the handle map has been dropped already"
244
+ case .rustPanic(let message): return message
245
+ }
246
+ }
247
+}
248
+
249
+extension NSLock {
250
+ fileprivate func withLock<T>(f: () throws -> T) rethrows -> T {
251
+ self.lock()
252
+ defer { self.unlock() }
253
+ return try f()
254
+ }
255
+}
256
+
257
+private let CALL_SUCCESS: Int8 = 0
258
+private let CALL_ERROR: Int8 = 1
259
+private let CALL_UNEXPECTED_ERROR: Int8 = 2
260
+private let CALL_CANCELLED: Int8 = 3
261
+
262
+extension RustCallStatus {
263
+ fileprivate init() {
264
+ self.init(
265
+ code: CALL_SUCCESS,
266
+ errorBuf: RustBuffer.init(
267
+ capacity: 0,
268
+ len: 0,
269
+ data: nil
270
+ )
271
+ )
272
+ }
273
+}
274
+
275
+private func rustCall<T>(_ callback: (UnsafeMutablePointer<RustCallStatus>) -> T) throws -> T {
276
+ let neverThrow: ((RustBuffer) throws -> Never)? = nil
277
+ return try makeRustCall(callback, errorHandler: neverThrow)
278
+}
279
+
280
+private func rustCallWithError<T, E: Swift.Error>(
281
+ _ errorHandler: @escaping (RustBuffer) throws -> E,
282
+ _ callback: (UnsafeMutablePointer<RustCallStatus>) -> T
283
+) throws -> T {
284
+ try makeRustCall(callback, errorHandler: errorHandler)
285
+}
286
+
287
+private func makeRustCall<T, E: Swift.Error>(
288
+ _ callback: (UnsafeMutablePointer<RustCallStatus>) -> T,
289
+ errorHandler: ((RustBuffer) throws -> E)?
290
+) throws -> T {
291
+ uniffiEnsureOndeInitialized()
292
+ var callStatus = RustCallStatus.init()
293
+ let returnedVal = callback(&callStatus)
294
+ try uniffiCheckCallStatus(callStatus: callStatus, errorHandler: errorHandler)
295
+ return returnedVal
296
+}
297
+
298
+private func uniffiCheckCallStatus<E: Swift.Error>(
299
+ callStatus: RustCallStatus,
300
+ errorHandler: ((RustBuffer) throws -> E)?
301
+) throws {
302
+ switch callStatus.code {
303
+ case CALL_SUCCESS:
304
+ return
305
+
306
+ case CALL_ERROR:
307
+ if let errorHandler = errorHandler {
308
+ throw try errorHandler(callStatus.errorBuf)
309
+ } else {
310
+ callStatus.errorBuf.deallocate()
311
+ throw UniffiInternalError.unexpectedRustCallError
312
+ }
313
+
314
+ case CALL_UNEXPECTED_ERROR:
315
+ // When the rust code sees a panic, it tries to construct a RustBuffer
316
+ // with the message. But if that code panics, then it just sends back
317
+ // an empty buffer.
318
+ if callStatus.errorBuf.len > 0 {
319
+ throw UniffiInternalError.rustPanic(try FfiConverterString.lift(callStatus.errorBuf))
320
+ } else {
321
+ callStatus.errorBuf.deallocate()
322
+ throw UniffiInternalError.rustPanic("Rust panic")
323
+ }
324
+
325
+ case CALL_CANCELLED:
326
+ fatalError("Cancellation not supported yet")
327
+
328
+ default:
329
+ throw UniffiInternalError.unexpectedRustCallStatusCode
330
+ }
331
+}
332
+
333
+private func uniffiTraitInterfaceCall<T>(
334
+ callStatus: UnsafeMutablePointer<RustCallStatus>,
335
+ makeCall: () throws -> T,
336
+ writeReturn: (T) -> Void
337
+) {
338
+ do {
339
+ try writeReturn(makeCall())
340
+ } catch let error {
341
+ callStatus.pointee.code = CALL_UNEXPECTED_ERROR
342
+ callStatus.pointee.errorBuf = FfiConverterString.lower(String(describing: error))
343
+ }
344
+}
345
+
346
+private func uniffiTraitInterfaceCallWithError<T, E>(
347
+ callStatus: UnsafeMutablePointer<RustCallStatus>,
348
+ makeCall: () throws -> T,
349
+ writeReturn: (T) -> Void,
350
+ lowerError: (E) -> RustBuffer
351
+) {
352
+ do {
353
+ try writeReturn(makeCall())
354
+ } catch let error as E {
355
+ callStatus.pointee.code = CALL_ERROR
356
+ callStatus.pointee.errorBuf = lowerError(error)
357
+ } catch {
358
+ callStatus.pointee.code = CALL_UNEXPECTED_ERROR
359
+ callStatus.pointee.errorBuf = FfiConverterString.lower(String(describing: error))
360
+ }
361
+}
362
+// Initial value and increment amount for handles.
363
+// These ensure that SWIFT handles always have the lowest bit set
364
+private let UNIFFI_HANDLEMAP_INITIAL: UInt64 = 1
365
+private let UNIFFI_HANDLEMAP_DELTA: UInt64 = 2
366
+
367
+private final class UniffiHandleMap<T>: @unchecked Sendable {
368
+ // All mutation happens with this lock held, which is why we implement @unchecked Sendable.
369
+ private let lock = NSLock()
370
+ private var map: [UInt64: T] = [:]
371
+ private var currentHandle: UInt64 = UNIFFI_HANDLEMAP_INITIAL
372
+
373
+ func insert(obj: T) -> UInt64 {
374
+ lock.withLock {
375
+ return doInsert(obj)
376
+ }
377
+ }
378
+
379
+ // Low-level insert function, this assumes `lock` is held.
380
+ private func doInsert(_ obj: T) -> UInt64 {
381
+ let handle = currentHandle
382
+ currentHandle += UNIFFI_HANDLEMAP_DELTA
383
+ map[handle] = obj
384
+ return handle
385
+ }
386
+
387
+ func get(handle: UInt64) throws -> T {
388
+ try lock.withLock {
389
+ guard let obj = map[handle] else {
390
+ throw UniffiInternalError.unexpectedStaleHandle
391
+ }
392
+ return obj
393
+ }
394
+ }
395
+
396
+ func clone(handle: UInt64) throws -> UInt64 {
397
+ try lock.withLock {
398
+ guard let obj = map[handle] else {
399
+ throw UniffiInternalError.unexpectedStaleHandle
400
+ }
401
+ return doInsert(obj)
402
+ }
403
+ }
404
+
405
+ @discardableResult
406
+ func remove(handle: UInt64) throws -> T {
407
+ try lock.withLock {
408
+ guard let obj = map.removeValue(forKey: handle) else {
409
+ throw UniffiInternalError.unexpectedStaleHandle
410
+ }
411
+ return obj
412
+ }
413
+ }
414
+
415
+ var count: Int {
416
+ map.count
417
+ }
418
+}
419
+
420
+// Public interface members begin here.
421
+// Magic number for the Rust proxy to call using the same mechanism as every other method,
422
+// to free the callback once it's dropped by Rust.
423
+private let IDX_CALLBACK_FREE: Int32 = 0
424
+// Callback return codes
425
+private let UNIFFI_CALLBACK_SUCCESS: Int32 = 0
426
+private let UNIFFI_CALLBACK_ERROR: Int32 = 1
427
+private let UNIFFI_CALLBACK_UNEXPECTED_ERROR: Int32 = 2
428
+
429
+#if swift(>=5.8)
430
+ @_documentation(visibility: private)
431
+#endif
432
+private struct FfiConverterUInt8: FfiConverterPrimitive {
433
+ typealias FfiType = UInt8
434
+ typealias SwiftType = UInt8
435
+
436
+ public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> UInt8 {
437
+ return try lift(readInt(&buf))
438
+ }
439
+
440
+ public static func write(_ value: UInt8, into buf: inout [UInt8]) {
441
+ writeInt(&buf, lower(value))
442
+ }
443
+}
444
+
445
+#if swift(>=5.8)
446
+ @_documentation(visibility: private)
447
+#endif
448
+private struct FfiConverterUInt64: FfiConverterPrimitive {
449
+ typealias FfiType = UInt64
450
+ typealias SwiftType = UInt64
451
+
452
+ public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> UInt64 {
453
+ return try lift(readInt(&buf))
454
+ }
455
+
456
+ public static func write(_ value: SwiftType, into buf: inout [UInt8]) {
457
+ writeInt(&buf, lower(value))
458
+ }
459
+}
460
+
461
+#if swift(>=5.8)
462
+ @_documentation(visibility: private)
463
+#endif
464
+private struct FfiConverterFloat: FfiConverterPrimitive {
465
+ typealias FfiType = Float
466
+ typealias SwiftType = Float
467
+
468
+ public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> Float {
469
+ return try lift(readFloat(&buf))
470
+ }
471
+
472
+ public static func write(_ value: Float, into buf: inout [UInt8]) {
473
+ writeFloat(&buf, lower(value))
474
+ }
475
+}
476
+
477
+#if swift(>=5.8)
478
+ @_documentation(visibility: private)
479
+#endif
480
+private struct FfiConverterDouble: FfiConverterPrimitive {
481
+ typealias FfiType = Double
482
+ typealias SwiftType = Double
483
+
484
+ public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> Double {
485
+ return try lift(readDouble(&buf))
486
+ }
487
+
488
+ public static func write(_ value: Double, into buf: inout [UInt8]) {
489
+ writeDouble(&buf, lower(value))
490
+ }
491
+}
492
+
493
+#if swift(>=5.8)
494
+ @_documentation(visibility: private)
495
+#endif
496
+private struct FfiConverterBool: FfiConverter {
497
+ typealias FfiType = Int8
498
+ typealias SwiftType = Bool
499
+
500
+ public static func lift(_ value: Int8) throws -> Bool {
501
+ return value != 0
502
+ }
503
+
504
+ public static func lower(_ value: Bool) -> Int8 {
505
+ return value ? 1 : 0
506
+ }
507
+
508
+ public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> Bool {
509
+ return try lift(readInt(&buf))
510
+ }
511
+
512
+ public static func write(_ value: Bool, into buf: inout [UInt8]) {
513
+ writeInt(&buf, lower(value))
514
+ }
515
+}
516
+
517
+#if swift(>=5.8)
518
+ @_documentation(visibility: private)
519
+#endif
520
+private struct FfiConverterString: FfiConverter {
521
+ typealias SwiftType = String
522
+ typealias FfiType = RustBuffer
523
+
524
+ public static func lift(_ value: RustBuffer) throws -> String {
525
+ defer {
526
+ value.deallocate()
527
+ }
528
+ if value.data == nil {
529
+ return String()
530
+ }
531
+ let bytes = UnsafeBufferPointer<UInt8>(start: value.data!, count: Int(value.len))
532
+ return String(bytes: bytes, encoding: String.Encoding.utf8)!
533
+ }
534
+
535
+ public static func lower(_ value: String) -> RustBuffer {
536
+ return value.utf8CString.withUnsafeBufferPointer { ptr in
537
+ // The swift string gives us int8_t, we want uint8_t.
538
+ ptr.withMemoryRebound(to: UInt8.self) { ptr in
539
+ // The swift string gives us a trailing null byte, we don't want it.
540
+ let buf = UnsafeBufferPointer(rebasing: ptr.prefix(upTo: ptr.count - 1))
541
+ return RustBuffer.from(buf)
542
+ }
543
+ }
544
+ }
545
+
546
+ public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> String {
547
+ let len: Int32 = try readInt(&buf)
548
+ return String(bytes: try readBytes(&buf, count: Int(len)), encoding: String.Encoding.utf8)!
549
+ }
550
+
551
+ public static func write(_ value: String, into buf: inout [UInt8]) {
552
+ let len = Int32(value.utf8.count)
553
+ writeInt(&buf, len)
554
+ writeBytes(&buf, value.utf8)
555
+ }
556
+}
557
+
558
+/// On-device LLM chat inference engine — UniFFI-exported wrapper.
559
+///
560
+/// This is the primary entry point for Swift / Kotlin consumers. It wraps
561
+/// [`ChatEngine`] with FFI-safe method signatures (no generics, no Rust
562
+/// channels, concrete `String` parameters).
563
+///
564
+/// Construct with [`OndeChatEngine::new()`]. The engine starts with no
565
+/// model loaded — call [`load_gguf_model`] or [`load_default_model`] first.
566
+public protocol OndeChatEngineProtocol: AnyObject, Sendable {
567
+
568
+ /**
569
+ * Clear the conversation history but keep the model loaded.
570
+ *
571
+ * Returns the number of turns that were removed.
572
+ */
573
+ func clearHistory() async -> UInt64
574
+
575
+ /**
576
+ * Clear the system prompt.
577
+ */
578
+ func clearSystemPrompt() async
579
+
580
+ /**
581
+ * Run inference on an explicit list of messages WITHOUT modifying the
582
+ * engine's internal history.
583
+ *
584
+ * Useful for one-shot prompts (e.g. prompt enhancement).
585
+ */
586
+ func generate(messages: [ChatMessage], sampling: SamplingConfig?) async throws
587
+ -> InferenceResult
588
+
589
+ /**
590
+ * Get a copy of the full conversation history.
591
+ */
592
+ func history() async -> [ChatMessage]
593
+
594
+ /**
595
+ * Get a snapshot of the engine's current state.
596
+ */
597
+ func info() async -> EngineInfo
598
+
599
+ /**
600
+ * Check whether a model is currently loaded.
601
+ */
602
+ func isLoaded() async -> Bool
603
+
604
+ /**
605
+ * Load the platform-appropriate default model.
606
+ *
607
+ * - tvOS / iOS / Android → Qwen 2.5 1.5B (~941 MB)
608
+ * - macOS / Windows / Linux → Qwen 2.5 3B (~1.93 GB)
609
+ *
610
+ * Returns the wall-clock loading time in seconds.
611
+ */
612
+ func loadDefaultModel(systemPrompt: String?, sampling: SamplingConfig?) async throws -> Double
613
+
614
+ /**
615
+ * Load a GGUF model into the engine.
616
+ *
617
+ * If a model is already loaded it will be unloaded first.
618
+ *
619
+ * Returns the wall-clock loading time in seconds.
620
+ */
621
+ func loadGgufModel(config: GgufModelConfig, systemPrompt: String?, sampling: SamplingConfig?)
622
+ async throws -> Double
623
+
624
+ /**
625
+ * Append a message to history without running inference.
626
+ */
627
+ func pushHistory(message: ChatMessage) async
628
+
629
+ /**
630
+ * Send a user message and receive a complete assistant reply.
631
+ *
632
+ * The user message and assistant reply are automatically appended to
633
+ * the conversation history on success.
634
+ */
635
+ func sendMessage(message: String) async throws -> InferenceResult
636
+
637
+ /**
638
+ * Replace the sampling configuration.
639
+ */
640
+ func setSampling(sampling: SamplingConfig) async
641
+
642
+ /**
643
+ * Set or replace the system prompt.
644
+ */
645
+ func setSystemPrompt(prompt: String) async
646
+
647
+ /**
648
+ * Unload the current model, freeing all memory.
649
+ *
650
+ * Returns the display name of the model that was unloaded, or `nil`
651
+ * if no model was loaded.
652
+ */
653
+ func unloadModel() async -> String?
654
+
655
+}
656
+/// On-device LLM chat inference engine — UniFFI-exported wrapper.
657
+///
658
+/// This is the primary entry point for Swift / Kotlin consumers. It wraps
659
+/// [`ChatEngine`] with FFI-safe method signatures (no generics, no Rust
660
+/// channels, concrete `String` parameters).
661
+///
662
+/// Construct with [`OndeChatEngine::new()`]. The engine starts with no
663
+/// model loaded — call [`load_gguf_model`] or [`load_default_model`] first.
664
+open class OndeChatEngine: OndeChatEngineProtocol, @unchecked Sendable {
665
+ fileprivate let handle: UInt64
666
+
667
+ /// Used to instantiate a [FFIObject] without an actual handle, for fakes in tests, mostly.
668
+ #if swift(>=5.8)
669
+ @_documentation(visibility: private)
670
+ #endif
671
+ public struct NoHandle {
672
+ public init() {}
673
+ }
674
+
675
+ // TODO: We'd like this to be `private` but for Swifty reasons,
676
+ // we can't implement `FfiConverter` without making this `required` and we can't
677
+ // make it `required` without making it `public`.
678
+ #if swift(>=5.8)
679
+ @_documentation(visibility: private)
680
+ #endif
681
+ required public init(unsafeFromHandle handle: UInt64) {
682
+ self.handle = handle
683
+ }
684
+
685
+ // This constructor can be used to instantiate a fake object.
686
+ // - Parameter noHandle: Placeholder value so we can have a constructor separate from the default empty one that may be implemented for classes extending [FFIObject].
687
+ //
688
+ // - Warning:
689
+ // Any object instantiated with this constructor cannot be passed to an actual Rust-backed object. Since there isn't a backing handle the FFI lower functions will crash.
690
+ #if swift(>=5.8)
691
+ @_documentation(visibility: private)
692
+ #endif
693
+ public init(noHandle: NoHandle) {
694
+ self.handle = 0
695
+ }
696
+
697
+ #if swift(>=5.8)
698
+ @_documentation(visibility: private)
699
+ #endif
700
+ public func uniffiCloneHandle() -> UInt64 {
701
+ return try! rustCall { uniffi_onde_fn_clone_ondechatengine(self.handle, $0) }
702
+ }
703
+ /**
704
+ * Create a new engine with no model loaded.
705
+ */
706
+ public convenience init() {
707
+ let handle =
708
+ try! rustCall {
709
+ uniffi_onde_fn_constructor_ondechatengine_new(
710
+ $0
711
+ )
712
+ }
713
+ self.init(unsafeFromHandle: handle)
714
+ }
715
+
716
+ deinit {
717
+ if handle == 0 {
718
+ // Mock objects have handle=0 don't try to free them
719
+ return
720
+ }
721
+
722
+ try! rustCall { uniffi_onde_fn_free_ondechatengine(handle, $0) }
723
+ }
724
+
725
+ /**
726
+ * Clear the conversation history but keep the model loaded.
727
+ *
728
+ * Returns the number of turns that were removed.
729
+ */
730
+ open func clearHistory() async -> UInt64 {
731
+ return
732
+ try! await uniffiRustCallAsync(
733
+ rustFutureFunc: {
734
+ uniffi_onde_fn_method_ondechatengine_clear_history(
735
+ self.uniffiCloneHandle()
736
+
737
+ )
738
+ },
739
+ pollFunc: ffi_onde_rust_future_poll_u64,
740
+ completeFunc: ffi_onde_rust_future_complete_u64,
741
+ freeFunc: ffi_onde_rust_future_free_u64,
742
+ liftFunc: FfiConverterUInt64.lift,
743
+ errorHandler: nil
744
+
745
+ )
746
+ }
747
+
748
+ /**
749
+ * Clear the system prompt.
750
+ */
751
+ open func clearSystemPrompt() async {
752
+ return
753
+ try! await uniffiRustCallAsync(
754
+ rustFutureFunc: {
755
+ uniffi_onde_fn_method_ondechatengine_clear_system_prompt(
756
+ self.uniffiCloneHandle()
757
+
758
+ )
759
+ },
760
+ pollFunc: ffi_onde_rust_future_poll_void,
761
+ completeFunc: ffi_onde_rust_future_complete_void,
762
+ freeFunc: ffi_onde_rust_future_free_void,
763
+ liftFunc: { $0 },
764
+ errorHandler: nil
765
+
766
+ )
767
+ }
768
+
769
+ /**
770
+ * Run inference on an explicit list of messages WITHOUT modifying the
771
+ * engine's internal history.
772
+ *
773
+ * Useful for one-shot prompts (e.g. prompt enhancement).
774
+ */
775
+ open func generate(messages: [ChatMessage], sampling: SamplingConfig?) async throws
776
+ -> InferenceResult
777
+ {
778
+ return
779
+ try await uniffiRustCallAsync(
780
+ rustFutureFunc: {
781
+ uniffi_onde_fn_method_ondechatengine_generate(
782
+ self.uniffiCloneHandle(),
783
+ FfiConverterSequenceTypeChatMessage.lower(messages),
784
+ FfiConverterOptionTypeSamplingConfig.lower(sampling)
785
+ )
786
+ },
787
+ pollFunc: ffi_onde_rust_future_poll_rust_buffer,
788
+ completeFunc: ffi_onde_rust_future_complete_rust_buffer,
789
+ freeFunc: ffi_onde_rust_future_free_rust_buffer,
790
+ liftFunc: FfiConverterTypeInferenceResult_lift,
791
+ errorHandler: FfiConverterTypeInferenceError_lift
792
+ )
793
+ }
794
+
795
+ /**
796
+ * Get a copy of the full conversation history.
797
+ */
798
+ open func history() async -> [ChatMessage] {
799
+ return
800
+ try! await uniffiRustCallAsync(
801
+ rustFutureFunc: {
802
+ uniffi_onde_fn_method_ondechatengine_history(
803
+ self.uniffiCloneHandle()
804
+
805
+ )
806
+ },
807
+ pollFunc: ffi_onde_rust_future_poll_rust_buffer,
808
+ completeFunc: ffi_onde_rust_future_complete_rust_buffer,
809
+ freeFunc: ffi_onde_rust_future_free_rust_buffer,
810
+ liftFunc: FfiConverterSequenceTypeChatMessage.lift,
811
+ errorHandler: nil
812
+
813
+ )
814
+ }
815
+
816
+ /**
817
+ * Get a snapshot of the engine's current state.
818
+ */
819
+ open func info() async -> EngineInfo {
820
+ return
821
+ try! await uniffiRustCallAsync(
822
+ rustFutureFunc: {
823
+ uniffi_onde_fn_method_ondechatengine_info(
824
+ self.uniffiCloneHandle()
825
+
826
+ )
827
+ },
828
+ pollFunc: ffi_onde_rust_future_poll_rust_buffer,
829
+ completeFunc: ffi_onde_rust_future_complete_rust_buffer,
830
+ freeFunc: ffi_onde_rust_future_free_rust_buffer,
831
+ liftFunc: FfiConverterTypeEngineInfo_lift,
832
+ errorHandler: nil
833
+
834
+ )
835
+ }
836
+
837
+ /**
838
+ * Check whether a model is currently loaded.
839
+ */
840
+ open func isLoaded() async -> Bool {
841
+ return
842
+ try! await uniffiRustCallAsync(
843
+ rustFutureFunc: {
844
+ uniffi_onde_fn_method_ondechatengine_is_loaded(
845
+ self.uniffiCloneHandle()
846
+
847
+ )
848
+ },
849
+ pollFunc: ffi_onde_rust_future_poll_i8,
850
+ completeFunc: ffi_onde_rust_future_complete_i8,
851
+ freeFunc: ffi_onde_rust_future_free_i8,
852
+ liftFunc: FfiConverterBool.lift,
853
+ errorHandler: nil
854
+
855
+ )
856
+ }
857
+
858
+ /**
859
+ * Load the platform-appropriate default model.
860
+ *
861
+ * - tvOS / iOS / Android → Qwen 2.5 1.5B (~941 MB)
862
+ * - macOS / Windows / Linux → Qwen 2.5 3B (~1.93 GB)
863
+ *
864
+ * Returns the wall-clock loading time in seconds.
865
+ */
866
+ open func loadDefaultModel(systemPrompt: String?, sampling: SamplingConfig?) async throws
867
+ -> Double
868
+ {
869
+ return
870
+ try await uniffiRustCallAsync(
871
+ rustFutureFunc: {
872
+ uniffi_onde_fn_method_ondechatengine_load_default_model(
873
+ self.uniffiCloneHandle(),
874
+ FfiConverterOptionString.lower(systemPrompt),
875
+ FfiConverterOptionTypeSamplingConfig.lower(sampling)
876
+ )
877
+ },
878
+ pollFunc: ffi_onde_rust_future_poll_f64,
879
+ completeFunc: ffi_onde_rust_future_complete_f64,
880
+ freeFunc: ffi_onde_rust_future_free_f64,
881
+ liftFunc: FfiConverterDouble.lift,
882
+ errorHandler: FfiConverterTypeInferenceError_lift
883
+ )
884
+ }
885
+
886
+ /**
887
+ * Load a GGUF model into the engine.
888
+ *
889
+ * If a model is already loaded it will be unloaded first.
890
+ *
891
+ * Returns the wall-clock loading time in seconds.
892
+ */
893
+ open func loadGgufModel(
894
+ config: GgufModelConfig, systemPrompt: String?, sampling: SamplingConfig?
895
+ ) async throws -> Double {
896
+ return
897
+ try await uniffiRustCallAsync(
898
+ rustFutureFunc: {
899
+ uniffi_onde_fn_method_ondechatengine_load_gguf_model(
900
+ self.uniffiCloneHandle(),
901
+ FfiConverterTypeGgufModelConfig_lower(config),
902
+ FfiConverterOptionString.lower(systemPrompt),
903
+ FfiConverterOptionTypeSamplingConfig.lower(sampling)
904
+ )
905
+ },
906
+ pollFunc: ffi_onde_rust_future_poll_f64,
907
+ completeFunc: ffi_onde_rust_future_complete_f64,
908
+ freeFunc: ffi_onde_rust_future_free_f64,
909
+ liftFunc: FfiConverterDouble.lift,
910
+ errorHandler: FfiConverterTypeInferenceError_lift
911
+ )
912
+ }
913
+
914
+ /**
915
+ * Append a message to history without running inference.
916
+ */
917
+ open func pushHistory(message: ChatMessage) async {
918
+ return
919
+ try! await uniffiRustCallAsync(
920
+ rustFutureFunc: {
921
+ uniffi_onde_fn_method_ondechatengine_push_history(
922
+ self.uniffiCloneHandle(),
923
+ FfiConverterTypeChatMessage_lower(message)
924
+ )
925
+ },
926
+ pollFunc: ffi_onde_rust_future_poll_void,
927
+ completeFunc: ffi_onde_rust_future_complete_void,
928
+ freeFunc: ffi_onde_rust_future_free_void,
929
+ liftFunc: { $0 },
930
+ errorHandler: nil
931
+
932
+ )
933
+ }
934
+
935
+ /**
936
+ * Send a user message and receive a complete assistant reply.
937
+ *
938
+ * The user message and assistant reply are automatically appended to
939
+ * the conversation history on success.
940
+ */
941
+ open func sendMessage(message: String) async throws -> InferenceResult {
942
+ return
943
+ try await uniffiRustCallAsync(
944
+ rustFutureFunc: {
945
+ uniffi_onde_fn_method_ondechatengine_send_message(
946
+ self.uniffiCloneHandle(),
947
+ FfiConverterString.lower(message)
948
+ )
949
+ },
950
+ pollFunc: ffi_onde_rust_future_poll_rust_buffer,
951
+ completeFunc: ffi_onde_rust_future_complete_rust_buffer,
952
+ freeFunc: ffi_onde_rust_future_free_rust_buffer,
953
+ liftFunc: FfiConverterTypeInferenceResult_lift,
954
+ errorHandler: FfiConverterTypeInferenceError_lift
955
+ )
956
+ }
957
+
958
+ /**
959
+ * Replace the sampling configuration.
960
+ */
961
+ open func setSampling(sampling: SamplingConfig) async {
962
+ return
963
+ try! await uniffiRustCallAsync(
964
+ rustFutureFunc: {
965
+ uniffi_onde_fn_method_ondechatengine_set_sampling(
966
+ self.uniffiCloneHandle(),
967
+ FfiConverterTypeSamplingConfig_lower(sampling)
968
+ )
969
+ },
970
+ pollFunc: ffi_onde_rust_future_poll_void,
971
+ completeFunc: ffi_onde_rust_future_complete_void,
972
+ freeFunc: ffi_onde_rust_future_free_void,
973
+ liftFunc: { $0 },
974
+ errorHandler: nil
975
+
976
+ )
977
+ }
978
+
979
+ /**
980
+ * Set or replace the system prompt.
981
+ */
982
+ open func setSystemPrompt(prompt: String) async {
983
+ return
984
+ try! await uniffiRustCallAsync(
985
+ rustFutureFunc: {
986
+ uniffi_onde_fn_method_ondechatengine_set_system_prompt(
987
+ self.uniffiCloneHandle(),
988
+ FfiConverterString.lower(prompt)
989
+ )
990
+ },
991
+ pollFunc: ffi_onde_rust_future_poll_void,
992
+ completeFunc: ffi_onde_rust_future_complete_void,
993
+ freeFunc: ffi_onde_rust_future_free_void,
994
+ liftFunc: { $0 },
995
+ errorHandler: nil
996
+
997
+ )
998
+ }
999
+
1000
+ /**
1001
+ * Unload the current model, freeing all memory.
1002
+ *
1003
+ * Returns the display name of the model that was unloaded, or `nil`
1004
+ * if no model was loaded.
1005
+ */
1006
+ open func unloadModel() async -> String? {
1007
+ return
1008
+ try! await uniffiRustCallAsync(
1009
+ rustFutureFunc: {
1010
+ uniffi_onde_fn_method_ondechatengine_unload_model(
1011
+ self.uniffiCloneHandle()
1012
+
1013
+ )
1014
+ },
1015
+ pollFunc: ffi_onde_rust_future_poll_rust_buffer,
1016
+ completeFunc: ffi_onde_rust_future_complete_rust_buffer,
1017
+ freeFunc: ffi_onde_rust_future_free_rust_buffer,
1018
+ liftFunc: FfiConverterOptionString.lift,
1019
+ errorHandler: nil
1020
+
1021
+ )
1022
+ }
1023
+
1024
+}
1025
+
1026
+#if swift(>=5.8)
1027
+ @_documentation(visibility: private)
1028
+#endif
1029
+public struct FfiConverterTypeOndeChatEngine: FfiConverter {
1030
+ typealias FfiType = UInt64
1031
+ typealias SwiftType = OndeChatEngine
1032
+
1033
+ public static func lift(_ handle: UInt64) throws -> OndeChatEngine {
1034
+ return OndeChatEngine(unsafeFromHandle: handle)
1035
+ }
1036
+
1037
+ public static func lower(_ value: OndeChatEngine) -> UInt64 {
1038
+ return value.uniffiCloneHandle()
1039
+ }
1040
+
1041
+ public static func read(from buf: inout (data: Data, offset: Data.Index)) throws
1042
+ -> OndeChatEngine
1043
+ {
1044
+ let handle: UInt64 = try readInt(&buf)
1045
+ return try lift(handle)
1046
+ }
1047
+
1048
+ public static func write(_ value: OndeChatEngine, into buf: inout [UInt8]) {
1049
+ writeInt(&buf, lower(value))
1050
+ }
1051
+}
1052
+
1053
+#if swift(>=5.8)
1054
+ @_documentation(visibility: private)
1055
+#endif
1056
+public func FfiConverterTypeOndeChatEngine_lift(_ handle: UInt64) throws -> OndeChatEngine {
1057
+ return try FfiConverterTypeOndeChatEngine.lift(handle)
1058
+}
1059
+
1060
+#if swift(>=5.8)
1061
+ @_documentation(visibility: private)
1062
+#endif
1063
+public func FfiConverterTypeOndeChatEngine_lower(_ value: OndeChatEngine) -> UInt64 {
1064
+ return FfiConverterTypeOndeChatEngine.lower(value)
1065
+}
1066
+
1067
+/// A single message in a conversation.
1068
+public struct ChatMessage: Equatable, Hashable {
1069
+ public var role: ChatRole
1070
+ public var content: String
1071
+
1072
+ // Default memberwise initializers are never public by default, so we
1073
+ // declare one manually.
1074
+ public init(role: ChatRole, content: String) {
1075
+ self.role = role
1076
+ self.content = content
1077
+ }
1078
+
1079
+}
1080
+
1081
+#if compiler(>=6)
1082
+ extension ChatMessage: Sendable {}
1083
+#endif
1084
+
1085
+#if swift(>=5.8)
1086
+ @_documentation(visibility: private)
1087
+#endif
1088
+public struct FfiConverterTypeChatMessage: FfiConverterRustBuffer {
1089
+ public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> ChatMessage
1090
+ {
1091
+ return
1092
+ try ChatMessage(
1093
+ role: FfiConverterTypeChatRole.read(from: &buf),
1094
+ content: FfiConverterString.read(from: &buf)
1095
+ )
1096
+ }
1097
+
1098
+ public static func write(_ value: ChatMessage, into buf: inout [UInt8]) {
1099
+ FfiConverterTypeChatRole.write(value.role, into: &buf)
1100
+ FfiConverterString.write(value.content, into: &buf)
1101
+ }
1102
+}
1103
+
1104
+#if swift(>=5.8)
1105
+ @_documentation(visibility: private)
1106
+#endif
1107
+public func FfiConverterTypeChatMessage_lift(_ buf: RustBuffer) throws -> ChatMessage {
1108
+ return try FfiConverterTypeChatMessage.lift(buf)
1109
+}
1110
+
1111
+#if swift(>=5.8)
1112
+ @_documentation(visibility: private)
1113
+#endif
1114
+public func FfiConverterTypeChatMessage_lower(_ value: ChatMessage) -> RustBuffer {
1115
+ return FfiConverterTypeChatMessage.lower(value)
1116
+}
1117
+
1118
+/// A point-in-time snapshot of the engine's state, suitable for status UIs.
1119
+///
1120
+/// Note: `history_length` is `u64` (not `usize`) for UniFFI compatibility.
1121
+public struct EngineInfo: Equatable, Hashable {
1122
+ public var status: EngineStatus
1123
+ /**
1124
+ * Display name of the currently loaded model, if any.
1125
+ */
1126
+ public var modelName: String?
1127
+ /**
1128
+ * Approximate memory footprint description, if a model is loaded.
1129
+ */
1130
+ public var approxMemory: String?
1131
+ /**
1132
+ * Number of conversation turns in the current history.
1133
+ */
1134
+ public var historyLength: UInt64
1135
+
1136
+ // Default memberwise initializers are never public by default, so we
1137
+ // declare one manually.
1138
+ public init(
1139
+ status: EngineStatus,
1140
+ /**
1141
+ * Display name of the currently loaded model, if any.
1142
+ */
1143
+ modelName: String?,
1144
+ /**
1145
+ * Approximate memory footprint description, if a model is loaded.
1146
+ */
1147
+ approxMemory: String?,
1148
+ /**
1149
+ * Number of conversation turns in the current history.
1150
+ */
1151
+ historyLength: UInt64
1152
+ ) {
1153
+ self.status = status
1154
+ self.modelName = modelName
1155
+ self.approxMemory = approxMemory
1156
+ self.historyLength = historyLength
1157
+ }
1158
+
1159
+}
1160
+
1161
+#if compiler(>=6)
1162
+ extension EngineInfo: Sendable {}
1163
+#endif
1164
+
1165
+#if swift(>=5.8)
1166
+ @_documentation(visibility: private)
1167
+#endif
1168
+public struct FfiConverterTypeEngineInfo: FfiConverterRustBuffer {
1169
+ public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> EngineInfo {
1170
+ return
1171
+ try EngineInfo(
1172
+ status: FfiConverterTypeEngineStatus.read(from: &buf),
1173
+ modelName: FfiConverterOptionString.read(from: &buf),
1174
+ approxMemory: FfiConverterOptionString.read(from: &buf),
1175
+ historyLength: FfiConverterUInt64.read(from: &buf)
1176
+ )
1177
+ }
1178
+
1179
+ public static func write(_ value: EngineInfo, into buf: inout [UInt8]) {
1180
+ FfiConverterTypeEngineStatus.write(value.status, into: &buf)
1181
+ FfiConverterOptionString.write(value.modelName, into: &buf)
1182
+ FfiConverterOptionString.write(value.approxMemory, into: &buf)
1183
+ FfiConverterUInt64.write(value.historyLength, into: &buf)
1184
+ }
1185
+}
1186
+
1187
+#if swift(>=5.8)
1188
+ @_documentation(visibility: private)
1189
+#endif
1190
+public func FfiConverterTypeEngineInfo_lift(_ buf: RustBuffer) throws -> EngineInfo {
1191
+ return try FfiConverterTypeEngineInfo.lift(buf)
1192
+}
1193
+
1194
+#if swift(>=5.8)
1195
+ @_documentation(visibility: private)
1196
+#endif
1197
+public func FfiConverterTypeEngineInfo_lower(_ value: EngineInfo) -> RustBuffer {
1198
+ return FfiConverterTypeEngineInfo.lower(value)
1199
+}
1200
+
1201
+/// Configuration for loading a GGUF model via mistral.rs.
1202
+///
1203
+/// This is the primary model format for on-device mobile/desktop inference
1204
+/// because GGUF files are pre-quantized and load at their compressed size,
1205
+/// avoiding the large memory spike of in-situ quantization.
1206
+public struct GgufModelConfig: Equatable, Hashable {
1207
+ /**
1208
+ * HuggingFace model repository ID, e.g. `"bartowski/Qwen2.5-1.5B-Instruct-GGUF"`.
1209
+ */
1210
+ public var modelId: String
1211
+ /**
1212
+ * GGUF filename(s) within the repository, e.g. `["Qwen2.5-1.5B-Instruct-Q4_K_M.gguf"]`.
1213
+ */
1214
+ public var files: [String]
1215
+ /**
1216
+ * Optional: explicit tokenizer model ID (required on Android where GGUF
1217
+ * embedded tokenizers are not supported by the candle backend).
1218
+ */
1219
+ public var tokModelId: String?
1220
+ /**
1221
+ * Human-friendly display name, e.g. `"Qwen 2.5 1.5B"`.
1222
+ */
1223
+ public var displayName: String
1224
+ /**
1225
+ * Approximate memory footprint description, e.g. `"~941 MB (GGUF Q4_K_M)"`.
1226
+ */
1227
+ public var approxMemory: String
1228
+
1229
+ // Default memberwise initializers are never public by default, so we
1230
+ // declare one manually.
1231
+ public init(
1232
+ /**
1233
+ * HuggingFace model repository ID, e.g. `"bartowski/Qwen2.5-1.5B-Instruct-GGUF"`.
1234
+ */
1235
+ modelId: String,
1236
+ /**
1237
+ * GGUF filename(s) within the repository, e.g. `["Qwen2.5-1.5B-Instruct-Q4_K_M.gguf"]`.
1238
+ */
1239
+ files: [String],
1240
+ /**
1241
+ * Optional: explicit tokenizer model ID (required on Android where GGUF
1242
+ * embedded tokenizers are not supported by the candle backend).
1243
+ */
1244
+ tokModelId: String?,
1245
+ /**
1246
+ * Human-friendly display name, e.g. `"Qwen 2.5 1.5B"`.
1247
+ */
1248
+ displayName: String,
1249
+ /**
1250
+ * Approximate memory footprint description, e.g. `"~941 MB (GGUF Q4_K_M)"`.
1251
+ */
1252
+ approxMemory: String
1253
+ ) {
1254
+ self.modelId = modelId
1255
+ self.files = files
1256
+ self.tokModelId = tokModelId
1257
+ self.displayName = displayName
1258
+ self.approxMemory = approxMemory
1259
+ }
1260
+
1261
+}
1262
+
1263
+#if compiler(>=6)
1264
+ extension GgufModelConfig: Sendable {}
1265
+#endif
1266
+
1267
+#if swift(>=5.8)
1268
+ @_documentation(visibility: private)
1269
+#endif
1270
+public struct FfiConverterTypeGgufModelConfig: FfiConverterRustBuffer {
1271
+ public static func read(from buf: inout (data: Data, offset: Data.Index)) throws
1272
+ -> GgufModelConfig
1273
+ {
1274
+ return
1275
+ try GgufModelConfig(
1276
+ modelId: FfiConverterString.read(from: &buf),
1277
+ files: FfiConverterSequenceString.read(from: &buf),
1278
+ tokModelId: FfiConverterOptionString.read(from: &buf),
1279
+ displayName: FfiConverterString.read(from: &buf),
1280
+ approxMemory: FfiConverterString.read(from: &buf)
1281
+ )
1282
+ }
1283
+
1284
+ public static func write(_ value: GgufModelConfig, into buf: inout [UInt8]) {
1285
+ FfiConverterString.write(value.modelId, into: &buf)
1286
+ FfiConverterSequenceString.write(value.files, into: &buf)
1287
+ FfiConverterOptionString.write(value.tokModelId, into: &buf)
1288
+ FfiConverterString.write(value.displayName, into: &buf)
1289
+ FfiConverterString.write(value.approxMemory, into: &buf)
1290
+ }
1291
+}
1292
+
1293
+#if swift(>=5.8)
1294
+ @_documentation(visibility: private)
1295
+#endif
1296
+public func FfiConverterTypeGgufModelConfig_lift(_ buf: RustBuffer) throws -> GgufModelConfig {
1297
+ return try FfiConverterTypeGgufModelConfig.lift(buf)
1298
+}
1299
+
1300
+#if swift(>=5.8)
1301
+ @_documentation(visibility: private)
1302
+#endif
1303
+public func FfiConverterTypeGgufModelConfig_lower(_ value: GgufModelConfig) -> RustBuffer {
1304
+ return FfiConverterTypeGgufModelConfig.lower(value)
1305
+}
1306
+
1307
+/// The result of a chat inference request.
1308
+public struct InferenceResult: Equatable, Hashable {
1309
+ /**
1310
+ * The generated assistant reply text.
1311
+ */
1312
+ public var text: String
1313
+ /**
1314
+ * Wall-clock duration of the inference in seconds.
1315
+ */
1316
+ public var durationSecs: Double
1317
+ /**
1318
+ * Human-readable duration string (e.g. `"2m 3.1s"` or `"4.5s"`).
1319
+ */
1320
+ public var durationDisplay: String
1321
+ /**
1322
+ * Finish reason reported by the model (e.g. `"stop"`, `"length"`).
1323
+ */
1324
+ public var finishReason: String
1325
+
1326
+ // Default memberwise initializers are never public by default, so we
1327
+ // declare one manually.
1328
+ public init(
1329
+ /**
1330
+ * The generated assistant reply text.
1331
+ */
1332
+ text: String,
1333
+ /**
1334
+ * Wall-clock duration of the inference in seconds.
1335
+ */
1336
+ durationSecs: Double,
1337
+ /**
1338
+ * Human-readable duration string (e.g. `"2m 3.1s"` or `"4.5s"`).
1339
+ */
1340
+ durationDisplay: String,
1341
+ /**
1342
+ * Finish reason reported by the model (e.g. `"stop"`, `"length"`).
1343
+ */
1344
+ finishReason: String
1345
+ ) {
1346
+ self.text = text
1347
+ self.durationSecs = durationSecs
1348
+ self.durationDisplay = durationDisplay
1349
+ self.finishReason = finishReason
1350
+ }
1351
+
1352
+}
1353
+
1354
+#if compiler(>=6)
1355
+ extension InferenceResult: Sendable {}
1356
+#endif
1357
+
1358
+#if swift(>=5.8)
1359
+ @_documentation(visibility: private)
1360
+#endif
1361
+public struct FfiConverterTypeInferenceResult: FfiConverterRustBuffer {
1362
+ public static func read(from buf: inout (data: Data, offset: Data.Index)) throws
1363
+ -> InferenceResult
1364
+ {
1365
+ return
1366
+ try InferenceResult(
1367
+ text: FfiConverterString.read(from: &buf),
1368
+ durationSecs: FfiConverterDouble.read(from: &buf),
1369
+ durationDisplay: FfiConverterString.read(from: &buf),
1370
+ finishReason: FfiConverterString.read(from: &buf)
1371
+ )
1372
+ }
1373
+
1374
+ public static func write(_ value: InferenceResult, into buf: inout [UInt8]) {
1375
+ FfiConverterString.write(value.text, into: &buf)
1376
+ FfiConverterDouble.write(value.durationSecs, into: &buf)
1377
+ FfiConverterString.write(value.durationDisplay, into: &buf)
1378
+ FfiConverterString.write(value.finishReason, into: &buf)
1379
+ }
1380
+}
1381
+
1382
+#if swift(>=5.8)
1383
+ @_documentation(visibility: private)
1384
+#endif
1385
+public func FfiConverterTypeInferenceResult_lift(_ buf: RustBuffer) throws -> InferenceResult {
1386
+ return try FfiConverterTypeInferenceResult.lift(buf)
1387
+}
1388
+
1389
+#if swift(>=5.8)
1390
+ @_documentation(visibility: private)
1391
+#endif
1392
+public func FfiConverterTypeInferenceResult_lower(_ value: InferenceResult) -> RustBuffer {
1393
+ return FfiConverterTypeInferenceResult.lower(value)
1394
+}
1395
+
1396
+/// Configuration for loading an ISQ (in-situ quantised) model via mistral.rs
1397
+/// `TextModelBuilder`.
1398
+///
1399
+/// Unlike GGUF models, ISQ models are loaded directly from a HuggingFace
1400
+/// safetensors repo and quantised in-situ on the device. They require more
1401
+/// RAM during the load phase but support a wider range of architectures
1402
+/// (e.g. DeepSeek-Coder-V2-Lite, Qwen2.5-Coder-7B).
1403
+///
1404
+/// **macOS-only for now** — ISQ with Metal acceleration requires the `metal`
1405
+/// feature on mistral.rs. The struct is still defined on all platforms so
1406
+/// that types.rs compiles everywhere without `cfg` gates on the record
1407
+/// (UniFFI requires all record types to be reachable without feature flags).
1408
+public struct IsqModelConfig: Equatable, Hashable {
1409
+ /**
1410
+ * HuggingFace model repository ID, e.g. `"Qwen/Qwen2.5-Coder-7B-Instruct"`.
1411
+ */
1412
+ public var modelId: String
1413
+ /**
1414
+ * Number of quantisation bits. `4` → Q4K (AFQ4 on Metal), `8` → Q8_0 (AFQ8 on Metal).
1415
+ * Any value outside `{4, 8}` defaults to 4-bit.
1416
+ */
1417
+ public var isqBits: UInt8
1418
+ /**
1419
+ * Human-friendly display name, e.g. `"Qwen 2.5 Coder 7B"`.
1420
+ */
1421
+ public var displayName: String
1422
+ /**
1423
+ * Approximate memory footprint description, e.g. `"~4.5 GB (Q4K, Metal)"`.
1424
+ */
1425
+ public var approxMemory: String
1426
+
1427
+ // Default memberwise initializers are never public by default, so we
1428
+ // declare one manually.
1429
+ public init(
1430
+ /**
1431
+ * HuggingFace model repository ID, e.g. `"Qwen/Qwen2.5-Coder-7B-Instruct"`.
1432
+ */
1433
+ modelId: String,
1434
+ /**
1435
+ * Number of quantisation bits. `4` → Q4K (AFQ4 on Metal), `8` → Q8_0 (AFQ8 on Metal).
1436
+ * Any value outside `{4, 8}` defaults to 4-bit.
1437
+ */
1438
+ isqBits: UInt8,
1439
+ /**
1440
+ * Human-friendly display name, e.g. `"Qwen 2.5 Coder 7B"`.
1441
+ */
1442
+ displayName: String,
1443
+ /**
1444
+ * Approximate memory footprint description, e.g. `"~4.5 GB (Q4K, Metal)"`.
1445
+ */
1446
+ approxMemory: String
1447
+ ) {
1448
+ self.modelId = modelId
1449
+ self.isqBits = isqBits
1450
+ self.displayName = displayName
1451
+ self.approxMemory = approxMemory
1452
+ }
1453
+
1454
+}
1455
+
1456
+#if compiler(>=6)
1457
+ extension IsqModelConfig: Sendable {}
1458
+#endif
1459
+
1460
+#if swift(>=5.8)
1461
+ @_documentation(visibility: private)
1462
+#endif
1463
+public struct FfiConverterTypeIsqModelConfig: FfiConverterRustBuffer {
1464
+ public static func read(from buf: inout (data: Data, offset: Data.Index)) throws
1465
+ -> IsqModelConfig
1466
+ {
1467
+ return
1468
+ try IsqModelConfig(
1469
+ modelId: FfiConverterString.read(from: &buf),
1470
+ isqBits: FfiConverterUInt8.read(from: &buf),
1471
+ displayName: FfiConverterString.read(from: &buf),
1472
+ approxMemory: FfiConverterString.read(from: &buf)
1473
+ )
1474
+ }
1475
+
1476
+ public static func write(_ value: IsqModelConfig, into buf: inout [UInt8]) {
1477
+ FfiConverterString.write(value.modelId, into: &buf)
1478
+ FfiConverterUInt8.write(value.isqBits, into: &buf)
1479
+ FfiConverterString.write(value.displayName, into: &buf)
1480
+ FfiConverterString.write(value.approxMemory, into: &buf)
1481
+ }
1482
+}
1483
+
1484
+#if swift(>=5.8)
1485
+ @_documentation(visibility: private)
1486
+#endif
1487
+public func FfiConverterTypeIsqModelConfig_lift(_ buf: RustBuffer) throws -> IsqModelConfig {
1488
+ return try FfiConverterTypeIsqModelConfig.lift(buf)
1489
+}
1490
+
1491
+#if swift(>=5.8)
1492
+ @_documentation(visibility: private)
1493
+#endif
1494
+public func FfiConverterTypeIsqModelConfig_lower(_ value: IsqModelConfig) -> RustBuffer {
1495
+ return FfiConverterTypeIsqModelConfig.lower(value)
1496
+}
1497
+
1498
+/// Sampling parameters for text generation.
1499
+///
1500
+/// All fields are optional — `None` means "use the engine default".
1501
+///
1502
+/// Note: `usize` is replaced with `u64` for UniFFI compatibility.
1503
+public struct SamplingConfig: Equatable, Hashable {
1504
+ /**
1505
+ * Sampling temperature (higher = more random). Typical range: 0.0–2.0.
1506
+ */
1507
+ public var temperature: Double?
1508
+ /**
1509
+ * Nucleus (top-p) sampling threshold. Typical value: 0.9–0.95.
1510
+ */
1511
+ public var topP: Double?
1512
+ /**
1513
+ * Top-k sampling limit.
1514
+ */
1515
+ public var topK: UInt64?
1516
+ /**
1517
+ * Min-p sampling threshold.
1518
+ */
1519
+ public var minP: Double?
1520
+ /**
1521
+ * Maximum number of tokens to generate.
1522
+ */
1523
+ public var maxTokens: UInt64?
1524
+ /**
1525
+ * Frequency penalty (penalise tokens proportional to occurrence count).
1526
+ */
1527
+ public var frequencyPenalty: Float?
1528
+ /**
1529
+ * Presence penalty (penalise tokens that appeared at all).
1530
+ */
1531
+ public var presencePenalty: Float?
1532
+
1533
+ // Default memberwise initializers are never public by default, so we
1534
+ // declare one manually.
1535
+ public init(
1536
+ /**
1537
+ * Sampling temperature (higher = more random). Typical range: 0.0–2.0.
1538
+ */
1539
+ temperature: Double?,
1540
+ /**
1541
+ * Nucleus (top-p) sampling threshold. Typical value: 0.9–0.95.
1542
+ */
1543
+ topP: Double?,
1544
+ /**
1545
+ * Top-k sampling limit.
1546
+ */
1547
+ topK: UInt64?,
1548
+ /**
1549
+ * Min-p sampling threshold.
1550
+ */
1551
+ minP: Double?,
1552
+ /**
1553
+ * Maximum number of tokens to generate.
1554
+ */
1555
+ maxTokens: UInt64?,
1556
+ /**
1557
+ * Frequency penalty (penalise tokens proportional to occurrence count).
1558
+ */
1559
+ frequencyPenalty: Float?,
1560
+ /**
1561
+ * Presence penalty (penalise tokens that appeared at all).
1562
+ */
1563
+ presencePenalty: Float?
1564
+ ) {
1565
+ self.temperature = temperature
1566
+ self.topP = topP
1567
+ self.topK = topK
1568
+ self.minP = minP
1569
+ self.maxTokens = maxTokens
1570
+ self.frequencyPenalty = frequencyPenalty
1571
+ self.presencePenalty = presencePenalty
1572
+ }
1573
+
1574
+}
1575
+
1576
+#if compiler(>=6)
1577
+ extension SamplingConfig: Sendable {}
1578
+#endif
1579
+
1580
+#if swift(>=5.8)
1581
+ @_documentation(visibility: private)
1582
+#endif
1583
+public struct FfiConverterTypeSamplingConfig: FfiConverterRustBuffer {
1584
+ public static func read(from buf: inout (data: Data, offset: Data.Index)) throws
1585
+ -> SamplingConfig
1586
+ {
1587
+ return
1588
+ try SamplingConfig(
1589
+ temperature: FfiConverterOptionDouble.read(from: &buf),
1590
+ topP: FfiConverterOptionDouble.read(from: &buf),
1591
+ topK: FfiConverterOptionUInt64.read(from: &buf),
1592
+ minP: FfiConverterOptionDouble.read(from: &buf),
1593
+ maxTokens: FfiConverterOptionUInt64.read(from: &buf),
1594
+ frequencyPenalty: FfiConverterOptionFloat.read(from: &buf),
1595
+ presencePenalty: FfiConverterOptionFloat.read(from: &buf)
1596
+ )
1597
+ }
1598
+
1599
+ public static func write(_ value: SamplingConfig, into buf: inout [UInt8]) {
1600
+ FfiConverterOptionDouble.write(value.temperature, into: &buf)
1601
+ FfiConverterOptionDouble.write(value.topP, into: &buf)
1602
+ FfiConverterOptionUInt64.write(value.topK, into: &buf)
1603
+ FfiConverterOptionDouble.write(value.minP, into: &buf)
1604
+ FfiConverterOptionUInt64.write(value.maxTokens, into: &buf)
1605
+ FfiConverterOptionFloat.write(value.frequencyPenalty, into: &buf)
1606
+ FfiConverterOptionFloat.write(value.presencePenalty, into: &buf)
1607
+ }
1608
+}
1609
+
1610
+#if swift(>=5.8)
1611
+ @_documentation(visibility: private)
1612
+#endif
1613
+public func FfiConverterTypeSamplingConfig_lift(_ buf: RustBuffer) throws -> SamplingConfig {
1614
+ return try FfiConverterTypeSamplingConfig.lift(buf)
1615
+}
1616
+
1617
+#if swift(>=5.8)
1618
+ @_documentation(visibility: private)
1619
+#endif
1620
+public func FfiConverterTypeSamplingConfig_lower(_ value: SamplingConfig) -> RustBuffer {
1621
+ return FfiConverterTypeSamplingConfig.lower(value)
1622
+}
1623
+
1624
+/// A single streaming token chunk from the inference engine.
1625
+public struct StreamChunk: Equatable, Hashable {
1626
+ /**
1627
+ * The token text delta (may be empty for the final chunk).
1628
+ */
1629
+ public var delta: String
1630
+ /**
1631
+ * Whether this is the final chunk in the stream.
1632
+ */
1633
+ public var done: Bool
1634
+ /**
1635
+ * Finish reason (only set on the final chunk).
1636
+ */
1637
+ public var finishReason: String?
1638
+
1639
+ // Default memberwise initializers are never public by default, so we
1640
+ // declare one manually.
1641
+ public init(
1642
+ /**
1643
+ * The token text delta (may be empty for the final chunk).
1644
+ */
1645
+ delta: String,
1646
+ /**
1647
+ * Whether this is the final chunk in the stream.
1648
+ */
1649
+ done: Bool,
1650
+ /**
1651
+ * Finish reason (only set on the final chunk).
1652
+ */
1653
+ finishReason: String?
1654
+ ) {
1655
+ self.delta = delta
1656
+ self.done = done
1657
+ self.finishReason = finishReason
1658
+ }
1659
+
1660
+}
1661
+
1662
+#if compiler(>=6)
1663
+ extension StreamChunk: Sendable {}
1664
+#endif
1665
+
1666
+#if swift(>=5.8)
1667
+ @_documentation(visibility: private)
1668
+#endif
1669
+public struct FfiConverterTypeStreamChunk: FfiConverterRustBuffer {
1670
+ public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> StreamChunk
1671
+ {
1672
+ return
1673
+ try StreamChunk(
1674
+ delta: FfiConverterString.read(from: &buf),
1675
+ done: FfiConverterBool.read(from: &buf),
1676
+ finishReason: FfiConverterOptionString.read(from: &buf)
1677
+ )
1678
+ }
1679
+
1680
+ public static func write(_ value: StreamChunk, into buf: inout [UInt8]) {
1681
+ FfiConverterString.write(value.delta, into: &buf)
1682
+ FfiConverterBool.write(value.done, into: &buf)
1683
+ FfiConverterOptionString.write(value.finishReason, into: &buf)
1684
+ }
1685
+}
1686
+
1687
+#if swift(>=5.8)
1688
+ @_documentation(visibility: private)
1689
+#endif
1690
+public func FfiConverterTypeStreamChunk_lift(_ buf: RustBuffer) throws -> StreamChunk {
1691
+ return try FfiConverterTypeStreamChunk.lift(buf)
1692
+}
1693
+
1694
+#if swift(>=5.8)
1695
+ @_documentation(visibility: private)
1696
+#endif
1697
+public func FfiConverterTypeStreamChunk_lower(_ value: StreamChunk) -> RustBuffer {
1698
+ return FfiConverterTypeStreamChunk.lower(value)
1699
+}
1700
+
1701
+// Note that we don't yet support `indirect` for enums.
1702
+// See https://github.com/mozilla/uniffi-rs/issues/396 for further discussion.
1703
+/**
1704
+ * Role of a message in a chat conversation.
1705
+ *
1706
+ * Mirrors the standard OpenAI / mistral.rs role taxonomy but is decoupled
1707
+ * from `mistralrs::TextMessageRole` so that callers don't need a direct
1708
+ * dependency on mistral.rs.
1709
+ */
1710
+
1711
+public enum ChatRole: Equatable, Hashable {
1712
+
1713
+ case system
1714
+ case user
1715
+ case assistant
1716
+
1717
+}
1718
+
1719
+#if compiler(>=6)
1720
+ extension ChatRole: Sendable {}
1721
+#endif
1722
+
1723
+#if swift(>=5.8)
1724
+ @_documentation(visibility: private)
1725
+#endif
1726
+public struct FfiConverterTypeChatRole: FfiConverterRustBuffer {
1727
+ typealias SwiftType = ChatRole
1728
+
1729
+ public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> ChatRole {
1730
+ let variant: Int32 = try readInt(&buf)
1731
+ switch variant {
1732
+
1733
+ case 1: return .system
1734
+
1735
+ case 2: return .user
1736
+
1737
+ case 3: return .assistant
1738
+
1739
+ default: throw UniffiInternalError.unexpectedEnumCase
1740
+ }
1741
+ }
1742
+
1743
+ public static func write(_ value: ChatRole, into buf: inout [UInt8]) {
1744
+ switch value {
1745
+
1746
+ case .system:
1747
+ writeInt(&buf, Int32(1))
1748
+
1749
+ case .user:
1750
+ writeInt(&buf, Int32(2))
1751
+
1752
+ case .assistant:
1753
+ writeInt(&buf, Int32(3))
1754
+
1755
+ }
1756
+ }
1757
+}
1758
+
1759
+#if swift(>=5.8)
1760
+ @_documentation(visibility: private)
1761
+#endif
1762
+public func FfiConverterTypeChatRole_lift(_ buf: RustBuffer) throws -> ChatRole {
1763
+ return try FfiConverterTypeChatRole.lift(buf)
1764
+}
1765
+
1766
+#if swift(>=5.8)
1767
+ @_documentation(visibility: private)
1768
+#endif
1769
+public func FfiConverterTypeChatRole_lower(_ value: ChatRole) -> RustBuffer {
1770
+ return FfiConverterTypeChatRole.lower(value)
1771
+}
1772
+
1773
+// Note that we don't yet support `indirect` for enums.
1774
+// See https://github.com/mozilla/uniffi-rs/issues/396 for further discussion.
1775
+/**
1776
+ * Lifecycle status of the inference engine.
1777
+ */
1778
+
1779
+public enum EngineStatus: Equatable, Hashable {
1780
+
1781
+ /**
1782
+ * No model loaded.
1783
+ */
1784
+ case unloaded
1785
+ /**
1786
+ * Model is being downloaded / loaded into memory.
1787
+ */
1788
+ case loading
1789
+ /**
1790
+ * Model is loaded and ready to accept requests.
1791
+ */
1792
+ case ready
1793
+ /**
1794
+ * Model is currently running inference.
1795
+ */
1796
+ case generating
1797
+ /**
1798
+ * An error occurred (model may or may not still be loaded).
1799
+ */
1800
+ case error
1801
+
1802
+}
1803
+
1804
+#if compiler(>=6)
1805
+ extension EngineStatus: Sendable {}
1806
+#endif
1807
+
1808
+#if swift(>=5.8)
1809
+ @_documentation(visibility: private)
1810
+#endif
1811
+public struct FfiConverterTypeEngineStatus: FfiConverterRustBuffer {
1812
+ typealias SwiftType = EngineStatus
1813
+
1814
+ public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> EngineStatus
1815
+ {
1816
+ let variant: Int32 = try readInt(&buf)
1817
+ switch variant {
1818
+
1819
+ case 1: return .unloaded
1820
+
1821
+ case 2: return .loading
1822
+
1823
+ case 3: return .ready
1824
+
1825
+ case 4: return .generating
1826
+
1827
+ case 5: return .error
1828
+
1829
+ default: throw UniffiInternalError.unexpectedEnumCase
1830
+ }
1831
+ }
1832
+
1833
+ public static func write(_ value: EngineStatus, into buf: inout [UInt8]) {
1834
+ switch value {
1835
+
1836
+ case .unloaded:
1837
+ writeInt(&buf, Int32(1))
1838
+
1839
+ case .loading:
1840
+ writeInt(&buf, Int32(2))
1841
+
1842
+ case .ready:
1843
+ writeInt(&buf, Int32(3))
1844
+
1845
+ case .generating:
1846
+ writeInt(&buf, Int32(4))
1847
+
1848
+ case .error:
1849
+ writeInt(&buf, Int32(5))
1850
+
1851
+ }
1852
+ }
1853
+}
1854
+
1855
+#if swift(>=5.8)
1856
+ @_documentation(visibility: private)
1857
+#endif
1858
+public func FfiConverterTypeEngineStatus_lift(_ buf: RustBuffer) throws -> EngineStatus {
1859
+ return try FfiConverterTypeEngineStatus.lift(buf)
1860
+}
1861
+
1862
+#if swift(>=5.8)
1863
+ @_documentation(visibility: private)
1864
+#endif
1865
+public func FfiConverterTypeEngineStatus_lower(_ value: EngineStatus) -> RustBuffer {
1866
+ return FfiConverterTypeEngineStatus.lower(value)
1867
+}
1868
+
1869
+/// Errors that can occur during inference engine operations.
1870
+///
1871
+/// Exposed to Swift / Kotlin as a sealed class / enum via `uniffi::Error`.
1872
+public enum InferenceError: Swift.Error, Equatable, Hashable, Foundation.LocalizedError {
1873
+
1874
+ case NoModelLoaded
1875
+ case AlreadyLoaded(
1876
+ modelName: String
1877
+ )
1878
+ case ModelBuild(
1879
+ reason: String
1880
+ )
1881
+ case Inference(
1882
+ reason: String
1883
+ )
1884
+ case Cancelled
1885
+ case Other(
1886
+ reason: String
1887
+ )
1888
+
1889
+ public var errorDescription: String? {
1890
+ String(reflecting: self)
1891
+ }
1892
+
1893
+}
1894
+
1895
+#if compiler(>=6)
1896
+ extension InferenceError: Sendable {}
1897
+#endif
1898
+
1899
+#if swift(>=5.8)
1900
+ @_documentation(visibility: private)
1901
+#endif
1902
+public struct FfiConverterTypeInferenceError: FfiConverterRustBuffer {
1903
+ typealias SwiftType = InferenceError
1904
+
1905
+ public static func read(from buf: inout (data: Data, offset: Data.Index)) throws
1906
+ -> InferenceError
1907
+ {
1908
+ let variant: Int32 = try readInt(&buf)
1909
+ switch variant {
1910
+
1911
+ case 1: return .NoModelLoaded
1912
+ case 2:
1913
+ return .AlreadyLoaded(
1914
+ modelName: try FfiConverterString.read(from: &buf)
1915
+ )
1916
+ case 3:
1917
+ return .ModelBuild(
1918
+ reason: try FfiConverterString.read(from: &buf)
1919
+ )
1920
+ case 4:
1921
+ return .Inference(
1922
+ reason: try FfiConverterString.read(from: &buf)
1923
+ )
1924
+ case 5: return .Cancelled
1925
+ case 6:
1926
+ return .Other(
1927
+ reason: try FfiConverterString.read(from: &buf)
1928
+ )
1929
+
1930
+ default: throw UniffiInternalError.unexpectedEnumCase
1931
+ }
1932
+ }
1933
+
1934
+ public static func write(_ value: InferenceError, into buf: inout [UInt8]) {
1935
+ switch value {
1936
+
1937
+ case .NoModelLoaded:
1938
+ writeInt(&buf, Int32(1))
1939
+
1940
+ case .AlreadyLoaded(let modelName):
1941
+ writeInt(&buf, Int32(2))
1942
+ FfiConverterString.write(modelName, into: &buf)
1943
+
1944
+ case .ModelBuild(let reason):
1945
+ writeInt(&buf, Int32(3))
1946
+ FfiConverterString.write(reason, into: &buf)
1947
+
1948
+ case .Inference(let reason):
1949
+ writeInt(&buf, Int32(4))
1950
+ FfiConverterString.write(reason, into: &buf)
1951
+
1952
+ case .Cancelled:
1953
+ writeInt(&buf, Int32(5))
1954
+
1955
+ case .Other(let reason):
1956
+ writeInt(&buf, Int32(6))
1957
+ FfiConverterString.write(reason, into: &buf)
1958
+
1959
+ }
1960
+ }
1961
+}
1962
+
1963
+#if swift(>=5.8)
1964
+ @_documentation(visibility: private)
1965
+#endif
1966
+public func FfiConverterTypeInferenceError_lift(_ buf: RustBuffer) throws -> InferenceError {
1967
+ return try FfiConverterTypeInferenceError.lift(buf)
1968
+}
1969
+
1970
+#if swift(>=5.8)
1971
+ @_documentation(visibility: private)
1972
+#endif
1973
+public func FfiConverterTypeInferenceError_lower(_ value: InferenceError) -> RustBuffer {
1974
+ return FfiConverterTypeInferenceError.lower(value)
1975
+}
1976
+
1977
+/// Callback interface for receiving streaming token chunks.
1978
+///
1979
+/// Implement this in Swift / Kotlin and pass it to the free function
1980
+/// [`stream_chat_message`].
1981
+///
1982
+/// ```swift
1983
+/// class MyStreamHandler: StreamChunkListener {
1984
+/// func onChunk(chunk: StreamChunk) -> Bool {
1985
+/// print(chunk.delta, terminator: "")
1986
+/// return !chunk.done // return false to stop early
1987
+/// }
1988
+/// }
1989
+/// ```
1990
+public protocol StreamChunkListener: AnyObject, Sendable {
1991
+
1992
+ /**
1993
+ * Called for each token chunk during streaming inference.
1994
+ *
1995
+ * Return `true` to continue receiving chunks, or `false` to cancel
1996
+ * the stream early (the engine will still persist partial history).
1997
+ */
1998
+ func onChunk(chunk: StreamChunk) -> Bool
1999
+
2000
+}
2001
+
2002
+// Put the implementation in a struct so we don't pollute the top-level namespace
2003
+private struct UniffiCallbackInterfaceStreamChunkListener {
2004
+
2005
+ // Create the VTable using a series of closures.
2006
+ // Swift automatically converts these into C callback functions.
2007
+ //
2008
+ // This creates 1-element array, since this seems to be the only way to construct a const
2009
+ // pointer that we can pass to the Rust code.
2010
+ static let vtable: [UniffiVTableCallbackInterfaceStreamChunkListener] = [
2011
+ UniffiVTableCallbackInterfaceStreamChunkListener(
2012
+ uniffiFree: { (uniffiHandle: UInt64) -> Void in
2013
+ do {
2014
+ try FfiConverterCallbackInterfaceStreamChunkListener.handleMap.remove(
2015
+ handle: uniffiHandle)
2016
+ } catch {
2017
+ print(
2018
+ "Uniffi callback interface StreamChunkListener: handle missing in uniffiFree"
2019
+ )
2020
+ }
2021
+ },
2022
+ uniffiClone: { (uniffiHandle: UInt64) -> UInt64 in
2023
+ do {
2024
+ return try FfiConverterCallbackInterfaceStreamChunkListener.handleMap.clone(
2025
+ handle: uniffiHandle)
2026
+ } catch {
2027
+ fatalError(
2028
+ "Uniffi callback interface StreamChunkListener: handle missing in uniffiClone"
2029
+ )
2030
+ }
2031
+ },
2032
+ onChunk: {
2033
+ (
2034
+ uniffiHandle: UInt64,
2035
+ chunk: RustBuffer,
2036
+ uniffiOutReturn: UnsafeMutablePointer<Int8>,
2037
+ uniffiCallStatus: UnsafeMutablePointer<RustCallStatus>
2038
+ ) in
2039
+ let makeCall = {
2040
+ () throws -> Bool in
2041
+ guard
2042
+ let uniffiObj =
2043
+ try? FfiConverterCallbackInterfaceStreamChunkListener.handleMap.get(
2044
+ handle: uniffiHandle)
2045
+ else {
2046
+ throw UniffiInternalError.unexpectedStaleHandle
2047
+ }
2048
+ return uniffiObj.onChunk(
2049
+ chunk: try FfiConverterTypeStreamChunk_lift(chunk)
2050
+ )
2051
+ }
2052
+
2053
+ let writeReturn = { uniffiOutReturn.pointee = FfiConverterBool.lower($0) }
2054
+ uniffiTraitInterfaceCall(
2055
+ callStatus: uniffiCallStatus,
2056
+ makeCall: makeCall,
2057
+ writeReturn: writeReturn
2058
+ )
2059
+ }
2060
+ )
2061
+ ]
2062
+}
2063
+
2064
+private func uniffiCallbackInitStreamChunkListener() {
2065
+ uniffi_onde_fn_init_callback_vtable_streamchunklistener(
2066
+ UniffiCallbackInterfaceStreamChunkListener.vtable)
2067
+}
2068
+
2069
+// FfiConverter protocol for callback interfaces
2070
+#if swift(>=5.8)
2071
+ @_documentation(visibility: private)
2072
+#endif
2073
+private struct FfiConverterCallbackInterfaceStreamChunkListener {
2074
+ fileprivate static let handleMap = UniffiHandleMap<StreamChunkListener>()
2075
+}
2076
+
2077
+#if swift(>=5.8)
2078
+ @_documentation(visibility: private)
2079
+#endif
2080
+extension FfiConverterCallbackInterfaceStreamChunkListener: FfiConverter {
2081
+ typealias SwiftType = StreamChunkListener
2082
+ typealias FfiType = UInt64
2083
+
2084
+ #if swift(>=5.8)
2085
+ @_documentation(visibility: private)
2086
+ #endif
2087
+ public static func lift(_ handle: UInt64) throws -> SwiftType {
2088
+ try handleMap.get(handle: handle)
2089
+ }
2090
+
2091
+ #if swift(>=5.8)
2092
+ @_documentation(visibility: private)
2093
+ #endif
2094
+ public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> SwiftType {
2095
+ let handle: UInt64 = try readInt(&buf)
2096
+ return try lift(handle)
2097
+ }
2098
+
2099
+ #if swift(>=5.8)
2100
+ @_documentation(visibility: private)
2101
+ #endif
2102
+ public static func lower(_ v: SwiftType) -> UInt64 {
2103
+ return handleMap.insert(obj: v)
2104
+ }
2105
+
2106
+ #if swift(>=5.8)
2107
+ @_documentation(visibility: private)
2108
+ #endif
2109
+ public static func write(_ v: SwiftType, into buf: inout [UInt8]) {
2110
+ writeInt(&buf, lower(v))
2111
+ }
2112
+}
2113
+
2114
+#if swift(>=5.8)
2115
+ @_documentation(visibility: private)
2116
+#endif
2117
+public func FfiConverterCallbackInterfaceStreamChunkListener_lift(_ handle: UInt64) throws
2118
+ -> StreamChunkListener
2119
+{
2120
+ return try FfiConverterCallbackInterfaceStreamChunkListener.lift(handle)
2121
+}
2122
+
2123
+#if swift(>=5.8)
2124
+ @_documentation(visibility: private)
2125
+#endif
2126
+public func FfiConverterCallbackInterfaceStreamChunkListener_lower(_ v: StreamChunkListener)
2127
+ -> UInt64
2128
+{
2129
+ return FfiConverterCallbackInterfaceStreamChunkListener.lower(v)
2130
+}
2131
+
2132
+#if swift(>=5.8)
2133
+ @_documentation(visibility: private)
2134
+#endif
2135
+private struct FfiConverterOptionUInt64: FfiConverterRustBuffer {
2136
+ typealias SwiftType = UInt64?
2137
+
2138
+ public static func write(_ value: SwiftType, into buf: inout [UInt8]) {
2139
+ guard let value = value else {
2140
+ writeInt(&buf, Int8(0))
2141
+ return
2142
+ }
2143
+ writeInt(&buf, Int8(1))
2144
+ FfiConverterUInt64.write(value, into: &buf)
2145
+ }
2146
+
2147
+ public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> SwiftType {
2148
+ switch try readInt(&buf) as Int8 {
2149
+ case 0: return nil
2150
+ case 1: return try FfiConverterUInt64.read(from: &buf)
2151
+ default: throw UniffiInternalError.unexpectedOptionalTag
2152
+ }
2153
+ }
2154
+}
2155
+
2156
+#if swift(>=5.8)
2157
+ @_documentation(visibility: private)
2158
+#endif
2159
+private struct FfiConverterOptionFloat: FfiConverterRustBuffer {
2160
+ typealias SwiftType = Float?
2161
+
2162
+ public static func write(_ value: SwiftType, into buf: inout [UInt8]) {
2163
+ guard let value = value else {
2164
+ writeInt(&buf, Int8(0))
2165
+ return
2166
+ }
2167
+ writeInt(&buf, Int8(1))
2168
+ FfiConverterFloat.write(value, into: &buf)
2169
+ }
2170
+
2171
+ public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> SwiftType {
2172
+ switch try readInt(&buf) as Int8 {
2173
+ case 0: return nil
2174
+ case 1: return try FfiConverterFloat.read(from: &buf)
2175
+ default: throw UniffiInternalError.unexpectedOptionalTag
2176
+ }
2177
+ }
2178
+}
2179
+
2180
+#if swift(>=5.8)
2181
+ @_documentation(visibility: private)
2182
+#endif
2183
+private struct FfiConverterOptionDouble: FfiConverterRustBuffer {
2184
+ typealias SwiftType = Double?
2185
+
2186
+ public static func write(_ value: SwiftType, into buf: inout [UInt8]) {
2187
+ guard let value = value else {
2188
+ writeInt(&buf, Int8(0))
2189
+ return
2190
+ }
2191
+ writeInt(&buf, Int8(1))
2192
+ FfiConverterDouble.write(value, into: &buf)
2193
+ }
2194
+
2195
+ public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> SwiftType {
2196
+ switch try readInt(&buf) as Int8 {
2197
+ case 0: return nil
2198
+ case 1: return try FfiConverterDouble.read(from: &buf)
2199
+ default: throw UniffiInternalError.unexpectedOptionalTag
2200
+ }
2201
+ }
2202
+}
2203
+
2204
+#if swift(>=5.8)
2205
+ @_documentation(visibility: private)
2206
+#endif
2207
+private struct FfiConverterOptionString: FfiConverterRustBuffer {
2208
+ typealias SwiftType = String?
2209
+
2210
+ public static func write(_ value: SwiftType, into buf: inout [UInt8]) {
2211
+ guard let value = value else {
2212
+ writeInt(&buf, Int8(0))
2213
+ return
2214
+ }
2215
+ writeInt(&buf, Int8(1))
2216
+ FfiConverterString.write(value, into: &buf)
2217
+ }
2218
+
2219
+ public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> SwiftType {
2220
+ switch try readInt(&buf) as Int8 {
2221
+ case 0: return nil
2222
+ case 1: return try FfiConverterString.read(from: &buf)
2223
+ default: throw UniffiInternalError.unexpectedOptionalTag
2224
+ }
2225
+ }
2226
+}
2227
+
2228
+#if swift(>=5.8)
2229
+ @_documentation(visibility: private)
2230
+#endif
2231
+private struct FfiConverterOptionTypeSamplingConfig: FfiConverterRustBuffer {
2232
+ typealias SwiftType = SamplingConfig?
2233
+
2234
+ public static func write(_ value: SwiftType, into buf: inout [UInt8]) {
2235
+ guard let value = value else {
2236
+ writeInt(&buf, Int8(0))
2237
+ return
2238
+ }
2239
+ writeInt(&buf, Int8(1))
2240
+ FfiConverterTypeSamplingConfig.write(value, into: &buf)
2241
+ }
2242
+
2243
+ public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> SwiftType {
2244
+ switch try readInt(&buf) as Int8 {
2245
+ case 0: return nil
2246
+ case 1: return try FfiConverterTypeSamplingConfig.read(from: &buf)
2247
+ default: throw UniffiInternalError.unexpectedOptionalTag
2248
+ }
2249
+ }
2250
+}
2251
+
2252
+#if swift(>=5.8)
2253
+ @_documentation(visibility: private)
2254
+#endif
2255
+private struct FfiConverterSequenceString: FfiConverterRustBuffer {
2256
+ typealias SwiftType = [String]
2257
+
2258
+ public static func write(_ value: [String], into buf: inout [UInt8]) {
2259
+ let len = Int32(value.count)
2260
+ writeInt(&buf, len)
2261
+ for item in value {
2262
+ FfiConverterString.write(item, into: &buf)
2263
+ }
2264
+ }
2265
+
2266
+ public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> [String] {
2267
+ let len: Int32 = try readInt(&buf)
2268
+ var seq = [String]()
2269
+ seq.reserveCapacity(Int(len))
2270
+ for _ in 0..<len {
2271
+ seq.append(try FfiConverterString.read(from: &buf))
2272
+ }
2273
+ return seq
2274
+ }
2275
+}
2276
+
2277
+#if swift(>=5.8)
2278
+ @_documentation(visibility: private)
2279
+#endif
2280
+private struct FfiConverterSequenceTypeChatMessage: FfiConverterRustBuffer {
2281
+ typealias SwiftType = [ChatMessage]
2282
+
2283
+ public static func write(_ value: [ChatMessage], into buf: inout [UInt8]) {
2284
+ let len = Int32(value.count)
2285
+ writeInt(&buf, len)
2286
+ for item in value {
2287
+ FfiConverterTypeChatMessage.write(item, into: &buf)
2288
+ }
2289
+ }
2290
+
2291
+ public static func read(from buf: inout (data: Data, offset: Data.Index)) throws
2292
+ -> [ChatMessage]
2293
+ {
2294
+ let len: Int32 = try readInt(&buf)
2295
+ var seq = [ChatMessage]()
2296
+ seq.reserveCapacity(Int(len))
2297
+ for _ in 0..<len {
2298
+ seq.append(try FfiConverterTypeChatMessage.read(from: &buf))
2299
+ }
2300
+ return seq
2301
+ }
2302
+}
2303
+private let UNIFFI_RUST_FUTURE_POLL_READY: Int8 = 0
2304
+private let UNIFFI_RUST_FUTURE_POLL_WAKE: Int8 = 1
2305
+
2306
+private let uniffiContinuationHandleMap = UniffiHandleMap<UnsafeContinuation<Int8, Never>>()
2307
+
2308
+private func uniffiRustCallAsync<F, T>(
2309
+ rustFutureFunc: () -> UInt64,
2310
+ pollFunc: (UInt64, @escaping UniffiRustFutureContinuationCallback, UInt64) -> Void,
2311
+ completeFunc: (UInt64, UnsafeMutablePointer<RustCallStatus>) -> F,
2312
+ freeFunc: (UInt64) -> Void,
2313
+ liftFunc: (F) throws -> T,
2314
+ errorHandler: ((RustBuffer) throws -> Swift.Error)?
2315
+) async throws -> T {
2316
+ // Make sure to call the ensure init function since future creation doesn't have a
2317
+ // RustCallStatus param, so doesn't use makeRustCall()
2318
+ uniffiEnsureOndeInitialized()
2319
+ let rustFuture = rustFutureFunc()
2320
+ defer {
2321
+ freeFunc(rustFuture)
2322
+ }
2323
+ var pollResult: Int8
2324
+ repeat {
2325
+ pollResult = await withUnsafeContinuation {
2326
+ pollFunc(
2327
+ rustFuture,
2328
+ { handle, pollResult in
2329
+ uniffiFutureContinuationCallback(handle: handle, pollResult: pollResult)
2330
+ },
2331
+ uniffiContinuationHandleMap.insert(obj: $0)
2332
+ )
2333
+ }
2334
+ } while pollResult != UNIFFI_RUST_FUTURE_POLL_READY
2335
+
2336
+ return try liftFunc(
2337
+ makeRustCall(
2338
+ { completeFunc(rustFuture, $0) },
2339
+ errorHandler: errorHandler
2340
+ ))
2341
+}
2342
+
2343
+// Callback handlers for an async calls. These are invoked by Rust when the future is ready. They
2344
+// lift the return value or error and resume the suspended function.
2345
+private func uniffiFutureContinuationCallback(handle: UInt64, pollResult: Int8) {
2346
+ if let continuation = try? uniffiContinuationHandleMap.remove(handle: handle) {
2347
+ continuation.resume(returning: pollResult)
2348
+ } else {
2349
+ print("uniffiFutureContinuationCallback invalid handle")
2350
+ }
2351
+}
2352
+/// Create an assistant message.
2353
+public func assistantMessage(content: String) -> ChatMessage {
2354
+ return try! FfiConverterTypeChatMessage_lift(
2355
+ try! rustCall {
2356
+ uniffi_onde_fn_func_assistant_message(
2357
+ FfiConverterString.lower(content), $0
2358
+ )
2359
+ })
2360
+}
2361
+/// Return the platform-appropriate default GGUF model configuration.
2362
+///
2363
+/// - tvOS / iOS / Android → Qwen 2.5 1.5B (~941 MB)
2364
+/// - macOS / Windows / Linux → Qwen 2.5 3B (~1.93 GB)
2365
+public func defaultModelConfig() -> GgufModelConfig {
2366
+ return try! FfiConverterTypeGgufModelConfig_lift(
2367
+ try! rustCall {
2368
+ uniffi_onde_fn_func_default_model_config(
2369
+ $0
2370
+ )
2371
+ })
2372
+}
2373
+/// Return default sampling parameters for creative chat.
2374
+public func defaultSamplingConfig() -> SamplingConfig {
2375
+ return try! FfiConverterTypeSamplingConfig_lift(
2376
+ try! rustCall {
2377
+ uniffi_onde_fn_func_default_sampling_config(
2378
+ $0
2379
+ )
2380
+ })
2381
+}
2382
+/// Return deterministic (greedy) sampling parameters.
2383
+public func deterministicSamplingConfig() -> SamplingConfig {
2384
+ return try! FfiConverterTypeSamplingConfig_lift(
2385
+ try! rustCall {
2386
+ uniffi_onde_fn_func_deterministic_sampling_config(
2387
+ $0
2388
+ )
2389
+ })
2390
+}
2391
+/// Return conservative sampling parameters for mobile devices.
2392
+public func mobileSamplingConfig() -> SamplingConfig {
2393
+ return try! FfiConverterTypeSamplingConfig_lift(
2394
+ try! rustCall {
2395
+ uniffi_onde_fn_func_mobile_sampling_config(
2396
+ $0
2397
+ )
2398
+ })
2399
+}
2400
+/// Return the Qwen 2.5 1.5B GGUF model configuration (~941 MB).
2401
+public func qwen2515bConfig() -> GgufModelConfig {
2402
+ return try! FfiConverterTypeGgufModelConfig_lift(
2403
+ try! rustCall {
2404
+ uniffi_onde_fn_func_qwen25_1_5b_config(
2405
+ $0
2406
+ )
2407
+ })
2408
+}
2409
+/// Return the Qwen 2.5 3B GGUF model configuration (~1.93 GB).
2410
+public func qwen253bConfig() -> GgufModelConfig {
2411
+ return try! FfiConverterTypeGgufModelConfig_lift(
2412
+ try! rustCall {
2413
+ uniffi_onde_fn_func_qwen25_3b_config(
2414
+ $0
2415
+ )
2416
+ })
2417
+}
2418
+/// Stream a chat message through the engine, delivering token chunks to
2419
+/// the `listener` callback.
2420
+///
2421
+/// This is a **free function** (not an Object method) because UniFFI 0.31
2422
+/// requires `callback_interface` parameters to be passed to free functions
2423
+/// rather than Object methods.
2424
+///
2425
+/// The `listener.on_chunk()` callback is called for each token delta.
2426
+/// Return `true` to continue, or `false` to cancel early.
2427
+///
2428
+/// The user message and assembled reply are automatically appended to the
2429
+/// engine's conversation history when streaming completes.
2430
+///
2431
+/// ```swift
2432
+/// class MyHandler: StreamChunkListener {
2433
+/// func onChunk(chunk: StreamChunk) -> Bool {
2434
+/// print(chunk.delta, terminator: "")
2435
+/// return !chunk.done
2436
+/// }
2437
+/// }
2438
+///
2439
+/// try await streamChatMessage(
2440
+/// engine: engine,
2441
+/// message: "Tell me a story.",
2442
+/// listener: MyHandler()
2443
+/// )
2444
+/// ```
2445
+public func streamChatMessage(
2446
+ engine: OndeChatEngine, message: String, listener: StreamChunkListener
2447
+) async throws {
2448
+ return
2449
+ try await uniffiRustCallAsync(
2450
+ rustFutureFunc: {
2451
+ uniffi_onde_fn_func_stream_chat_message(
2452
+ FfiConverterTypeOndeChatEngine_lower(engine), FfiConverterString.lower(message),
2453
+ FfiConverterCallbackInterfaceStreamChunkListener_lower(listener)
2454
+ )
2455
+ },
2456
+ pollFunc: ffi_onde_rust_future_poll_void,
2457
+ completeFunc: ffi_onde_rust_future_complete_void,
2458
+ freeFunc: ffi_onde_rust_future_free_void,
2459
+ liftFunc: { $0 },
2460
+ errorHandler: FfiConverterTypeInferenceError_lift
2461
+ )
2462
+}
2463
+/// Create a system message.
2464
+public func systemMessage(content: String) -> ChatMessage {
2465
+ return try! FfiConverterTypeChatMessage_lift(
2466
+ try! rustCall {
2467
+ uniffi_onde_fn_func_system_message(
2468
+ FfiConverterString.lower(content), $0
2469
+ )
2470
+ })
2471
+}
2472
+/// Create a user message.
2473
+public func userMessage(content: String) -> ChatMessage {
2474
+ return try! FfiConverterTypeChatMessage_lift(
2475
+ try! rustCall {
2476
+ uniffi_onde_fn_func_user_message(
2477
+ FfiConverterString.lower(content), $0
2478
+ )
2479
+ })
2480
+}
2481
+
2482
+private enum InitializationResult {
2483
+ case ok
2484
+ case contractVersionMismatch
2485
+ case apiChecksumMismatch
2486
+}
2487
+// Use a global variable to perform the versioning checks. Swift ensures that
2488
+// the code inside is only computed once.
2489
+private let initializationResult: InitializationResult = {
2490
+ // Get the bindings contract version from our ComponentInterface
2491
+ let bindings_contract_version = 30
2492
+ // Get the scaffolding contract version by calling the into the dylib
2493
+ let scaffolding_contract_version = ffi_onde_uniffi_contract_version()
2494
+ if bindings_contract_version != scaffolding_contract_version {
2495
+ return InitializationResult.contractVersionMismatch
2496
+ }
2497
+ if uniffi_onde_checksum_func_assistant_message() != 47135 {
2498
+ return InitializationResult.apiChecksumMismatch
2499
+ }
2500
+ if uniffi_onde_checksum_func_default_model_config() != 34766 {
2501
+ return InitializationResult.apiChecksumMismatch
2502
+ }
2503
+ if uniffi_onde_checksum_func_default_sampling_config() != 57358 {
2504
+ return InitializationResult.apiChecksumMismatch
2505
+ }
2506
+ if uniffi_onde_checksum_func_deterministic_sampling_config() != 3003 {
2507
+ return InitializationResult.apiChecksumMismatch
2508
+ }
2509
+ if uniffi_onde_checksum_func_mobile_sampling_config() != 46137 {
2510
+ return InitializationResult.apiChecksumMismatch
2511
+ }
2512
+ if uniffi_onde_checksum_func_qwen25_1_5b_config() != 41668 {
2513
+ return InitializationResult.apiChecksumMismatch
2514
+ }
2515
+ if uniffi_onde_checksum_func_qwen25_3b_config() != 36458 {
2516
+ return InitializationResult.apiChecksumMismatch
2517
+ }
2518
+ if uniffi_onde_checksum_func_stream_chat_message() != 5168 {
2519
+ return InitializationResult.apiChecksumMismatch
2520
+ }
2521
+ if uniffi_onde_checksum_func_system_message() != 55655 {
2522
+ return InitializationResult.apiChecksumMismatch
2523
+ }
2524
+ if uniffi_onde_checksum_func_user_message() != 23108 {
2525
+ return InitializationResult.apiChecksumMismatch
2526
+ }
2527
+ if uniffi_onde_checksum_method_ondechatengine_clear_history() != 5662 {
2528
+ return InitializationResult.apiChecksumMismatch
2529
+ }
2530
+ if uniffi_onde_checksum_method_ondechatengine_clear_system_prompt() != 46275 {
2531
+ return InitializationResult.apiChecksumMismatch
2532
+ }
2533
+ if uniffi_onde_checksum_method_ondechatengine_generate() != 63069 {
2534
+ return InitializationResult.apiChecksumMismatch
2535
+ }
2536
+ if uniffi_onde_checksum_method_ondechatengine_history() != 45301 {
2537
+ return InitializationResult.apiChecksumMismatch
2538
+ }
2539
+ if uniffi_onde_checksum_method_ondechatengine_info() != 42415 {
2540
+ return InitializationResult.apiChecksumMismatch
2541
+ }
2542
+ if uniffi_onde_checksum_method_ondechatengine_is_loaded() != 59838 {
2543
+ return InitializationResult.apiChecksumMismatch
2544
+ }
2545
+ if uniffi_onde_checksum_method_ondechatengine_load_default_model() != 32187 {
2546
+ return InitializationResult.apiChecksumMismatch
2547
+ }
2548
+ if uniffi_onde_checksum_method_ondechatengine_load_gguf_model() != 6873 {
2549
+ return InitializationResult.apiChecksumMismatch
2550
+ }
2551
+ if uniffi_onde_checksum_method_ondechatengine_push_history() != 61696 {
2552
+ return InitializationResult.apiChecksumMismatch
2553
+ }
2554
+ if uniffi_onde_checksum_method_ondechatengine_send_message() != 23695 {
2555
+ return InitializationResult.apiChecksumMismatch
2556
+ }
2557
+ if uniffi_onde_checksum_method_ondechatengine_set_sampling() != 10759 {
2558
+ return InitializationResult.apiChecksumMismatch
2559
+ }
2560
+ if uniffi_onde_checksum_method_ondechatengine_set_system_prompt() != 63168 {
2561
+ return InitializationResult.apiChecksumMismatch
2562
+ }
2563
+ if uniffi_onde_checksum_method_ondechatengine_unload_model() != 33799 {
2564
+ return InitializationResult.apiChecksumMismatch
2565
+ }
2566
+ if uniffi_onde_checksum_constructor_ondechatengine_new() != 39683 {
2567
+ return InitializationResult.apiChecksumMismatch
2568
+ }
2569
+ if uniffi_onde_checksum_method_streamchunklistener_on_chunk() != 33920 {
2570
+ return InitializationResult.apiChecksumMismatch
2571
+ }
2572
+
2573
+ uniffiCallbackInitStreamChunkListener()
2574
+ return InitializationResult.ok
2575
+}()
2576
+
2577
+// Make the ensure init function public so that other modules which have external type references to
2578
+// our types can call it.
2579
+public func uniffiEnsureOndeInitialized() {
2580
+ switch initializationResult {
2581
+ case .ok:
2582
+ break
2583
+ case .contractVersionMismatch:
2584
+ fatalError("UniFFI contract version mismatch: try cleaning and rebuilding your project")
2585
+ case .apiChecksumMismatch:
2586
+ fatalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project")
2587
+ }
2588
+}
2589
+
2590
+// swiftlint:enable all