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