Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 51 additions & 2 deletions deployment/on-device/leap-sdk-changelog.mdx
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
---
title: "Changelog"
description: "Release notes for the LEAP SDK, including the 0.9.x → 0.10.x Kotlin Multiplatform transition."

Check warning on line 3 in deployment/on-device/leap-sdk-changelog.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai) - vale-spellcheck

deployment/on-device/leap-sdk-changelog.mdx#L3

Did you really mean 'Multiplatform'?

Check warning on line 3 in deployment/on-device/leap-sdk-changelog.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai-main) - vale-spellcheck

deployment/on-device/leap-sdk-changelog.mdx#L3

Did you really mean 'Multiplatform'?
---

Latest release: **v0.10.7** ([GitHub](https://github.com/Liquid4All/leap-sdk/releases/tag/v0.10.7)).
Latest release: **v0.10.8** ([GitHub](https://github.com/Liquid4All/leap-sdk/releases/tag/v0.10.8)).

This page covers user-visible changes in the LEAP SDK across releases. For per-build commit detail, see the release notes on [`Liquid4All/leap-sdk`](https://github.com/Liquid4All/leap-sdk/releases).

## 0.9.x → 0.10.x: Kotlin Multiplatform unification

Check warning on line 10 in deployment/on-device/leap-sdk-changelog.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai) - vale-spellcheck

deployment/on-device/leap-sdk-changelog.mdx#L10

Did you really mean 'Multiplatform'?

Check warning on line 10 in deployment/on-device/leap-sdk-changelog.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai-main) - vale-spellcheck

deployment/on-device/leap-sdk-changelog.mdx#L10

Did you really mean 'Multiplatform'?

Starting with v0.10.0, the LEAP SDK ships from a single Kotlin Multiplatform codebase. The two previously separate distributions (the Android-only `ai.liquid.leap:*` Maven artifacts and the iOS-only `Liquid4All/leap-ios` Swift package) were collapsed into one source tree that publishes to:

Check warning on line 12 in deployment/on-device/leap-sdk-changelog.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai) - vale-spellcheck

deployment/on-device/leap-sdk-changelog.mdx#L12

Did you really mean 'Multiplatform'?

Check warning on line 12 in deployment/on-device/leap-sdk-changelog.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai-main) - vale-spellcheck

deployment/on-device/leap-sdk-changelog.mdx#L12

Did you really mean 'Multiplatform'?

- **Swift Package Manager** — [`Liquid4All/leap-sdk`](https://github.com/Liquid4All/leap-sdk) (new repo, for iOS / macOS consumers).
- **Maven Central** — `ai.liquid.leap:*` (Android, JVM, and Kotlin/Native targets).
Expand All @@ -25,7 +25,7 @@
| `LeapSDK` | `ai.liquid.leap:leap-sdk` | Core inference + conversation API |
| `LeapModelDownloader` | `ai.liquid.leap:leap-model-downloader` | Hosted / manifest-based model fetch |
| `LeapOpenAIClient` | `ai.liquid.leap:leap-openai-client` | OpenAI-compatible cloud chat client (new in 0.10.0) |
| `LeapUI` | `ai.liquid.leap:leap-ui` | Voice assistant widget — Compose Multiplatform (new in 0.10.0) |

Check warning on line 28 in deployment/on-device/leap-sdk-changelog.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai) - vale-spellcheck

deployment/on-device/leap-sdk-changelog.mdx#L28

Did you really mean 'Multiplatform'?

Check warning on line 28 in deployment/on-device/leap-sdk-changelog.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai-main) - vale-spellcheck

deployment/on-device/leap-sdk-changelog.mdx#L28

Did you really mean 'Multiplatform'?
| `LeapSDKMacros` | _(Swift only)_ | `@Generatable` / `@Guide` constrained-generation macros |

### Breaking changes for iOS consumers
Expand All @@ -36,8 +36,8 @@

- **SPM URL change.** Point your Swift Package Manager dependency at `https://github.com/Liquid4All/leap-sdk.git` (not the deprecated `leap-ios` repo).
- **CocoaPods removed.** The SDK ships exclusively through SPM in v0.10.0 onward.
- **Toolchain bump.** Xcode 16 and Swift 6.0 are required.

Check warning on line 39 in deployment/on-device/leap-sdk-changelog.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai) - vale-spellcheck

deployment/on-device/leap-sdk-changelog.mdx#L39

Did you really mean 'Toolchain'?

Check warning on line 39 in deployment/on-device/leap-sdk-changelog.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai) - vale-spellcheck

deployment/on-device/leap-sdk-changelog.mdx#L39

Did you really mean 'Xcode'?

Check warning on line 39 in deployment/on-device/leap-sdk-changelog.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai-main) - vale-spellcheck

deployment/on-device/leap-sdk-changelog.mdx#L39

Did you really mean 'Toolchain'?

Check warning on line 39 in deployment/on-device/leap-sdk-changelog.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai-main) - vale-spellcheck

deployment/on-device/leap-sdk-changelog.mdx#L39

Did you really mean 'Xcode'?
- **Swift downloader name.** In current 0.10.x, Swift code instantiates `ModelDownloader` from the `LeapModelDownloader` SPM product. Android code still uses the Kotlin class `ai.liquid.leap.downloader.LeapModelDownloader`. See [Model Loading](/deployment/on-device/sdk/model-loading) for the constructor signatures.

Check warning on line 40 in deployment/on-device/leap-sdk-changelog.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai) - vale-spellcheck

deployment/on-device/leap-sdk-changelog.mdx#L40

Did you really mean 'downloader'?

Check warning on line 40 in deployment/on-device/leap-sdk-changelog.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai-main) - vale-spellcheck

deployment/on-device/leap-sdk-changelog.mdx#L40

Did you really mean 'downloader'?

## Major additions since 0.9.x

Expand All @@ -51,11 +51,11 @@

### Voice assistant widget

`LeapUI` / `leap-ui` is a Compose Multiplatform module that ships a drop-in voice assistant widget — an animated orb, mic button, and status label — backed by a state machine that handles recording, generation, and audio playback. Stable on iOS, macOS, Android, and JVM; Wasm/Web is present in the source tree as preview.

Check warning on line 54 in deployment/on-device/leap-sdk-changelog.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai) - vale-spellcheck

deployment/on-device/leap-sdk-changelog.mdx#L54

Did you really mean 'Multiplatform'?

Check warning on line 54 in deployment/on-device/leap-sdk-changelog.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai-main) - vale-spellcheck

deployment/on-device/leap-sdk-changelog.mdx#L54

Did you really mean 'Multiplatform'?

See [Voice Assistant Widget](/deployment/on-device/sdk/voice-assistant).

### Sideloading models from explicit paths

Check warning on line 58 in deployment/on-device/leap-sdk-changelog.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai) - vale-spellcheck

deployment/on-device/leap-sdk-changelog.mdx#L58

Did you really mean 'Sideloading'?

Check warning on line 58 in deployment/on-device/leap-sdk-changelog.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai-main) - vale-spellcheck

deployment/on-device/leap-sdk-changelog.mdx#L58

Did you really mean 'Sideloading'?

`LeapDownloader.loadSimpleModel` and `LeapModelDownloader.loadSimpleModel` load a model from explicit resource paths or URLs without going through the LEAP Model Library manifest. Useful for ADB-pushed bundles, app-bundled models, or any setup where you've already placed the model files on disk.

Expand All @@ -63,16 +63,16 @@

### iOS background downloads

The iOS / macOS Swift `ModelDownloader(sessionConfiguration:)` initializer accepts an optional `URLSessionConfiguration?` so downloads can continue when the app is suspended or killed. See [Model Loading → Constructing the downloader](/deployment/on-device/sdk/model-loading#constructing-the-downloader).

Check warning on line 66 in deployment/on-device/leap-sdk-changelog.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai) - vale-spellcheck

deployment/on-device/leap-sdk-changelog.mdx#L66

Did you really mean 'initializer'?

Check warning on line 66 in deployment/on-device/leap-sdk-changelog.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai-main) - vale-spellcheck

deployment/on-device/leap-sdk-changelog.mdx#L66

Did you really mean 'initializer'?

### `autoDetectCompanionFiles`

`Leap.load(url:options:)` on iOS gained an `autoDetectCompanionFiles: Bool = true` parameter that picks up companion files sitting next to the model file (e.g. multimodal projection weights).

Check warning on line 70 in deployment/on-device/leap-sdk-changelog.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai) - vale-spellcheck

deployment/on-device/leap-sdk-changelog.mdx#L70

Did you really mean 'multimodal'?

Check warning on line 70 in deployment/on-device/leap-sdk-changelog.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai-main) - vale-spellcheck

deployment/on-device/leap-sdk-changelog.mdx#L70

Did you really mean 'multimodal'?

### Swift ergonomics

- **Compatibility layer** keeps 0.9.x call sites (`Leap.load(...)`, `Conversation.generateResponse(...)`) compiling on top of the unified KMP surface.
- **`onEnum(of:)`** — SKIE-bridged sealed-class switching for Kotlin enums and sealed hierarchies (e.g. `MessageResponse`).

Check warning on line 75 in deployment/on-device/leap-sdk-changelog.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai) - vale-spellcheck

deployment/on-device/leap-sdk-changelog.mdx#L75

Did you really mean 'enums'?

Check warning on line 75 in deployment/on-device/leap-sdk-changelog.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai-main) - vale-spellcheck

deployment/on-device/leap-sdk-changelog.mdx#L75

Did you really mean 'enums'?
- **`ChatMessageContent` static factories** — `.text(...)`, `.image(...)`, `.audio(...)` helpers instead of constructor calls.
- **Builder-style options** — `LiquidInferenceEngineOptions.with(cacheOptions:)`, etc.

Expand All @@ -80,11 +80,11 @@

Starting in **v0.10.4** and on by default through the current release, the inference engine loads model weights via `mmap` (`use_mmap=true`). It's the default behavior for every loaded model. On mobile this is the most user-visible runtime change in the 0.10.x line. A public opt-out arrived in **v0.10.5** as `ModelLoadingOptions.useMmap: Boolean?` (Kotlin) / `LiquidInferenceEngineOptions(useMmap:)` (Swift) — leave it `null`/`nil` to keep the default, or set `false` for filesystems where `mmap` misbehaves (some Android scoped-storage paths, certain network mounts).

**What changed.** Previously the engine `read(2)`-ed the entire model file into a heap-allocated buffer before running prefill. Now it memory-maps the file: the kernel maps the on-disk weights into the process's virtual address space and loads pages lazily as they're accessed.

Check warning on line 83 in deployment/on-device/leap-sdk-changelog.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai) - vale-spellcheck

deployment/on-device/leap-sdk-changelog.mdx#L83

Did you really mean 'prefill'?

Check warning on line 83 in deployment/on-device/leap-sdk-changelog.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai-main) - vale-spellcheck

deployment/on-device/leap-sdk-changelog.mdx#L83

Did you really mean 'prefill'?

**Performance implications on mobile:**

- **Lower private RSS.** mmap'd weights are file-backed pages, not "anonymous private" RSS. iOS's jetsam and Android's low-memory killer both score apps primarily by anonymous RSS, so a 1.2B-Q4 model that previously counted as ~700 MB of dirty heap now shows as backing pages the OS may evict for free. Foreground apps are significantly less likely to be terminated under memory pressure.

Check warning on line 87 in deployment/on-device/leap-sdk-changelog.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai) - vale-spellcheck

deployment/on-device/leap-sdk-changelog.mdx#L87

Did you really mean 'mmap'd'?

Check warning on line 87 in deployment/on-device/leap-sdk-changelog.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai-main) - vale-spellcheck

deployment/on-device/leap-sdk-changelog.mdx#L87

