Skip to content

docs(leap-sdk): refresh through v0.10.8 (SKIE on openai-client + MessageResponse.Error)#100

Open
iamstuffed wants to merge 4 commits into
mainfrom
feat/leap-sdk-0.10.8
Open

docs(leap-sdk): refresh through v0.10.8 (SKIE on openai-client + MessageResponse.Error)#100
iamstuffed wants to merge 4 commits into
mainfrom
feat/leap-sdk-0.10.8

Conversation

@iamstuffed
Copy link
Copy Markdown
Collaborator

Summary

  • Refresh docs for leap-sdk v0.10.8 (source PR, commit 17f5fe1).
  • Two source changes in v0.10.8 drive every doc edit:
    1. SKIE applied to leap-sdk-openai-client — Swift consumers now get an AsyncSequence, onEnum(of:) exhaustive switching over ChatCompletionEvent, nested Kotlin type names preserved (ChatCompletionEvent.Delta instead of K/N-flattened ChatCompletionEventDelta, same for ChatMessage.System/.User/.Assistant), and a real OpenAiClient(config:) Swift convenience init from the SKIE-bundled top-level factory. Framework is now distributable so import LeapOpenAIClient is enough.
    2. New in-band MessageResponse.Error(throwable, message) sealed-class case (mirrored as LiquidMessageResponse.Error on the iOS compat layer). SKIE bridges Kotlin Flow with Failure = Never, so Swift for await could not previously observe a close(error) — generation failures silently terminated the stream. The new in-band Error value closes that gap; Kotlin behavior is unchanged (the channel still closes with the same throwable, so Flow.catch { } keeps working). The flow is also backed by buffer(Channel.UNLIMITED) so the terminal Error emission cannot be silently dropped under collector backpressure.
  • Toolchain bumps: Kotlin 2.3.20 → 2.3.21, SKIE 0.10.11 → 0.10.12 (no Xcode / Swift baseline change).

Commits

  1. docs(leap-sdk): bump example dependency pins to 0.10.8 — mechanical version bumps in the five Android example tutorials.
  2. docs(leap-sdk): add v0.10.8 changelog + document MessageResponse.Error — new `### v0.10.8 — 2026-05-21` changelog entry, updated `MessageResponse` reference block with the new `Error` case (Swift + Kotlin), and the streaming-generation examples gain explicit `.error` / `is MessageResponse.Error` arms.
  3. docs(openai-client): rewrite Swift surface for v0.10.8 SKIE bridge — every Swift code block on `openai-client.mdx` rewritten to use `OpenAiClient(config:)` + `for try await event in client.streamChatCompletion(...)` + `switch onEnum(of: event)`. Also fixes two source-vs-doc accuracy gaps from the v0.10.7 docs (the misleading `do/catch` transport-failure claim and the inaccurate "stream parsing failure" half of the `Error` row).
  4. docs(leap-sdk): bump SDK page version pins + exhaustive MessageResponse switches — version bumps across the rest of the SDK pages + every `when (response)` / `switch onEnum(of: response)` over `MessageResponse` converted from `else -> {}` / `default: break` fallback to an explicit listing of all six sealed-class arms (`Chunk`, `ReasoningChunk`, `FunctionCalls`, `AudioSample`, `Complete`, `Error`). Reader-facing rationale: under v0.10.8 the Swift compiler enforces exhaustiveness (call sites stop compiling against v0.10.8 until `.error` is added) and Kotlin statement-`when` compiles only with a warning — showing the explicit `.error` arm in every example puts the migration path right next to the surrounding code.

Outstanding (does not block review)

  • XCFramework SHA-256 values in `quick-start.mdx` are placeholders (``). The v0.10.8 GitHub release isn't published yet — once it is, a follow-up commit drops in the real checksums for the `LeapSDK`, `LeapModelDownloader`, `LeapOpenAIClient`, and `LeapUi` binary targets.

