Release 1.2.3

github-actions[bot] committed Aug 19, 2026 at 09:26 UTC b08a412e8f89c20743551d423cb6c0308f900be1
2 files changed +188 -2
Package.swift
+2 -2
@@ -24,9 +24,9 @@ let packageRoot = URL(fileURLWithPath: #filePath).deletingLastPathComponent()
24 let localFrameworkPath = "OndeFramework.xcframework"
25 let localFrameworkAbsolutePath = packageRoot.appendingPathComponent(localFrameworkPath).path
26 let releaseFrameworkURL =
27 - "https://github.com/ondeinference/onde/releases/download/1.2.2/OndeFramework.xcframework.zip"
27 + "https://github.com/ondeinference/onde/releases/download/1.2.3/OndeFramework.xcframework.zip"
28 let releaseFrameworkChecksum =
29 - "3e930144fd078d1bed78ebafa22edf9763a3bc6588b0a4667fb37096ba78220b"
29 + "256ff064dbb77b7d433fe768db3dae5b63ded2768d47ed913815cc1c876cbaf3"
30
31 let ondeFrameworkTarget: Target
32 if FileManager.default.fileExists(atPath: localFrameworkAbsolutePath) {
Sources/Onde/onde.swift
+186
@@ -632,6 +632,18 @@ public protocol OndeChatEngineProtocol: AnyObject, Sendable {
632 */
633 func loadGgufModel(config: GgufModelConfig, systemPrompt: String?, sampling: SamplingConfig?) async throws -> Double
634
635 + /**
636 + * Load a UQFF model into the engine.
637 + *
638 + * UQFF files are pre-quantised and load directly without runtime
639 + * conversion. `config.model_id` names the UQFF export (not the original
640 + * unquantised repo), and `config.files` should contain the first UQFF
641 + * shard or explicit shard filenames.
642 + *
643 + * Returns the wall-clock loading time in seconds.
644 + */
645 + func loadUqffModel(config: UqffModelConfig, systemPrompt: String?, sampling: SamplingConfig?) async throws -> Double
646 +
647 /**
648 * Append a message to history without running inference.
649 */
@@ -943,6 +955,33 @@ open func loadGgufModel(config: GgufModelConfig, systemPrompt: String?, sampling
955 )
956 }
957
958 + /**
959 + * Load a UQFF model into the engine.
960 + *
961 + * UQFF files are pre-quantised and load directly without runtime
962 + * conversion. `config.model_id` names the UQFF export (not the original
963 + * unquantised repo), and `config.files` should contain the first UQFF
964 + * shard or explicit shard filenames.
965 + *
966 + * Returns the wall-clock loading time in seconds.
967 + */
968 +open func loadUqffModel(config: UqffModelConfig, systemPrompt: String?, sampling: SamplingConfig?)async throws -> Double {
969 + return
970 + try await uniffiRustCallAsync(
971 + rustFutureFunc: {
972 + uniffi_onde_fn_method_ondechatengine_load_uqff_model(
973 + self.uniffiCloneHandle(),
974 + FfiConverterTypeUqffModelConfig_lower(config),FfiConverterOptionString.lower(systemPrompt),FfiConverterOptionTypeSamplingConfig.lower(sampling)
975 + )
976 + },
977 + pollFunc: ffi_onde_rust_future_poll_f64,
978 + completeFunc: ffi_onde_rust_future_complete_f64,
979 + freeFunc: ffi_onde_rust_future_free_f64,
980 + liftFunc: FfiConverterDouble.lift,
981 + errorHandler: FfiConverterTypeInferenceError_lift
982 + )
983 +}
984 +
985 /**
986 * Append a message to history without running inference.
987 */
@@ -1991,6 +2030,127 @@ public func FfiConverterTypeToolResult_lower(_ value: ToolResult) -> RustBuffer
2030 return FfiConverterTypeToolResult.lower(value)
2031 }
2032
2033 +
2034 +/**
2035 + * Configuration for loading a UQFF model via mistral.rs
2036 + * `UqffTextModelBuilder`.
2037 + *
2038 + * UQFF files store pre-quantised weights and load directly
2039 + * without the runtime memory spike of in-situ quantisation. `model_id` points
2040 + * at the UQFF *export* — the directory or repository holding the shards
2041 + * alongside `residual.safetensors`, `config.json`, and the tokenizer — and
2042 + * `files` identifies the first UQFF shard or explicit UQFF shard files.
2043 + *
2044 + * Note that `model_id` is **not** the original unquantised model repository:
2045 + * mistral.rs resolves the shards, the residual weights, and the JSON assets by
2046 + * sibling lookup next to `model_id`, so pointing it at the source repo fails
2047 + * with a missing-file error. A UQFF export is self-contained by design.
2048 + */
2049 +public struct UqffModelConfig: Equatable, Hashable {
2050 + /**
2051 + * HuggingFace repository ID or local directory of the UQFF export, e.g.
2052 + * `"mistralrs-community/gemma-4-E4B-it-UQFF"`.
2053 + */
2054 + public var modelId: String
2055 + /**
2056 + * UQFF filename(s) within the repository. For sharded UQFFs, passing the
2057 + * first shard, e.g. `["q4k-0.uqff"]`, is enough for mistral.rs to discover
2058 + * siblings. Numeric and ISQ-name shorthands such as `"4"` and `"q4k"` are
2059 + * also accepted by the underlying loader.
2060 + */
2061 + public var files: [String]
2062 + /**
2063 + * Human-friendly display name, e.g. `"Gemma 4 E4B (UQFF Q4K)"`.
2064 + */
2065 + public var displayName: String
2066 + /**
2067 + * Approximate memory footprint description, e.g. `"~2.5 GB (UQFF Q4K)"`.
2068 + */
2069 + public var approxMemory: String
2070 + /**
2071 + * Optional Jinja chat template string. When set, this overrides the
2072 + * template resolved from the base model.
2073 + */
2074 + public var chatTemplate: String?
2075 +
2076 + // Default memberwise initializers are never public by default, so we
2077 + // declare one manually.
2078 + public init(
2079 + /**
2080 + * HuggingFace repository ID or local directory of the UQFF export, e.g.
2081 + * `"mistralrs-community/gemma-4-E4B-it-UQFF"`.
2082 + */modelId: String,
2083 + /**
2084 + * UQFF filename(s) within the repository. For sharded UQFFs, passing the
2085 + * first shard, e.g. `["q4k-0.uqff"]`, is enough for mistral.rs to discover
2086 + * siblings. Numeric and ISQ-name shorthands such as `"4"` and `"q4k"` are
2087 + * also accepted by the underlying loader.
2088 + */files: [String],
2089 + /**
2090 + * Human-friendly display name, e.g. `"Gemma 4 E4B (UQFF Q4K)"`.
2091 + */displayName: String,
2092 + /**
2093 + * Approximate memory footprint description, e.g. `"~2.5 GB (UQFF Q4K)"`.
2094 + */approxMemory: String,
2095 + /**
2096 + * Optional Jinja chat template string. When set, this overrides the
2097 + * template resolved from the base model.
2098 + */chatTemplate: String?) {
2099 + self.modelId = modelId
2100 + self.files = files
2101 + self.displayName = displayName
2102 + self.approxMemory = approxMemory
2103 + self.chatTemplate = chatTemplate
2104 + }
2105 +
2106 +
2107 +
2108 +
2109 +}
2110 +
2111 +#if compiler(>=6)
2112 +extension UqffModelConfig: Sendable {}
2113 +#endif
2114 +
2115 +#if swift(>=5.8)
2116 +@_documentation(visibility: private)
2117 +#endif
2118 +public struct FfiConverterTypeUqffModelConfig: FfiConverterRustBuffer {
2119 + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> UqffModelConfig {
2120 + return
2121 + try UqffModelConfig(
2122 + modelId: FfiConverterString.read(from: &buf),
2123 + files: FfiConverterSequenceString.read(from: &buf),
2124 + displayName: FfiConverterString.read(from: &buf),
2125 + approxMemory: FfiConverterString.read(from: &buf),
2126 + chatTemplate: FfiConverterOptionString.read(from: &buf)
2127 + )
2128 + }
2129 +
2130 + public static func write(_ value: UqffModelConfig, into buf: inout [UInt8]) {
2131 + FfiConverterString.write(value.modelId, into: &buf)
2132 + FfiConverterSequenceString.write(value.files, into: &buf)
2133 + FfiConverterString.write(value.displayName, into: &buf)
2134 + FfiConverterString.write(value.approxMemory, into: &buf)
2135 + FfiConverterOptionString.write(value.chatTemplate, into: &buf)
2136 + }
2137 +}
2138 +
2139 +
2140 +#if swift(>=5.8)
2141 +@_documentation(visibility: private)
2142 +#endif
2143 +public func FfiConverterTypeUqffModelConfig_lift(_ buf: RustBuffer) throws -> UqffModelConfig {
2144 + return try FfiConverterTypeUqffModelConfig.lift(buf)
2145 +}
2146 +
2147 +#if swift(>=5.8)
2148 +@_documentation(visibility: private)
2149 +#endif
2150 +public func FfiConverterTypeUqffModelConfig_lower(_ value: UqffModelConfig) -> RustBuffer {
2151 + return FfiConverterTypeUqffModelConfig.lower(value)
2152 +}
2153 +
2154 // Note that we don't yet support `indirect` for enums.
2155 // See https://github.com/mozilla/uniffi-rs/issues/396 for further discussion.
2156 /**
@@ -2919,6 +3079,26 @@ public func systemMessage(content: String) -> ChatMessage {
3079 )
3080 })
3081 }
3082 +/**
3083 + * Create a generic UQFF model configuration.
3084 + *
3085 + * `model_id` is the HuggingFace repo or local directory of the UQFF export
3086 + * (the shards plus `residual.safetensors`, `config.json`, and the tokenizer),
3087 + * not the original unquantised repo. `files` accepts a first shard
3088 + * (`q4k-0.uqff`), explicit shards, or mistral.rs shorthands such as `q4k`
3089 + * and `4`.
3090 + */
3091 +public func uqffModelConfig(modelId: String, files: [String], displayName: String, approxMemory: String, chatTemplate: String?) -> UqffModelConfig {
3092 + return try! FfiConverterTypeUqffModelConfig_lift(try! rustCall() {
3093 + uniffi_onde_fn_func_uqff_model_config(
3094 + FfiConverterString.lower(modelId),
3095 + FfiConverterSequenceString.lower(files),
3096 + FfiConverterString.lower(displayName),
3097 + FfiConverterString.lower(approxMemory),
3098 + FfiConverterOptionString.lower(chatTemplate),$0
3099 + )
3100 +})
3101 +}
3102 /**
3103 * Create a user message.
3104 */
@@ -3005,6 +3185,9 @@ private let initializationResult: InitializationResult = {
3185 if (uniffi_onde_checksum_func_system_message() != 55655) {
3186 return InitializationResult.apiChecksumMismatch
3187 }
3188 + if (uniffi_onde_checksum_func_uqff_model_config() != 61694) {
3189 + return InitializationResult.apiChecksumMismatch
3190 + }
3191 if (uniffi_onde_checksum_func_user_message() != 23108) {
3192 return InitializationResult.apiChecksumMismatch
3193 }
@@ -3035,6 +3218,9 @@ private let initializationResult: InitializationResult = {
3218 if (uniffi_onde_checksum_method_ondechatengine_load_gguf_model() != 6873) {
3219 return InitializationResult.apiChecksumMismatch
3220 }
3221 + if (uniffi_onde_checksum_method_ondechatengine_load_uqff_model() != 18211) {
3222 + return InitializationResult.apiChecksumMismatch
3223 + }
3224 if (uniffi_onde_checksum_method_ondechatengine_push_history() != 61696) {
3225 return InitializationResult.apiChecksumMismatch
3226 }