Did you really mean 'mmap'd'?
- **Faster cold load.** The constructor returns as soon as the file is mapped — typically tens of milliseconds — instead of waiting for the entire model to be read into RAM. The first inference pays the page-in cost incrementally as the engine touches weights.
- **Faster warm reloads.** After the first load, the kernel's page cache holds the model's hot pages. Re-creating a runner on the same model (e.g. after a background termination and relaunch within the same boot) is near-instant — pages stream from the page cache, not disk.
- **Multi-model sharing.** Two processes (or two runners in one process) loading the same model file share physical pages via the page cache, with no extra RAM cost.
Expand All @@ -92,7 +92,7 @@

**Trade-offs:**

- **First-token latency on cold pages.** The first generation against a freshly-mapped model triggers page faults as the engine walks the weights. This adds disk-I/O latency to TTFT on the first call after process start. The KV cache reuse documented [above](#kv-cache-reuse-across-generations) compounds well here: cached prefixes skip both prefill compute *and* the page-fault cost for weights touched during prefill.

Check warning on line 95 in deployment/on-device/leap-sdk-changelog.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai) - vale-spellcheck

deployment/on-device/leap-sdk-changelog.mdx#L95

Did you really mean 'prefill'?

Check warning on line 95 in deployment/on-device/leap-sdk-changelog.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai) - vale-spellcheck

deployment/on-device/leap-sdk-changelog.mdx#L95

Did you really mean 'prefill'?

Check warning on line 95 in deployment/on-device/leap-sdk-changelog.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai-main) - vale-spellcheck

deployment/on-device/leap-sdk-changelog.mdx#L95

Did you really mean 'prefill'?

Check warning on line 95 in deployment/on-device/leap-sdk-changelog.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai-main) - vale-spellcheck

deployment/on-device/leap-sdk-changelog.mdx#L95

Did you really mean 'prefill'?
- **Storage type matters.** On devices with slow eMMC / external SD storage, lazy page-in can be noticeably slower than the old eager-read flow that loaded the whole file once. Internal flash on every shipped iOS device and any modern Android device is fast enough that this isn't visible in practice.
- **Opt-out available since v0.10.5.** Pass `useMmap = false` on `ModelLoadingOptions` (Kotlin) or `LiquidInferenceEngineOptions(useMmap: false)` (Swift) to force the legacy full-read loader. Use only when `mmap` misbehaves on the target filesystem; the default of `null`/`nil` keeps the engine default.

Expand All @@ -100,13 +100,13 @@

### KV cache reuse across generations

`CacheOptions` (new in v0.10.4, ergonomic Swift surface in v0.10.4.3) lets the engine persist KV-cache data between `generateResponse` calls so requests that share a prompt prefix skip the prefill work for the shared tokens.

Check warning on line 103 in deployment/on-device/leap-sdk-changelog.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai) - vale-spellcheck

deployment/on-device/leap-sdk-changelog.mdx#L103

Did you really mean 'prefill'?

Check warning on line 103 in deployment/on-device/leap-sdk-changelog.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai-main) - vale-spellcheck

deployment/on-device/leap-sdk-changelog.mdx#L103

Did you really mean 'prefill'?

<Warning>
**Disabled by default.** `cacheOptions` is `nil` (Swift) / `null` (Kotlin) until you explicitly pass `LiquidCacheOptions.enabled(path:)` / `ModelLoadingOptions.cacheOptions(path:)`. Apps that don't opt in see no prefix reuse and no on-disk cache directory created — same behavior as 0.9.x and pre-0.10.4 builds.
</Warning>

**Why it matters.** Transformer inference has two phases: **prefill** (compute keys and values for every prompt token) and **decode** (generate one new token at a time, reusing those K/V vectors). On mobile, prefill dominates time-to-first-token for any prompt longer than a few hundred tokens. With `CacheOptions` enabled, a previously seen prefix is read from disk instead of recomputed — TTFT can drop from seconds to under a hundred milliseconds on cache hits. Per-token decode cost is unchanged.

Check warning on line 109 in deployment/on-device/leap-sdk-changelog.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai) - vale-spellcheck

deployment/on-device/leap-sdk-changelog.mdx#L109

Did you really mean 'prefill'?

Check warning on line 109 in deployment/on-device/leap-sdk-changelog.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai) - vale-spellcheck

deployment/on-device/leap-sdk-changelog.mdx#L109

Did you really mean 'prefill'?

Check warning on line 109 in deployment/on-device/leap-sdk-changelog.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai-main) - vale-spellcheck

deployment/on-device/leap-sdk-changelog.mdx#L109

Did you really mean 'prefill'?

Check warning on line 109 in deployment/on-device/leap-sdk-changelog.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai-main) - vale-spellcheck

deployment/on-device/leap-sdk-changelog.mdx#L109

Did you really mean 'prefill'?

**When it speeds things up.** Anywhere the same tokens appear at the start of many requests:

Expand All @@ -114,7 +114,7 @@
- **RAG / retrieval-augmented generation.** Many queries share the retrieved-document preamble.
- **Few-shot prompting.** A fixed set of examples precedes every request.
- **Agent loops.** Tool definitions, role instructions, and task scaffold are stable across iterations.
- **Voice assistant continuations.** Conversation history grows; everything before the latest user turn is cacheable.

Check warning on line 117 in deployment/on-device/leap-sdk-changelog.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai) - vale-spellcheck

deployment/on-device/leap-sdk-changelog.mdx#L117

Did you really mean 'cacheable'?

Check warning on line 117 in deployment/on-device/leap-sdk-changelog.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai-main) - vale-spellcheck

deployment/on-device/leap-sdk-changelog.mdx#L117

Did you really mean 'cacheable'?

The cache is a bounded LRU — the engine caps cache size and evicts the least-recently-used entries automatically; you do not need to manage the directory yourself. See [Model Loading → KV cache reuse](/deployment/on-device/sdk/model-loading#kv-cache-reuse) for the per-platform configuration.

Expand Down Expand Up @@ -147,20 +147,69 @@

## Per-release notes

### v0.10.8 — 2026-05-21

SKIE finally lands on `leap-sdk-openai-client`, closing the last Apple-side gap in the unified KMP surface. In the same release, generation errors gain an in-band representation so they survive the SKIE `Flow` → `AsyncSequence` bridge.

**SKIE applied to `leap-sdk-openai-client`** ([PR #258](https://github.com/Liquid4All/leap-android-sdk/pull/258)):

- `client.streamChatCompletion(request:)` is now a Swift `AsyncSequence` — collect with `for try await event in client.streamChatCompletion(...)` instead of the v0.10.6 / v0.10.7 manual `Flow.collect(collector: FlowCollector { ... })` shape.
- `onEnum(of: event)` switches exhaustively over `ChatCompletionEvent` — the compiler errors on a missing case.
- Nested Kotlin class names are preserved on the Swift side: `ChatCompletionEvent.Delta`, `ChatCompletionEvent.Done`, `ChatCompletionEvent.Error` (previously K/N flattened these to `ChatCompletionEventDelta`, etc.). `ChatMessage.System` / `ChatMessage.User` / `ChatMessage.Assistant` follow the same convention now.
- The top-level Kotlin `fun OpenAiClient(config:)` factory exports as a real Swift convenience init — Swift call sites can drop the `OpenAiClientKt.` prefix and just write `OpenAiClient(config: ...)`.
- `LeapOpenAIClient.xcframework` is now a distributable framework (`skie { build { produceDistributableFramework() } }`) that bundles the SKIE-generated Swift wrappers, so a plain `import LeapOpenAIClient` is enough — no companion SKIE setup in consumer projects.
- The Kotlin / JVM / wasmJs / K/N surface is unchanged — same `OpenAiClient(config:)` constructor, same `Flow<ChatCompletionEvent>`, same `ChatCompletionEvent.Delta` / `.Done` / `.Error` cases, same `OpenAiClientConfig` shape and OpenRouter extra-headers support.

Check warning on line 161 in deployment/on-device/leap-sdk-changelog.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai) - vale-spellcheck

deployment/on-device/leap-sdk-changelog.mdx#L161

Did you really mean 'wasmJs'?

Check warning on line 161 in deployment/on-device/leap-sdk-changelog.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai-main) - vale-spellcheck

deployment/on-device/leap-sdk-changelog.mdx#L161

Did you really mean 'wasmJs'?

See [OpenAI-Compatible Client](/deployment/on-device/sdk/openai-client) for the updated Swift call sites.

**In-band `MessageResponse.Error` (Kotlin) / `LiquidMessageResponse.Error` (Swift compat layer)** ([PR #258](https://github.com/Liquid4All/leap-android-sdk/pull/258)):

Check warning on line 165 in deployment/on-device/leap-sdk-changelog.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai) - vale-spellcheck

deployment/on-device/leap-sdk-changelog.mdx#L165

Did you really mean 'compat'?

Check warning on line 165 in deployment/on-device/leap-sdk-changelog.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai-main) - vale-spellcheck

deployment/on-device/leap-sdk-changelog.mdx#L165

Did you really mean 'compat'?

`Conversation.generateResponse(...)` now emits a terminal `MessageResponse.Error(throwable, message)` value **before** closing the underlying channel with the same throwable. This closes a Swift gap: SKIE bridges Kotlin `Flow` to a Swift `AsyncSequence` with `Failure = Never`, so a thrown `LeapGenerationException` could not be observed from Swift — `for await response in conversation.generateResponse(...)` simply terminated silently. With the new in-band case, Swift consumers `switch onEnum(of: response)` over the `.error` arm and surface the failure to the user; Kotlin consumers using `Flow.catch { }` / `try/catch` keep working unchanged because the exceptional close is still emitted.

Check warning on line 167 in deployment/on-device/leap-sdk-changelog.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai) - vale-spellcheck

deployment/on-device/leap-sdk-changelog.mdx#L167

Did you really mean 'throwable'?

Check warning on line 167 in deployment/on-device/leap-sdk-changelog.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai-main) - vale-spellcheck

deployment/on-device/leap-sdk-changelog.mdx#L167

Did you really mean 'throwable'?

```kotlin
sealed interface MessageResponse {
// ... existing cases ...
data class Error(
val throwable: Throwable,
val message: String = throwable.message ?: throwable::class.simpleName ?: throwable.toString(),
) : MessageResponse
}
```

**Public API: additive** — binary-compatible — but exhaustive consumers need a small fix:

- **Kotlin:** add `is MessageResponse.Error -> { ... }` to any exhaustive `when (response)` over `MessageResponse`, or an `else -> { }` fallback. Statement-position `when` blocks compile with a warning today; expression-position `when` blocks (returning a value) won't compile until the new arm is added.
- **Swift:** add `case .error(let err): ...` to any `switch onEnum(of: response)` or `switch onEnum(of: liquidResponse)` — the Swift compiler enforces exhaustiveness, so call sites stop compiling against v0.10.8 until updated.

The same shape mirrors to the iOS compat layer as `LiquidMessageResponse.Error(throwable, message)` for callers still on the 0.9.x `LiquidConversation` API surface.

Check warning on line 184 in deployment/on-device/leap-sdk-changelog.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai) - vale-spellcheck

deployment/on-device/leap-sdk-changelog.mdx#L184

Did you really mean 'compat'?

Check warning on line 184 in deployment/on-device/leap-sdk-changelog.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai-main) - vale-spellcheck

deployment/on-device/leap-sdk-changelog.mdx#L184

Did you really mean 'compat'?

<Warning>
**Terminal-operator caveat (Kotlin).** Terminal operators that stop after the first matching event — `first()`, `first { ... }`, `take(1)` — may now consume the in-band `MessageResponse.Error` value and complete *normally*, where previously they would have propagated the underlying exception. Pattern-match on the result before acting (or keep a `.catch { }` operator wired up) if your retry pipeline depended on exceptional completion.
</Warning>

The `Flow` returned by `generateResponse` is now backed by an unlimited-capacity buffer (`buffer(Channel.UNLIMITED)`) so the terminal `Error` emission can never be dropped under collector backpressure — losing it would silently strand Swift callers. Generated token volume is bounded by the model's max-tokens setting, so the memory cost is negligible.

Check warning on line 190 in deployment/on-device/leap-sdk-changelog.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai) - vale-spellcheck

deployment/on-device/leap-sdk-changelog.mdx#L190

Did you really mean 'backpressure'?

Check warning on line 190 in deployment/on-device/leap-sdk-changelog.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai-main) - vale-spellcheck

deployment/on-device/leap-sdk-changelog.mdx#L190

Did you really mean 'backpressure'?

**Toolchain bumps** (no consumer-visible effect):

Check warning on line 192 in deployment/on-device/leap-sdk-changelog.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai) - vale-spellcheck

deployment/on-device/leap-sdk-changelog.mdx#L192

Did you really mean 'Toolchain'?

Check warning on line 192 in deployment/on-device/leap-sdk-changelog.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai-main) - vale-spellcheck

deployment/on-device/leap-sdk-changelog.mdx#L192

Did you really mean 'Toolchain'?

- Kotlin 2.3.20 → **2.3.21**.
- SKIE 0.10.11 → **0.10.12**.

iOS / macOS Swift consumers don't need to bump Xcode or Swift — the Xcode 16 / Swift 6 baseline from v0.10.0 still holds.

Check warning on line 197 in deployment/on-device/leap-sdk-changelog.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai) - vale-spellcheck

deployment/on-device/leap-sdk-changelog.mdx#L197

Did you really mean 'Xcode'?

Check warning on line 197 in deployment/on-device/leap-sdk-changelog.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai) - vale-spellcheck

deployment/on-device/leap-sdk-changelog.mdx#L197

Did you really mean 'Xcode'?

Check warning on line 197 in deployment/on-device/leap-sdk-changelog.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai-main) - vale-spellcheck

deployment/on-device/leap-sdk-changelog.mdx#L197

Did you really mean 'Xcode'?

Check warning on line 197 in deployment/on-device/leap-sdk-changelog.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai-main) - vale-spellcheck

deployment/on-device/leap-sdk-changelog.mdx#L197

Did you really mean 'Xcode'?

### v0.10.7 — 2026-05-18

KMP target completion for `leap-openai-client` plus a repo-wide bytecode-hardening pass. iOS / macOS Swift surface is unchanged from v0.10.6 — this is a Kotlin/JVM ergonomics release for non-Apple consumers.

**New targets on `leap-openai-client`** ([PR #256](https://github.com/Liquid4All/leap-android-sdk/pull/256)):

- **`jvm`** (Ktor CIO engine) — Maven Central now publishes `ai.liquid.leap:leap-openai-client-jvm:0.10.7`. Pure-JVM desktop / server apps can route OpenAI-compatible chat completions without dragging in Android or KMP targets. (The 0.10.0 — 0.10.6 SPM cascade only shipped Android + Apple + Linux/MinGW K/N + wasmJs metadata; the JVM slice was absent.)

Check warning on line 205 in deployment/on-device/leap-sdk-changelog.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai) - vale-spellcheck

deployment/on-device/leap-sdk-changelog.mdx#L205

Did you really mean 'Ktor'?

Check warning on line 205 in deployment/on-device/leap-sdk-changelog.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai) - vale-spellcheck

deployment/on-device/leap-sdk-changelog.mdx#L205

Did you really mean 'wasmJs'?

Check warning on line 205 in deployment/on-device/leap-sdk-changelog.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai-main) - vale-spellcheck

deployment/on-device/leap-sdk-changelog.mdx#L205

Did you really mean 'Ktor'?

Check warning on line 205 in deployment/on-device/leap-sdk-changelog.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai-main) - vale-spellcheck

deployment/on-device/leap-sdk-changelog.mdx#L205

Did you really mean 'wasmJs'?
- **`wasmJs`** (Ktor Js engine) — browser-side chat-completions client matching what `leap-sdk` already targets.

Check warning on line 206 in deployment/on-device/leap-sdk-changelog.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai) - vale-spellcheck

deployment/on-device/leap-sdk-changelog.mdx#L206

Did you really mean 'Ktor'?

Check warning on line 206 in deployment/on-device/leap-sdk-changelog.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai) - vale-spellcheck

deployment/on-device/leap-sdk-changelog.mdx#L206

Did you really mean 'Js'?

Check warning on line 206 in deployment/on-device/leap-sdk-changelog.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai-main) - vale-spellcheck

deployment/on-device/leap-sdk-changelog.mdx#L206

Did you really mean 'Ktor'?

Check warning on line 206 in deployment/on-device/leap-sdk-changelog.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai-main) - vale-spellcheck

deployment/on-device/leap-sdk-changelog.mdx#L206

Did you really mean 'Js'?

The Apple slice (`LeapOpenAIClient.xcframework`) ships unchanged — same SSE-stream surface, same `OpenAiClientConfig`, same OpenRouter extra-headers support. SKIE is still not applied to this module in v0.10.7, so the Kotlin/Native exports remain the same as v0.10.6: `Flow<ChatCompletionEvent>` is not bridged to Swift `AsyncSequence`, and `onEnum(of:)` is not generated for `ChatCompletionEvent`. **The next release will enable SKIE on `leap-sdk-openai-client`**, bringing `for try await` over the stream, exhaustive `onEnum(of:)` switching, and SKIE-bundled Swift convenience inits — see the [OpenAI client page](/deployment/on-device/sdk/openai-client) for the current pinning guidance.
The Apple slice (`LeapOpenAIClient.xcframework`) ships unchanged — same SSE-stream surface, same `OpenAiClientConfig`, same OpenRouter extra-headers support. SKIE is still not applied to this module in v0.10.7, so the Kotlin/Native exports remain the same as v0.10.6: `Flow<ChatCompletionEvent>` is not bridged to Swift `AsyncSequence`, and `onEnum(of:)` is not generated for `ChatCompletionEvent`. **[v0.10.8](#v0-10-8-2026-05-21) enables SKIE on `leap-sdk-openai-client`** — see that entry for the new Swift surface (`for try await` over the stream, exhaustive `onEnum(of:)` switching, SKIE-bundled `OpenAiClient(config:)` convenience init). Pin to v0.10.7 only if you need the pre-SKIE surface frozen.

**Bytecode hardening:**

- The `leap-sdk-jvm`, `leap-openai-client-jvm`, `leap-ui-jvm`, and `leap-ui-android` artifacts had been silently shipping Java 17 / Java 21 bytecode against the project's stated JVM-target-11 stance. All ten published JVM / Android slices now consistently emit class-file major version `0x37` (Java 11). Consumers running on JDK 11 — particularly long-running services and JDK-11-pinned Android Gradle builds — are no longer at risk of `UnsupportedClassVersionError`.

Check warning on line 212 in deployment/on-device/leap-sdk-changelog.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai) - vale-spellcheck

deployment/on-device/leap-sdk-changelog.mdx#L212

Did you really mean 'Gradle'?

Check warning on line 212 in deployment/on-device/leap-sdk-changelog.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai-main) - vale-spellcheck

deployment/on-device/leap-sdk-changelog.mdx#L212

Did you really mean 'Gradle'?

**Internal: KMP build centralization** (no consumer-visible API change):

Expand All @@ -173,7 +222,7 @@

**iOS surface (unchanged from v0.10.6):**

The four XCFrameworks (`LeapSDK`, `LeapModelDownloader`, `LeapOpenAIClient`, `LeapUi`) ship the same Swift APIs as v0.10.6. The v0.10.6 ObjC class rename to `ModelDownloader`, the dual-import guard, the dynamic `LeapModelDownloader` framework, and the `LeapDownloaderConfig()` parameterless init all remain in place.

Check warning on line 225 in deployment/on-device/leap-sdk-changelog.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai) - vale-spellcheck

deployment/on-device/leap-sdk-changelog.mdx#L225

Did you really mean 'XCFrameworks'?

Check warning on line 225 in deployment/on-device/leap-sdk-changelog.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai-main) - vale-spellcheck

deployment/on-device/leap-sdk-changelog.mdx#L225

Did you really mean 'XCFrameworks'?

### v0.10.6 — 2026-05-12

Expand All @@ -181,9 +230,9 @@

**New iOS API on `ModelDownloader`:**

- **`loadModel(modelName:, quantizationType:, options:, generationTimeParameters:, forceDownload:, downloadProgress:)`** — downloads (when needed) and loads in one call. The transfer registers in `queryStatus`, is cancellable via `requestStopDownload`, and continues across backgrounding when constructed with `sessionConfiguration: .backgroundSessionConfiguration(withIdentifier:)`.

Check warning on line 233 in deployment/on-device/leap-sdk-changelog.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai) - vale-spellcheck

deployment/on-device/leap-sdk-changelog.mdx#L233

Did you really mean 'backgrounding'?

Check warning on line 233 in deployment/on-device/leap-sdk-changelog.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai-main) - vale-spellcheck

deployment/on-device/leap-sdk-changelog.mdx#L233

Did you really mean 'backgrounding'?
- **`loadModel(manifestUrl:, options:, generationTimeParameters:, forceDownload:, downloadProgress:)`** — same flow keyed by a manifest URL.
- **`loadSimpleModel(model: ModelSource, options:, generationTimeParameters:, downloadProgress:)`** — sideload from explicit paths or URLs; HTTPS sources stream through `URLSession`, local paths pass straight through.

Check warning on line 235 in deployment/on-device/leap-sdk-changelog.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai) - vale-spellcheck

deployment/on-device/leap-sdk-changelog.mdx#L235

Did you really mean 'sideload'?

Check warning on line 235 in deployment/on-device/leap-sdk-changelog.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai-main) - vale-spellcheck

deployment/on-device/leap-sdk-changelog.mdx#L235

Did you really mean 'sideload'?
- **`forceDownload: Bool = false`** on all three load methods. Resolves the manifest first, then deletes the local cache, then re-downloads — a registry failure on resolve leaves the previously-working cached copy intact.
- **Resource-lookup helpers** that previously lived only on the cross-platform `LeapDownloader`: `getModelResourceFolder(...)`, `getCachedManifest(...)`, `getCachedFilePath(...)`, `resolve(...)`, `deleteModelFile(...)`.
- **`requestDownloadModel(manifestUrl:, forceDownload:)`** overload for symmetry with `removeModel(manifestUrl:)` / `queryStatus(manifestUrl:)`.
Expand All @@ -197,18 +246,18 @@
```
- **Parameter labels renamed across the iOS `ModelDownloader` surface** — `model:` / `quantization:` → `modelName:` / `quantizationType:` on every method that already existed: `downloadModel(...)`, `requestDownloadModel(...)`, `requestStopDownload(...)`, `queryStatus(...)`, `removeModel(...)`, `getModelSize(...)`. Every loader now uses the same labels across Swift and Kotlin — `ModelDownloader` (iOS, macOS), `LeapModelDownloader` (Android), and `LeapDownloader` (cross-platform) all share `modelName:` / `quantizationType:`.
- **`LeapModelDownloader` SPM library product is now single-target.** It no longer bundles the `LeapSDK` target. Apps depending on this product must drop any direct `LeapSDK` SPM dependency from the same target — `import LeapModelDownloader` re-exports every LeapSDK Kotlin type (`Conversation`, `ModelRunner`, `ChatMessage`, `Leap`, the convenience extensions, …). Keeping both library products on the same target double-bundles the inference engine dylibs and triggers a build-time `#error` from the LMD umbrella header (see "dual-import guard" below); the `LeapUI` library product still bundles `LeapSDK` because LeapUI does not re-emit those types in its ObjC binding.
- **`LeapModelDownloader.xcframework` is now a dynamic framework.** It was a static archive in 0.10.5. SPM applies Embed & Sign automatically; manual integrators must add the framework with "Embed & Sign" instead of "Do Not Embed". The shipped XCFramework now also bundles the inference engine dylibs (`libinference_engine.dylib`, `libinference_engine_llamacpp_backend.dylib`, `libie_zip.dylib`) under `Frameworks/` with an `@loader_path/Frameworks` LC_RPATH — consumers using LMD on its own no longer need `LeapSDK.framework/Frameworks` on their search path.

Check warning on line 249 in deployment/on-device/leap-sdk-changelog.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai) - vale-spellcheck