Test plan

  • `npx mintlify dev --port 3010` boots clean.
  • Every changed page probes `200` (`/deployment/on-device/leap-sdk-changelog`, `/sdk/openai-client`, `/sdk/conversation-generation`, `/sdk/quick-start`, `/sdk/ai-agent-usage-guide`, `/sdk/function-calling`, `/sdk/cloud-ai-comparison`, `/sdk/voice-assistant`, `/sdk/desktop-platforms`, plus the 5 example pages).
  • No MDX parse errors from the new exhaustive arms.
  • `scripts/generateLinkSnapshot.ts --check` passes (pre-commit hook ran each commit; `link-snapshot.yaml` clean).
  • Real XCFramework SHA-256s dropped in once v0.10.8 release publishes.
  • Spot-check on a real Xcode project that `OpenAiClient(config:)` + `for try await event in client.streamChatCompletion(...)` + `onEnum(of: event)` resolves and compiles against `leap-sdk:0.10.8`.
  • Spot-check on a real Android Studio project that the new `is MessageResponse.Error -> ...` arms compile against `ai.liquid.leap:leap-sdk:0.10.8`.

Notes for reviewers

  • The do/catch on the `conversation.generateResponse` Swift example in `conversation-generation.mdx` is intentionally left in place — the `catch` still catches Swift-side throws inside the loop body (e.g. from `handleFunctionCalls`), even though Kotlin-thrown errors now route through the in-band `.error` arm. The inline comment on `.error` makes the SKIE `Failure = Never` rationale explicit.
  • The two source-accuracy fixes on `openai-client.mdx` (transport-failure `` + `Error` variant row) were latent bugs from the v0.10.7 docs that became more visible once SKIE was applied — they're scoped to this PR since they sit in the same Swift sample I was rewriting anyway.

@iamstuffed iamstuffed marked this pull request as ready for review May 21, 2026 16:53
@iamstuffed iamstuffed requested a review from a team as a code owner May 21, 2026 16:53
Copilot AI review requested due to automatic review settings May 21, 2026 16:53
@iamstuffed iamstuffed requested a review from Paulescu as a code owner May 21, 2026 16:53
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Refreshes the on-device LEAP SDK documentation set to match leap-sdk v0.10.8, primarily reflecting (1) SKIE being applied to leap-sdk-openai-client (new Swift AsyncSequence + onEnum(of:) surface and preserved nested type names) and (2) the new in-band MessageResponse.Error case to make generation failures observable to Swift stream consumers.

Changes:

  • Bumps all dependency/version pins from 0.10.7 → 0.10.8 across SDK pages and Android examples.
  • Updates Swift OpenAI-client docs to the new SKIE-bridged surface (OpenAiClient(config:), for … await, onEnum(of:)).
  • Documents and propagates the new MessageResponse.Error case throughout streaming examples (Swift + Kotlin), making switches/when blocks exhaustive.

Reviewed changes

Copilot reviewed 16 out of 16 changed files in this pull request and generated 10 comments.

