main
swift 3,344 lines 105 KB
Raw
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 fileprivate extension RustBuffer {
15 // Allocate a new buffer, copying the contents of a `UInt8` array.
16 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 static func empty() -> RustBuffer {
24 RustBuffer(capacity: 0, len:0, data: nil)
25 }
26
27 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 func deallocate() {
34 try! rustCall { ffi_onde_rustbuffer_free(self, $0) }
35 }
36 }
37
38 fileprivate extension ForeignBytes {
39 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 fileprivate extension Data {
52 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 fileprivate 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 fileprivate func readInt<T: FixedWidthInteger>(_ reader: inout (data: Data, offset: Data.Index)) throws -> T {
83 let range = reader.offset..<reader.offset + MemoryLayout<T>.size
84 guard reader.data.count >= range.upperBound else {
85 throw UniffiInternalError.bufferOverflow
86 }
87 if T.self == UInt8.self {
88 let value = reader.data[reader.offset]
89 reader.offset += 1
90 return value as! T
91 }
92 var value: T = 0
93 let _ = withUnsafeMutableBytes(of: &value, { reader.data.copyBytes(to: $0, from: range)})
94 reader.offset = range.upperBound
95 return value.bigEndian
96 }
97
98 // Reads an arbitrary number of bytes, to be used to read
99 // raw bytes, this is useful when lifting strings
100 fileprivate func readBytes(_ reader: inout (data: Data, offset: Data.Index), count: Int) throws -> Array<UInt8> {
101 let range = reader.offset..<(reader.offset+count)
102 guard reader.data.count >= range.upperBound else {
103 throw UniffiInternalError.bufferOverflow
104 }
105 var value = [UInt8](repeating: 0, count: count)
106 value.withUnsafeMutableBufferPointer({ buffer in
107 reader.data.copyBytes(to: buffer, from: range)
108 })
109 reader.offset = range.upperBound
110 return value
111 }
112
113 // Reads a float at the current offset.
114 fileprivate func readFloat(_ reader: inout (data: Data, offset: Data.Index)) throws -> Float {
115 return Float(bitPattern: try readInt(&reader))
116 }
117
118 // Reads a float at the current offset.
119 fileprivate func readDouble(_ reader: inout (data: Data, offset: Data.Index)) throws -> Double {
120 return Double(bitPattern: try readInt(&reader))
121 }
122
123 // Indicates if the offset has reached the end of the buffer.
124 fileprivate func hasRemaining(_ reader: (data: Data, offset: Data.Index)) -> Bool {
125 return reader.offset < reader.data.count
126 }
127
128 // Define writer functionality. Normally this would be defined in a class or
129 // struct, but we use standalone functions instead in order to make external
130 // types work. See the above discussion on Readers for details.
131
132 fileprivate func createWriter() -> [UInt8] {
133 return []
134 }
135
136 fileprivate func writeBytes<S>(_ writer: inout [UInt8], _ byteArr: S) where S: Sequence, S.Element == UInt8 {
137 writer.append(contentsOf: byteArr)
138 }
139
140 // Writes an integer in big-endian order.
141 //
142 // Warning: make sure what you are trying to write
143 // is in the correct type!
144 fileprivate func writeInt<T: FixedWidthInteger>(_ writer: inout [UInt8], _ value: T) {
145 var value = value.bigEndian
146 withUnsafeBytes(of: &value) { writer.append(contentsOf: $0) }
147 }
148
149 fileprivate func writeFloat(_ writer: inout [UInt8], _ value: Float) {
150 writeInt(&writer, value.bitPattern)
151 }
152
153 fileprivate func writeDouble(_ writer: inout [UInt8], _ value: Double) {
154 writeInt(&writer, value.bitPattern)
155 }
156
157 // Protocol for types that transfer other types across the FFI. This is
158 // analogous to the Rust trait of the same name.
159 fileprivate protocol FfiConverter {
160 associatedtype FfiType
161 associatedtype SwiftType
162
163 static func lift(_ value: FfiType) throws -> SwiftType
164 static func lower(_ value: SwiftType) -> FfiType
165 static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> SwiftType
166 static func write(_ value: SwiftType, into buf: inout [UInt8])
167 }
168
169 // Types conforming to `Primitive` pass themselves directly over the FFI.
170 fileprivate protocol FfiConverterPrimitive: FfiConverter where FfiType == SwiftType { }
171
172 extension FfiConverterPrimitive {
173 #if swift(>=5.8)
174 @_documentation(visibility: private)
175 #endif
176 public static func lift(_ value: FfiType) throws -> SwiftType {
177 return value
178 }
179
180 #if swift(>=5.8)
181 @_documentation(visibility: private)
182 #endif
183 public static func lower(_ value: SwiftType) -> FfiType {
184 return value
185 }
186 }
187
188 // Types conforming to `FfiConverterRustBuffer` lift and lower into a `RustBuffer`.
189 // Used for complex types where it's hard to write a custom lift/lower.
190 fileprivate protocol FfiConverterRustBuffer: FfiConverter where FfiType == RustBuffer {}
191
192 extension FfiConverterRustBuffer {
193 #if swift(>=5.8)
194 @_documentation(visibility: private)
195 #endif
196 public static func lift(_ buf: RustBuffer) throws -> SwiftType {
197 var reader = createReader(data: Data(rustBuffer: buf))
198 let value = try read(from: &reader)
199 if hasRemaining(reader) {
200 throw UniffiInternalError.incompleteData
201 }
202 buf.deallocate()
203 return value
204 }
205
206 #if swift(>=5.8)
207 @_documentation(visibility: private)
208 #endif
209 public static func lower(_ value: SwiftType) -> RustBuffer {
210 var writer = createWriter()
211 write(value, into: &writer)
212 return RustBuffer(bytes: writer)
213 }
214 }
215 // An error type for FFI errors. These errors occur at the UniFFI level, not
216 // the library level.
217 fileprivate enum UniffiInternalError: LocalizedError {
218 case bufferOverflow
219 case incompleteData
220 case unexpectedOptionalTag
221 case unexpectedEnumCase
222 case unexpectedNullPointer
223 case unexpectedRustCallStatusCode
224 case unexpectedRustCallError
225 case unexpectedStaleHandle
226 case rustPanic(_ message: String)
227
228 public var errorDescription: String? {
229 switch self {
230 case .bufferOverflow: return "Reading the requested value would read past the end of the buffer"
231 case .incompleteData: return "The buffer still has data after lifting its containing value"
232 case .unexpectedOptionalTag: return "Unexpected optional tag; should be 0 or 1"
233 case .unexpectedEnumCase: return "Raw enum value doesn't match any cases"
234 case .unexpectedNullPointer: return "Raw pointer value was null"
235 case .unexpectedRustCallStatusCode: return "Unexpected RustCallStatus code"
236 case .unexpectedRustCallError: return "CALL_ERROR but no errorClass specified"
237 case .unexpectedStaleHandle: return "The object in the handle map has been dropped already"
238 case let .rustPanic(message): return message
239 }
240 }
241 }
242
243 fileprivate extension NSLock {
244 func withLock<T>(f: () throws -> T) rethrows -> T {
245 self.lock()
246 defer { self.unlock() }
247 return try f()
248 }
249 }
250
251 fileprivate let CALL_SUCCESS: Int8 = 0
252 fileprivate let CALL_ERROR: Int8 = 1
253 fileprivate let CALL_UNEXPECTED_ERROR: Int8 = 2
254 fileprivate let CALL_CANCELLED: Int8 = 3
255
256 fileprivate extension RustCallStatus {
257 init() {
258 self.init(
259 code: CALL_SUCCESS,
260 errorBuf: RustBuffer.init(
261 capacity: 0,
262 len: 0,
263 data: nil
264 )
265 )
266 }
267 }
268
269 private func rustCall<T>(_ callback: (UnsafeMutablePointer<RustCallStatus>) -> T) throws -> T {
270 let neverThrow: ((RustBuffer) throws -> Never)? = nil
271 return try makeRustCall(callback, errorHandler: neverThrow)
272 }
273
274 private func rustCallWithError<T, E: Swift.Error>(
275 _ errorHandler: @escaping (RustBuffer) throws -> E,
276 _ callback: (UnsafeMutablePointer<RustCallStatus>) -> T) throws -> T {
277 try makeRustCall(callback, errorHandler: errorHandler)
278 }
279
280 private func makeRustCall<T, E: Swift.Error>(
281 _ callback: (UnsafeMutablePointer<RustCallStatus>) -> T,
282 errorHandler: ((RustBuffer) throws -> E)?
283 ) throws -> T {
284 uniffiEnsureOndeInitialized()
285 var callStatus = RustCallStatus.init()
286 let returnedVal = callback(&callStatus)
287 try uniffiCheckCallStatus(callStatus: callStatus, errorHandler: errorHandler)
288 return returnedVal
289 }
290
291 private func uniffiCheckCallStatus<E: Swift.Error>(
292 callStatus: RustCallStatus,
293 errorHandler: ((RustBuffer) throws -> E)?
294 ) throws {
295 switch callStatus.code {
296 case CALL_SUCCESS:
297 return
298
299 case CALL_ERROR:
300 if let errorHandler = errorHandler {
301 throw try errorHandler(callStatus.errorBuf)
302 } else {
303 callStatus.errorBuf.deallocate()
304 throw UniffiInternalError.unexpectedRustCallError
305 }
306
307 case CALL_UNEXPECTED_ERROR:
308 // When the rust code sees a panic, it tries to construct a RustBuffer
309 // with the message. But if that code panics, then it just sends back
310 // an empty buffer.
311 if callStatus.errorBuf.len > 0 {
312 throw UniffiInternalError.rustPanic(try FfiConverterString.lift(callStatus.errorBuf))
313 } else {
314 callStatus.errorBuf.deallocate()
315 throw UniffiInternalError.rustPanic("Rust panic")
316 }
317
318 case CALL_CANCELLED:
319 fatalError("Cancellation not supported yet")
320
321 default:
322 throw UniffiInternalError.unexpectedRustCallStatusCode
323 }
324 }
325
326 private func uniffiTraitInterfaceCall<T>(
327 callStatus: UnsafeMutablePointer<RustCallStatus>,
328 makeCall: () throws -> T,
329 writeReturn: (T) -> ()
330 ) {
331 do {
332 try writeReturn(makeCall())
333 } catch let error {
334 callStatus.pointee.code = CALL_UNEXPECTED_ERROR
335 callStatus.pointee.errorBuf = FfiConverterString.lower(String(describing: error))
336 }
337 }
338
339 private func uniffiTraitInterfaceCallWithError<T, E>(
340 callStatus: UnsafeMutablePointer<RustCallStatus>,
341 makeCall: () throws -> T,
342 writeReturn: (T) -> (),
343 lowerError: (E) -> RustBuffer
344 ) {
345 do {
346 try writeReturn(makeCall())
347 } catch let error as E {
348 callStatus.pointee.code = CALL_ERROR
349 callStatus.pointee.errorBuf = lowerError(error)
350 } catch {
351 callStatus.pointee.code = CALL_UNEXPECTED_ERROR
352 callStatus.pointee.errorBuf = FfiConverterString.lower(String(describing: error))
353 }
354 }
355 // Initial value and increment amount for handles.
356 // These ensure that SWIFT handles always have the lowest bit set
357 fileprivate let UNIFFI_HANDLEMAP_INITIAL: UInt64 = 1
358 fileprivate let UNIFFI_HANDLEMAP_DELTA: UInt64 = 2
359
360 fileprivate final class UniffiHandleMap<T>: @unchecked Sendable {
361 // All mutation happens with this lock held, which is why we implement @unchecked Sendable.
362 private let lock = NSLock()
363 private var map: [UInt64: T] = [:]
364 private var currentHandle: UInt64 = UNIFFI_HANDLEMAP_INITIAL
365
366 func insert(obj: T) -> UInt64 {
367 lock.withLock {
368 return doInsert(obj)
369 }
370 }
371
372 // Low-level insert function, this assumes `lock` is held.
373 private func doInsert(_ obj: T) -> UInt64 {
374 let handle = currentHandle
375 currentHandle += UNIFFI_HANDLEMAP_DELTA
376 map[handle] = obj
377 return handle
378 }
379
380 func get(handle: UInt64) throws -> T {
381 try lock.withLock {
382 guard let obj = map[handle] else {
383 throw UniffiInternalError.unexpectedStaleHandle
384 }
385 return obj
386 }
387 }
388
389 func clone(handle: UInt64) throws -> UInt64 {
390 try lock.withLock {
391 guard let obj = map[handle] else {
392 throw UniffiInternalError.unexpectedStaleHandle
393 }
394 return doInsert(obj)
395 }
396 }
397
398 @discardableResult
399 func remove(handle: UInt64) throws -> T {
400 try lock.withLock {
401 guard let obj = map.removeValue(forKey: handle) else {
402 throw UniffiInternalError.unexpectedStaleHandle
403 }
404 return obj
405 }
406 }
407
408 var count: Int {
409 get {
410 map.count
411 }
412 }
413 }
414
415
416 // Public interface members begin here.
417 // Magic number for the Rust proxy to call using the same mechanism as every other method,
418 // to free the callback once it's dropped by Rust.
419 private let IDX_CALLBACK_FREE: Int32 = 0
420 // Callback return codes
421 private let UNIFFI_CALLBACK_SUCCESS: Int32 = 0
422 private let UNIFFI_CALLBACK_ERROR: Int32 = 1
423 private let UNIFFI_CALLBACK_UNEXPECTED_ERROR: Int32 = 2
424
425 #if swift(>=5.8)
426 @_documentation(visibility: private)
427 #endif
428 fileprivate struct FfiConverterUInt8: FfiConverterPrimitive {
429 typealias FfiType = UInt8
430 typealias SwiftType = UInt8
431
432 public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> UInt8 {
433 return try lift(readInt(&buf))
434 }
435
436 public static func write(_ value: UInt8, into buf: inout [UInt8]) {
437 writeInt(&buf, lower(value))
438 }
439 }
440
441 #if swift(>=5.8)
442 @_documentation(visibility: private)
443 #endif
444 fileprivate struct FfiConverterUInt64: FfiConverterPrimitive {
445 typealias FfiType = UInt64
446 typealias SwiftType = UInt64
447
448 public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> UInt64 {
449 return try lift(readInt(&buf))
450 }
451
452 public static func write(_ value: SwiftType, into buf: inout [UInt8]) {
453 writeInt(&buf, lower(value))
454 }
455 }
456
457 #if swift(>=5.8)
458 @_documentation(visibility: private)
459 #endif
460 fileprivate struct FfiConverterFloat: FfiConverterPrimitive {
461 typealias FfiType = Float
462 typealias SwiftType = Float
463
464 public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> Float {
465 return try lift(readFloat(&buf))
466 }
467
468 public static func write(_ value: Float, into buf: inout [UInt8]) {
469 writeFloat(&buf, lower(value))
470 }
471 }
472
473 #if swift(>=5.8)
474 @_documentation(visibility: private)
475 #endif
476 fileprivate struct FfiConverterDouble: FfiConverterPrimitive {
477 typealias FfiType = Double
478 typealias SwiftType = Double
479
480 public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> Double {
481 return try lift(readDouble(&buf))
482 }
483
484 public static func write(_ value: Double, into buf: inout [UInt8]) {
485 writeDouble(&buf, lower(value))
486 }
487 }
488
489 #if swift(>=5.8)
490 @_documentation(visibility: private)
491 #endif
492 fileprivate struct FfiConverterBool : FfiConverter {
493 typealias FfiType = Int8
494 typealias SwiftType = Bool
495
496 public static func lift(_ value: Int8) throws -> Bool {
497 return value != 0
498 }
499
500 public static func lower(_ value: Bool) -> Int8 {
501 return value ? 1 : 0
502 }
503
504 public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> Bool {
505 return try lift(readInt(&buf))
506 }
507
508 public static func write(_ value: Bool, into buf: inout [UInt8]) {
509 writeInt(&buf, lower(value))
510 }
511 }
512
513 #if swift(>=5.8)
514 @_documentation(visibility: private)
515 #endif
516 fileprivate struct FfiConverterString: FfiConverter {
517 typealias SwiftType = String
518 typealias FfiType = RustBuffer
519
520 public static func lift(_ value: RustBuffer) throws -> String {
521 defer {
522 value.deallocate()
523 }
524 if value.data == nil {
525 return String()
526 }
527 let bytes = UnsafeBufferPointer<UInt8>(start: value.data!, count: Int(value.len))
528 return String(bytes: bytes, encoding: String.Encoding.utf8)!
529 }
530
531 public static func lower(_ value: String) -> RustBuffer {
532 return value.utf8CString.withUnsafeBufferPointer { ptr in
533 // The swift string gives us int8_t, we want uint8_t.
534 ptr.withMemoryRebound(to: UInt8.self) { ptr in
535 // The swift string gives us a trailing null byte, we don't want it.
536 let buf = UnsafeBufferPointer(rebasing: ptr.prefix(upTo: ptr.count - 1))
537 return RustBuffer.from(buf)
538 }
539 }
540 }
541
542 public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> String {
543 let len: Int32 = try readInt(&buf)
544 return String(bytes: try readBytes(&buf, count: Int(len)), encoding: String.Encoding.utf8)!
545 }
546
547 public static func write(_ value: String, into buf: inout [UInt8]) {
548 let len = Int32(value.utf8.count)
549 writeInt(&buf, len)
550 writeBytes(&buf, value.utf8)
551 }
552 }
553
554
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 */
567 public protocol OndeChatEngineProtocol: AnyObject, Sendable {
568
569 /**
570 * Clear the conversation history but keep the model loaded.
571 *
572 * Returns the number of turns that were removed.
573 */
574 func clearHistory() async -> UInt64
575
576 /**
577 * Clear the system prompt.
578 */
579 func clearSystemPrompt() async
580
581 /**
582 * Run inference on an explicit list of messages WITHOUT modifying the
583 * engine's internal history.
584 *
585 * Useful for one-shot prompts (e.g. prompt enhancement).
586 */
587 func generate(messages: [ChatMessage], sampling: SamplingConfig?) async throws -> 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 model assigned to this app via the Onde dashboard.
606 *
607 * The `app_id` and `app_secret` identify your app on
608 * [ondeinference.com](https://ondeinference.com). The backend returns
609 * the GGUF model configuration assigned to your app; if no model is
610 * assigned (HTTP 404) the platform default is loaded instead.
611 *
612 * Returns the wall-clock loading time in seconds.
613 */
614 func loadAssignedModel(appId: String, appSecret: String, systemPrompt: String?, sampling: SamplingConfig?) async throws -> Double
615
616 /**
617 * Load the platform-appropriate default model.
618 *
619 * - tvOS / iOS / Android → Qwen 2.5 1.5B (~941 MB)
620 * - macOS / Windows / Linux → Qwen 2.5 3B (~1.93 GB)
621 *
622 * Returns the wall-clock loading time in seconds.
623 */
624 func loadDefaultModel(systemPrompt: String?, sampling: SamplingConfig?) async throws -> Double
625
626 /**
627 * Load a GGUF model into the engine.
628 *
629 * If a model is already loaded it will be unloaded first.
630 *
631 * Returns the wall-clock loading time in seconds.
632 */
633 func loadGgufModel(config: GgufModelConfig, systemPrompt: String?, sampling: SamplingConfig?) async throws -> Double
634
635 /**
636 * Load a UQFF model into the engine.
637 *
638 * UQFF files are pre-quantised and load directly without runtime
639 * conversion. `config.model_id` names the UQFF export (not the original
640 * unquantised repo), and `config.files` should contain the first UQFF
641 * shard or explicit shard filenames.
642 *
643 * Returns the wall-clock loading time in seconds.
644 */
645 func loadUqffModel(config: UqffModelConfig, systemPrompt: String?, sampling: SamplingConfig?) async throws -> Double
646
647 /**
648 * Append a message to history without running inference.
649 */
650 func pushHistory(message: ChatMessage) async
651
652 /**
653 * Send a user message and receive a complete assistant reply.
654 *
655 * The user message and assistant reply are automatically appended to
656 * the conversation history on success.
657 */
658 func sendMessage(message: String) async throws -> InferenceResult
659
660 /**
661 * Replace the sampling configuration.
662 */
663 func setSampling(sampling: SamplingConfig) async
664
665 /**
666 * Set or replace the system prompt.
667 */
668 func setSystemPrompt(prompt: String) async
669
670 /**
671 * Unload the current model, freeing all memory.
672 *
673 * Returns the display name of the model that was unloaded, or `nil`
674 * if no model was loaded.
675 */
676 func unloadModel() async -> String?
677
678 }
679 /**
680 * On-device LLM chat inference engine — UniFFI-exported wrapper.
681 *
682 * This is the primary entry point for Swift / Kotlin consumers. It wraps
683 * [`ChatEngine`] with FFI-safe method signatures (no generics, no Rust
684 * channels, concrete `String` parameters).
685 *
686 * Construct with [`OndeChatEngine::new()`]. The engine starts with no
687 * model loaded — call [`load_gguf_model`] or [`load_default_model`] first.
688 */
689 open class OndeChatEngine: OndeChatEngineProtocol, @unchecked Sendable {
690 fileprivate let handle: UInt64
691
692 /// Used to instantiate a [FFIObject] without an actual handle, for fakes in tests, mostly.
693 #if swift(>=5.8)
694 @_documentation(visibility: private)
695 #endif
696 public struct NoHandle {
697 public init() {}
698 }
699
700 // TODO: We'd like this to be `private` but for Swifty reasons,
701 // we can't implement `FfiConverter` without making this `required` and we can't
702 // make it `required` without making it `public`.
703 #if swift(>=5.8)
704 @_documentation(visibility: private)
705 #endif
706 required public init(unsafeFromHandle handle: UInt64) {
707 self.handle = handle
708 }
709
710 // This constructor can be used to instantiate a fake object.
711 // - Parameter noHandle: Placeholder value so we can have a constructor separate from the default empty one that may be implemented for classes extending [FFIObject].
712 //
713 // - Warning:
714 // 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.
715 #if swift(>=5.8)
716 @_documentation(visibility: private)
717 #endif
718 public init(noHandle: NoHandle) {
719 self.handle = 0
720 }
721
722 #if swift(>=5.8)
723 @_documentation(visibility: private)
724 #endif
725 public func uniffiCloneHandle() -> UInt64 {
726 return try! rustCall { uniffi_onde_fn_clone_ondechatengine(self.handle, $0) }
727 }
728 /**
729 * Create a new engine with no model loaded.
730 */
731 public convenience init() {
732 let handle =
733 try! rustCall() {
734 uniffi_onde_fn_constructor_ondechatengine_new($0
735 )
736 }
737 self.init(unsafeFromHandle: handle)
738 }
739
740 deinit {
741 if handle == 0 {
742 // Mock objects have handle=0 don't try to free them
743 return
744 }
745
746 try! rustCall { uniffi_onde_fn_free_ondechatengine(handle, $0) }
747 }
748
749
750
751
752 /**
753 * Clear the conversation history but keep the model loaded.
754 *
755 * Returns the number of turns that were removed.
756 */
757 open func clearHistory()async -> UInt64 {
758 return
759 try! await uniffiRustCallAsync(
760 rustFutureFunc: {
761 uniffi_onde_fn_method_ondechatengine_clear_history(
762 self.uniffiCloneHandle()
763
764 )
765 },
766 pollFunc: ffi_onde_rust_future_poll_u64,
767 completeFunc: ffi_onde_rust_future_complete_u64,
768 freeFunc: ffi_onde_rust_future_free_u64,
769 liftFunc: FfiConverterUInt64.lift,
770 errorHandler: nil
771
772 )
773 }
774
775 /**
776 * Clear the system prompt.
777 */
778 open func clearSystemPrompt()async {
779 return
780 try! await uniffiRustCallAsync(
781 rustFutureFunc: {
782 uniffi_onde_fn_method_ondechatengine_clear_system_prompt(
783 self.uniffiCloneHandle()
784
785 )
786 },
787 pollFunc: ffi_onde_rust_future_poll_void,
788 completeFunc: ffi_onde_rust_future_complete_void,
789 freeFunc: ffi_onde_rust_future_free_void,
790 liftFunc: { $0 },
791 errorHandler: nil
792
793 )
794 }
795
796 /**
797 * Run inference on an explicit list of messages WITHOUT modifying the
798 * engine's internal history.
799 *
800 * Useful for one-shot prompts (e.g. prompt enhancement).
801 */
802 open func generate(messages: [ChatMessage], sampling: SamplingConfig?)async throws -> InferenceResult {
803 return
804 try await uniffiRustCallAsync(
805 rustFutureFunc: {
806 uniffi_onde_fn_method_ondechatengine_generate(
807 self.uniffiCloneHandle(),
808 FfiConverterSequenceTypeChatMessage.lower(messages),FfiConverterOptionTypeSamplingConfig.lower(sampling)
809 )
810 },
811 pollFunc: ffi_onde_rust_future_poll_rust_buffer,
812 completeFunc: ffi_onde_rust_future_complete_rust_buffer,
813 freeFunc: ffi_onde_rust_future_free_rust_buffer,
814 liftFunc: FfiConverterTypeInferenceResult_lift,
815 errorHandler: FfiConverterTypeInferenceError_lift
816 )
817 }
818
819 /**
820 * Get a copy of the full conversation history.
821 */
822 open func history()async -> [ChatMessage] {
823 return
824 try! await uniffiRustCallAsync(
825 rustFutureFunc: {
826 uniffi_onde_fn_method_ondechatengine_history(
827 self.uniffiCloneHandle()
828
829 )
830 },
831 pollFunc: ffi_onde_rust_future_poll_rust_buffer,
832 completeFunc: ffi_onde_rust_future_complete_rust_buffer,
833 freeFunc: ffi_onde_rust_future_free_rust_buffer,
834 liftFunc: FfiConverterSequenceTypeChatMessage.lift,
835 errorHandler: nil
836
837 )
838 }
839
840 /**
841 * Get a snapshot of the engine's current state.
842 */
843 open func info()async -> EngineInfo {
844 return
845 try! await uniffiRustCallAsync(
846 rustFutureFunc: {
847 uniffi_onde_fn_method_ondechatengine_info(
848 self.uniffiCloneHandle()
849
850 )
851 },
852 pollFunc: ffi_onde_rust_future_poll_rust_buffer,
853 completeFunc: ffi_onde_rust_future_complete_rust_buffer,
854 freeFunc: ffi_onde_rust_future_free_rust_buffer,
855 liftFunc: FfiConverterTypeEngineInfo_lift,
856 errorHandler: nil
857
858 )
859 }
860
861 /**
862 * Check whether a model is currently loaded.
863 */
864 open func isLoaded()async -> Bool {
865 return
866 try! await uniffiRustCallAsync(
867 rustFutureFunc: {
868 uniffi_onde_fn_method_ondechatengine_is_loaded(
869 self.uniffiCloneHandle()
870
871 )
872 },
873 pollFunc: ffi_onde_rust_future_poll_i8,
874 completeFunc: ffi_onde_rust_future_complete_i8,
875 freeFunc: ffi_onde_rust_future_free_i8,
876 liftFunc: FfiConverterBool.lift,
877 errorHandler: nil
878
879 )
880 }
881
882 /**
883 * Load the model assigned to this app via the Onde dashboard.
884 *
885 * The `app_id` and `app_secret` identify your app on
886 * [ondeinference.com](https://ondeinference.com). The backend returns
887 * the GGUF model configuration assigned to your app; if no model is
888 * assigned (HTTP 404) the platform default is loaded instead.
889 *
890 * Returns the wall-clock loading time in seconds.
891 */
892 open func loadAssignedModel(appId: String, appSecret: String, systemPrompt: String?, sampling: SamplingConfig?)async throws -> Double {
893 return
894 try await uniffiRustCallAsync(
895 rustFutureFunc: {
896 uniffi_onde_fn_method_ondechatengine_load_assigned_model(
897 self.uniffiCloneHandle(),
898 FfiConverterString.lower(appId),FfiConverterString.lower(appSecret),FfiConverterOptionString.lower(systemPrompt),FfiConverterOptionTypeSamplingConfig.lower(sampling)
899 )
900 },
901 pollFunc: ffi_onde_rust_future_poll_f64,
902 completeFunc: ffi_onde_rust_future_complete_f64,
903 freeFunc: ffi_onde_rust_future_free_f64,
904 liftFunc: FfiConverterDouble.lift,
905 errorHandler: FfiConverterTypeInferenceError_lift
906 )
907 }
908
909 /**
910 * Load the platform-appropriate default model.
911 *
912 * - tvOS / iOS / Android → Qwen 2.5 1.5B (~941 MB)
913 * - macOS / Windows / Linux → Qwen 2.5 3B (~1.93 GB)
914 *
915 * Returns the wall-clock loading time in seconds.
916 */
917 open func loadDefaultModel(systemPrompt: String?, sampling: SamplingConfig?)async throws -> Double {
918 return
919 try await uniffiRustCallAsync(
920 rustFutureFunc: {
921 uniffi_onde_fn_method_ondechatengine_load_default_model(
922 self.uniffiCloneHandle(),
923 FfiConverterOptionString.lower(systemPrompt),FfiConverterOptionTypeSamplingConfig.lower(sampling)
924 )
925 },
926 pollFunc: ffi_onde_rust_future_poll_f64,
927 completeFunc: ffi_onde_rust_future_complete_f64,
928 freeFunc: ffi_onde_rust_future_free_f64,
929 liftFunc: FfiConverterDouble.lift,
930 errorHandler: FfiConverterTypeInferenceError_lift
931 )
932 }
933
934 /**
935 * Load a GGUF model into the engine.
936 *
937 * If a model is already loaded it will be unloaded first.
938 *
939 * Returns the wall-clock loading time in seconds.
940 */
941 open func loadGgufModel(config: GgufModelConfig, systemPrompt: String?, sampling: SamplingConfig?)async throws -> Double {
942 return
943 try await uniffiRustCallAsync(
944 rustFutureFunc: {
945 uniffi_onde_fn_method_ondechatengine_load_gguf_model(
946 self.uniffiCloneHandle(),
947 FfiConverterTypeGgufModelConfig_lower(config),FfiConverterOptionString.lower(systemPrompt),FfiConverterOptionTypeSamplingConfig.lower(sampling)
948 )
949 },
950 pollFunc: ffi_onde_rust_future_poll_f64,
951 completeFunc: ffi_onde_rust_future_complete_f64,
952 freeFunc: ffi_onde_rust_future_free_f64,
953 liftFunc: FfiConverterDouble.lift,
954 errorHandler: FfiConverterTypeInferenceError_lift
955 )
956 }
957
958 /**
959 * Load a UQFF model into the engine.
960 *
961 * UQFF files are pre-quantised and load directly without runtime
962 * conversion. `config.model_id` names the UQFF export (not the original
963 * unquantised repo), and `config.files` should contain the first UQFF
964 * shard or explicit shard filenames.
965 *
966 * Returns the wall-clock loading time in seconds.
967 */
968 open func loadUqffModel(config: UqffModelConfig, systemPrompt: String?, sampling: SamplingConfig?)async throws -> Double {
969 return
970 try await uniffiRustCallAsync(
971 rustFutureFunc: {
972 uniffi_onde_fn_method_ondechatengine_load_uqff_model(
973 self.uniffiCloneHandle(),
974 FfiConverterTypeUqffModelConfig_lower(config),FfiConverterOptionString.lower(systemPrompt),FfiConverterOptionTypeSamplingConfig.lower(sampling)
975 )
976 },
977 pollFunc: ffi_onde_rust_future_poll_f64,
978 completeFunc: ffi_onde_rust_future_complete_f64,
979 freeFunc: ffi_onde_rust_future_free_f64,
980 liftFunc: FfiConverterDouble.lift,
981 errorHandler: FfiConverterTypeInferenceError_lift
982 )
983 }
984
985 /**
986 * Append a message to history without running inference.
987 */
988 open func pushHistory(message: ChatMessage)async {
989 return
990 try! await uniffiRustCallAsync(
991 rustFutureFunc: {
992 uniffi_onde_fn_method_ondechatengine_push_history(
993 self.uniffiCloneHandle(),
994 FfiConverterTypeChatMessage_lower(message)
995 )
996 },
997 pollFunc: ffi_onde_rust_future_poll_void,
998 completeFunc: ffi_onde_rust_future_complete_void,
999 freeFunc: ffi_onde_rust_future_free_void,
1000 liftFunc: { $0 },
1001 errorHandler: nil
1002
1003 )
1004 }
1005
1006 /**
1007 * Send a user message and receive a complete assistant reply.
1008 *
1009 * The user message and assistant reply are automatically appended to
1010 * the conversation history on success.
1011 */
1012 open func sendMessage(message: String)async throws -> InferenceResult {
1013 return
1014 try await uniffiRustCallAsync(
1015 rustFutureFunc: {
1016 uniffi_onde_fn_method_ondechatengine_send_message(
1017 self.uniffiCloneHandle(),
1018 FfiConverterString.lower(message)
1019 )
1020 },
1021 pollFunc: ffi_onde_rust_future_poll_rust_buffer,
1022 completeFunc: ffi_onde_rust_future_complete_rust_buffer,
1023 freeFunc: ffi_onde_rust_future_free_rust_buffer,
1024 liftFunc: FfiConverterTypeInferenceResult_lift,
1025 errorHandler: FfiConverterTypeInferenceError_lift
1026 )
1027 }
1028
1029 /**
1030 * Replace the sampling configuration.
1031 */
1032 open func setSampling(sampling: SamplingConfig)async {
1033 return
1034 try! await uniffiRustCallAsync(
1035 rustFutureFunc: {
1036 uniffi_onde_fn_method_ondechatengine_set_sampling(
1037 self.uniffiCloneHandle(),
1038 FfiConverterTypeSamplingConfig_lower(sampling)
1039 )
1040 },
1041 pollFunc: ffi_onde_rust_future_poll_void,
1042 completeFunc: ffi_onde_rust_future_complete_void,
1043 freeFunc: ffi_onde_rust_future_free_void,
1044 liftFunc: { $0 },
1045 errorHandler: nil
1046
1047 )
1048 }
1049
1050 /**
1051 * Set or replace the system prompt.
1052 */
1053 open func setSystemPrompt(prompt: String)async {
1054 return
1055 try! await uniffiRustCallAsync(
1056 rustFutureFunc: {
1057 uniffi_onde_fn_method_ondechatengine_set_system_prompt(
1058 self.uniffiCloneHandle(),
1059 FfiConverterString.lower(prompt)
1060 )
1061 },
1062 pollFunc: ffi_onde_rust_future_poll_void,
1063 completeFunc: ffi_onde_rust_future_complete_void,
1064 freeFunc: ffi_onde_rust_future_free_void,
1065 liftFunc: { $0 },
1066 errorHandler: nil
1067
1068 )
1069 }
1070
1071 /**
1072 * Unload the current model, freeing all memory.
1073 *
1074 * Returns the display name of the model that was unloaded, or `nil`
1075 * if no model was loaded.
1076 */
1077 open func unloadModel()async -> String? {
1078 return
1079 try! await uniffiRustCallAsync(
1080 rustFutureFunc: {
1081 uniffi_onde_fn_method_ondechatengine_unload_model(
1082 self.uniffiCloneHandle()
1083
1084 )
1085 },
1086 pollFunc: ffi_onde_rust_future_poll_rust_buffer,
1087 completeFunc: ffi_onde_rust_future_complete_rust_buffer,
1088 freeFunc: ffi_onde_rust_future_free_rust_buffer,
1089 liftFunc: FfiConverterOptionString.lift,
1090 errorHandler: nil
1091
1092 )
1093 }
1094
1095
1096
1097 }
1098
1099
1100 #if swift(>=5.8)
1101 @_documentation(visibility: private)
1102 #endif
1103 public struct FfiConverterTypeOndeChatEngine: FfiConverter {
1104 typealias FfiType = UInt64
1105 typealias SwiftType = OndeChatEngine
1106
1107 public static func lift(_ handle: UInt64) throws -> OndeChatEngine {
1108 return OndeChatEngine(unsafeFromHandle: handle)
1109 }
1110
1111 public static func lower(_ value: OndeChatEngine) -> UInt64 {
1112 return value.uniffiCloneHandle()
1113 }
1114
1115 public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> OndeChatEngine {
1116 let handle: UInt64 = try readInt(&buf)
1117 return try lift(handle)
1118 }
1119
1120 public static func write(_ value: OndeChatEngine, into buf: inout [UInt8]) {
1121 writeInt(&buf, lower(value))
1122 }
1123 }
1124
1125
1126 #if swift(>=5.8)
1127 @_documentation(visibility: private)
1128 #endif
1129 public func FfiConverterTypeOndeChatEngine_lift(_ handle: UInt64) throws -> OndeChatEngine {
1130 return try FfiConverterTypeOndeChatEngine.lift(handle)
1131 }
1132
1133 #if swift(>=5.8)
1134 @_documentation(visibility: private)
1135 #endif
1136 public func FfiConverterTypeOndeChatEngine_lower(_ value: OndeChatEngine) -> UInt64 {
1137 return FfiConverterTypeOndeChatEngine.lower(value)
1138 }
1139
1140
1141
1142
1143 /**
1144 * A single message in a conversation.
1145 */
1146 public struct ChatMessage: Equatable, Hashable {
1147 public var role: ChatRole
1148 public var content: String
1149
1150 // Default memberwise initializers are never public by default, so we
1151 // declare one manually.
1152 public init(role: ChatRole, content: String) {
1153 self.role = role
1154 self.content = content
1155 }
1156
1157
1158
1159
1160 }
1161
1162 #if compiler(>=6)
1163 extension ChatMessage: Sendable {}
1164 #endif
1165
1166 #if swift(>=5.8)
1167 @_documentation(visibility: private)
1168 #endif
1169 public struct FfiConverterTypeChatMessage: FfiConverterRustBuffer {
1170 public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> ChatMessage {
1171 return
1172 try ChatMessage(
1173 role: FfiConverterTypeChatRole.read(from: &buf),
1174 content: FfiConverterString.read(from: &buf)
1175 )
1176 }
1177
1178 public static func write(_ value: ChatMessage, into buf: inout [UInt8]) {
1179 FfiConverterTypeChatRole.write(value.role, into: &buf)
1180 FfiConverterString.write(value.content, into: &buf)
1181 }
1182 }
1183
1184
1185 #if swift(>=5.8)
1186 @_documentation(visibility: private)
1187 #endif
1188 public func FfiConverterTypeChatMessage_lift(_ buf: RustBuffer) throws -> ChatMessage {
1189 return try FfiConverterTypeChatMessage.lift(buf)
1190 }
1191
1192 #if swift(>=5.8)
1193 @_documentation(visibility: private)
1194 #endif
1195 public func FfiConverterTypeChatMessage_lower(_ value: ChatMessage) -> RustBuffer {
1196 return FfiConverterTypeChatMessage.lower(value)
1197 }
1198
1199
1200 /**
1201 * A point-in-time snapshot of the engine's state, suitable for status UIs.
1202 *
1203 * Note: `history_length` is `u64` (not `usize`) for UniFFI compatibility.
1204 */
1205 public struct EngineInfo: Equatable, Hashable {
1206 public var status: EngineStatus
1207 /**
1208 * Display name of the currently loaded model, if any.
1209 */
1210 public var modelName: String?
1211 /**
1212 * Approximate memory footprint description, if a model is loaded.
1213 */
1214 public var approxMemory: String?
1215 /**
1216 * Number of conversation turns in the current history.
1217 */
1218 public var historyLength: UInt64
1219
1220 // Default memberwise initializers are never public by default, so we
1221 // declare one manually.
1222 public init(status: EngineStatus,
1223 /**
1224 * Display name of the currently loaded model, if any.
1225 */modelName: String?,
1226 /**
1227 * Approximate memory footprint description, if a model is loaded.
1228 */approxMemory: String?,
1229 /**
1230 * Number of conversation turns in the current history.
1231 */historyLength: UInt64) {
1232 self.status = status
1233 self.modelName = modelName
1234 self.approxMemory = approxMemory
1235 self.historyLength = historyLength
1236 }
1237
1238
1239
1240
1241 }
1242
1243 #if compiler(>=6)
1244 extension EngineInfo: Sendable {}
1245 #endif
1246
1247 #if swift(>=5.8)
1248 @_documentation(visibility: private)
1249 #endif
1250 public struct FfiConverterTypeEngineInfo: FfiConverterRustBuffer {
1251 public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> EngineInfo {
1252 return
1253 try EngineInfo(
1254 status: FfiConverterTypeEngineStatus.read(from: &buf),
1255 modelName: FfiConverterOptionString.read(from: &buf),
1256 approxMemory: FfiConverterOptionString.read(from: &buf),
1257 historyLength: FfiConverterUInt64.read(from: &buf)
1258 )
1259 }
1260
1261 public static func write(_ value: EngineInfo, into buf: inout [UInt8]) {
1262 FfiConverterTypeEngineStatus.write(value.status, into: &buf)
1263 FfiConverterOptionString.write(value.modelName, into: &buf)
1264 FfiConverterOptionString.write(value.approxMemory, into: &buf)
1265 FfiConverterUInt64.write(value.historyLength, into: &buf)
1266 }
1267 }
1268
1269
1270 #if swift(>=5.8)
1271 @_documentation(visibility: private)
1272 #endif
1273 public func FfiConverterTypeEngineInfo_lift(_ buf: RustBuffer) throws -> EngineInfo {
1274 return try FfiConverterTypeEngineInfo.lift(buf)
1275 }
1276
1277 #if swift(>=5.8)
1278 @_documentation(visibility: private)
1279 #endif
1280 public func FfiConverterTypeEngineInfo_lower(_ value: EngineInfo) -> RustBuffer {
1281 return FfiConverterTypeEngineInfo.lower(value)
1282 }
1283
1284
1285 /**
1286 * Configuration for loading a GGUF model via mistral.rs.
1287 *
1288 * This is the primary model format for on-device mobile/desktop inference
1289 * because GGUF files are pre-quantized and load at their compressed size,
1290 * avoiding the large memory spike of in-situ quantization.
1291 */
1292 public struct GgufModelConfig: Equatable, Hashable {
1293 /**
1294 * HuggingFace model repository ID, e.g. `"bartowski/Qwen2.5-1.5B-Instruct-GGUF"`.
1295 */
1296 public var modelId: String
1297 /**
1298 * GGUF filename(s) within the repository, e.g. `["Qwen2.5-1.5B-Instruct-Q4_K_M.gguf"]`.
1299 */
1300 public var files: [String]
1301 /**
1302 * Optional: explicit tokenizer model ID (required on Android where GGUF
1303 * embedded tokenizers are not supported by the candle backend).
1304 */
1305 public var tokModelId: String?
1306 /**
1307 * Human-friendly display name, e.g. `"Qwen 2.5 1.5B"`.
1308 */
1309 public var displayName: String
1310 /**
1311 * Approximate memory footprint description, e.g. `"~941 MB (GGUF Q4_K_M)"`.
1312 */
1313 public var approxMemory: String
1314 /**
1315 * Optional Jinja chat template string. When set, this overrides the
1316 * template embedded in the GGUF file (if any). Required for older GGUF
1317 * files that don't embed a chat template (e.g. TheBloke models).
1318 */
1319 public var chatTemplate: String?
1320
1321 // Default memberwise initializers are never public by default, so we
1322 // declare one manually.
1323 public init(
1324 /**
1325 * HuggingFace model repository ID, e.g. `"bartowski/Qwen2.5-1.5B-Instruct-GGUF"`.
1326 */modelId: String,
1327 /**
1328 * GGUF filename(s) within the repository, e.g. `["Qwen2.5-1.5B-Instruct-Q4_K_M.gguf"]`.
1329 */files: [String],
1330 /**
1331 * Optional: explicit tokenizer model ID (required on Android where GGUF
1332 * embedded tokenizers are not supported by the candle backend).
1333 */tokModelId: String?,
1334 /**
1335 * Human-friendly display name, e.g. `"Qwen 2.5 1.5B"`.
1336 */displayName: String,
1337 /**
1338 * Approximate memory footprint description, e.g. `"~941 MB (GGUF Q4_K_M)"`.
1339 */approxMemory: String,
1340 /**
1341 * Optional Jinja chat template string. When set, this overrides the
1342 * template embedded in the GGUF file (if any). Required for older GGUF
1343 * files that don't embed a chat template (e.g. TheBloke models).
1344 */chatTemplate: String?) {
1345 self.modelId = modelId
1346 self.files = files
1347 self.tokModelId = tokModelId
1348 self.displayName = displayName
1349 self.approxMemory = approxMemory
1350 self.chatTemplate = chatTemplate
1351 }
1352
1353
1354
1355
1356 }
1357
1358 #if compiler(>=6)
1359 extension GgufModelConfig: Sendable {}
1360 #endif
1361
1362 #if swift(>=5.8)
1363 @_documentation(visibility: private)
1364 #endif
1365 public struct FfiConverterTypeGgufModelConfig: FfiConverterRustBuffer {
1366 public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> GgufModelConfig {
1367 return
1368 try GgufModelConfig(
1369 modelId: FfiConverterString.read(from: &buf),
1370 files: FfiConverterSequenceString.read(from: &buf),
1371 tokModelId: FfiConverterOptionString.read(from: &buf),
1372 displayName: FfiConverterString.read(from: &buf),
1373 approxMemory: FfiConverterString.read(from: &buf),
1374 chatTemplate: FfiConverterOptionString.read(from: &buf)
1375 )
1376 }
1377
1378 public static func write(_ value: GgufModelConfig, into buf: inout [UInt8]) {
1379 FfiConverterString.write(value.modelId, into: &buf)
1380 FfiConverterSequenceString.write(value.files, into: &buf)
1381 FfiConverterOptionString.write(value.tokModelId, into: &buf)
1382 FfiConverterString.write(value.displayName, into: &buf)
1383 FfiConverterString.write(value.approxMemory, into: &buf)
1384 FfiConverterOptionString.write(value.chatTemplate, into: &buf)
1385 }
1386 }
1387
1388
1389 #if swift(>=5.8)
1390 @_documentation(visibility: private)
1391 #endif
1392 public func FfiConverterTypeGgufModelConfig_lift(_ buf: RustBuffer) throws -> GgufModelConfig {
1393 return try FfiConverterTypeGgufModelConfig.lift(buf)
1394 }
1395
1396 #if swift(>=5.8)
1397 @_documentation(visibility: private)
1398 #endif
1399 public func FfiConverterTypeGgufModelConfig_lower(_ value: GgufModelConfig) -> RustBuffer {
1400 return FfiConverterTypeGgufModelConfig.lower(value)
1401 }
1402
1403
1404 /**
1405 * The result of a chat inference request.
1406 */
1407 public struct InferenceResult: Equatable, Hashable {
1408 /**
1409 * The generated assistant reply text.
1410 */
1411 public var text: String
1412 /**
1413 * Wall-clock duration of the inference in seconds.
1414 */
1415 public var durationSecs: Double
1416 /**
1417 * Human-readable duration string (e.g. `"2m 3.1s"` or `"4.5s"`).
1418 */
1419 public var durationDisplay: String
1420 /**
1421 * Finish reason reported by the model (e.g. `"stop"`, `"length"`).
1422 */
1423 public var finishReason: String
1424 /**
1425 * Tool calls requested by the model (empty when no tools were invoked).
1426 */
1427 public var toolCalls: [ToolCallInfo]
1428
1429 // Default memberwise initializers are never public by default, so we
1430 // declare one manually.
1431 public init(
1432 /**
1433 * The generated assistant reply text.
1434 */text: String,
1435 /**
1436 * Wall-clock duration of the inference in seconds.
1437 */durationSecs: Double,
1438 /**
1439 * Human-readable duration string (e.g. `"2m 3.1s"` or `"4.5s"`).
1440 */durationDisplay: String,
1441 /**
1442 * Finish reason reported by the model (e.g. `"stop"`, `"length"`).
1443 */finishReason: String,
1444 /**
1445 * Tool calls requested by the model (empty when no tools were invoked).
1446 */toolCalls: [ToolCallInfo]) {
1447 self.text = text
1448 self.durationSecs = durationSecs
1449 self.durationDisplay = durationDisplay
1450 self.finishReason = finishReason
1451 self.toolCalls = toolCalls
1452 }
1453
1454
1455
1456
1457 }
1458
1459 #if compiler(>=6)
1460 extension InferenceResult: Sendable {}
1461 #endif
1462
1463 #if swift(>=5.8)
1464 @_documentation(visibility: private)
1465 #endif
1466 public struct FfiConverterTypeInferenceResult: FfiConverterRustBuffer {
1467 public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> InferenceResult {
1468 return
1469 try InferenceResult(
1470 text: FfiConverterString.read(from: &buf),
1471 durationSecs: FfiConverterDouble.read(from: &buf),
1472 durationDisplay: FfiConverterString.read(from: &buf),
1473 finishReason: FfiConverterString.read(from: &buf),
1474 toolCalls: FfiConverterSequenceTypeToolCallInfo.read(from: &buf)
1475 )
1476 }
1477
1478 public static func write(_ value: InferenceResult, into buf: inout [UInt8]) {
1479 FfiConverterString.write(value.text, into: &buf)
1480 FfiConverterDouble.write(value.durationSecs, into: &buf)
1481 FfiConverterString.write(value.durationDisplay, into: &buf)
1482 FfiConverterString.write(value.finishReason, into: &buf)
1483 FfiConverterSequenceTypeToolCallInfo.write(value.toolCalls, into: &buf)
1484 }
1485 }
1486
1487
1488 #if swift(>=5.8)
1489 @_documentation(visibility: private)
1490 #endif
1491 public func FfiConverterTypeInferenceResult_lift(_ buf: RustBuffer) throws -> InferenceResult {
1492 return try FfiConverterTypeInferenceResult.lift(buf)
1493 }
1494
1495 #if swift(>=5.8)
1496 @_documentation(visibility: private)
1497 #endif
1498 public func FfiConverterTypeInferenceResult_lower(_ value: InferenceResult) -> RustBuffer {
1499 return FfiConverterTypeInferenceResult.lower(value)
1500 }
1501
1502
1503 /**
1504 * Configuration for loading an ISQ (in-situ quantised) model via mistral.rs
1505 * `TextModelBuilder`.
1506 *
1507 * Unlike GGUF models, ISQ models are loaded directly from a HuggingFace
1508 * safetensors repo and quantised in-situ on the device. They require more
1509 * RAM during the load phase but support a wider range of architectures
1510 * (e.g. DeepSeek-Coder-V2-Lite, Qwen2.5-Coder-7B).
1511 *
1512 * **macOS-only for now** — ISQ with Metal acceleration requires the `metal`
1513 * feature on mistral.rs. The struct is still defined on all platforms so
1514 * that types.rs compiles everywhere without `cfg` gates on the record
1515 * (UniFFI requires all record types to be reachable without feature flags).
1516 */
1517 public struct IsqModelConfig: Equatable, Hashable {
1518 /**
1519 * HuggingFace model repository ID, e.g. `"Qwen/Qwen2.5-Coder-7B-Instruct"`.
1520 */
1521 public var modelId: String
1522 /**
1523 * Number of quantisation bits. `4` → Q4K (AFQ4 on Metal), `8` → Q8_0 (AFQ8 on Metal).
1524 * Any value outside `{4, 8}` defaults to 4-bit.
1525 */
1526 public var isqBits: UInt8
1527 /**
1528 * Human-friendly display name, e.g. `"Qwen 2.5 Coder 7B"`.
1529 */
1530 public var displayName: String
1531 /**
1532 * Approximate memory footprint description, e.g. `"~4.5 GB (Q4K, Metal)"`.
1533 */
1534 public var approxMemory: String
1535
1536 // Default memberwise initializers are never public by default, so we
1537 // declare one manually.
1538 public init(
1539 /**
1540 * HuggingFace model repository ID, e.g. `"Qwen/Qwen2.5-Coder-7B-Instruct"`.
1541 */modelId: String,
1542 /**
1543 * Number of quantisation bits. `4` → Q4K (AFQ4 on Metal), `8` → Q8_0 (AFQ8 on Metal).
1544 * Any value outside `{4, 8}` defaults to 4-bit.
1545 */isqBits: UInt8,
1546 /**
1547 * Human-friendly display name, e.g. `"Qwen 2.5 Coder 7B"`.
1548 */displayName: String,
1549 /**
1550 * Approximate memory footprint description, e.g. `"~4.5 GB (Q4K, Metal)"`.
1551 */approxMemory: String) {
1552 self.modelId = modelId
1553 self.isqBits = isqBits
1554 self.displayName = displayName
1555 self.approxMemory = approxMemory
1556 }
1557
1558
1559
1560
1561 }
1562
1563 #if compiler(>=6)
1564 extension IsqModelConfig: Sendable {}
1565 #endif
1566
1567 #if swift(>=5.8)
1568 @_documentation(visibility: private)
1569 #endif
1570 public struct FfiConverterTypeIsqModelConfig: FfiConverterRustBuffer {
1571 public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> IsqModelConfig {
1572 return
1573 try IsqModelConfig(
1574 modelId: FfiConverterString.read(from: &buf),
1575 isqBits: FfiConverterUInt8.read(from: &buf),
1576 displayName: FfiConverterString.read(from: &buf),
1577 approxMemory: FfiConverterString.read(from: &buf)
1578 )
1579 }
1580
1581 public static func write(_ value: IsqModelConfig, into buf: inout [UInt8]) {
1582 FfiConverterString.write(value.modelId, into: &buf)
1583 FfiConverterUInt8.write(value.isqBits, into: &buf)
1584 FfiConverterString.write(value.displayName, into: &buf)
1585 FfiConverterString.write(value.approxMemory, into: &buf)
1586 }
1587 }
1588
1589
1590 #if swift(>=5.8)
1591 @_documentation(visibility: private)
1592 #endif
1593 public func FfiConverterTypeIsqModelConfig_lift(_ buf: RustBuffer) throws -> IsqModelConfig {
1594 return try FfiConverterTypeIsqModelConfig.lift(buf)
1595 }
1596
1597 #if swift(>=5.8)
1598 @_documentation(visibility: private)
1599 #endif
1600 public func FfiConverterTypeIsqModelConfig_lower(_ value: IsqModelConfig) -> RustBuffer {
1601 return FfiConverterTypeIsqModelConfig.lower(value)
1602 }
1603
1604
1605 /**
1606 * Sampling parameters for text generation.
1607 *
1608 * All fields are optional — `None` means "use the engine default".
1609 *
1610 * Note: `usize` is replaced with `u64` for UniFFI compatibility.
1611 */
1612 public struct SamplingConfig: Equatable, Hashable {
1613 /**
1614 * Sampling temperature (higher = more random). Typical range: 0.0–2.0.
1615 */
1616 public var temperature: Double?
1617 /**
1618 * Nucleus (top-p) sampling threshold. Typical value: 0.9–0.95.
1619 */
1620 public var topP: Double?
1621 /**
1622 * Top-k sampling limit.
1623 */
1624 public var topK: UInt64?
1625 /**
1626 * Min-p sampling threshold.
1627 */
1628 public var minP: Double?
1629 /**
1630 * Maximum number of tokens to generate.
1631 */
1632 public var maxTokens: UInt64?
1633 /**
1634 * Frequency penalty (penalise tokens proportional to occurrence count).
1635 */
1636 public var frequencyPenalty: Float?
1637 /**
1638 * Presence penalty (penalise tokens that appeared at all).
1639 */
1640 public var presencePenalty: Float?
1641
1642 // Default memberwise initializers are never public by default, so we
1643 // declare one manually.
1644 public init(
1645 /**
1646 * Sampling temperature (higher = more random). Typical range: 0.0–2.0.
1647 */temperature: Double?,
1648 /**
1649 * Nucleus (top-p) sampling threshold. Typical value: 0.9–0.95.
1650 */topP: Double?,
1651 /**
1652 * Top-k sampling limit.
1653 */topK: UInt64?,
1654 /**
1655 * Min-p sampling threshold.
1656 */minP: Double?,
1657 /**
1658 * Maximum number of tokens to generate.
1659 */maxTokens: UInt64?,
1660 /**
1661 * Frequency penalty (penalise tokens proportional to occurrence count).
1662 */frequencyPenalty: Float?,
1663 /**
1664 * Presence penalty (penalise tokens that appeared at all).
1665 */presencePenalty: Float?) {
1666 self.temperature = temperature
1667 self.topP = topP
1668 self.topK = topK
1669 self.minP = minP
1670 self.maxTokens = maxTokens
1671 self.frequencyPenalty = frequencyPenalty
1672 self.presencePenalty = presencePenalty
1673 }
1674
1675
1676
1677
1678 }
1679
1680 #if compiler(>=6)
1681 extension SamplingConfig: Sendable {}
1682 #endif
1683
1684 #if swift(>=5.8)
1685 @_documentation(visibility: private)
1686 #endif
1687 public struct FfiConverterTypeSamplingConfig: FfiConverterRustBuffer {
1688 public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> SamplingConfig {
1689 return
1690 try SamplingConfig(
1691 temperature: FfiConverterOptionDouble.read(from: &buf),
1692 topP: FfiConverterOptionDouble.read(from: &buf),
1693 topK: FfiConverterOptionUInt64.read(from: &buf),
1694 minP: FfiConverterOptionDouble.read(from: &buf),
1695 maxTokens: FfiConverterOptionUInt64.read(from: &buf),
1696 frequencyPenalty: FfiConverterOptionFloat.read(from: &buf),
1697 presencePenalty: FfiConverterOptionFloat.read(from: &buf)
1698 )
1699 }
1700
1701 public static func write(_ value: SamplingConfig, into buf: inout [UInt8]) {
1702 FfiConverterOptionDouble.write(value.temperature, into: &buf)
1703 FfiConverterOptionDouble.write(value.topP, into: &buf)
1704 FfiConverterOptionUInt64.write(value.topK, into: &buf)
1705 FfiConverterOptionDouble.write(value.minP, into: &buf)
1706 FfiConverterOptionUInt64.write(value.maxTokens, into: &buf)
1707 FfiConverterOptionFloat.write(value.frequencyPenalty, into: &buf)
1708 FfiConverterOptionFloat.write(value.presencePenalty, into: &buf)
1709 }
1710 }
1711
1712
1713 #if swift(>=5.8)
1714 @_documentation(visibility: private)
1715 #endif
1716 public func FfiConverterTypeSamplingConfig_lift(_ buf: RustBuffer) throws -> SamplingConfig {
1717 return try FfiConverterTypeSamplingConfig.lift(buf)
1718 }
1719
1720 #if swift(>=5.8)
1721 @_documentation(visibility: private)
1722 #endif
1723 public func FfiConverterTypeSamplingConfig_lower(_ value: SamplingConfig) -> RustBuffer {
1724 return FfiConverterTypeSamplingConfig.lower(value)
1725 }
1726
1727
1728 /**
1729 * A single streaming token chunk from the inference engine.
1730 */
1731 public struct StreamChunk: Equatable, Hashable {
1732 /**
1733 * The token text delta (may be empty for the final chunk).
1734 */
1735 public var delta: String
1736 /**
1737 * Whether this is the final chunk in the stream.
1738 */
1739 public var done: Bool
1740 /**
1741 * Finish reason (only set on the final chunk).
1742 */
1743 public var finishReason: String?
1744
1745 // Default memberwise initializers are never public by default, so we
1746 // declare one manually.
1747 public init(
1748 /**
1749 * The token text delta (may be empty for the final chunk).
1750 */delta: String,
1751 /**
1752 * Whether this is the final chunk in the stream.
1753 */done: Bool,
1754 /**
1755 * Finish reason (only set on the final chunk).
1756 */finishReason: String?) {
1757 self.delta = delta
1758 self.done = done
1759 self.finishReason = finishReason
1760 }
1761
1762
1763
1764
1765 }
1766
1767 #if compiler(>=6)
1768 extension StreamChunk: Sendable {}
1769 #endif
1770
1771 #if swift(>=5.8)
1772 @_documentation(visibility: private)
1773 #endif
1774 public struct FfiConverterTypeStreamChunk: FfiConverterRustBuffer {
1775 public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> StreamChunk {
1776 return
1777 try StreamChunk(
1778 delta: FfiConverterString.read(from: &buf),
1779 done: FfiConverterBool.read(from: &buf),
1780 finishReason: FfiConverterOptionString.read(from: &buf)
1781 )
1782 }
1783
1784 public static func write(_ value: StreamChunk, into buf: inout [UInt8]) {
1785 FfiConverterString.write(value.delta, into: &buf)
1786 FfiConverterBool.write(value.done, into: &buf)
1787 FfiConverterOptionString.write(value.finishReason, into: &buf)
1788 }
1789 }
1790
1791
1792 #if swift(>=5.8)
1793 @_documentation(visibility: private)
1794 #endif
1795 public func FfiConverterTypeStreamChunk_lift(_ buf: RustBuffer) throws -> StreamChunk {
1796 return try FfiConverterTypeStreamChunk.lift(buf)
1797 }
1798
1799 #if swift(>=5.8)
1800 @_documentation(visibility: private)
1801 #endif
1802 public func FfiConverterTypeStreamChunk_lower(_ value: StreamChunk) -> RustBuffer {
1803 return FfiConverterTypeStreamChunk.lower(value)
1804 }
1805
1806
1807 /**
1808 * Information about a single tool call requested by the model.
1809 */
1810 public struct ToolCallInfo: Equatable, Hashable {
1811 /**
1812 * Unique identifier for this tool call (used to correlate results).
1813 */
1814 public var id: String
1815 /**
1816 * The name of the function the model wants to invoke.
1817 */
1818 public var functionName: String
1819 /**
1820 * JSON-encoded arguments for the function.
1821 */
1822 public var arguments: String
1823
1824 // Default memberwise initializers are never public by default, so we
1825 // declare one manually.
1826 public init(
1827 /**
1828 * Unique identifier for this tool call (used to correlate results).
1829 */id: String,
1830 /**
1831 * The name of the function the model wants to invoke.
1832 */functionName: String,
1833 /**
1834 * JSON-encoded arguments for the function.
1835 */arguments: String) {
1836 self.id = id
1837 self.functionName = functionName
1838 self.arguments = arguments
1839 }
1840
1841
1842
1843
1844 }
1845
1846 #if compiler(>=6)
1847 extension ToolCallInfo: Sendable {}
1848 #endif
1849
1850 #if swift(>=5.8)
1851 @_documentation(visibility: private)
1852 #endif
1853 public struct FfiConverterTypeToolCallInfo: FfiConverterRustBuffer {
1854 public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> ToolCallInfo {
1855 return
1856 try ToolCallInfo(
1857 id: FfiConverterString.read(from: &buf),
1858 functionName: FfiConverterString.read(from: &buf),
1859 arguments: FfiConverterString.read(from: &buf)
1860 )
1861 }
1862
1863 public static func write(_ value: ToolCallInfo, into buf: inout [UInt8]) {
1864 FfiConverterString.write(value.id, into: &buf)
1865 FfiConverterString.write(value.functionName, into: &buf)
1866 FfiConverterString.write(value.arguments, into: &buf)
1867 }
1868 }
1869
1870
1871 #if swift(>=5.8)
1872 @_documentation(visibility: private)
1873 #endif
1874 public func FfiConverterTypeToolCallInfo_lift(_ buf: RustBuffer) throws -> ToolCallInfo {
1875 return try FfiConverterTypeToolCallInfo.lift(buf)
1876 }
1877
1878 #if swift(>=5.8)
1879 @_documentation(visibility: private)
1880 #endif
1881 public func FfiConverterTypeToolCallInfo_lower(_ value: ToolCallInfo) -> RustBuffer {
1882 return FfiConverterTypeToolCallInfo.lower(value)
1883 }
1884
1885
1886 /**
1887 * A tool definition passed to the model so it knows which tools are available.
1888 */
1889 public struct ToolDefinition: Equatable, Hashable {
1890 /**
1891 * Tool name (e.g. `"read_file"`).
1892 */
1893 public var name: String
1894 /**
1895 * Human-readable description of what the tool does.
1896 */
1897 public var description: String
1898 /**
1899 * JSON Schema string describing the tool's parameters.
1900 */
1901 public var parametersSchema: String
1902
1903 // Default memberwise initializers are never public by default, so we
1904 // declare one manually.
1905 public init(
1906 /**
1907 * Tool name (e.g. `"read_file"`).
1908 */name: String,
1909 /**
1910 * Human-readable description of what the tool does.
1911 */description: String,
1912 /**
1913 * JSON Schema string describing the tool's parameters.
1914 */parametersSchema: String) {
1915 self.name = name
1916 self.description = description
1917 self.parametersSchema = parametersSchema
1918 }
1919
1920
1921
1922
1923 }
1924
1925 #if compiler(>=6)
1926 extension ToolDefinition: Sendable {}
1927 #endif
1928
1929 #if swift(>=5.8)
1930 @_documentation(visibility: private)
1931 #endif
1932 public struct FfiConverterTypeToolDefinition: FfiConverterRustBuffer {
1933 public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> ToolDefinition {
1934 return
1935 try ToolDefinition(
1936 name: FfiConverterString.read(from: &buf),
1937 description: FfiConverterString.read(from: &buf),
1938 parametersSchema: FfiConverterString.read(from: &buf)
1939 )
1940 }
1941
1942 public static func write(_ value: ToolDefinition, into buf: inout [UInt8]) {
1943 FfiConverterString.write(value.name, into: &buf)
1944 FfiConverterString.write(value.description, into: &buf)
1945 FfiConverterString.write(value.parametersSchema, into: &buf)
1946 }
1947 }
1948
1949
1950 #if swift(>=5.8)
1951 @_documentation(visibility: private)
1952 #endif
1953 public func FfiConverterTypeToolDefinition_lift(_ buf: RustBuffer) throws -> ToolDefinition {
1954 return try FfiConverterTypeToolDefinition.lift(buf)
1955 }
1956
1957 #if swift(>=5.8)
1958 @_documentation(visibility: private)
1959 #endif
1960 public func FfiConverterTypeToolDefinition_lower(_ value: ToolDefinition) -> RustBuffer {
1961 return FfiConverterTypeToolDefinition.lower(value)
1962 }
1963
1964
1965 /**
1966 * The result of executing a tool, sent back to the model.
1967 */
1968 public struct ToolResult: Equatable, Hashable {
1969 /**
1970 * The tool call ID this result corresponds to.
1971 */
1972 public var toolCallId: String
1973 /**
1974 * The output produced by executing the tool.
1975 */
1976 public var content: String
1977
1978 // Default memberwise initializers are never public by default, so we
1979 // declare one manually.
1980 public init(
1981 /**
1982 * The tool call ID this result corresponds to.
1983 */toolCallId: String,
1984 /**
1985 * The output produced by executing the tool.
1986 */content: String) {
1987 self.toolCallId = toolCallId
1988 self.content = content
1989 }
1990
1991
1992
1993
1994 }
1995
1996 #if compiler(>=6)
1997 extension ToolResult: Sendable {}
1998 #endif
1999
2000 #if swift(>=5.8)
2001 @_documentation(visibility: private)
2002 #endif
2003 public struct FfiConverterTypeToolResult: FfiConverterRustBuffer {
2004 public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> ToolResult {
2005 return
2006 try ToolResult(
2007 toolCallId: FfiConverterString.read(from: &buf),
2008 content: FfiConverterString.read(from: &buf)
2009 )
2010 }
2011
2012 public static func write(_ value: ToolResult, into buf: inout [UInt8]) {
2013 FfiConverterString.write(value.toolCallId, into: &buf)
2014 FfiConverterString.write(value.content, into: &buf)
2015 }
2016 }
2017
2018
2019 #if swift(>=5.8)
2020 @_documentation(visibility: private)
2021 #endif
2022 public func FfiConverterTypeToolResult_lift(_ buf: RustBuffer) throws -> ToolResult {
2023 return try FfiConverterTypeToolResult.lift(buf)
2024 }
2025
2026 #if swift(>=5.8)
2027 @_documentation(visibility: private)
2028 #endif
2029 public func FfiConverterTypeToolResult_lower(_ value: ToolResult) -> RustBuffer {
2030 return FfiConverterTypeToolResult.lower(value)
2031 }
2032
2033
2034 /**
2035 * Configuration for loading a UQFF model via mistral.rs
2036 * `UqffTextModelBuilder`.
2037 *
2038 * UQFF files store pre-quantised weights and load directly
2039 * without the runtime memory spike of in-situ quantisation. `model_id` points
2040 * at the UQFF *export* — the directory or repository holding the shards
2041 * alongside `residual.safetensors`, `config.json`, and the tokenizer — and
2042 * `files` identifies the first UQFF shard or explicit UQFF shard files.
2043 *
2044 * Note that `model_id` is **not** the original unquantised model repository:
2045 * mistral.rs resolves the shards, the residual weights, and the JSON assets by
2046 * sibling lookup next to `model_id`, so pointing it at the source repo fails
2047 * with a missing-file error. A UQFF export is self-contained by design.
2048 */
2049 public struct UqffModelConfig: Equatable, Hashable {
2050 /**
2051 * HuggingFace repository ID or local directory of the UQFF export, e.g.
2052 * `"mistralrs-community/gemma-4-E4B-it-UQFF"`.
2053 */
2054 public var modelId: String
2055 /**
2056 * UQFF filename(s) within the repository. For sharded UQFFs, passing the
2057 * first shard, e.g. `["q4k-0.uqff"]`, is enough for mistral.rs to discover
2058 * siblings. Numeric and ISQ-name shorthands such as `"4"` and `"q4k"` are
2059 * also accepted by the underlying loader.
2060 */
2061 public var files: [String]
2062 /**
2063 * Human-friendly display name, e.g. `"Gemma 4 E4B (UQFF Q4K)"`.
2064 */
2065 public var displayName: String
2066 /**
2067 * Approximate memory footprint description, e.g. `"~2.5 GB (UQFF Q4K)"`.
2068 */
2069 public var approxMemory: String
2070 /**
2071 * Optional Jinja chat template string. When set, this overrides the
2072 * template resolved from the base model.
2073 */
2074 public var chatTemplate: String?
2075
2076 // Default memberwise initializers are never public by default, so we
2077 // declare one manually.
2078 public init(
2079 /**
2080 * HuggingFace repository ID or local directory of the UQFF export, e.g.
2081 * `"mistralrs-community/gemma-4-E4B-it-UQFF"`.
2082 */modelId: String,
2083 /**
2084 * UQFF filename(s) within the repository. For sharded UQFFs, passing the
2085 * first shard, e.g. `["q4k-0.uqff"]`, is enough for mistral.rs to discover
2086 * siblings. Numeric and ISQ-name shorthands such as `"4"` and `"q4k"` are
2087 * also accepted by the underlying loader.
2088 */files: [String],
2089 /**
2090 * Human-friendly display name, e.g. `"Gemma 4 E4B (UQFF Q4K)"`.
2091 */displayName: String,
2092 /**
2093 * Approximate memory footprint description, e.g. `"~2.5 GB (UQFF Q4K)"`.
2094 */approxMemory: String,
2095 /**
2096 * Optional Jinja chat template string. When set, this overrides the
2097 * template resolved from the base model.
2098 */chatTemplate: String?) {
2099 self.modelId = modelId
2100 self.files = files
2101 self.displayName = displayName
2102 self.approxMemory = approxMemory
2103 self.chatTemplate = chatTemplate
2104 }
2105
2106
2107
2108
2109 }
2110
2111 #if compiler(>=6)
2112 extension UqffModelConfig: Sendable {}
2113 #endif
2114
2115 #if swift(>=5.8)
2116 @_documentation(visibility: private)
2117 #endif
2118 public struct FfiConverterTypeUqffModelConfig: FfiConverterRustBuffer {
2119 public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> UqffModelConfig {
2120 return
2121 try UqffModelConfig(
2122 modelId: FfiConverterString.read(from: &buf),
2123 files: FfiConverterSequenceString.read(from: &buf),
2124 displayName: FfiConverterString.read(from: &buf),
2125 approxMemory: FfiConverterString.read(from: &buf),
2126 chatTemplate: FfiConverterOptionString.read(from: &buf)
2127 )
2128 }
2129
2130 public static func write(_ value: UqffModelConfig, into buf: inout [UInt8]) {
2131 FfiConverterString.write(value.modelId, into: &buf)
2132 FfiConverterSequenceString.write(value.files, into: &buf)
2133 FfiConverterString.write(value.displayName, into: &buf)
2134 FfiConverterString.write(value.approxMemory, into: &buf)
2135 FfiConverterOptionString.write(value.chatTemplate, into: &buf)
2136 }
2137 }
2138
2139
2140 #if swift(>=5.8)
2141 @_documentation(visibility: private)
2142 #endif
2143 public func FfiConverterTypeUqffModelConfig_lift(_ buf: RustBuffer) throws -> UqffModelConfig {
2144 return try FfiConverterTypeUqffModelConfig.lift(buf)
2145 }
2146
2147 #if swift(>=5.8)
2148 @_documentation(visibility: private)
2149 #endif
2150 public func FfiConverterTypeUqffModelConfig_lower(_ value: UqffModelConfig) -> RustBuffer {
2151 return FfiConverterTypeUqffModelConfig.lower(value)
2152 }
2153
2154 // Note that we don't yet support `indirect` for enums.
2155 // See https://github.com/mozilla/uniffi-rs/issues/396 for further discussion.
2156 /**
2157 * Role of a message in a chat conversation.
2158 *
2159 * Mirrors the standard OpenAI / mistral.rs role taxonomy but is decoupled
2160 * from `mistralrs::TextMessageRole` so that callers don't need a direct
2161 * dependency on mistral.rs.
2162 */
2163
2164 public enum ChatRole: Equatable, Hashable {
2165
2166 case system
2167 case user
2168 case assistant
2169
2170
2171
2172
2173
2174 }
2175
2176 #if compiler(>=6)
2177 extension ChatRole: Sendable {}
2178 #endif
2179
2180 #if swift(>=5.8)
2181 @_documentation(visibility: private)
2182 #endif
2183 public struct FfiConverterTypeChatRole: FfiConverterRustBuffer {
2184 typealias SwiftType = ChatRole
2185
2186 public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> ChatRole {
2187 let variant: Int32 = try readInt(&buf)
2188 switch variant {
2189
2190 case 1: return .system
2191
2192 case 2: return .user
2193
2194 case 3: return .assistant
2195
2196 default: throw UniffiInternalError.unexpectedEnumCase
2197 }
2198 }
2199
2200 public static func write(_ value: ChatRole, into buf: inout [UInt8]) {
2201 switch value {
2202
2203
2204 case .system:
2205 writeInt(&buf, Int32(1))
2206
2207
2208 case .user:
2209 writeInt(&buf, Int32(2))
2210
2211
2212 case .assistant:
2213 writeInt(&buf, Int32(3))
2214
2215 }
2216 }
2217 }
2218
2219
2220 #if swift(>=5.8)
2221 @_documentation(visibility: private)
2222 #endif
2223 public func FfiConverterTypeChatRole_lift(_ buf: RustBuffer) throws -> ChatRole {
2224 return try FfiConverterTypeChatRole.lift(buf)
2225 }
2226
2227 #if swift(>=5.8)
2228 @_documentation(visibility: private)
2229 #endif
2230 public func FfiConverterTypeChatRole_lower(_ value: ChatRole) -> RustBuffer {
2231 return FfiConverterTypeChatRole.lower(value)
2232 }
2233
2234
2235 // Note that we don't yet support `indirect` for enums.
2236 // See https://github.com/mozilla/uniffi-rs/issues/396 for further discussion.
2237 /**
2238 * Lifecycle status of the inference engine.
2239 */
2240
2241 public enum EngineStatus: Equatable, Hashable {
2242
2243 /**
2244 * No model loaded.
2245 */
2246 case unloaded
2247 /**
2248 * Model is being downloaded / loaded into memory.
2249 */
2250 case loading
2251 /**
2252 * Model is loaded and ready to accept requests.
2253 */
2254 case ready
2255 /**
2256 * Model is currently running inference.
2257 */
2258 case generating
2259 /**
2260 * An error occurred (model may or may not still be loaded).
2261 */
2262 case error
2263
2264
2265
2266
2267
2268 }
2269
2270 #if compiler(>=6)
2271 extension EngineStatus: Sendable {}
2272 #endif
2273
2274 #if swift(>=5.8)
2275 @_documentation(visibility: private)
2276 #endif
2277 public struct FfiConverterTypeEngineStatus: FfiConverterRustBuffer {
2278 typealias SwiftType = EngineStatus
2279
2280 public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> EngineStatus {
2281 let variant: Int32 = try readInt(&buf)
2282 switch variant {
2283
2284 case 1: return .unloaded
2285
2286 case 2: return .loading
2287
2288 case 3: return .ready
2289
2290 case 4: return .generating
2291
2292 case 5: return .error
2293
2294 default: throw UniffiInternalError.unexpectedEnumCase
2295 }
2296 }
2297
2298 public static func write(_ value: EngineStatus, into buf: inout [UInt8]) {
2299 switch value {
2300
2301
2302 case .unloaded:
2303 writeInt(&buf, Int32(1))
2304
2305
2306 case .loading:
2307 writeInt(&buf, Int32(2))
2308
2309
2310 case .ready:
2311 writeInt(&buf, Int32(3))
2312
2313
2314 case .generating:
2315 writeInt(&buf, Int32(4))
2316
2317
2318 case .error:
2319 writeInt(&buf, Int32(5))
2320
2321 }
2322 }
2323 }
2324
2325
2326 #if swift(>=5.8)
2327 @_documentation(visibility: private)
2328 #endif
2329 public func FfiConverterTypeEngineStatus_lift(_ buf: RustBuffer) throws -> EngineStatus {
2330 return try FfiConverterTypeEngineStatus.lift(buf)
2331 }
2332
2333 #if swift(>=5.8)
2334 @_documentation(visibility: private)
2335 #endif
2336 public func FfiConverterTypeEngineStatus_lower(_ value: EngineStatus) -> RustBuffer {
2337 return FfiConverterTypeEngineStatus.lower(value)
2338 }
2339
2340
2341
2342 /**
2343 * Errors that can occur during inference engine operations.
2344 *
2345 * Exposed to Swift / Kotlin as a sealed class / enum via `uniffi::Error`.
2346 */
2347 public enum InferenceError: Swift.Error, Equatable, Hashable, Foundation.LocalizedError {
2348
2349
2350
2351 case NoModelLoaded
2352 case AlreadyLoaded(modelName: String
2353 )
2354 case ModelBuild(reason: String
2355 )
2356 case Inference(reason: String
2357 )
2358 case Cancelled
2359 case Other(reason: String
2360 )
2361
2362
2363
2364
2365
2366
2367 public var errorDescription: String? {
2368 String(reflecting: self)
2369 }
2370
2371 }
2372
2373 #if compiler(>=6)
2374 extension InferenceError: Sendable {}
2375 #endif
2376
2377 #if swift(>=5.8)
2378 @_documentation(visibility: private)
2379 #endif
2380 public struct FfiConverterTypeInferenceError: FfiConverterRustBuffer {
2381 typealias SwiftType = InferenceError
2382
2383 public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> InferenceError {
2384 let variant: Int32 = try readInt(&buf)
2385 switch variant {
2386
2387
2388
2389
2390 case 1: return .NoModelLoaded
2391 case 2: return .AlreadyLoaded(
2392 modelName: try FfiConverterString.read(from: &buf)
2393 )
2394 case 3: return .ModelBuild(
2395 reason: try FfiConverterString.read(from: &buf)
2396 )
2397 case 4: return .Inference(
2398 reason: try FfiConverterString.read(from: &buf)
2399 )
2400 case 5: return .Cancelled
2401 case 6: return .Other(
2402 reason: try FfiConverterString.read(from: &buf)
2403 )
2404
2405 default: throw UniffiInternalError.unexpectedEnumCase
2406 }
2407 }
2408
2409 public static func write(_ value: InferenceError, into buf: inout [UInt8]) {
2410 switch value {
2411
2412
2413
2414
2415
2416 case .NoModelLoaded:
2417 writeInt(&buf, Int32(1))
2418
2419
2420 case let .AlreadyLoaded(modelName):
2421 writeInt(&buf, Int32(2))
2422 FfiConverterString.write(modelName, into: &buf)
2423
2424
2425 case let .ModelBuild(reason):
2426 writeInt(&buf, Int32(3))
2427 FfiConverterString.write(reason, into: &buf)
2428
2429
2430 case let .Inference(reason):
2431 writeInt(&buf, Int32(4))
2432 FfiConverterString.write(reason, into: &buf)
2433
2434
2435 case .Cancelled:
2436 writeInt(&buf, Int32(5))
2437
2438
2439 case let .Other(reason):
2440 writeInt(&buf, Int32(6))
2441 FfiConverterString.write(reason, into: &buf)
2442
2443 }
2444 }
2445 }
2446
2447
2448 #if swift(>=5.8)
2449 @_documentation(visibility: private)
2450 #endif
2451 public func FfiConverterTypeInferenceError_lift(_ buf: RustBuffer) throws -> InferenceError {
2452 return try FfiConverterTypeInferenceError.lift(buf)
2453 }
2454
2455 #if swift(>=5.8)
2456 @_documentation(visibility: private)
2457 #endif
2458 public func FfiConverterTypeInferenceError_lower(_ value: InferenceError) -> RustBuffer {
2459 return FfiConverterTypeInferenceError.lower(value)
2460 }
2461
2462 // Note that we don't yet support `indirect` for enums.
2463 // See https://github.com/mozilla/uniffi-rs/issues/396 for further discussion.
2464 /**
2465 * Whether the loaded model can reliably produce structured tool calls.
2466 *
2467 * `Unknown` is used for custom model repositories that Onde does not ship in
2468 * its built-in catalogue. Callers may choose to try those models, but should
2469 * surface that the capability has not been verified.
2470 */
2471
2472 public enum ToolCallingSupport: Equatable, Hashable {
2473
2474 case supported
2475 case unsupported
2476 case unknown
2477
2478
2479
2480
2481
2482 }
2483
2484 #if compiler(>=6)
2485 extension ToolCallingSupport: Sendable {}
2486 #endif
2487
2488 #if swift(>=5.8)
2489 @_documentation(visibility: private)
2490 #endif
2491 public struct FfiConverterTypeToolCallingSupport: FfiConverterRustBuffer {
2492 typealias SwiftType = ToolCallingSupport
2493
2494 public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> ToolCallingSupport {
2495 let variant: Int32 = try readInt(&buf)
2496 switch variant {
2497
2498 case 1: return .supported
2499
2500 case 2: return .unsupported
2501
2502 case 3: return .unknown
2503
2504 default: throw UniffiInternalError.unexpectedEnumCase
2505 }
2506 }
2507
2508 public static func write(_ value: ToolCallingSupport, into buf: inout [UInt8]) {
2509 switch value {
2510
2511
2512 case .supported:
2513 writeInt(&buf, Int32(1))
2514
2515
2516 case .unsupported:
2517 writeInt(&buf, Int32(2))
2518
2519
2520 case .unknown:
2521 writeInt(&buf, Int32(3))
2522
2523 }
2524 }
2525 }
2526
2527
2528 #if swift(>=5.8)
2529 @_documentation(visibility: private)
2530 #endif
2531 public func FfiConverterTypeToolCallingSupport_lift(_ buf: RustBuffer) throws -> ToolCallingSupport {
2532 return try FfiConverterTypeToolCallingSupport.lift(buf)
2533 }
2534
2535 #if swift(>=5.8)
2536 @_documentation(visibility: private)
2537 #endif
2538 public func FfiConverterTypeToolCallingSupport_lower(_ value: ToolCallingSupport) -> RustBuffer {
2539 return FfiConverterTypeToolCallingSupport.lower(value)
2540 }
2541
2542
2543
2544
2545
2546 /**
2547 * Callback interface for receiving streaming token chunks.
2548 *
2549 * Implement this in Swift / Kotlin and pass it to the free function
2550 * [`stream_chat_message`].
2551 *
2552 * ```swift
2553 * class MyStreamHandler: StreamChunkListener {
2554 * func onChunk(chunk: StreamChunk) -> Bool {
2555 * print(chunk.delta, terminator: "")
2556 * return !chunk.done // return false to stop early
2557 * }
2558 * }
2559 * ```
2560 */
2561 public protocol StreamChunkListener: AnyObject, Sendable {
2562
2563 /**
2564 * Called for each token chunk during streaming inference.
2565 *
2566 * Return `true` to continue receiving chunks, or `false` to cancel
2567 * the stream early (the engine will still persist partial history).
2568 */
2569 func onChunk(chunk: StreamChunk) -> Bool
2570
2571 }
2572
2573
2574 // Put the implementation in a struct so we don't pollute the top-level namespace
2575 fileprivate struct UniffiCallbackInterfaceStreamChunkListener {
2576
2577 // Create the VTable using a series of closures.
2578 // Swift automatically converts these into C callback functions.
2579 //
2580 // This creates 1-element array, since this seems to be the only way to construct a const
2581 // pointer that we can pass to the Rust code.
2582 static let vtable: [UniffiVTableCallbackInterfaceStreamChunkListener] = [UniffiVTableCallbackInterfaceStreamChunkListener(
2583 uniffiFree: { (uniffiHandle: UInt64) -> () in
2584 do {
2585 try FfiConverterCallbackInterfaceStreamChunkListener.handleMap.remove(handle: uniffiHandle)
2586 } catch {
2587 print("Uniffi callback interface StreamChunkListener: handle missing in uniffiFree")
2588 }
2589 },
2590 uniffiClone: { (uniffiHandle: UInt64) -> UInt64 in
2591 do {
2592 return try FfiConverterCallbackInterfaceStreamChunkListener.handleMap.clone(handle: uniffiHandle)
2593 } catch {
2594 fatalError("Uniffi callback interface StreamChunkListener: handle missing in uniffiClone")
2595 }
2596 },
2597 onChunk: { (
2598 uniffiHandle: UInt64,
2599 chunk: RustBuffer,
2600 uniffiOutReturn: UnsafeMutablePointer<Int8>,
2601 uniffiCallStatus: UnsafeMutablePointer<RustCallStatus>
2602 ) in
2603 let makeCall = {
2604 () throws -> Bool in
2605 guard let uniffiObj = try? FfiConverterCallbackInterfaceStreamChunkListener.handleMap.get(handle: uniffiHandle) else {
2606 throw UniffiInternalError.unexpectedStaleHandle
2607 }
2608 return uniffiObj.onChunk(
2609 chunk: try FfiConverterTypeStreamChunk_lift(chunk)
2610 )
2611 }
2612
2613
2614 let writeReturn = { uniffiOutReturn.pointee = FfiConverterBool.lower($0) }
2615 uniffiTraitInterfaceCall(
2616 callStatus: uniffiCallStatus,
2617 makeCall: makeCall,
2618 writeReturn: writeReturn
2619 )
2620 }
2621 )]
2622 }
2623
2624 private func uniffiCallbackInitStreamChunkListener() {
2625 uniffi_onde_fn_init_callback_vtable_streamchunklistener(UniffiCallbackInterfaceStreamChunkListener.vtable)
2626 }
2627
2628 // FfiConverter protocol for callback interfaces
2629 #if swift(>=5.8)
2630 @_documentation(visibility: private)
2631 #endif
2632 fileprivate struct FfiConverterCallbackInterfaceStreamChunkListener {
2633 fileprivate static let handleMap = UniffiHandleMap<StreamChunkListener>()
2634 }
2635
2636 #if swift(>=5.8)
2637 @_documentation(visibility: private)
2638 #endif
2639 extension FfiConverterCallbackInterfaceStreamChunkListener : FfiConverter {
2640 typealias SwiftType = StreamChunkListener
2641 typealias FfiType = UInt64
2642
2643 #if swift(>=5.8)
2644 @_documentation(visibility: private)
2645 #endif
2646 public static func lift(_ handle: UInt64) throws -> SwiftType {
2647 try handleMap.get(handle: handle)
2648 }
2649
2650 #if swift(>=5.8)
2651 @_documentation(visibility: private)
2652 #endif
2653 public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> SwiftType {
2654 let handle: UInt64 = try readInt(&buf)
2655 return try lift(handle)
2656 }
2657
2658 #if swift(>=5.8)
2659 @_documentation(visibility: private)
2660 #endif
2661 public static func lower(_ v: SwiftType) -> UInt64 {
2662 return handleMap.insert(obj: v)
2663 }
2664
2665 #if swift(>=5.8)
2666 @_documentation(visibility: private)
2667 #endif
2668 public static func write(_ v: SwiftType, into buf: inout [UInt8]) {
2669 writeInt(&buf, lower(v))
2670 }
2671 }
2672
2673
2674 #if swift(>=5.8)
2675 @_documentation(visibility: private)
2676 #endif
2677 public func FfiConverterCallbackInterfaceStreamChunkListener_lift(_ handle: UInt64) throws -> StreamChunkListener {
2678 return try FfiConverterCallbackInterfaceStreamChunkListener.lift(handle)
2679 }
2680
2681 #if swift(>=5.8)
2682 @_documentation(visibility: private)
2683 #endif
2684 public func FfiConverterCallbackInterfaceStreamChunkListener_lower(_ v: StreamChunkListener) -> UInt64 {
2685 return FfiConverterCallbackInterfaceStreamChunkListener.lower(v)
2686 }
2687
2688 #if swift(>=5.8)
2689 @_documentation(visibility: private)
2690 #endif
2691 fileprivate struct FfiConverterOptionUInt64: FfiConverterRustBuffer {
2692 typealias SwiftType = UInt64?
2693
2694 public static func write(_ value: SwiftType, into buf: inout [UInt8]) {
2695 guard let value = value else {
2696 writeInt(&buf, Int8(0))
2697 return
2698 }
2699 writeInt(&buf, Int8(1))
2700 FfiConverterUInt64.write(value, into: &buf)
2701 }
2702
2703 public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> SwiftType {
2704 switch try readInt(&buf) as Int8 {
2705 case 0: return nil
2706 case 1: return try FfiConverterUInt64.read(from: &buf)
2707 default: throw UniffiInternalError.unexpectedOptionalTag
2708 }
2709 }
2710 }
2711
2712 #if swift(>=5.8)
2713 @_documentation(visibility: private)
2714 #endif
2715 fileprivate struct FfiConverterOptionFloat: FfiConverterRustBuffer {
2716 typealias SwiftType = Float?
2717
2718 public static func write(_ value: SwiftType, into buf: inout [UInt8]) {
2719 guard let value = value else {
2720 writeInt(&buf, Int8(0))
2721 return
2722 }
2723 writeInt(&buf, Int8(1))
2724 FfiConverterFloat.write(value, into: &buf)
2725 }
2726
2727 public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> SwiftType {
2728 switch try readInt(&buf) as Int8 {
2729 case 0: return nil
2730 case 1: return try FfiConverterFloat.read(from: &buf)
2731 default: throw UniffiInternalError.unexpectedOptionalTag
2732 }
2733 }
2734 }
2735
2736 #if swift(>=5.8)
2737 @_documentation(visibility: private)
2738 #endif
2739 fileprivate struct FfiConverterOptionDouble: FfiConverterRustBuffer {
2740 typealias SwiftType = Double?
2741
2742 public static func write(_ value: SwiftType, into buf: inout [UInt8]) {
2743 guard let value = value else {
2744 writeInt(&buf, Int8(0))
2745 return
2746 }
2747 writeInt(&buf, Int8(1))
2748 FfiConverterDouble.write(value, into: &buf)
2749 }
2750
2751 public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> SwiftType {
2752 switch try readInt(&buf) as Int8 {
2753 case 0: return nil
2754 case 1: return try FfiConverterDouble.read(from: &buf)
2755 default: throw UniffiInternalError.unexpectedOptionalTag
2756 }
2757 }
2758 }
2759
2760 #if swift(>=5.8)
2761 @_documentation(visibility: private)
2762 #endif
2763 fileprivate struct FfiConverterOptionString: FfiConverterRustBuffer {
2764 typealias SwiftType = String?
2765
2766 public static func write(_ value: SwiftType, into buf: inout [UInt8]) {
2767 guard let value = value else {
2768 writeInt(&buf, Int8(0))
2769 return
2770 }
2771 writeInt(&buf, Int8(1))
2772 FfiConverterString.write(value, into: &buf)
2773 }
2774
2775 public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> SwiftType {
2776 switch try readInt(&buf) as Int8 {
2777 case 0: return nil
2778 case 1: return try FfiConverterString.read(from: &buf)
2779 default: throw UniffiInternalError.unexpectedOptionalTag
2780 }
2781 }
2782 }
2783
2784 #if swift(>=5.8)
2785 @_documentation(visibility: private)
2786 #endif
2787 fileprivate struct FfiConverterOptionTypeSamplingConfig: FfiConverterRustBuffer {
2788 typealias SwiftType = SamplingConfig?
2789
2790 public static func write(_ value: SwiftType, into buf: inout [UInt8]) {
2791 guard let value = value else {
2792 writeInt(&buf, Int8(0))
2793 return
2794 }
2795 writeInt(&buf, Int8(1))
2796 FfiConverterTypeSamplingConfig.write(value, into: &buf)
2797 }
2798
2799 public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> SwiftType {
2800 switch try readInt(&buf) as Int8 {
2801 case 0: return nil
2802 case 1: return try FfiConverterTypeSamplingConfig.read(from: &buf)
2803 default: throw UniffiInternalError.unexpectedOptionalTag
2804 }
2805 }
2806 }
2807
2808 #if swift(>=5.8)
2809 @_documentation(visibility: private)
2810 #endif
2811 fileprivate struct FfiConverterSequenceString: FfiConverterRustBuffer {
2812 typealias SwiftType = [String]
2813
2814 public static func write(_ value: [String], into buf: inout [UInt8]) {
2815 let len = Int32(value.count)
2816 writeInt(&buf, len)
2817 for item in value {
2818 FfiConverterString.write(item, into: &buf)
2819 }
2820 }
2821
2822 public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> [String] {
2823 let len: Int32 = try readInt(&buf)
2824 var seq = [String]()
2825 seq.reserveCapacity(Int(len))
2826 for _ in 0 ..< len {
2827 seq.append(try FfiConverterString.read(from: &buf))
2828 }
2829 return seq
2830 }
2831 }
2832
2833 #if swift(>=5.8)
2834 @_documentation(visibility: private)
2835 #endif
2836 fileprivate struct FfiConverterSequenceTypeChatMessage: FfiConverterRustBuffer {
2837 typealias SwiftType = [ChatMessage]
2838
2839 public static func write(_ value: [ChatMessage], into buf: inout [UInt8]) {
2840 let len = Int32(value.count)
2841 writeInt(&buf, len)
2842 for item in value {
2843 FfiConverterTypeChatMessage.write(item, into: &buf)
2844 }
2845 }
2846
2847 public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> [ChatMessage] {
2848 let len: Int32 = try readInt(&buf)
2849 var seq = [ChatMessage]()
2850 seq.reserveCapacity(Int(len))
2851 for _ in 0 ..< len {
2852 seq.append(try FfiConverterTypeChatMessage.read(from: &buf))
2853 }
2854 return seq
2855 }
2856 }
2857
2858 #if swift(>=5.8)
2859 @_documentation(visibility: private)
2860 #endif
2861 fileprivate struct FfiConverterSequenceTypeToolCallInfo: FfiConverterRustBuffer {
2862 typealias SwiftType = [ToolCallInfo]
2863
2864 public static func write(_ value: [ToolCallInfo], into buf: inout [UInt8]) {
2865 let len = Int32(value.count)
2866 writeInt(&buf, len)
2867 for item in value {
2868 FfiConverterTypeToolCallInfo.write(item, into: &buf)
2869 }
2870 }
2871
2872 public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> [ToolCallInfo] {
2873 let len: Int32 = try readInt(&buf)
2874 var seq = [ToolCallInfo]()
2875 seq.reserveCapacity(Int(len))
2876 for _ in 0 ..< len {
2877 seq.append(try FfiConverterTypeToolCallInfo.read(from: &buf))
2878 }
2879 return seq
2880 }
2881 }
2882 private let UNIFFI_RUST_FUTURE_POLL_READY: Int8 = 0
2883 private let UNIFFI_RUST_FUTURE_POLL_WAKE: Int8 = 1
2884
2885 fileprivate let uniffiContinuationHandleMap = UniffiHandleMap<UnsafeContinuation<Int8, Never>>()
2886
2887 fileprivate func uniffiRustCallAsync<F, T>(
2888 rustFutureFunc: () -> UInt64,
2889 pollFunc: (UInt64, @escaping UniffiRustFutureContinuationCallback, UInt64) -> (),
2890 completeFunc: (UInt64, UnsafeMutablePointer<RustCallStatus>) -> F,
2891 freeFunc: (UInt64) -> (),
2892 liftFunc: (F) throws -> T,
2893 errorHandler: ((RustBuffer) throws -> Swift.Error)?
2894 ) async throws -> T {
2895 // Make sure to call the ensure init function since future creation doesn't have a
2896 // RustCallStatus param, so doesn't use makeRustCall()
2897 uniffiEnsureOndeInitialized()
2898 let rustFuture = rustFutureFunc()
2899 defer {
2900 freeFunc(rustFuture)
2901 }
2902 var pollResult: Int8;
2903 repeat {
2904 pollResult = await withUnsafeContinuation {
2905 pollFunc(
2906 rustFuture,
2907 { handle, pollResult in
2908 uniffiFutureContinuationCallback(handle: handle, pollResult: pollResult)
2909 },
2910 uniffiContinuationHandleMap.insert(obj: $0)
2911 )
2912 }
2913 } while pollResult != UNIFFI_RUST_FUTURE_POLL_READY
2914
2915 return try liftFunc(makeRustCall(
2916 { completeFunc(rustFuture, $0) },
2917 errorHandler: errorHandler
2918 ))
2919 }
2920
2921 // Callback handlers for an async calls. These are invoked by Rust when the future is ready. They
2922 // lift the return value or error and resume the suspended function.
2923 fileprivate func uniffiFutureContinuationCallback(handle: UInt64, pollResult: Int8) {
2924 if let continuation = try? uniffiContinuationHandleMap.remove(handle: handle) {
2925 continuation.resume(returning: pollResult)
2926 } else {
2927 print("uniffiFutureContinuationCallback invalid handle")
2928 }
2929 }
2930 /**
2931 * Create an assistant message.
2932 */
2933 public func assistantMessage(content: String) -> ChatMessage {
2934 return try! FfiConverterTypeChatMessage_lift(try! rustCall() {
2935 uniffi_onde_fn_func_assistant_message(
2936 FfiConverterString.lower(content),$0
2937 )
2938 })
2939 }
2940 /**
2941 * Configure the HF cache directory for sandboxed platforms.
2942 *
2943 * Call this before any model-loading method (`load_gguf_model`,
2944 * `load_default_model`, etc.) on iOS, tvOS, and Android where the
2945 * default `~/.cache/huggingface` path is inaccessible.
2946 *
2947 * `path` should be a writable app data directory (e.g. the App Group
2948 * container or Application Support directory on Apple platforms).
2949 *
2950 * This sets the `HF_HOME` and `HF_HUB_CACHE` environment variables
2951 * and creates the directory structure.
2952 */
2953 public func configureCacheDir(path: String) {try! rustCall() {
2954 uniffi_onde_fn_func_configure_cache_dir(
2955 FfiConverterString.lower(path),$0
2956 )
2957 }
2958 }
2959 /**
2960 * Return the platform-appropriate default GGUF model configuration.
2961 *
2962 * - tvOS / iOS / Android → Qwen 2.5 1.5B (~941 MB)
2963 * - macOS / Windows / Linux → Qwen 2.5 3B (~1.93 GB)
2964 */
2965 public func defaultModelConfig() -> GgufModelConfig {
2966 return try! FfiConverterTypeGgufModelConfig_lift(try! rustCall() {
2967 uniffi_onde_fn_func_default_model_config($0
2968 )
2969 })
2970 }
2971 /**
2972 * Return default sampling parameters for creative chat.
2973 */
2974 public func defaultSamplingConfig() -> SamplingConfig {
2975 return try! FfiConverterTypeSamplingConfig_lift(try! rustCall() {
2976 uniffi_onde_fn_func_default_sampling_config($0
2977 )
2978 })
2979 }
2980 /**
2981 * Return deterministic (greedy) sampling parameters.
2982 */
2983 public func deterministicSamplingConfig() -> SamplingConfig {
2984 return try! FfiConverterTypeSamplingConfig_lift(try! rustCall() {
2985 uniffi_onde_fn_func_deterministic_sampling_config($0
2986 )
2987 })
2988 }
2989 /**
2990 * Return conservative sampling parameters for mobile devices.
2991 */
2992 public func mobileSamplingConfig() -> SamplingConfig {
2993 return try! FfiConverterTypeSamplingConfig_lift(try! rustCall() {
2994 uniffi_onde_fn_func_mobile_sampling_config($0
2995 )
2996 })
2997 }
2998 /**
2999 * Return the Qwen 2.5 0.5B GGUF model configuration (~380 MB).
3000 */
3001 public func qwen2505bConfig() -> GgufModelConfig {
3002 return try! FfiConverterTypeGgufModelConfig_lift(try! rustCall() {
3003 uniffi_onde_fn_func_qwen25_0_5b_config($0
3004 )
3005 })
3006 }
3007 /**
3008 * Return the Qwen 2.5 1.5B GGUF model configuration (~941 MB).
3009 */
3010 public func qwen2515bConfig() -> GgufModelConfig {
3011 return try! FfiConverterTypeGgufModelConfig_lift(try! rustCall() {
3012 uniffi_onde_fn_func_qwen25_1_5b_config($0
3013 )
3014 })
3015 }
3016 /**
3017 * Return the Qwen 2.5 3B GGUF model configuration (~1.93 GB).
3018 */
3019 public func qwen253bConfig() -> GgufModelConfig {
3020 return try! FfiConverterTypeGgufModelConfig_lift(try! rustCall() {
3021 uniffi_onde_fn_func_qwen25_3b_config($0
3022 )
3023 })
3024 }
3025 /**
3026 * Return the Qwen 3 0.6B GGUF model configuration (~0.5 GB).
3027 */
3028 public func qwen306bConfig() -> GgufModelConfig {
3029 return try! FfiConverterTypeGgufModelConfig_lift(try! rustCall() {
3030 uniffi_onde_fn_func_qwen3_0_6b_config($0
3031 )
3032 })
3033 }
3034 /**
3035 * Return the Qwen 3 14B GGUF model configuration (~8.4 GB).
3036 */
3037 public func qwen314bConfig() -> GgufModelConfig {
3038 return try! FfiConverterTypeGgufModelConfig_lift(try! rustCall() {
3039 uniffi_onde_fn_func_qwen3_14b_config($0
3040 )
3041 })
3042 }
3043 /**
3044 * Return the Qwen 3 1.7B GGUF model configuration (~1.3 GB).
3045 */
3046 public func qwen317bConfig() -> GgufModelConfig {
3047 return try! FfiConverterTypeGgufModelConfig_lift(try! rustCall() {
3048 uniffi_onde_fn_func_qwen3_1_7b_config($0
3049 )
3050 })
3051 }
3052 /**
3053 * Return the Qwen 3 30B-A3B Instruct 2507 (MoE) GGUF model configuration (~18.6 GB).
3054 */
3055 public func qwen330bA3bInstruct2507Config() -> GgufModelConfig {
3056 return try! FfiConverterTypeGgufModelConfig_lift(try! rustCall() {
3057 uniffi_onde_fn_func_qwen3_30b_a3b_instruct_2507_config($0
3058 )
3059 })
3060 }
3061 /**
3062 * Return the Qwen 3 32B GGUF model configuration (~19.8 GB).
3063 */
3064 public func qwen332bConfig() -> GgufModelConfig {
3065 return try! FfiConverterTypeGgufModelConfig_lift(try! rustCall() {
3066 uniffi_onde_fn_func_qwen3_32b_config($0
3067 )
3068 })
3069 }
3070 /**
3071 * Return the Qwen 3 4B GGUF model configuration (~2.7 GB).
3072 */
3073 public func qwen34bConfig() -> GgufModelConfig {
3074 return try! FfiConverterTypeGgufModelConfig_lift(try! rustCall() {
3075 uniffi_onde_fn_func_qwen3_4b_config($0
3076 )
3077 })
3078 }
3079 /**
3080 * Return the Qwen 3 4B Instruct 2507 GGUF model configuration (~2.5 GB).
3081 *
3082 * Latest non-thinking 4B checkpoint — recommended general-purpose Qwen 3 model.
3083 */
3084 public func qwen34bInstruct2507Config() -> GgufModelConfig {
3085 return try! FfiConverterTypeGgufModelConfig_lift(try! rustCall() {
3086 uniffi_onde_fn_func_qwen3_4b_instruct_2507_config($0
3087 )
3088 })
3089 }
3090 /**
3091 * Return the Qwen 3 4B Thinking 2507 GGUF model configuration (~2.5 GB).
3092 *
3093 * Latest reasoning-focused 4B checkpoint; load with `max_tokens ≥ 4096`.
3094 */
3095 public func qwen34bThinking2507Config() -> GgufModelConfig {
3096 return try! FfiConverterTypeGgufModelConfig_lift(try! rustCall() {
3097 uniffi_onde_fn_func_qwen3_4b_thinking_2507_config($0
3098 )
3099 })
3100 }
3101 /**
3102 * Return the Qwen 3 8B GGUF model configuration (~5 GB).
3103 */
3104 public func qwen38bConfig() -> GgufModelConfig {
3105 return try! FfiConverterTypeGgufModelConfig_lift(try! rustCall() {
3106 uniffi_onde_fn_func_qwen3_8b_config($0
3107 )
3108 })
3109 }
3110 /**
3111 * Stream a chat message through the engine, delivering token chunks to
3112 * the `listener` callback.
3113 *
3114 * This is a **free function** (not an Object method) because UniFFI 0.31
3115 * requires `callback_interface` parameters to be passed to free functions
3116 * rather than Object methods.
3117 *
3118 * The `listener.on_chunk()` callback is called for each token delta.
3119 * Return `true` to continue, or `false` to cancel early.
3120 *
3121 * The user message and assembled reply are automatically appended to the
3122 * engine's conversation history when streaming completes.
3123 *
3124 * ```swift
3125 * class MyHandler: StreamChunkListener {
3126 * func onChunk(chunk: StreamChunk) -> Bool {
3127 * print(chunk.delta, terminator: "")
3128 * return !chunk.done
3129 * }
3130 * }
3131 *
3132 * try await streamChatMessage(
3133 * engine: engine,
3134 * message: "Tell me a story.",
3135 * listener: MyHandler()
3136 * )
3137 * ```
3138 */
3139 public func streamChatMessage(engine: OndeChatEngine, message: String, listener: StreamChunkListener)async throws {
3140 return
3141 try await uniffiRustCallAsync(
3142 rustFutureFunc: {
3143 uniffi_onde_fn_func_stream_chat_message(FfiConverterTypeOndeChatEngine_lower(engine),FfiConverterString.lower(message),FfiConverterCallbackInterfaceStreamChunkListener_lower(listener)
3144 )
3145 },
3146 pollFunc: ffi_onde_rust_future_poll_void,
3147 completeFunc: ffi_onde_rust_future_complete_void,
3148 freeFunc: ffi_onde_rust_future_free_void,
3149 liftFunc: { $0 },
3150 errorHandler: FfiConverterTypeInferenceError_lift
3151 )
3152 }
3153 /**
3154 * Create a system message.
3155 */
3156 public func systemMessage(content: String) -> ChatMessage {
3157 return try! FfiConverterTypeChatMessage_lift(try! rustCall() {
3158 uniffi_onde_fn_func_system_message(
3159 FfiConverterString.lower(content),$0
3160 )
3161 })
3162 }
3163 /**
3164 * Create a generic UQFF model configuration.
3165 *
3166 * `model_id` is the HuggingFace repo or local directory of the UQFF export
3167 * (the shards plus `residual.safetensors`, `config.json`, and the tokenizer),
3168 * not the original unquantised repo. `files` accepts a first shard
3169 * (`q4k-0.uqff`), explicit shards, or mistral.rs shorthands such as `q4k`
3170 * and `4`.
3171 */
3172 public func uqffModelConfig(modelId: String, files: [String], displayName: String, approxMemory: String, chatTemplate: String?) -> UqffModelConfig {
3173 return try! FfiConverterTypeUqffModelConfig_lift(try! rustCall() {
3174 uniffi_onde_fn_func_uqff_model_config(
3175 FfiConverterString.lower(modelId),
3176 FfiConverterSequenceString.lower(files),
3177 FfiConverterString.lower(displayName),
3178 FfiConverterString.lower(approxMemory),
3179 FfiConverterOptionString.lower(chatTemplate),$0
3180 )
3181 })
3182 }
3183 /**
3184 * Create a user message.
3185 */
3186 public func userMessage(content: String) -> ChatMessage {
3187 return try! FfiConverterTypeChatMessage_lift(try! rustCall() {
3188 uniffi_onde_fn_func_user_message(
3189 FfiConverterString.lower(content),$0
3190 )
3191 })
3192 }
3193
3194 private enum InitializationResult {
3195 case ok
3196 case contractVersionMismatch
3197 case apiChecksumMismatch
3198 }
3199 // Use a global variable to perform the versioning checks. Swift ensures that
3200 // the code inside is only computed once.
3201 private let initializationResult: InitializationResult = {
3202 // Get the bindings contract version from our ComponentInterface
3203 let bindings_contract_version = 30
3204 // Get the scaffolding contract version by calling the into the dylib
3205 let scaffolding_contract_version = ffi_onde_uniffi_contract_version()
3206 if bindings_contract_version != scaffolding_contract_version {
3207 return InitializationResult.contractVersionMismatch
3208 }
3209 if (uniffi_onde_checksum_func_assistant_message() != 47135) {
3210 return InitializationResult.apiChecksumMismatch
3211 }
3212 if (uniffi_onde_checksum_func_configure_cache_dir() != 6269) {
3213 return InitializationResult.apiChecksumMismatch
3214 }
3215 if (uniffi_onde_checksum_func_default_model_config() != 34766) {
3216 return InitializationResult.apiChecksumMismatch
3217 }
3218 if (uniffi_onde_checksum_func_default_sampling_config() != 57358) {
3219 return InitializationResult.apiChecksumMismatch
3220 }
3221 if (uniffi_onde_checksum_func_deterministic_sampling_config() != 3003) {
3222 return InitializationResult.apiChecksumMismatch
3223 }
3224 if (uniffi_onde_checksum_func_mobile_sampling_config() != 46137) {
3225 return InitializationResult.apiChecksumMismatch
3226 }
3227 if (uniffi_onde_checksum_func_qwen25_0_5b_config() != 53289) {
3228 return InitializationResult.apiChecksumMismatch
3229 }
3230 if (uniffi_onde_checksum_func_qwen25_1_5b_config() != 41668) {
3231 return InitializationResult.apiChecksumMismatch
3232 }
3233 if (uniffi_onde_checksum_func_qwen25_3b_config() != 36458) {
3234 return InitializationResult.apiChecksumMismatch
3235 }
3236 if (uniffi_onde_checksum_func_qwen3_0_6b_config() != 20653) {
3237 return InitializationResult.apiChecksumMismatch
3238 }
3239 if (uniffi_onde_checksum_func_qwen3_14b_config() != 44701) {
3240 return InitializationResult.apiChecksumMismatch
3241 }
3242 if (uniffi_onde_checksum_func_qwen3_1_7b_config() != 32382) {
3243 return InitializationResult.apiChecksumMismatch
3244 }
3245 if (uniffi_onde_checksum_func_qwen3_30b_a3b_instruct_2507_config() != 55315) {
3246 return InitializationResult.apiChecksumMismatch
3247 }
3248 if (uniffi_onde_checksum_func_qwen3_32b_config() != 20244) {
3249 return InitializationResult.apiChecksumMismatch
3250 }
3251 if (uniffi_onde_checksum_func_qwen3_4b_config() != 44102) {
3252 return InitializationResult.apiChecksumMismatch
3253 }
3254 if (uniffi_onde_checksum_func_qwen3_4b_instruct_2507_config() != 20415) {
3255 return InitializationResult.apiChecksumMismatch
3256 }
3257 if (uniffi_onde_checksum_func_qwen3_4b_thinking_2507_config() != 9987) {
3258 return InitializationResult.apiChecksumMismatch
3259 }
3260 if (uniffi_onde_checksum_func_qwen3_8b_config() != 16355) {
3261 return InitializationResult.apiChecksumMismatch
3262 }
3263 if (uniffi_onde_checksum_func_stream_chat_message() != 5168) {
3264 return InitializationResult.apiChecksumMismatch
3265 }
3266 if (uniffi_onde_checksum_func_system_message() != 55655) {
3267 return InitializationResult.apiChecksumMismatch
3268 }
3269 if (uniffi_onde_checksum_func_uqff_model_config() != 61694) {
3270 return InitializationResult.apiChecksumMismatch
3271 }
3272 if (uniffi_onde_checksum_func_user_message() != 23108) {
3273 return InitializationResult.apiChecksumMismatch
3274 }
3275 if (uniffi_onde_checksum_method_ondechatengine_clear_history() != 5662) {
3276 return InitializationResult.apiChecksumMismatch
3277 }
3278 if (uniffi_onde_checksum_method_ondechatengine_clear_system_prompt() != 46275) {
3279 return InitializationResult.apiChecksumMismatch
3280 }
3281 if (uniffi_onde_checksum_method_ondechatengine_generate() != 63069) {
3282 return InitializationResult.apiChecksumMismatch
3283 }
3284 if (uniffi_onde_checksum_method_ondechatengine_history() != 45301) {
3285 return InitializationResult.apiChecksumMismatch
3286 }
3287 if (uniffi_onde_checksum_method_ondechatengine_info() != 42415) {
3288 return InitializationResult.apiChecksumMismatch
3289 }
3290 if (uniffi_onde_checksum_method_ondechatengine_is_loaded() != 59838) {
3291 return InitializationResult.apiChecksumMismatch
3292 }
3293 if (uniffi_onde_checksum_method_ondechatengine_load_assigned_model() != 25824) {
3294 return InitializationResult.apiChecksumMismatch
3295 }
3296 if (uniffi_onde_checksum_method_ondechatengine_load_default_model() != 32187) {
3297 return InitializationResult.apiChecksumMismatch
3298 }
3299 if (uniffi_onde_checksum_method_ondechatengine_load_gguf_model() != 6873) {
3300 return InitializationResult.apiChecksumMismatch
3301 }
3302 if (uniffi_onde_checksum_method_ondechatengine_load_uqff_model() != 18211) {
3303 return InitializationResult.apiChecksumMismatch
3304 }
3305 if (uniffi_onde_checksum_method_ondechatengine_push_history() != 61696) {
3306 return InitializationResult.apiChecksumMismatch
3307 }
3308 if (uniffi_onde_checksum_method_ondechatengine_send_message() != 23695) {
3309 return InitializationResult.apiChecksumMismatch
3310 }
3311 if (uniffi_onde_checksum_method_ondechatengine_set_sampling() != 10759) {
3312 return InitializationResult.apiChecksumMismatch
3313 }
3314 if (uniffi_onde_checksum_method_ondechatengine_set_system_prompt() != 63168) {
3315 return InitializationResult.apiChecksumMismatch
3316 }
3317 if (uniffi_onde_checksum_method_ondechatengine_unload_model() != 33799) {
3318 return InitializationResult.apiChecksumMismatch
3319 }
3320 if (uniffi_onde_checksum_constructor_ondechatengine_new() != 39683) {
3321 return InitializationResult.apiChecksumMismatch
3322 }
3323 if (uniffi_onde_checksum_method_streamchunklistener_on_chunk() != 33920) {
3324 return InitializationResult.apiChecksumMismatch
3325 }
3326
3327 uniffiCallbackInitStreamChunkListener()
3328 return InitializationResult.ok
3329 }()
3330
3331 // Make the ensure init function public so that other modules which have external type references to
3332 // our types can call it.
3333 public func uniffiEnsureOndeInitialized() {
3334 switch initializationResult {
3335 case .ok:
3336 break
3337 case .contractVersionMismatch:
3338 fatalError("UniFFI contract version mismatch: try cleaning and rebuilding your project")
3339 case .apiChecksumMismatch:
3340 fatalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project")
3341 }
3342 }
3343
3344 // swiftlint:enable all