deployment/on-device/leap-sdk-changelog.mdx#L249

Did you really mean 'XCFramework'?

Check warning on line 249 in deployment/on-device/leap-sdk-changelog.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai) - vale-spellcheck

deployment/on-device/leap-sdk-changelog.mdx#L249

Did you really mean 'dylibs'?

Check warning on line 249 in deployment/on-device/leap-sdk-changelog.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai-main) - vale-spellcheck

deployment/on-device/leap-sdk-changelog.mdx#L249

Did you really mean 'XCFramework'?

Check warning on line 249 in deployment/on-device/leap-sdk-changelog.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai-main) - vale-spellcheck

deployment/on-device/leap-sdk-changelog.mdx#L249

Did you really mean 'dylibs'?
- **Dual-import build-time guard.** LMD's umbrella header carries a `__has_include(<LeapSDK/LeapSDK.h>) && !defined(LEAP_DUAL_IMPORT_ALLOW)` check that fires `#error` at the consumer's preprocessing time when both `LeapSDK` and `LeapModelDownloader` frameworks are reachable in the same target. To opt out for legitimate combinations (e.g. transitive linkage via `LeapUI`), add `LEAP_DUAL_IMPORT_ALLOW=1` to `OTHER_CFLAGS`.

**New Swift conveniences:**

- **`ModelDownloader()`**, **`ModelDownloader(sessionConfiguration:)`**, **`ModelDownloader(config:)`** — Kotlin/Native ObjC export strips default-argument metadata, so 0.10.5 forced Swift callers to pass every parameter (and `LeapDownloaderConfig` has seven). These new SKIE-bundled convenience inits restore the parameterless / single-arg forms.
- **`LeapDownloaderConfig()`** parameterless convenience init mirroring the Kotlin defaults (`saveDir = "leap_models"`, `validateSha256 = true`, etc.). Same rationale — `LeapDownloaderConfig` is a Kotlin `data class` with seven defaulted fields that the ObjC export couldn't carry through.

Check warning on line 255 in deployment/on-device/leap-sdk-changelog.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai) - vale-spellcheck

deployment/on-device/leap-sdk-changelog.mdx#L255

Did you really mean 'parameterless'?

Check warning on line 255 in deployment/on-device/leap-sdk-changelog.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai-main) - vale-spellcheck

deployment/on-device/leap-sdk-changelog.mdx#L255

Did you really mean 'parameterless'?

**Behavior changes:**

- **`requestDownloadModel(forceDownload: false)`** now short-circuits when a cached manifest already exists *and* every resource referenced by that manifest is present on disk — matches both the Android downloader's idempotent-call semantics and what `queryStatus(...)` already reports. Earlier 0.10.5 builds would short-circuit on the manifest alone, leaving the caller stuck if any resource file had been removed. Pass `forceDownload: true` to re-download on top of a cache.

Check warning on line 259 in deployment/on-device/leap-sdk-changelog.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai) - vale-spellcheck

deployment/on-device/leap-sdk-changelog.mdx#L259

Did you really mean 'downloader's'?

Check warning on line 259 in deployment/on-device/leap-sdk-changelog.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai-main) - vale-spellcheck

deployment/on-device/leap-sdk-changelog.mdx#L259

Did you really mean 'downloader's'?
- **Cached-file lookup** uses Ktor URL parsing instead of substring slicing, so URLs with fragments or query strings now produce the same filename the loader expects (`getCachedFilePath` was previously brittle for those shapes).

Check warning on line 260 in deployment/on-device/leap-sdk-changelog.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai) - vale-spellcheck

deployment/on-device/leap-sdk-changelog.mdx#L260

Did you really mean 'Ktor'?

Check warning on line 260 in deployment/on-device/leap-sdk-changelog.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai) - vale-spellcheck

deployment/on-device/leap-sdk-changelog.mdx#L260

Did you really mean 'substring'?

Check warning on line 260 in deployment/on-device/leap-sdk-changelog.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai-main) - vale-spellcheck

deployment/on-device/leap-sdk-changelog.mdx#L260

Did you really mean 'Ktor'?

Check warning on line 260 in deployment/on-device/leap-sdk-changelog.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai-main) - vale-spellcheck

deployment/on-device/leap-sdk-changelog.mdx#L260

Did you really mean 'substring'?

**Fixes:**

Expand All @@ -228,11 +277,11 @@

- **`ModelLoadingOptions.cacheDir: String?` → `cacheOptions: EngineOptions.CacheOptions?`** — KV cache configuration moves to a bounded-LRU `CacheOptions` value with explicit `enabled` master switch, per-tier caps (`maxEntriesDisk`, `maxEntriesMemory`, `maxBytesMemory`), and optional `diskDisabled = true` for memory-only mode. Migrate via the `ModelLoadingOptions.cacheOptions(path = ...)` factory (preserves the historical 40-entry disk budget and sets `enabled = true`). Constructing a raw `CacheOptions` requires `enabled = true` to enable the cache — a positive `maxEntries` alone is no longer sufficient.
- **`LeapDownloader.loadModel(modelName, quantizationSlug, modelLoadingOptions, …)` → `loadModel(modelName, quantizationType, options, …)`** — parameter renames bring `LeapDownloader` in line with `LeapModelDownloader`. The same rename applies to `loadSimpleModel(model, modelLoadingOptions, …)` → `loadSimpleModel(model, options, …)` and `loadModelFromManifestUrl(…)`. Swift sites that called `downloader.loadModel(modelName:, quantizationSlug:, modelLoadingOptions:)` need to swap to `quantizationType:` / `options:` after upgrading.
- **`progress` is now nullable** (`progress: ((ProgressData) -> Unit)? = null`) — pass `null` to opt out (was an empty-lambda default).

Check warning on line 280 in deployment/on-device/leap-sdk-changelog.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai) - vale-spellcheck

deployment/on-device/leap-sdk-changelog.mdx#L280

Did you really mean 'nullable'?

Check warning on line 280 in deployment/on-device/leap-sdk-changelog.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai-main) - vale-spellcheck

deployment/on-device/leap-sdk-changelog.mdx#L280

Did you really mean 'nullable'?

**New features:**

- **`ModelLoadingOptions.useMmap: Boolean? = null`** — exposes the engine's `use_mmap` toggle to Kotlin/Swift callers. `null` (default) defers to the engine default of `true`. Set `false` only on filesystems where `mmap` misbehaves (some Android scoped-storage paths, certain network mounts). On Swift, `LiquidInferenceEngineOptions` gained a matching `.with(useMmap:)` builder. Previously mmap could not be disabled from the SDK.

Check warning on line 284 in deployment/on-device/leap-sdk-changelog.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai) - vale-spellcheck

deployment/on-device/leap-sdk-changelog.mdx#L284

Did you really mean 'mmap'?

Check warning on line 284 in deployment/on-device/leap-sdk-changelog.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai-main) - vale-spellcheck

deployment/on-device/leap-sdk-changelog.mdx#L284

Did you really mean 'mmap'?
- **Leap Model Service (Android)** — `leap-model-service` is a new optional Android service that hosts loaded models in its own process and lets multiple client apps share them. Apps using `LeapModelDownloader.loadModel(...)` route through the service transparently when it's installed on the device; otherwise they fall back to in-process loading. Per-UID session quotas, persistent foreground notification, disk-backed KV cache reuse across cold starts, and AIDL-routed `registerFunction(s)`. Pass `forceLocal = true` on `LeapModelDownloader.loadModel(...)` to bypass the service for testing. See [Model Loading](/deployment/on-device/sdk/model-loading) for the routing model.
- **Service-side load progress** — when routing through the model service, `LeapModelDownloader.loadModel`'s `progress` callback now fires for service-side downloads too (was previously local-path-only).

Expand Down Expand Up @@ -261,7 +310,7 @@
- New `with(cacheOptions:)` builders on `LiquidInferenceEngineOptions` and `LiquidInferenceEngineManifestOptions`.
- New `LiquidCacheOptions.enabled(path:)` static factory — Swift analog of `ModelLoadingOptions.cacheOptions(path:)`.

(v0.10.4.2 was staged to Sonatype but never released; superseded by 0.10.4.3.)

Check warning on line 313 in deployment/on-device/leap-sdk-changelog.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai) - vale-spellcheck

deployment/on-device/leap-sdk-changelog.mdx#L313

Did you really mean 'Sonatype'?

Check warning on line 313 in deployment/on-device/leap-sdk-changelog.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai-main) - vale-spellcheck

deployment/on-device/leap-sdk-changelog.mdx#L313

Did you really mean 'Sonatype'?

### v0.10.4.1 — 2026-05-07

Expand All @@ -269,10 +318,10 @@

### v0.10.4 — 2026-05-06

- **Bounded-LRU `CacheOptions` API** across JVM, Android, Kotlin/Native, Apple, and wasmJs.

Check warning on line 321 in deployment/on-device/leap-sdk-changelog.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai) - vale-spellcheck

deployment/on-device/leap-sdk-changelog.mdx#L321

Did you really mean 'wasmJs'?

Check warning on line 321 in deployment/on-device/leap-sdk-changelog.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai-main) - vale-spellcheck

deployment/on-device/leap-sdk-changelog.mdx#L321

Did you really mean 'wasmJs'?
- **`use_mmap=true` is now the engine default** (via vendored IE pin `v26.02.1-79+`). Model weights are memory-mapped instead of `read(2)`-ed into a heap buffer. See [Memory-mapped model loading by default](#memory-mapped-model-loading-by-default) above for the mobile performance impact.

Check warning on line 322 in deployment/on-device/leap-sdk-changelog.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai) - vale-spellcheck

deployment/on-device/leap-sdk-changelog.mdx#L322

Did you really mean 'vendored'?

Check warning on line 322 in deployment/on-device/leap-sdk-changelog.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai-main) - vale-spellcheck

deployment/on-device/leap-sdk-changelog.mdx#L322

Did you really mean 'vendored'?
- K/N Linux link fix (`--allow-shlib-undefined` for `libinference_engine.so` against modern glibc).

Check warning on line 323 in deployment/on-device/leap-sdk-changelog.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai) - vale-spellcheck

deployment/on-device/leap-sdk-changelog.mdx#L323

Did you really mean 'glibc'?

Check warning on line 323 in deployment/on-device/leap-sdk-changelog.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai-main) - vale-spellcheck

deployment/on-device/leap-sdk-changelog.mdx#L323

Did you really mean 'glibc'?
- Dynamic vendor pipeline + `DT_NEEDED`-based shipped-libs verify; `inference_engine` RUNPATH=`$ORIGIN` cascade for Linux/Windows shared vendor libs.

Check warning on line 324 in deployment/on-device/leap-sdk-changelog.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai) - vale-spellcheck

deployment/on-device/leap-sdk-changelog.mdx#L324

Did you really mean 'libs'?

Check warning on line 324 in deployment/on-device/leap-sdk-changelog.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai-main) - vale-spellcheck

deployment/on-device/leap-sdk-changelog.mdx#L324

Did you really mean 'libs'?
- `NativeLibLoader` cross-platform load fixes (resource extraction + Windows pre-load topo-retry).
- Three release-gate smokes (Linux K/N, Apple SwiftPM consumer, Windows JVM) wired into CI.

Expand All @@ -281,9 +330,9 @@
Additive fix release for Linux/MinGW Kotlin/Native consumers. Apple/SPM consumers see no API or behavior changes vs v0.10.0.

- `leap-sdk` Linux/MinGW K/N artifacts on Maven Central now publish a `-natives.zip` classifier containing the runtime `.so`/`.dll` libraries.
- New `ai.liquid.leap.nativelibs` Gradle plugin auto-wires the natives ZIP into consumer K/N executables.

Check warning on line 333 in deployment/on-device/leap-sdk-changelog.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai) - vale-spellcheck

deployment/on-device/leap-sdk-changelog.mdx#L333

Did you really mean 'Gradle'?

Check warning on line 333 in deployment/on-device/leap-sdk-changelog.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai-main) - vale-spellcheck