Show a summary per file
File Description
link-snapshot.yaml Adds the SDK overview route to the link snapshot allowlist.
examples/android/web-content-summarizer.mdx Updates Gradle dependency pins to v0.10.8.
examples/android/vision-language-model-example.mdx Updates Gradle dependency pins to v0.10.8.
examples/android/slogan-generator.mdx Updates Gradle dependency pins to v0.10.8.
examples/android/recipe-generator-constrained-output.mdx Updates dependency pins and referenced version text to v0.10.8.
examples/android/leap-koog-agent.mdx Updates Gradle dependency pins to v0.10.8.
deployment/on-device/sdk/voice-assistant.mdx Bumps version pins and adds explicit handling for MessageResponse.Error in examples.
deployment/on-device/sdk/quick-start.mdx Bumps “latest version” + dependency pins; adds .error handling to streaming example; updates XCFramework URLs to v0.10.8.
deployment/on-device/sdk/openai-client.mdx Rewrites Swift examples to the SKIE-bridged v0.10.8 API and updates error semantics text/table.
deployment/on-device/sdk/model-loading.mdx Updates version-scoped note from v0.10.7 → v0.10.8.
deployment/on-device/sdk/function-calling.mdx Adds explicit .error / MessageResponse.Error handling and removes catch-all branches.
deployment/on-device/sdk/desktop-platforms.mdx Bumps dependency pins; updates native ZIP coordinates and adds explicit error handling in samples.
deployment/on-device/sdk/conversation-generation.mdx Documents the new MessageResponse.Error case and updates examples/warnings accordingly.
deployment/on-device/sdk/cloud-ai-comparison.mdx Adds explicit handling for the new .error / MessageResponse.Error case.
deployment/on-device/sdk/ai-agent-usage-guide.mdx Makes response handling exhaustive and adds error propagation/handling.
deployment/on-device/leap-sdk-changelog.mdx Adds the v0.10.8 changelog entry describing SKIE-on-openai-client + in-band generation errors.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 103 to 108
```swift
.binaryTarget(
name: "LeapSDK",
url: "https://github.com/Liquid4All/leap-sdk/releases/download/v0.10.7/LeapSDK.xcframework.zip",
checksum: "6f2721aa45d7555646f78cbcaedb57aba3d869f56b24d681ad332846e131ae3d"
url: "https://github.com/Liquid4All/leap-sdk/releases/download/v0.10.8/LeapSDK.xcframework.zip",
checksum: "<copy from the v0.10.8 release page>"
),
@@ -222,11 +222,11 @@ The Leap SDK is a Kotlin Multiplatform library: the same `ModelRunner` / `Conver
// build.gradle.kts
plugins {
kotlin("multiplatform") version "2.3.20"
Comment on lines +479 to +482
case .error(let err):
// In-band failure (v0.10.8+) — SKIE bridges `Flow` with `Failure = Never`,
// so generation failures arrive here instead of on the `catch` block above.
print("Generation failed:", err.message)
@@ -194,11 +197,11 @@
// build.gradle.kts
plugins {
kotlin("multiplatform") version "2.3.20"
Comment on lines 227 to +233
```kotlin
plugins {
kotlin("multiplatform") version "2.3.20"
}

dependencies {
implementation("ai.liquid.leap:leap-sdk:0.10.7")
implementation("ai.liquid.leap:leap-sdk:0.10.8")
@@ -269,11 +272,11 @@
```kotlin
plugins {
kotlin("multiplatform") version "2.3.20"
name: "LeapSDK",
url: "https://github.com/Liquid4All/leap-sdk/releases/download/v0.10.7/LeapSDK.xcframework.zip",
url: "https://github.com/Liquid4All/leap-sdk/releases/download/v0.10.8/LeapSDK.xcframework.zip",
checksum: "6f2721aa45d7555646f78cbcaedb57aba3d869f56b24d681ad332846e131ae3d"
Comment on lines +112 to +114
<Note>
SKIE bridges Kotlin `Flow` to a Swift `AsyncSequence` with `Failure = Never`, so transport-level failures (network drop, TLS error, etc.) silently terminate the stream rather than throwing. Only HTTP-level errors (non-2xx response) arrive as in-band `.error` events; malformed SSE chunks are logged and skipped. If you need to react to silent termination, track whether `.done` was observed and treat a stream that ended without it as a transport failure.
</Note>
Comment on lines +171 to +175
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.

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

`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.
@mintlify
Copy link
Copy Markdown

mintlify Bot commented May 21, 2026

Preview deployment for your docs. Learn more about Mintlify Previews.

Project Status Preview Updated (UTC)
liquid-docs 🟢 Ready View Preview May 21, 2026, 4:59 PM

💡 Tip: Enable Workflows to automatically generate PRs for you.

Mechanical version bump across the five Android example tutorials —
`ai.liquid.leap:leap-sdk` and `ai.liquid.leap:leap-model-downloader`
Gradle pins from `0.10.7` → `0.10.8`. No prose changes; the example
snippets continue to demonstrate the same APIs.
Add the v0.10.8 release entry to the SDK changelog and the corresponding
reference-doc updates for the new in-band failure event.

Changelog (`leap-sdk-changelog.mdx`):

- Bump headline "Latest release" v0.10.7 → v0.10.8.
- Convert the v0.10.7 "next release will enable SKIE..." teaser into a
  past-tense pointer at the new v0.10.8 section so the v0.10.7 entry
  stays internally consistent.
- New `### v0.10.8 — 2026-05-21` section covering:
  - SKIE applied to `leap-sdk-openai-client` — `client.streamChatCompletion`
    is now a Swift `AsyncSequence`, `onEnum(of:)` switches exhaustively
    over `ChatCompletionEvent`, nested Kotlin class names are preserved
    (`ChatCompletionEvent.Delta` instead of K/N-flattened
    `ChatCompletionEventDelta`), and the top-level
    `fun OpenAiClient(config:)` factory exports as a real Swift
    convenience init (no more `OpenAiClientKt.` prefix). The framework is
    now distributable so a plain `import LeapOpenAIClient` is enough.
  - New in-band `MessageResponse.Error(throwable, message)` /
    `LiquidMessageResponse.Error` — closes the Swift `Failure = Never`
    gap on `Conversation.generateResponse(...)`. Kotlin consumers keep
    working unchanged because the channel still closes with the
    underlying throwable.
  - Exhaustive-`when` / `switch` migration notes for both Kotlin and
    Swift call sites.
  - Terminal-operator caveat warning — `first()` / `first { ... }` /
    `take(1)` may now consume the in-band `Error` value and complete
    *normally*, where they previously propagated exceptionally.
  - The `Flow` is now backed by `buffer(Channel.UNLIMITED)` so the
    terminal `Error` emission can never be silently dropped under
    collector backpressure.
  - Toolchain: Kotlin 2.3.20 → 2.3.21, SKIE 0.10.11 → 0.10.12. No Xcode
    or Swift baseline change.

`MessageResponse` reference (`conversation-generation.mdx`):

- Add the new sealed-class case to the Swift and Kotlin reference
  blocks: Swift `case error(Error)`; Kotlin
  `data class Error(throwable, message)` with the documented `message`
  default of `throwable.message ?: throwable::class.simpleName ?: throwable.toString()`.
- Add a bulleted entry documenting the new case alongside the existing
  ones, including the reference-equality-on-throwable caveat (since
  `Throwable` does not override `equals` / `hashCode`, the synthesised
  `data class` equality is reference-based).
- Update the streaming-generation Swift example's `switch onEnum(of:
  response)` with a `case .error(let err)` arm that explains the SKIE
  `Failure = Never` rationale inline.
- Update the streaming-generation Kotlin example's `when (response)`
  with an `is MessageResponse.Error -> Log.e(...)` arm.
- Rewrite the trailing "Errors propagate as `LeapGenerationException`"
  note into a two-paragraph explanation covering the dual error path
  (in-band `Error` value + exceptional flow close) and adding a
  `<Warning>` callout for the terminal-operator caveat.
v0.10.8 applies SKIE to `leap-sdk-openai-client`, so the entire Swift
side of the OpenAI-compatible client page needed to be rewritten — the
v0.10.7 docs described the manual `Flow.collect(collector: FlowCollector
{ ... })` shape with K/N-flattened type names. Two source-accuracy gaps
in the prior version also fixed in this pass.

SKIE surface rewrites:

- Replaced the v0.10.7 "no SKIE / manual collector" `<Warning>` with a
  v0.10.8 `<Info>` flip explaining the new surface and pointing readers
  who want the old behavior frozen to a `0.10.7` pin.
- Rewrote every Swift code block to use the new ergonomic surface:
  `OpenAiClient(config: ...)` instead of
  `OpenAiClientKt.OpenAiClient(config: ...)`; `for try await event in
  client.streamChatCompletion(request: ...)` with `switch onEnum(of:
  event) { case .delta / .done / .error }` instead of the manual
  `FlowCollector`. Affected blocks: Basic usage, OpenRouter
  configuration, self-hosted vLLM / llama-server, hybrid on-device +
  cloud routing.
- Switched all `ChatMessage` constructions from K/N-flattened
  `ChatMessageUser(content:)` / `ChatMessageSystem(content:)` to the
  SKIE-preserved nested form `ChatMessage.User(content:)` /
  `ChatMessage.System(content:)` — confirmed against the source
  `sealed interface ChatMessage { data class System, User, Assistant }`.
- Updated the Response-shape prose paragraph to drop the no-SKIE-bridge
  caveat — Swift consumers see a `AsyncSequence` now.
- Lifecycle section's Swift block dropped the `OpenAiClientKt.` prefix
  references; the SKIE-bundled `OpenAiClient(config:)` is the Swift
  entry point.

Bumped every dependency pin in the install-the-SDK Tabs from 0.10.7 →
0.10.8 (SPM `from:`, Android Gradle, JVM Gradle, Kotlin/Native Gradle).

Source-accuracy gaps caught while rewriting:

1. The Basic-usage Swift sample previously wrapped the `for try await`
   in a `do/catch` with a comment claiming that "transport-level
   failures (network drop, bad TLS, etc.) surface as a thrown error on
   the AsyncSequence." That claim is **wrong under SKIE FlowInterop with
   `Failure = Never`** — transport errors silently terminate the
   `AsyncSequence` rather than throwing. Dropped the misleading
   `do/catch` and added a `<Note>` explaining the silent-termination
   behavior, plus the "track whether `.done` was observed" workaround
   for detecting it.
2. The Response-shape table's `Error(message:)` row claimed it covers
   "HTTP error or stream parsing failure." Source contradicts the
   second half: `OpenAiClient.processChunk(...)` catches `Exception`
   from `json.decodeFromString` and `log.w { "Skipping malformed SSE
   chunk: ${e.message}" }; null` — malformed chunks are silently
   skipped, not surfaced. Updated the row to "Non-2xx HTTP response.
   Malformed SSE chunks are logged and skipped — they do not emit an
   `Error` event."
…se switches

Two related changes across the remaining SDK pages:

1. Version pins bumped 0.10.7 → 0.10.8 — every `ai.liquid.leap:*` Gradle
   coordinate, SPM `from: "0.10.7"`, `nativelibs` plugin version, the
   `gradle/libs.versions.toml` snippet, Maven `<version>` block,
   XCFramework binary-target URLs, and `*-natives@zip` classifier
   coordinates. Quick-start's XCFramework SHA-256 values were replaced
   with `<copy from the v0.10.8 release page>` placeholders since the
   v0.10.8 GitHub release wasn't live when these were drafted; a
   follow-up pass needs to drop in the real checksums.

2. Every Kotlin `when (response)` over `MessageResponse` and every Swift
   `switch onEnum(of: response)` that previously used an `else -> {}` /
   `else -> Unit` / `default: break` fallback was expanded into explicit
   arms covering all six `MessageResponse` subtypes (`Chunk`,
   `ReasoningChunk`, `FunctionCalls`, `AudioSample`, `Complete`, and the
   new `Error` case from v0.10.8). Rationale: the example code is what
   readers copy into their apps; under v0.10.8 a fallback-based pattern
   silently swallows the new `Error` arm on Kotlin (statement-`when`
   compiles with a warning, expression-`when` won't) and on Swift the
   compiler enforces exhaustiveness, so call sites stop compiling.
   Showing the explicit `.error` arm in every example puts the
   migration path right next to the surrounding code.

Per-file detail:

- `quick-start.mdx` — bump every dependency pin; XCFramework
  binary-target SHA-256s replaced with placeholders; iOS Swift
  streaming example gains `case .error(let err)` arm; Android Kotlin
  `when` gains `is MessageResponse.Error -> _errorMessage.value = ...`
  arm; Kotlin/Native quick-start `when` expanded from 2-arm + `else`
  to 6 explicit arms with `Error → System.err.println(...)`.
- `ai-agent-usage-guide.mdx` — first handler example: Swift `switch
  onEnum(of:)` gains `case .error(let err): log(...)`; Kotlin `when`
  gains `is MessageResponse.Error -> Log.e(...)`. ChatViewModel example:
  same treatment, Kotlin path writes to `_errorMessage` so SwiftUI /
  Compose can surface it. Agent-loop example: Swift `default: break`
  replaced with `case .reasoningChunk, .audioSample: break` +
  `case .error(let err): throw NSError(...)`; Kotlin `else -> {}`
  replaced with explicit no-op arms plus
  `is MessageResponse.Error -> throw response.throwable`.
- `function-calling.mdx` — Swift exhaustive case-list gains `.error`
  arm; Kotlin `when` expanded with explicit `ReasoningChunk` /
  `AudioSample` no-ops plus `Error → Log.e(...)`.
- `cloud-ai-comparison.mdx` — Swift case-list gains `.error` arm
  surfacing via `print(...)`; Kotlin `when` expanded to 6 arms.
- `voice-assistant.mdx` — bump SPM `from:` and Gradle pins; bump
  "stable release notes through v0.10.7" → "through v0.10.8"; Swift
  audio-streaming `switch` gains `case .error(let err): throw
  NSError(...)` so the surrounding `VoiceConversation` machinery
  surfaces the failure; Kotlin `when` expanded with explicit no-op
  arms plus `Error → throw response.throwable` matching the Swift
  shape.
- `desktop-platforms.mdx` — bump every dependency pin, plugin
  version, Maven `<version>`, natives-zip coords, and the XCFramework
  binary-target URL; Kotlin K/N quick-start `when` expanded to 6
  arms.
- `model-loading.mdx` — rewrite the "Sideloaded
  `LiquidInferenceEngineOptions` (URL-based load)" callout from "does
  NOT ship a Swift convenience init in v0.10.7" to "...through v0.10.8"
  so the version stays accurate — v0.10.8's SKIE-on-openai-client
  change didn't touch `LiquidInferenceEngineOptions`, so the all-12-
  fields situation is unchanged.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants