docs(leap-sdk): update to v0.10.0#94
Conversation
The leap SDK is now a single Kotlin Multiplatform distribution published from Liquid4All/leap-sdk. The standalone Liquid4All/leap-ios repo is no longer the iOS source-of-truth. - Quick-start: drop CocoaPods + manual XCFramework tabs, document the unified leap-sdk SPM URL with five products (LeapSDK, LeapModelDownloader, LeapOpenAIClient, LeapUI, LeapSDKMacros) plus a binary-target alternative carrying verified v0.10.0 SHA256 checksums. - Bump Prerequisites to iOS 17 / macOS 15 / Swift 6 / Xcode 16. Add a warning that this silently breaks apps targeting older iOS minimums. - Agent usage guide: rewrite Package.swift snippet for leap-sdk + 0.10.0, drop CocoaPods. - Model-loading: rename ModelDownloader -> LeapModelDownloader and add the new sessionConfiguration: NSURLSessionConfiguration? init param for background downloads via NSURLSession. Add autoDetectCompanionFiles to Leap.load(url:options:). Add a "What's new in 0.10.0" section covering builder-style options, onEnum(of:) SKIE switching, and ChatMessageContent static factories.
- Quick-start: bump version banner, Gradle plugin Kotlin example (2.3.10 -> 2.3.20 to match what 0.10.0 itself was built against), and all Gradle dep snippets. Add optional leap-openai-client + leap-ui entries to both Direct and Version-catalog blocks with cross-link comments. - Agent usage guide + utilities: bump Gradle dep examples to 0.10.0. - Model-loading: add a new "loadSimpleModel (sideloaded models)" section documenting LeapModelDownloader.loadSimpleModel and LeapDownloader.loadSimpleModel for app-asset / adb-pushed / multimodal workflows. Covers absolute paths, file:// URLs (RFC 8089), and the ModelSource shape (modelPath + mmprojPath + audioDecoderPath + audioTokenizerPath).
Five Android example pages had hardcoded 0.9.4 / 0.9.7 strings. Recipe generator alone had 7 scattered version mentions across L69-L317.
Two new modules shipped in v0.10.0 — leap-ui (Compose Multiplatform voice assistant widget) and leap-openai-client (OpenAI-compatible chat completions client) — get dedicated per-platform pages. - voice-assistant (iOS + Android): VoiceAssistantStore + VoiceAssistantWidget, VoiceAudioRecorder/Player interface contracts, makeForApple() factory on iOS, AndroidAudioRecorder/Player wiring, interruptToSpeak option (new in v0.10.0), VoiceConversation adapter pattern, audio-session / permission setup. - openai-client (iOS + Android): OpenAiClient + OpenAiClientConfig, streamChatCompletion SSE flow, OpenRouter / vLLM / llama-server overrides, hybrid on-device + cloud routing example, lifecycle and shared-HttpClient guidance. - docs.json: append both slugs to the iOS SDK and Android SDK navigation groups after function-calling.
Replace the small "Compose Multiplatform" callout on each voice-assistant page with an explicit platform list — iOS, macOS, Android, JVM/desktop stable, and Web (Wasm) flagged as experimental — plus cross-links between the iOS and Android pages and a note on the AppKit / NSViewControllerRepresentable hosting story for macOS callers.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 17 out of 18 changed files in this pull request and generated 5 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| If you need to share an `HttpClient` across multiple clients (e.g. you already manage one for other Ktor-based code), use the lower-level constructor that takes a `httpClient:` you own: | ||
|
|
||
| ```swift | ||
| let shared = HttpClient(Darwin) // your own instance | ||
| let client = OpenAiClient(config: config, httpClient: shared) |
There was a problem hiding this comment.
This block is labeled as Swift but HttpClient(Darwin) is Kotlin/Ktor syntax and won’t compile as Swift. Please either replace it with a Swift-valid way to supply a shared client (if the API is bridged into Swift), or change the example/language to Kotlin and explain how sharing works on Apple platforms.
| If you need to share an `HttpClient` across multiple clients (e.g. you already manage one for other Ktor-based code), use the lower-level constructor that takes a `httpClient:` you own: | |
| ```swift | |
| let shared = HttpClient(Darwin) // your own instance | |
| let client = OpenAiClient(config: config, httpClient: shared) | |
| If you need to share an `HttpClient` across multiple clients on Apple platforms via the Kotlin/Ktor API (for example, if you already manage one for other Ktor-based code), use the lower-level constructor that takes a `httpClient` you own: | |
| ```kotlin | |
| val shared = HttpClient(Darwin) // your own instance | |
| val client = OpenAiClient(config = config, httpClient = shared) |
| withIdentifier: "com.myapp.leap.downloads" | ||
| ) | ||
| let downloader = LeapModelDownloader(sessionConfiguration: backgroundConfig) | ||
| downloader.requestDownloadModel(model: "LFM2-1.2B", quantization: "Q5_K_M") |
There was a problem hiding this comment.
This background-download example calls requestDownloadModel(model:quantization:) with string arguments, but elsewhere in the docs requestDownloadModel is used with a resolved LeapDownloadableModel (e.g. from LeapDownloadableModel.resolve(...)). Please make this example consistent with the actual API signature (either resolve a LeapDownloadableModel first, or show the correct overload if one exists).
| downloader.requestDownloadModel(model: "LFM2-1.2B", quantization: "Q5_K_M") | |
| let model = try await LeapDownloadableModel.resolve( | |
| model: "LFM2-1.2B", | |
| quantization: "Q5_K_M" | |
| ) | |
| downloader.requestDownloadModel(model) |
There was a problem hiding this comment.
Thanks for the catch — keeping the current snippet here. The requestDownloadModel(model:quantization:) string-overload is the v0.10.0 KMP API:
- Source:
leap-sdk-model-downloader/src/appleMain/kotlin/ai/liquid/leap/downloader/LeapModelDownloader.kt:222definesfun requestDownloadModel(model: String, quantization: String). - The official iOS-SDK→KMP-SDK migration guide (
leap-sdk/src/appleMain/MIGRATION.md) shows the same shape:downloader.requestDownloadModel(model: "lfm-40b", quantization: "q4_k_m")
The LeapDownloadableModel.resolve(...) pattern is the legacy 0.9.x iOS-SDK flow — that overload no longer exists on LeapModelDownloader in v0.10.0. The accordion further down in ios-quick-start-guide.mdx that still references it is a legacy bundle/Executorch path I left untouched in this PR; cleaning that up belongs in a follow-up.
| <Tab title="Binary XCFrameworks"> | ||
| For explicit pinning, declare each framework as a `.binaryTarget` in your `Package.swift`. The XCFramework assets live on the `Liquid4All/leap-sdk` v0.10.0 release page. | ||
|
|
There was a problem hiding this comment.
The “Binary XCFrameworks” installation path lists binary targets for the runtime frameworks, but it doesn’t mention how (or whether) LeapSDKMacros can be used with this approach. Since Swift macros generally can’t be consumed as .binaryTarget XCFrameworks, please clarify that constrained-generation macros require adding the SPM package product (LeapSDKMacros) via the normal SPM flow (or explicitly state they’re unavailable when pinning via binary targets).
| let apiKey: String | ||
| let baseUrl: String = "https://api.openai.com/v1" | ||
| let chatCompletionsPath: String = "/chat/completions" | ||
| let extraHeaders: [String: String] = [:] |
There was a problem hiding this comment.
The OpenAiClientConfig type is shown as a public struct but its stored properties are not public, and no public init(...) is shown. As written, this snippet wouldn’t be constructible from another module (yet earlier examples instantiate it). Please update the snippet to reflect the actual public API surface (e.g., show the initializer signature or mark the properties/init as public), or drop public if it’s meant to be illustrative only.
| let apiKey: String | |
| let baseUrl: String = "https://api.openai.com/v1" | |
| let chatCompletionsPath: String = "/chat/completions" | |
| let extraHeaders: [String: String] = [:] | |
| public let apiKey: String | |
| public let baseUrl: String | |
| public let chatCompletionsPath: String | |
| public let extraHeaders: [String: String] | |
| public init( | |
| apiKey: String, | |
| baseUrl: String = "https://api.openai.com/v1", | |
| chatCompletionsPath: String = "/chat/completions", | |
| extraHeaders: [String: String] = [:] | |
| ) { | |
| self.apiKey = apiKey | |
| self.baseUrl = baseUrl | |
| self.chatCompletionsPath = chatCompletionsPath | |
| self.extraHeaders = extraHeaders | |
| } |
| ```swift | ||
| public struct ChatCompletionRequest { | ||
| let model: String | ||
| let messages: [ChatMessage] | ||
| let temperature: Double? = nil | ||
| let topP: Double? = nil | ||
| let maxCompletionTokens: Int? = nil // Preferred for newer OpenAI versions | ||
| let maxTokens: Int? = nil // Legacy alias — some custom backends still require it | ||
| let frequencyPenalty: Double? = nil | ||
| let presencePenalty: Double? = nil | ||
| let stop: [String]? = nil | ||
| let stream: Bool = true | ||
| // OpenRouter extensions | ||
| let topK: Int? = nil | ||
| let repetitionPenalty: Double? = nil | ||
| let minP: Double? = nil | ||
| let topA: Double? = nil | ||
| let transforms: [String]? = nil | ||
| let models: [String]? = nil | ||
| let route: String? = nil | ||
| let provider: ProviderPreferences? = nil | ||
| } | ||
| ``` |
There was a problem hiding this comment.
Same issue as the config snippet: ChatCompletionRequest is presented as a public struct with non-public stored properties and no public init(...), which wouldn’t be usable from Swift call sites as shown earlier. Please adjust this to match the real public API (initializer signature / access control), or clarify that this is a simplified schema diagram rather than compilable Swift.
- ios-quick-start-guide.mdx: in the Binary XCFrameworks tab, add a warning that LeapSDKMacros is a Swift macro source target — not an XCFramework — so that install path doesn't bring @Generatable / @Guide along. Point users at the SPM-package-URL flow for macros. - openai-client.mdx: drop fake Swift `struct` blocks for OpenAiClientConfig, ChatCompletionRequest, and Usage. They're Kotlin data classes bridged through SKIE; the snippets had non- public `let`s with default values that aren't valid Swift. Replace with call-site examples + parameter tables. - openai-client.mdx Lifecycle section: drop the broken `HttpClient(Darwin)` snippet (Kotlin/Ktor syntax inside a Swift fence). Explain that the externally-managed-HttpClient overload is the Kotlin surface and isn't bridged into Swift; share the `OpenAiClient` instance itself if you need cross-consumer sharing.
Summary
The Leap SDK was unified into a single Kotlin Multiplatform distribution for v0.10.0:
Liquid4All/leap-sdk(the standaloneLiquid4All/leap-iosrepo is no longer the source-of-truth).ai.liquid.leap:leap-sdk:0.10.0etc.).leap-ui(Compose Multiplatform voice assistant widget) andleap-openai-client(OpenAI-compatible cloud chat client).This PR brings the documentation in line with the v0.10.0 release.
iOS migration
LeapSDK,LeapModelDownloader,LeapOpenAIClient,LeapUI,LeapSDKMacros. Note theLeapUI(product) vsLeapUi(binary target /import) capitalization quirk.ModelDownloader→LeapModelDownloaderthroughout. Document the newsessionConfiguration: NSURLSessionConfiguration?init parameter for backgroundNSURLSessiondownloads.autoDetectCompanionFilesonLeap.load(url:), builder-style.with(...)options, exhaustiveonEnum(of:)SKIE switching,ChatMessageContentstatic factories..binaryTargetexamples.Android updates
0.10.0.leap-openai-clientandleap-uientries to both Direct and Version-catalog blocks.model-loading.mdxdocumentingLeapModelDownloader.loadSimpleModel(Android) andLeapDownloader.loadSimpleModel(cross-platform). Covers absolute paths,file://URLs (RFC 8089), and theModelSourceshape with multimodal companion files.New pages (per platform)
voice-assistant.mdx—leap-uimodule reference:VoiceAssistantStore+VoiceAssistantWidget, audio I/O contracts,makeForApple()factory (iOS),AndroidAudioRecorder/Playerwiring (Android),interruptToSpeakoption, full module surface table.openai-client.mdx—leap-openai-clientmodule reference:OpenAiClient(config)factory,streamChatCompletionSSE flow, OpenRouter / vLLM / llama-server overrides, hybrid on-device + cloud routing example, lifecycle / shared-HttpClient guidance.Examples touched
Bumped hardcoded version strings (0.9.4 / 0.9.7 → 0.10.0) in:
examples/android/vision-language-model-example.mdxexamples/android/web-content-summarizer.mdxexamples/android/slogan-generator.mdxexamples/android/leap-koog-agent.mdxexamples/android/recipe-generator-constrained-output.mdx(7 sites)Out of scope (follow-ups)
lfm/models/rather than the SDK pages.leap-model-serviceAIDL surface — separate Android-only feature worthy of its own page.Test plan
mintlify devrenders the fullDeployment > On-Device > {iOS,Android} SDKtab without MDX parser errors. (Verified locally.)voice-assistantandopenai-clientpages appear afterfunction-callingin the nav for both platforms.Package.swift, Swift, Kotlin) render with correct syntax highlighting; no stray self-closing JSX in new files.0.10.0; no leftover0.9.xorleap-ios.gitreferences.swift package resolve, confirm the four products resolve from the v0.10.0 tag and the binary-target checksums match../gradlew dependencies, confirm the four Maven Central artifacts resolve.References
leap-sdk/src/appleMain/MIGRATION.mdinside the v0.10.0 source.