deployment/on-device/leap-sdk-changelog.mdx#L333

Did you really mean 'Gradle'?
- `leap-openai-client` now publishes Linux/MinGW K/N klibs.

Check warning on line 334 in deployment/on-device/leap-sdk-changelog.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai) - vale-spellcheck

deployment/on-device/leap-sdk-changelog.mdx#L334

Did you really mean 'klibs'?

Check warning on line 334 in deployment/on-device/leap-sdk-changelog.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai-main) - vale-spellcheck

deployment/on-device/leap-sdk-changelog.mdx#L334

Did you really mean 'klibs'?

### v0.10.0 — 2026-04-28

Initial Kotlin Multiplatform unification release. See [the 0.9.x → 0.10.x section above](#0-9-x-0-10-x-kotlin-multiplatform-unification) for the full migration story.

Check warning on line 338 in deployment/on-device/leap-sdk-changelog.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai) - vale-spellcheck

deployment/on-device/leap-sdk-changelog.mdx#L338

Did you really mean 'Multiplatform'?

Check warning on line 338 in deployment/on-device/leap-sdk-changelog.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai-main) - vale-spellcheck

deployment/on-device/leap-sdk-changelog.mdx#L338

Did you really mean 'Multiplatform'?
15 changes: 13 additions & 2 deletions deployment/on-device/sdk/ai-agent-usage-guide.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
description: "End-to-end recipes for building AI agents with the LEAP SDK — same patterns across iOS, macOS, Android, JVM, and native."
---

This guide walks through the patterns for building a real AI agent — multi-turn conversation, function calling with tool dispatch, multimodal inputs, and a complete view-model wiring. The cross-platform pages cover individual APIs in depth — start here for the full picture, then drill into the dedicated references when you need details.

Check warning on line 6 in deployment/on-device/sdk/ai-agent-usage-guide.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai) - vale-spellcheck

deployment/on-device/sdk/ai-agent-usage-guide.mdx#L6

Did you really mean 'multimodal'?

Check warning on line 6 in deployment/on-device/sdk/ai-agent-usage-guide.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai-main) - vale-spellcheck

deployment/on-device/sdk/ai-agent-usage-guide.mdx#L6

Did you really mean 'multimodal'?

## Architecture

Expand Down Expand Up @@ -41,7 +41,7 @@
private func handle(_ response: MessageResponse) {
switch onEnum(of: response) {
case .chunk(let chunk):
currentText += chunk.text

Check warning on line 44 in deployment/on-device/sdk/ai-agent-usage-guide.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai) - vale-spellcheck

deployment/on-device/sdk/ai-agent-usage-guide.mdx#L44

Did you really mean 'currentText'?

Check warning on line 44 in deployment/on-device/sdk/ai-agent-usage-guide.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai-main) - vale-spellcheck

deployment/on-device/sdk/ai-agent-usage-guide.mdx#L44

Did you really mean 'currentText'?
case .reasoningChunk(let reasoning):
log("Reasoning:", reasoning.reasoning)
case .functionCalls(let payload):
Expand All @@ -52,12 +52,14 @@
// `audio.samples` is `KotlinFloatArray` — bridge to `[Float]` via
// `LeapSDK.ArrayConversionsKt.floatArrayToNSData(array:)` if your
// renderer expects a Swift array (see the demo in leap-ui-demo/shared/).
audioPlayer.enqueue(audio.samples, sampleRate: Int(audio.sampleRate))

Check warning on line 55 in deployment/on-device/sdk/ai-agent-usage-guide.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai) - vale-spellcheck

deployment/on-device/sdk/ai-agent-usage-guide.mdx#L55

Did you really mean 'sampleRate'?

Check warning on line 55 in deployment/on-device/sdk/ai-agent-usage-guide.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai-main) - vale-spellcheck

deployment/on-device/sdk/ai-agent-usage-guide.mdx#L55

Did you really mean 'sampleRate'?
case .complete(let completion):
currentText = ""
if let stats = completion.stats {
log("Done: \(stats.totalTokens) tokens at \(stats.tokenPerSecond) tok/s")
}
case .error(let err):
log("Generation failed: \(err.message)")
}
}
```
Expand All @@ -69,13 +71,14 @@
is MessageResponse.Chunk -> _text.value += response.text
is MessageResponse.ReasoningChunk -> Log.d(TAG, "Reasoning: ${response.reasoning}")
is MessageResponse.FunctionCalls -> {
response.functionCalls.forEach { call -> dispatch(call) }

Check warning on line 74 in deployment/on-device/sdk/ai-agent-usage-guide.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai) - vale-spellcheck

deployment/on-device/sdk/ai-agent-usage-guide.mdx#L74

Did you really mean 'functionCalls'?

Check warning on line 74 in deployment/on-device/sdk/ai-agent-usage-guide.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai-main) - vale-spellcheck

deployment/on-device/sdk/ai-agent-usage-guide.mdx#L74

Did you really mean 'functionCalls'?
}
is MessageResponse.AudioSample -> audioPlayer.enqueue(response.samples, response.sampleRate)
is MessageResponse.Complete -> {
_text.value = ""
Log.d(TAG, "Done: ${response.stats?.totalTokens} tokens at ${response.stats?.tokenPerSecond} tok/s")
}
is MessageResponse.Error -> Log.e(TAG, "Generation failed: ${response.message}", response.throwable)
}
}
```
Expand Down Expand Up @@ -103,8 +106,10 @@
toolCalls.append(contentsOf: payload.functionCalls)
case .complete:
break
default:
case .reasoningChunk, .audioSample:
break
case .error(let err):
throw NSError(domain: "AgentLoop", code: 1, userInfo: [NSLocalizedDescriptionKey: err.message])
}
}

Expand Down Expand Up @@ -139,7 +144,10 @@
when (response) {
is MessageResponse.Chunk -> appendUI(response.text)
is MessageResponse.FunctionCalls -> toolCalls.addAll(response.functionCalls)
else -> {}
is MessageResponse.ReasoningChunk -> {}
is MessageResponse.AudioSample -> {}
is MessageResponse.Complete -> {}
is MessageResponse.Error -> throw response.throwable
}
}

Expand All @@ -163,20 +171,20 @@

Define `runtimeDispatch(_:)` as your tool-call → result router: validate arguments, call the underlying implementation, JSON-encode the result. Register the corresponding `LeapFunction` definitions on the conversation before you start the loop — see [Function Calling](./function-calling).

## Multimodal inputs

Check warning on line 174 in deployment/on-device/sdk/ai-agent-usage-guide.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai) - vale-spellcheck

deployment/on-device/sdk/ai-agent-usage-guide.mdx#L174

Did you really mean 'Multimodal'?

Check warning on line 174 in deployment/on-device/sdk/ai-agent-usage-guide.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai-main) - vale-spellcheck

deployment/on-device/sdk/ai-agent-usage-guide.mdx#L174

Did you really mean 'Multimodal'?

<Info>
**Multimodality is model-specific.** Most multimodal models ship as text + one other modality (vision OR audio), not both. Send image parts (Swift `ChatMessageContent.fromJPEGData(_:)` / Kotlin `ImageUtils.fromBitmap(...)`) only to a vision-capable model, and audio parts (Swift `ChatMessageContent.fromWAVData(_:)` / Kotlin `ChatMessageContent.Audio(...)`) only to an audio-capable model. Verify on the model's [Hugging Face card](https://huggingface.co/LiquidAI) before wiring up the input.

Check warning on line 177 in deployment/on-device/sdk/ai-agent-usage-guide.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai) - vale-spellcheck

deployment/on-device/sdk/ai-agent-usage-guide.mdx#L177

Did you really mean 'multimodal'?

Check warning on line 177 in deployment/on-device/sdk/ai-agent-usage-guide.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai-main) - vale-spellcheck

deployment/on-device/sdk/ai-agent-usage-guide.mdx#L177

Did you really mean 'multimodal'?
</Info>

<Tabs>
<Tab title="Swift (iOS / macOS)">
```swift
// Vision-capable model
let imageMessage = ChatMessage(

Check warning on line 184 in deployment/on-device/sdk/ai-agent-usage-guide.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai) - vale-spellcheck

deployment/on-device/sdk/ai-agent-usage-guide.mdx#L184

Did you really mean 'imageMessage'?

Check warning on line 184 in deployment/on-device/sdk/ai-agent-usage-guide.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai-main) - vale-spellcheck

deployment/on-device/sdk/ai-agent-usage-guide.mdx#L184

Did you really mean 'imageMessage'?
role: .user,
content: [.text("Describe what you see."), ChatMessageContent.fromJPEGData(jpegData)],
reasoningContent: nil,

Check warning on line 187 in deployment/on-device/sdk/ai-agent-usage-guide.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai) - vale-spellcheck

deployment/on-device/sdk/ai-agent-usage-guide.mdx#L187

Did you really mean 'reasoningContent'?

Check warning on line 187 in deployment/on-device/sdk/ai-agent-usage-guide.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai-main) - vale-spellcheck

deployment/on-device/sdk/ai-agent-usage-guide.mdx#L187

Did you really mean 'reasoningContent'?
functionCalls: nil
)

Expand All @@ -201,7 +209,7 @@
<Tab title="Kotlin (all platforms)">
```kotlin
// Vision-capable model
val imageMessage = ChatMessage(

Check warning on line 212 in deployment/on-device/sdk/ai-agent-usage-guide.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai) - vale-spellcheck

deployment/on-device/sdk/ai-agent-usage-guide.mdx#L212

Did you really mean 'imageMessage'?

Check warning on line 212 in deployment/on-device/sdk/ai-agent-usage-guide.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai-main) - vale-spellcheck

deployment/on-device/sdk/ai-agent-usage-guide.mdx#L212

Did you really mean 'imageMessage'?
role = ChatMessage.Role.USER,
content = listOf(
ChatMessageContent.Text("Describe what you see."),
Expand Down Expand Up @@ -262,7 +270,7 @@
isLoading = true
defer { isLoading = false }
do {
let runner = try await downloader.loadModel(

Check warning on line 273 in deployment/on-device/sdk/ai-agent-usage-guide.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai) - vale-spellcheck

deployment/on-device/sdk/ai-agent-usage-guide.mdx#L273

Did you really mean 'downloader'?

Check warning on line 273 in deployment/on-device/sdk/ai-agent-usage-guide.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai-main) - vale-spellcheck

deployment/on-device/sdk/ai-agent-usage-guide.mdx#L273

Did you really mean 'downloader'?
modelName: "LFM2.5-1.2B-Instruct",
quantizationType: "Q4_K_M"
)
Expand Down Expand Up @@ -317,6 +325,8 @@
if let stats = c.stats {
print("\nFinished — \(stats.totalTokens) tokens at \(stats.tokenPerSecond) tok/s")
}
case .error(let err):
errorMessage = "Generation failed: \(err.message)"
}
}
}
Expand Down Expand Up @@ -408,6 +418,7 @@
is MessageResponse.FunctionCalls -> response.functionCalls.forEach { dispatch(it) }
is MessageResponse.AudioSample -> audioRenderer.enqueue(response.samples, response.sampleRate)
is MessageResponse.Complete -> Log.d(TAG, "Done: ${response.stats?.totalTokens} tokens")
is MessageResponse.Error -> _errorMessage.value = "Generation failed: ${response.message}"
}
}

Expand All @@ -428,7 +439,7 @@
- **Always handle every `MessageResponse` case.** Even if you only care about `.chunk` and `.complete`, give `.functionCalls`, `.audioSample`, and `.reasoningChunk` explicit (empty) branches — otherwise an exhaustive switch will fail to compile when a new variant is added.
- **Cancel before re-issuing.** Don't start a second `generateResponse(...)` while one is in flight. Either cancel the previous `Task` / `Job`, or check `conversation.isGenerating` first.
- **Don't `runBlocking` in production paths.** It's fine in `onCleared()` for guaranteed cleanup (because `viewModelScope` is already cancelled at that point). Anywhere else, it freezes the calling thread.
- **Use `cacheDir` (Android) / `cachesDirectory` (iOS) for KV-cache reuse paths.** They're regenerable — letting the OS reclaim them on storage pressure is the right semantics. See [Model Loading → KV cache reuse](./model-loading#kv-cache-reuse).

