LeapOpenAIClient / leap-openai-client (introduced in v0.10.0) is a small, dependency-light client for any OpenAI-compatible chat-completions endpoint β OpenAI itself, OpenRouter, vLLM, llama-server, or your own proxy. It ships in the same SDK release as LeapSDK, so you can route requests between an on-device LFM and a cloud model from a single app.
When to use it
- Hybrid on-device + cloud routing. Run small / fast models on-device with
LeapSDK, fall back to a larger cloud model for hard prompts. - Standardised cloud API. Talk to any OpenAI-compatible backend without pulling in a heavier OpenAI SDK.
- Streaming first. SSE streaming is the only mode β non-streaming requests arenβt exposed.
streamChatCompletion(...)forcesstream = trueon the outgoing request regardless of thestreamfield on theChatCompletionRequestyou pass in.
Add the dependency
- iOS / macOS (SPM)
- Android (Gradle)
- JVM (Gradle)
- Kotlin/Native (Gradle)
Add the In Swift sources,
LeapOpenAIClient product to your target. See the Quick Start for the full SPM setup.import LeapOpenAIClient. The Darwin (URLSession) Ktor engine is bundled β no extra HTTP setup needed.Basic usage
- Swift (iOS / macOS)
- Kotlin (all platforms)
Manual collection pattern (the
Flow<ChatCompletionEvent>.collect(...) shape varies by Kotlin/Native version β check the framework header in your Xcode build for the exact label):Configuration
OpenAiClientConfig is a Kotlin data class bridged identically on every platform.
| Field | Default | Notes |
|---|---|---|
apiKey | β (required) | Sent as Authorization: Bearer <apiKey>. |
baseUrl | https://api.openai.com/v1 | Override for OpenRouter, a self-hosted backend, etc. |
chatCompletionsPath | /chat/completions | Appended to baseUrl. |
extraHeaders | {} | Merged into every request β e.g. OpenRouterβs HTTP-Referer. |
OpenRouter
- Swift (iOS / macOS)
- Kotlin (all platforms)
Self-hosted vLLM / llama-server
- Swift (iOS / macOS)
- Kotlin (all platforms)
Request shape
ChatCompletionRequest covers standard OpenAI fields plus a few OpenRouter-specific extensions. OpenRouter-only fields are silently ignored by stock OpenAI-compatible APIs.
ChatMessage (the OpenAI-client one, distinct from LeapSDK.ChatMessage) is a sealed type with three cases β System, User, Assistant.
Response shape
streamChatCompletion(request) returns a Flow<ChatCompletionEvent> (Kotlin) β and the same Flow is exposed verbatim to Swift in v0.10.7 (no SKIE on this module yet, so itβs not bridged to a Swift AsyncSequence; collect it via the native Flow.collect(...) shape shown above). Events:
| Variant | Meaning |
|---|---|
Delta(content: String) | Text chunk from the model. May be empty for role-only deltas. |
Done(usage: Usage?) | Stream finished. usage is non-null when the API includes token counts. |
Error(message: String) | HTTP error or stream parsing failure. |
Hybrid routing example
Route simple prompts to a small on-device LFM; escalate harder prompts to a cloud model.- Swift (iOS / macOS)
- Kotlin (Android)
- Kotlin (JVM / native)
Lifecycle
The platformOpenAiClient(config:) factory (Kotlin fun OpenAiClient(config:) β Swift OpenAiClientKt.OpenAiClient(config:)) creates an HttpClient internally and ties it to the returned client β call close() when youβre done.
- Swift (iOS / macOS)
- Kotlin (all platforms)
HttpClient is part of the Kotlin/Ktor surface and isnβt a useful entry point from Swift β the Ktor engine machinery isnβt bridged into the public Swift API. Use OpenAiClientKt.OpenAiClient(config:) and let the SDK own the session. If multiple consumers share a client, share the OpenAiClient instance and close() once at teardown.