Release 0.1.0

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