Check warning on line 442 in deployment/on-device/sdk/ai-agent-usage-guide.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai) - vale-spellcheck

deployment/on-device/sdk/ai-agent-usage-guide.mdx#L442

Did you really mean 'regenerable'?

Check warning on line 442 in deployment/on-device/sdk/ai-agent-usage-guide.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai-main) - vale-spellcheck

deployment/on-device/sdk/ai-agent-usage-guide.mdx#L442

Did you really mean 'regenerable'?
- **Validate tool-call arguments before dispatching.** The `arguments: Map<String, Any?>` (Kotlin) / `[String: Any?]` (Swift) shape is unsafe by design — defensively coerce types and apply business-level invariants.
- **Match the model's recommended sampling parameters.** The LEAP bundle manifest (`sampling_parameters` under `generation_time_parameters` in each `<Quant>.json` on [LiquidAI/LeapBundles](https://huggingface.co/LiquidAI/LeapBundles)) carries defaults tuned per checkpoint for the llama.cpp engine the SDK runs. Overriding `temperature` and friends often hurts quality more than it helps — start from the manifest values rather than the HF model card defaults (the two can differ).

Expand All @@ -437,22 +448,22 @@
<Tabs>
<Tab title="iOS / macOS">
- iOS deployment target: **17.0+** · macOS: **15.0+**
- Xcode 16.0+, Swift 6.0

Check warning on line 451 in deployment/on-device/sdk/ai-agent-usage-guide.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai) - vale-spellcheck

deployment/on-device/sdk/ai-agent-usage-guide.mdx#L451

Did you really mean 'Xcode'?

Check warning on line 451 in deployment/on-device/sdk/ai-agent-usage-guide.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai-main) - vale-spellcheck

deployment/on-device/sdk/ai-agent-usage-guide.mdx#L451

Did you really mean 'Xcode'?
- Run model loads inside a `Task` from a `@MainActor` view model. `ModelDownloader` background downloads (via `URLSessionConfiguration.background(withIdentifier:)`) survive app suspension; see [Model Loading](./model-loading#constructing-the-downloader).
- The voice widget exists on UIKit and AppKit — see [Voice Assistant Widget](./voice-assistant).

Check warning on line 453 in deployment/on-device/sdk/ai-agent-usage-guide.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai) - vale-spellcheck

deployment/on-device/sdk/ai-agent-usage-guide.mdx#L453

Did you really mean 'UIKit'?

Check warning on line 453 in deployment/on-device/sdk/ai-agent-usage-guide.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai-main) - vale-spellcheck

deployment/on-device/sdk/ai-agent-usage-guide.mdx#L453

Did you really mean 'UIKit'?
</Tab>
<Tab title="Android">
- **Min SDK 31** (Android 12).
- Use a real device for testing — the emulator may crash loading model bundles.
- `LeapModelDownloader` (the Android one) requires `POST_NOTIFICATIONS` at runtime on Android 13+ and a few manifest entries — see [Quick Start → Install the SDK](./quick-start#2-install-the-sdk).
- Background prefetch uses `requestDownloadModel(...)`, which enqueues the WorkManager downloader and runs it as a foreground worker while files transfer. The SDK ships notification configuration via `LeapModelDownloaderNotificationConfig`.

Check warning on line 459 in deployment/on-device/sdk/ai-agent-usage-guide.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai) - vale-spellcheck

deployment/on-device/sdk/ai-agent-usage-guide.mdx#L459

Did you really mean 'prefetch'?

Check warning on line 459 in deployment/on-device/sdk/ai-agent-usage-guide.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai) - vale-spellcheck

deployment/on-device/sdk/ai-agent-usage-guide.mdx#L459

Did you really mean 'enqueues'?

Check warning on line 459 in deployment/on-device/sdk/ai-agent-usage-guide.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai-main) - vale-spellcheck

deployment/on-device/sdk/ai-agent-usage-guide.mdx#L459

Did you really mean 'prefetch'?

Check warning on line 459 in deployment/on-device/sdk/ai-agent-usage-guide.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai-main) - vale-spellcheck

deployment/on-device/sdk/ai-agent-usage-guide.mdx#L459

Did you really mean 'enqueues'?
- For most cases, hold the runner in a `ViewModel` with `viewModelScope`. Unload via `runBlocking(Dispatchers.IO) { runner.unload() }` in `onCleared()`.
</Tab>
<Tab title="JVM / Linux native / Windows native">
- JVM: JDK 11+. No `Context` parameter, no foreground service, no notifications — `LeapDownloader` is a simple async fetcher with a configurable `saveDir`.
- Linux native runtime: glibc **2.34+** (Ubuntu 22.04, Debian 12, RHEL 9 or newer). Older hosts fail at process start.

Check warning on line 464 in deployment/on-device/sdk/ai-agent-usage-guide.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai) - vale-spellcheck

deployment/on-device/sdk/ai-agent-usage-guide.mdx#L464

Did you really mean 'glibc'?

Check warning on line 464 in deployment/on-device/sdk/ai-agent-usage-guide.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai-main) - vale-spellcheck

deployment/on-device/sdk/ai-agent-usage-guide.mdx#L464

Did you really mean 'glibc'?
- Windows native: Windows 10+. DLLs co-locate next to the `.exe` (Windows' standard search order finds them).

Check warning on line 465 in deployment/on-device/sdk/ai-agent-usage-guide.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai) - vale-spellcheck

deployment/on-device/sdk/ai-agent-usage-guide.mdx#L465

Did you really mean 'DLLs'?

Check warning on line 465 in deployment/on-device/sdk/ai-agent-usage-guide.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai-main) - vale-spellcheck

deployment/on-device/sdk/ai-agent-usage-guide.mdx#L465

Did you really mean 'DLLs'?
- **Pin to 0.10.7 or newer** for Kotlin/Native — earlier 0.10.x releases (0.10.0, 0.10.1) have unresolved cinterop / linker issues that prevent producing a working executable; the fixes shipped in the 0.10.4.x point releases (SPM) and v0.10.6 / v0.10.7 (Android-SDK repo). See [Desktop & Native Platforms](./desktop-platforms).

Check warning on line 466 in deployment/on-device/sdk/ai-agent-usage-guide.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai) - vale-spellcheck

deployment/on-device/sdk/ai-agent-usage-guide.mdx#L466

Did you really mean 'cinterop'?

Check warning on line 466 in deployment/on-device/sdk/ai-agent-usage-guide.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai-main) - vale-spellcheck

deployment/on-device/sdk/ai-agent-usage-guide.mdx#L466

Did you really mean 'cinterop'?
</Tab>
</Tabs>

Expand All @@ -460,12 +471,12 @@

| Symptom | Likely cause / fix |
|---|---|
| `LeapModelLoadingException` / `LeapError.modelLoadingFailure` | Missing companion file for multimodal model (mmproj / audio decoder). Verify the manifest or pass explicit paths via `loadSimpleModel(ModelSource(...))`. |

Check warning on line 474 in deployment/on-device/sdk/ai-agent-usage-guide.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai) - vale-spellcheck

deployment/on-device/sdk/ai-agent-usage-guide.mdx#L474

Did you really mean 'multimodal'?

Check warning on line 474 in deployment/on-device/sdk/ai-agent-usage-guide.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai) - vale-spellcheck

deployment/on-device/sdk/ai-agent-usage-guide.mdx#L474

Did you really mean 'mmproj'?

Check warning on line 474 in deployment/on-device/sdk/ai-agent-usage-guide.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai-main) - vale-spellcheck

deployment/on-device/sdk/ai-agent-usage-guide.mdx#L474

Did you really mean 'multimodal'?

Check warning on line 474 in deployment/on-device/sdk/ai-agent-usage-guide.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai-main) - vale-spellcheck

deployment/on-device/sdk/ai-agent-usage-guide.mdx#L474

Did you really mean 'mmproj'?
| Model loads but generates gibberish | Wrong sampling parameters or wrong function-call parser for the model family. Check the model card; default to `LFMFunctionCallParser` for LFM models, `HermesFunctionCallParser` for Qwen3/Hermes. |
| "ZIP archive corrupted" on download | Network hiccup mid-download. `LeapDownloader` / `LeapModelDownloader` validates SHA-256, so a partial file fails the check. Remove the cache directory and retry. |
| Generation hangs after `cancel()` | Cancellation is cooperative — the engine checks between tokens. There's at most one extra token of slack. If it's longer, you may be missing a `Job` cancel or the stream is being awaited on a thread other than the one you're cancelling from. |
| Voice widget records silence | Missing microphone permission, or `AVAudioSession`/Android audio config not set to `playAndRecord` / mono / 16 kHz. See [Voice Assistant Widget](./voice-assistant). |
| K/N executable fails at start with `dlsym@GLIBC_2.34` | Runtime host's glibc is older than 2.34. Upgrade to Ubuntu 22.04+, Debian 12+, RHEL 9+, or build for an older runtime target. |

Check warning on line 479 in deployment/on-device/sdk/ai-agent-usage-guide.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai) - vale-spellcheck

deployment/on-device/sdk/ai-agent-usage-guide.mdx#L479

Did you really mean 'glibc'?

Check warning on line 479 in deployment/on-device/sdk/ai-agent-usage-guide.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai-main) - vale-spellcheck

deployment/on-device/sdk/ai-agent-usage-guide.mdx#L479

Did you really mean 'glibc'?
| Compile error "@Guide annotation missing" (Swift) | All properties on a `@Generatable` `struct` need a `@Guide`. Annotate every stored property. |

For deeper failure-mode coverage, see [Utilities → Errors](./utilities#errors).
7 changes: 6 additions & 1 deletion deployment/on-device/sdk/cloud-ai-comparison.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -53,25 +53,25 @@
</Tab>
<Tab title="Kotlin (Android)">
```kotlin
val downloader = LeapModelDownloader(context)

Check warning on line 56 in deployment/on-device/sdk/cloud-ai-comparison.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai) - vale-spellcheck

deployment/on-device/sdk/cloud-ai-comparison.mdx#L56

Did you really mean 'downloader'?

Check warning on line 56 in deployment/on-device/sdk/cloud-ai-comparison.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai-main) - vale-spellcheck

deployment/on-device/sdk/cloud-ai-comparison.mdx#L56

Did you really mean 'downloader'?
val runner = downloader.loadModel(
modelName = "LFM2.5-1.2B-Instruct",

Check warning on line 58 in deployment/on-device/sdk/cloud-ai-comparison.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai) - vale-spellcheck

deployment/on-device/sdk/cloud-ai-comparison.mdx#L58

Did you really mean 'modelName'?

Check warning on line 58 in deployment/on-device/sdk/cloud-ai-comparison.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai-main) - vale-spellcheck

deployment/on-device/sdk/cloud-ai-comparison.mdx#L58

Did you really mean 'modelName'?
quantizationType = "Q4_K_M",

Check warning on line 59 in deployment/on-device/sdk/cloud-ai-comparison.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai) - vale-spellcheck

deployment/on-device/sdk/cloud-ai-comparison.mdx#L59

Did you really mean 'quantizationType'?

Check warning on line 59 in deployment/on-device/sdk/cloud-ai-comparison.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai-main) - vale-spellcheck

deployment/on-device/sdk/cloud-ai-comparison.mdx#L59

Did you really mean 'quantizationType'?
)
```
</Tab>
<Tab title="Kotlin (JVM / native)">
```kotlin
val downloader = LeapDownloader(LeapDownloaderConfig(saveDir = cacheDir))

Check warning on line 65 in deployment/on-device/sdk/cloud-ai-comparison.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai) - vale-spellcheck

deployment/on-device/sdk/cloud-ai-comparison.mdx#L65

Did you really mean 'downloader'?

Check warning on line 65 in deployment/on-device/sdk/cloud-ai-comparison.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai) - vale-spellcheck

deployment/on-device/sdk/cloud-ai-comparison.mdx#L65

Did you really mean 'cacheDir'?

Check warning on line 65 in deployment/on-device/sdk/cloud-ai-comparison.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai-main) - vale-spellcheck

deployment/on-device/sdk/cloud-ai-comparison.mdx#L65

Did you really mean 'downloader'?

Check warning on line 65 in deployment/on-device/sdk/cloud-ai-comparison.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai-main) - vale-spellcheck

deployment/on-device/sdk/cloud-ai-comparison.mdx#L65

Did you really mean 'cacheDir'?
val runner = downloader.loadModel(
modelName = "LFM2.5-1.2B-Instruct",

Check warning on line 67 in deployment/on-device/sdk/cloud-ai-comparison.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai) - vale-spellcheck

deployment/on-device/sdk/cloud-ai-comparison.mdx#L67

Did you really mean 'modelName'?

Check warning on line 67 in deployment/on-device/sdk/cloud-ai-comparison.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai-main) - vale-spellcheck

deployment/on-device/sdk/cloud-ai-comparison.mdx#L67

Did you really mean 'modelName'?
quantizationType = "Q4_K_M",

Check warning on line 68 in deployment/on-device/sdk/cloud-ai-comparison.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai) - vale-spellcheck

deployment/on-device/sdk/cloud-ai-comparison.mdx#L68

Did you really mean 'quantizationType'?

Check warning on line 68 in deployment/on-device/sdk/cloud-ai-comparison.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai-main) - vale-spellcheck

deployment/on-device/sdk/cloud-ai-comparison.mdx#L68

Did you really mean 'quantizationType'?
)
```
</Tab>
</Tabs>

The returned `ModelRunner` plays the same role as the cloud API's client object — except it carries the model weights. Release it and you'll have to load again before generating.

Check warning on line 74 in deployment/on-device/sdk/cloud-ai-comparison.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai) - vale-spellcheck

deployment/on-device/sdk/cloud-ai-comparison.mdx#L74

Did you really mean 'API's'?

Check warning on line 74 in deployment/on-device/sdk/cloud-ai-comparison.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai-main) - vale-spellcheck

deployment/on-device/sdk/cloud-ai-comparison.mdx#L74

Did you really mean 'API's'?

## 2. Request generation

Expand Down Expand Up @@ -127,6 +127,8 @@
print("\nDone! Tokens: \(completion.stats?.totalTokens ?? 0)")
case .reasoningChunk, .audioSample, .functionCalls:
break
case .error(let err):
print("\nGeneration failed: \(err.message)")
}
}
```
Expand All @@ -137,7 +139,10 @@
when (response) {
is MessageResponse.Chunk -> print(response.text)
is MessageResponse.Complete -> println("\nDone! Tokens: ${response.stats?.totalTokens}")
else -> {}
is MessageResponse.ReasoningChunk -> {}
is MessageResponse.FunctionCalls -> {}
is MessageResponse.AudioSample -> {}
is MessageResponse.Error -> println("\nGeneration failed: ${response.message}")
}
}.collect()
```
Expand Down Expand Up @@ -187,7 +192,7 @@
```
</Tab>
<Tab title="Kotlin (Android)">
Use `viewModelScope` (or `lifecycleScope` for activity-bound work). The flow is collected on the coroutine; cancellation is cooperative.

Check warning on line 195 in deployment/on-device/sdk/cloud-ai-comparison.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai) - vale-spellcheck

deployment/on-device/sdk/cloud-ai-comparison.mdx#L195

Did you really mean 'coroutine'?

Check warning on line 195 in deployment/on-device/sdk/cloud-ai-comparison.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai-main) - vale-spellcheck

deployment/on-device/sdk/cloud-ai-comparison.mdx#L195

Did you really mean 'coroutine'?

```kotlin
class ChatViewModel(application: Application) : AndroidViewModel(application) {
Expand All @@ -214,7 +219,7 @@
```
</Tab>
<Tab title="Kotlin (JVM / native)">
Use any coroutine scope — `runBlocking` for CLIs, a custom `CoroutineScope` for server-side code, or `MainScope()` for Compose for Desktop.

Check warning on line 222 in deployment/on-device/sdk/cloud-ai-comparison.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai) - vale-spellcheck

deployment/on-device/sdk/cloud-ai-comparison.mdx#L222

Did you really mean 'coroutine'?

Check warning on line 222 in deployment/on-device/sdk/cloud-ai-comparison.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai) - vale-spellcheck

deployment/on-device/sdk/cloud-ai-comparison.mdx#L222

Did you really mean 'CLIs'?

Check warning on line 222 in deployment/on-device/sdk/cloud-ai-comparison.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai-main) - vale-spellcheck

deployment/on-device/sdk/cloud-ai-comparison.mdx#L222

Did you really mean 'coroutine'?

Check warning on line 222 in deployment/on-device/sdk/cloud-ai-comparison.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai-main) - vale-spellcheck

deployment/on-device/sdk/cloud-ai-comparison.mdx#L222

Did you really mean 'CLIs'?

```kotlin
fun main() = runBlocking {
Expand All @@ -238,7 +243,7 @@
| Concept | OpenAI | LEAP |
|---|---|---|
| Role-tagged messages | `{"role": "user", "content": "..."}` | `ChatMessage(role: .user, textContent: "...")` |
| Streaming responses | `stream=True` iterator | `SkieSwiftFlow<MessageResponse>` (Swift, iterable with `for try await`) / `Flow<MessageResponse>` (Kotlin) |

Check warning on line 246 in deployment/on-device/sdk/cloud-ai-comparison.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai) - vale-spellcheck

deployment/on-device/sdk/cloud-ai-comparison.mdx#L246

Did you really mean 'iterable'?

Check warning on line 246 in deployment/on-device/sdk/cloud-ai-comparison.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai-main) - vale-spellcheck

deployment/on-device/sdk/cloud-ai-comparison.mdx#L246

Did you really mean 'iterable'?
| Function calling | Tool definitions + `tool_calls` field | `registerFunction(LeapFunction)` + `MessageResponse.FunctionCalls` |
| Structured output | `response_format = json_schema` | Swift `options.with(jsonSchema: T.jsonSchema())` / Kotlin `setResponseFormatType<T>()` |
| Token usage stats | `usage` object on completion | `Complete.stats` (`promptTokens`, `completionTokens`, `tokenPerSecond`) |
Expand All @@ -247,8 +252,8 @@

- **No remote endpoint.** You ship the model with the app (or download it the first time it runs). Latency is bounded by device CPU/GPU, not network round-trips.
- **Explicit lifecycle.** Hold a `ModelRunner` reference; `unload()` when done. Cloud clients never load anything explicitly.
- **Multimodal inputs go in `content` array, same as OpenAI.** Image and audio parts use the same OpenAI `image_url` / `input_audio` wire format.

Check warning on line 255 in deployment/on-device/sdk/cloud-ai-comparison.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai) - vale-spellcheck

deployment/on-device/sdk/cloud-ai-comparison.mdx#L255

Did you really mean 'Multimodal'?

Check warning on line 255 in deployment/on-device/sdk/cloud-ai-comparison.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai-main) - vale-spellcheck

deployment/on-device/sdk/cloud-ai-comparison.mdx#L255

Did you really mean 'Multimodal'?
- **Companion files for multimodal models.** Vision and audio-capable models need an `mmproj` (vision) and/or audio decoder/tokenizer co-located on disk. Manifest-based loading handles this automatically; `loadSimpleModel` accepts explicit `mmprojPath` / `audioDecoderPath` / `audioTokenizerPath`.

Check warning on line 256 in deployment/on-device/sdk/cloud-ai-comparison.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai) - vale-spellcheck

deployment/on-device/sdk/cloud-ai-comparison.mdx#L256

Did you really mean 'multimodal'?

Check warning on line 256 in deployment/on-device/sdk/cloud-ai-comparison.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai-main) - vale-spellcheck

deployment/on-device/sdk/cloud-ai-comparison.mdx#L256

Did you really mean 'multimodal'?

## Next steps

Expand Down
22 changes: 20 additions & 2 deletions deployment/on-device/sdk/conversation-generation.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@

<Tabs>
<Tab title="Swift (iOS / macOS)">
`Conversation` is a Kotlin `interface` bridged to Swift as a protocol — the get-only properties surface as `{ get }` in Swift. The generation methods return a SKIE-bridged `SkieSwiftFlow<MessageResponse>` (iterable with `for try await`):

Check warning on line 63 in deployment/on-device/sdk/conversation-generation.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai) - vale-spellcheck

deployment/on-device/sdk/conversation-generation.mdx#L63

Did you really mean 'iterable'?

Check warning on line 63 in deployment/on-device/sdk/conversation-generation.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai-main) - vale-spellcheck

deployment/on-device/sdk/conversation-generation.mdx#L63

Did you really mean 'iterable'?

```swift
public protocol Conversation {
Expand Down Expand Up @@ -129,12 +129,12 @@

### Streaming generation

The async stream is the recommended way to drive generation — both platforms emit the same `MessageResponse` cases in the same order. Cancel the consuming task / coroutine to stop generation cleanly.

Check warning on line 132 in deployment/on-device/sdk/conversation-generation.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai) - vale-spellcheck

deployment/on-device/sdk/conversation-generation.mdx#L132

Did you really mean 'coroutine'?

Check warning on line 132 in deployment/on-device/sdk/conversation-generation.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai-main) - vale-spellcheck

deployment/on-device/sdk/conversation-generation.mdx#L132

Did you really mean 'coroutine'?

<Tabs>
<Tab title="Swift (iOS / macOS)">
```swift
let user = ChatMessage(role: .user, textContent: "Hello! What can you do?")

Check warning on line 137 in deployment/on-device/sdk/conversation-generation.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai) - vale-spellcheck

deployment/on-device/sdk/conversation-generation.mdx#L137

Did you really mean 'textContent'?

Check warning on line 137 in deployment/on-device/sdk/conversation-generation.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai-main) - vale-spellcheck

deployment/on-device/sdk/conversation-generation.mdx#L137

Did you really mean 'textContent'?
let options = GenerationOptions()
.with(temperature: 0.3)
.with(minP: 0.15)
Expand Down Expand Up @@ -168,6 +168,12 @@
if let stats = completion.stats {
print("Prompt tokens: \(stats.promptTokens), completion: \(stats.completionTokens)")
}
case .error(let err):
// SKIE bridges `Flow` as an `AsyncSequence` with `Failure = Never`, so the
// surrounding `for try await` cannot observe a thrown error from the Kotlin
// side. Generation failures surface as this in-band `.error` case (added in
// v0.10.8) — handle it here and present `err.message` to the user.
Comment on lines +171 to +175
print("\nGeneration failed:", err.message)
}
}
} catch {
Expand Down Expand Up @@ -199,6 +205,7 @@
is MessageResponse.FunctionCalls -> handleFunctionCalls(response.functionCalls)
is MessageResponse.AudioSample -> audioRenderer.enqueue(response.samples, response.sampleRate)
is MessageResponse.Complete -> Log.d(TAG, "Done. Stats: ${response.stats}")
is MessageResponse.Error -> Log.e(TAG, "Generation failed: ${response.message}", response.throwable)
}
}
?.catch { e -> Log.e(TAG, "Generation failed", e) }
Expand All @@ -216,12 +223,16 @@
}
```

Errors propagate as `LeapGenerationException` through the flow — handle with `.catch { ... }`.
Generation errors arrive **two ways** since v0.10.8: as a terminal `MessageResponse.Error(throwable, message)` value emitted before the flow closes (so Swift consumers, which see a SKIE-bridged `AsyncSequence` with `Failure = Never`, can react), **and** as a `LeapGenerationException` thrown when the flow closes (so `Flow.catch { ... }` and `try`/`catch` keep working). Pick one path or the other — they describe the same failure.
</Tab>
</Tabs>

<Warning>
**Terminal-operator caveat (Kotlin, v0.10.8+).** Terminal operators that stop after the first matching event — `first()`, `first { ... }`, `take(1)` — may now consume the in-band `MessageResponse.Error` value and complete *normally*, where previously they would have propagated the underlying `LeapGenerationException` exceptionally. Pattern-match on the result before acting (or keep a `.catch { }` operator wired up) if your retry pipeline depended on exceptional completion.
</Warning>

<Info>
**Cancellation.** Cancelling the Swift `Task` or the Kotlin coroutine `Job` stops generation and frees native resources. On both platforms cancellation is cooperative — the engine checks between tokens, so there's at most one extra token of slack after `cancel()`.

Check warning on line 235 in deployment/on-device/sdk/conversation-generation.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai) - vale-spellcheck

deployment/on-device/sdk/conversation-generation.mdx#L235

Did you really mean 'coroutine'?

Check warning on line 235 in deployment/on-device/sdk/conversation-generation.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai-main) - vale-spellcheck

deployment/on-device/sdk/conversation-generation.mdx#L235

Did you really mean 'coroutine'?
</Info>

### Export chat history
Expand All @@ -231,7 +242,7 @@
<Tabs>
<Tab title="Swift (iOS / macOS)">
```swift
let jsonString: String = conversation.exportToJSON()

Check warning on line 245 in deployment/on-device/sdk/conversation-generation.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai) - vale-spellcheck

deployment/on-device/sdk/conversation-generation.mdx#L245

Did you really mean 'jsonString'?

Check warning on line 245 in deployment/on-device/sdk/conversation-generation.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai-main) - vale-spellcheck

deployment/on-device/sdk/conversation-generation.mdx#L245

Did you really mean 'jsonString'?
```
</Tab>
<Tab title="Kotlin (all platforms)">
Expand Down Expand Up @@ -259,6 +270,7 @@
case functionCalls(FunctionCalls) // FunctionCalls.functionCalls — [LeapFunctionCall]
case audioSample(AudioSample) // AudioSample.samples, .sampleRate — PCM frames
case complete(Complete) // Complete.fullMessage, .finishReason, .stats
case error(Error) // Error.throwable, .message — generation failure (v0.10.8+)
}
```

Expand All @@ -276,6 +288,11 @@
val finishReason: GenerationFinishReason,
val stats: GenerationStats?,
) : MessageResponse
// v0.10.8+
data class Error(
val throwable: Throwable,
val message: String = throwable.message ?: throwable::class.simpleName ?: throwable.toString(),
) : MessageResponse
}
```
</Tab>
Expand All @@ -285,7 +302,8 @@
- **`ReasoningChunk`** — thinking-style tokens emitted by reasoning models (wrapped between `<think>` / `</think>` upstream). Only fires when `GenerationOptions.enableThinking = true` *and* the model supports it.
- **`FunctionCalls`** — one or more tool invocations the model wants you to execute. See [Function Calling](./function-calling).
- **`AudioSample`** — float32 mono PCM frames from audio-capable checkpoints. The sample rate is constant for a generation; route the frames to a renderer.
- **`Complete`** — final marker. `fullMessage` is the assembled assistant `ChatMessage` (also present in `conversation.history`). `stats` is nullable (`GenerationStats?`); when present it holds `promptTokens`, `completionTokens`, `totalTokens`, `tokenPerSecond` (non-nullable `Float`), and `cachedPromptTokens`.
- **`Complete`** — final marker for a successful generation. `fullMessage` is the assembled assistant `ChatMessage` (also present in `conversation.history`). `stats` is nullable (`GenerationStats?`); when present it holds `promptTokens`, `completionTokens`, `totalTokens`, `tokenPerSecond` (non-nullable `Float`), and `cachedPromptTokens`.

Check warning on line 305 in deployment/on-device/sdk/conversation-generation.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai) - vale-spellcheck

deployment/on-device/sdk/conversation-generation.mdx#L305

Did you really mean 'nullable'?

Check warning on line 305 in deployment/on-device/sdk/conversation-generation.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai-main) - vale-spellcheck

deployment/on-device/sdk/conversation-generation.mdx#L305

Did you really mean 'nullable'?
- **`Error`** _(v0.10.8+)_ — terminal failure event. `throwable` is the underlying cause (typically a `LeapGenerationException` or one of its subclasses); `message` defaults to `throwable.message`, falling back to the throwable's simple class name. Emitted as the final event before the flow closes — Kotlin consumers can additionally rely on `Flow.catch { }` / `try`/`catch`, but Swift consumers (which see a SKIE-bridged `AsyncSequence` with `Failure = Never`) must handle this case to detect generation failures. Partial output that arrived before the error is **not** appended to `conversation.history`. The data-class `equals` / `hashCode` falls back to reference equality on `throwable` — see the per-field comparison note in the SDK Kotlin docs if you need value-style equality.

Check warning on line 306 in deployment/on-device/sdk/conversation-generation.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai) - vale-spellcheck

deployment/on-device/sdk/conversation-generation.mdx#L306

Did you really mean 'throwable's'?

Check warning on line 306 in deployment/on-device/sdk/conversation-generation.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai-main) - vale-spellcheck

deployment/on-device/sdk/conversation-generation.mdx#L306

Did you really mean 'throwable's'?

### `GenerationFinishReason`

Expand All @@ -305,22 +323,22 @@

<Tabs>
<Tab title="Swift (iOS / macOS)">
`GenerationOptions` is a Kotlin `data class` bridged into Swift. Kotlin parameter defaults don't survive the ObjC bridge, so the canonical Swift idiom is the parameterless init plus chained `.with(...)` builders from `ConvenienceExtensions.swift`:

Check warning on line 326 in deployment/on-device/sdk/conversation-generation.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai) - vale-spellcheck

deployment/on-device/sdk/conversation-generation.mdx#L326

Did you really mean 'parameterless'?

Check warning on line 326 in deployment/on-device/sdk/conversation-generation.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai-main) - vale-spellcheck

deployment/on-device/sdk/conversation-generation.mdx#L326

Did you really mean 'parameterless'?

```swift
public class GenerationOptions {
public var temperature: Float?
public var topP: Float?
public var minP: Float?
public var repetitionPenalty: Float?

Check warning on line 333 in deployment/on-device/sdk/conversation-generation.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai) - vale-spellcheck

deployment/on-device/sdk/conversation-generation.mdx#L333

Did you really mean 'repetitionPenalty'?

Check warning on line 333 in deployment/on-device/sdk/conversation-generation.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai-main) - vale-spellcheck

deployment/on-device/sdk/conversation-generation.mdx#L333

Did you really mean 'repetitionPenalty'?
public var topK: Int32?
public var rngSeed: Int64?

Check warning on line 335 in deployment/on-device/sdk/conversation-generation.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai) - vale-spellcheck

deployment/on-device/sdk/conversation-generation.mdx#L335

Did you really mean 'rngSeed'?

Check warning on line 335 in deployment/on-device/sdk/conversation-generation.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai-main) - vale-spellcheck

deployment/on-device/sdk/conversation-generation.mdx#L335

Did you really mean 'rngSeed'?
public var jsonSchemaConstraint: String?
public var functionCallParser: LeapFunctionCallParser?
public var injectSchemaIntoPrompt: Bool // default true
public var maxTokens: Int32?

Check warning on line 339 in deployment/on-device/sdk/conversation-generation.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai) - vale-spellcheck

deployment/on-device/sdk/conversation-generation.mdx#L339

Did you really mean 'maxTokens'?

Check warning on line 339 in deployment/on-device/sdk/conversation-generation.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai-main) - vale-spellcheck

deployment/on-device/sdk/conversation-generation.mdx#L339

Did you really mean 'maxTokens'?
public var inlineThinkingTags: Bool // default false
public var enableThinking: Bool // default false

Check warning on line 341 in deployment/on-device/sdk/conversation-generation.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai) - vale-spellcheck

deployment/on-device/sdk/conversation-generation.mdx#L341

Did you really mean 'enableThinking'?

Check warning on line 341 in deployment/on-device/sdk/conversation-generation.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai-main) - vale-spellcheck

deployment/on-device/sdk/conversation-generation.mdx#L341

Did you really mean 'enableThinking'?
public var extras: String?

public convenience init() // builder entry point
Expand Down Expand Up @@ -390,12 +408,12 @@
</Tab>
</Tabs>

- **Sampling fields** (`temperature`, `topP`, `minP`, `topK`, `repetitionPenalty`) — standard sampling knobs. Use the values from the LEAP bundle manifest (`sampling_parameters` under `generation_time_parameters` in each model's `<Quant>.json` on [LiquidAI/LeapBundles](https://huggingface.co/LiquidAI/LeapBundles)); they're tuned per checkpoint by the training team and differ from the HF model card defaults (the manifest values are the llama.cpp-engine path the SDK runs). Arbitrary "0.7" defaults from generic AI tutorials usually underperform.

Check warning on line 411 in deployment/on-device/sdk/conversation-generation.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai) - vale-spellcheck

deployment/on-device/sdk/conversation-generation.mdx#L411

Did you really mean 'underperform'?

Check warning on line 411 in deployment/on-device/sdk/conversation-generation.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai-main) - vale-spellcheck

deployment/on-device/sdk/conversation-generation.mdx#L411

Did you really mean 'underperform'?
- **`rngSeed`** — set for deterministic / reproducible output (testing, debugging). Default is non-deterministic.
- **`maxTokens`** — cap the response length. The model stops after this many completion tokens (prompt tokens don't count). Defaults to "until EOS or context limit." Useful for cost control with constrained output.
- **`jsonSchemaConstraint`** — JSON Schema string for constrained generation. Use the higher-level helpers — Swift `options.with(jsonSchema: T.jsonSchema())` (or `GenerationOptionsCompat.setResponseFormat(jsonSchema:)`) / Kotlin `setResponseFormatType<T>()` — with `@Generatable` types. See [Constrained Generation](./constrained-generation).
- **`injectSchemaIntoPrompt`** — when `true` (default), the schema is appended to the system message for semantic guidance *in addition* to the structural constraint at decode time. Set `false` to skip the prompt injection (matches `llama-server` grammar mode) — saves prompt tokens for large schemas.
- **`functionCallParser`** — picks the tokenizer expected by the model. `LFMFunctionCallParser` (default) for Liquid Foundation Models; `HermesFunctionCallParser()` for Hermes/Qwen3 formats; `null` to receive raw tool-call text in `Chunk`s.

Check warning on line 416 in deployment/on-device/sdk/conversation-generation.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai) - vale-spellcheck

deployment/on-device/sdk/conversation-generation.mdx#L416

Did you really mean 'tokenizer'?

Check warning on line 416 in deployment/on-device/sdk/conversation-generation.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai-main) - vale-spellcheck

deployment/on-device/sdk/conversation-generation.mdx#L416

Did you really mean 'tokenizer'?
- **`enableThinking`** — turn on reasoning mode for models that support it (e.g. LFM2.5-Thinking). Reasoning tokens arrive as `ReasoningChunk`s.
- **`inlineThinkingTags`** — when `true`, thinking tokens are emitted as ordinary `Chunk`s with the literal `<think>...</think>` tags intact (instead of `ReasoningChunk`). `ChatMessage.reasoningContent` is still populated on the final message.
- **`extras`** — backend-specific JSON payload (internal use).
Expand All @@ -411,4 +429,4 @@
cache is disabled or missed.
```

`cachedPromptTokens` is useful for observing KV-cache effectiveness — a high ratio of cached tokens to total prompt tokens means the prefix matched and you skipped the prefill compute for those tokens.

Check warning on line 432 in deployment/on-device/sdk/conversation-generation.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai) - vale-spellcheck

deployment/on-device/sdk/conversation-generation.mdx#L432

Did you really mean 'prefill'?

Check warning on line 432 in deployment/on-device/sdk/conversation-generation.mdx

View check run for this annotation

Mintlify / Mintlify Validation (liquidai-main) - vale-spellcheck

deployment/on-device/sdk/conversation-generation.mdx#L432

Did you really mean 'prefill'?
Loading