chore(0.10.6): bump every demo to leap-sdk 0.10.6 + adopt LMD-only iOS import#48
Open
iamstuffed wants to merge 3 commits into
Open
chore(0.10.6): bump every demo to leap-sdk 0.10.6 + adopt LMD-only iOS import#48iamstuffed wants to merge 3 commits into
iamstuffed wants to merge 3 commits into
Conversation
There was a problem hiding this comment.
Pull request overview
Adds three new desktop chat CLI examples (JVM, Linux, Windows) that load a local LeapSDK .bundle and stream assistant responses in a simple REPL, plus links from the root README so they’re discoverable alongside existing demos.
Changes:
- Introduce
JVM/LeapChatCli(Kotlin/JVM + Gradle Application) using LeapSDK0.10.1. - Introduce
Linux/LeapChatCliandWindows/LeapChatCli(Kotlin/NativelinuxX64/mingwX64) using theai.liquid.leap.nativelibsGradle plugin to extract native inference libs next to the produced binary. - Update root
README.mdto document the new desktop examples and quick-start commands.
Reviewed changes
Copilot reviewed 31 out of 34 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
README.md |
Adds JVM/Linux/Windows example sections + quick start commands and updates LeapSDK positioning to include desktop platforms. |
JVM/LeapChatCli/src/main/kotlin/ai/liquid/leap/cli/Main.kt |
Implements JVM REPL that flushes stdout for true token streaming and prints stats. |
JVM/LeapChatCli/build.gradle.kts |
Sets up Kotlin/JVM app packaging and main class entry. |
JVM/LeapChatCli/settings.gradle.kts + wrapper/catalog files |
Standalone Gradle project setup for the JVM CLI. |
Linux/LeapChatCli/src/linuxX64Main/kotlin/ai/liquid/leap/cli/Main.kt |
Implements Linux Kotlin/Native REPL (streaming + stats). |
Linux/LeapChatCli/build.gradle.kts |
Configures Kotlin/Native linuxX64 executable and Leap native-libs plugin wiring. |
Linux/LeapChatCli/README.md |
Documents Linux build/run steps and how native libs are provided. |
Linux/LeapChatCli/settings.gradle.kts + wrapper/catalog files |
Standalone Gradle project setup for the Linux CLI. |
Windows/LeapChatCli/src/mingwX64Main/kotlin/ai/liquid/leap/cli/Main.kt |
Implements Windows Kotlin/Native REPL (streaming + stats). |
Windows/LeapChatCli/build.gradle.kts |
Configures Kotlin/Native mingwX64 executable and Leap native-libs plugin wiring. |
Windows/LeapChatCli/README.md |
Documents Windows build/run steps and how native libs are provided. |
Windows/LeapChatCli/settings.gradle.kts + wrapper/catalog files |
Standalone Gradle project setup for the Windows CLI. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+51
to
+58
| conversation.generateResponse(line).collect { response -> | ||
| when (response) { | ||
| is MessageResponse.Chunk -> print(response.text) | ||
| is MessageResponse.Complete -> { | ||
| println() | ||
| response.stats?.let { stats -> | ||
| println("[${stats.completionTokens} tok, ${stats.tokenPerSecond} tok/s]") | ||
| } |
| ## Build | ||
|
|
||
| ```bash | ||
| JAVA_HOME="$(/usr/libexec/java_home -v 21)" ./gradlew linkReleaseExecutableLinuxX64 |
Comment on lines
+9
to
+17
| - Windows x86_64 host (Windows 10/11 tested; or build via WSL2 / Linux host | ||
| with mingw cross-toolchain) | ||
| - JDK 21 to run Gradle (Zulu recommended) | ||
| - A LeapSDK model bundle on local disk (e.g. `LFM2-1.2B-Q4_0.bundle`) | ||
|
|
||
| > **Note on cross-compile**: Kotlin/Native can compile `mingwX64` Kotlin code | ||
| > from any host (verified on macOS), but cross-linking the final `.exe` | ||
| > against `inference_engine.dll` from non-Windows hosts isn't supported by | ||
| > Kotlin/Native. Build + run from Windows. |
Comment on lines
+51
to
+58
| conversation.generateResponse(line).collect { response -> | ||
| when (response) { | ||
| is MessageResponse.Chunk -> print(response.text) | ||
| is MessageResponse.Complete -> { | ||
| println() | ||
| response.stats?.let { stats -> | ||
| println("[${stats.completionTokens} tok, ${stats.tokenPerSecond} tok/s]") | ||
| } |
iamstuffed
added a commit
that referenced
this pull request
Apr 29, 2026
- Linux + Windows Main.kt: flush stdout after every Chunk and after the prompt. Kotlin/Native print()/println() route through stdio which is fully buffered when stdout is not a TTY (and only line-buffered when it is) — without an explicit flush the streaming chunks would appear in one burst on Complete, defeating the REPL. Use fflush(NULL) which flushes all open output streams per POSIX, avoiding per-target stdout symbol lookup. File-level @OptIn(ExperimentalForeignApi::class) required for the cinterop fflush(null) call. - Linux README: replaced /usr/libexec/java_home (a macOS-only command) in the build instructions with a Linux-native JAVA_HOME example pointing at /usr/lib/jvm/java-21-openjdk-amd64 and a SDKMAN alternative. - Windows README: removed the conflicting "build via WSL2 / Linux host with mingw cross-toolchain" prerequisite. Kotlin/Native cross-link from non-Windows isn't supported (already noted in the cross-compile callout); WSL2 is Linux under the hood and hits the same limitation. Reworded the callout to make this explicit. Both Native targets recompile cleanly with the changes.
42e4bbf to
3e17d55
Compare
iamstuffed
added a commit
that referenced
this pull request
Apr 29, 2026
- Linux + Windows Main.kt: flush stdout after every Chunk and after the prompt. Kotlin/Native print()/println() route through stdio which is fully buffered when stdout is not a TTY (and only line-buffered when it is) — without an explicit flush the streaming chunks would appear in one burst on Complete, defeating the REPL. Use fflush(NULL) which flushes all open output streams per POSIX, avoiding per-target stdout symbol lookup. File-level @OptIn(ExperimentalForeignApi::class) required for the cinterop fflush(null) call. - Linux README: replaced /usr/libexec/java_home (a macOS-only command) in the build instructions with a Linux-native JAVA_HOME example pointing at /usr/lib/jvm/java-21-openjdk-amd64 and a SDKMAN alternative. - Windows README: removed the conflicting "build via WSL2 / Linux host with mingw cross-toolchain" prerequisite. Kotlin/Native cross-link from non-Windows isn't supported (already noted in the cross-compile callout); WSL2 is Linux under the hood and hits the same limitation. Reworded the callout to make this explicit. Both Native targets recompile cleanly with the changes.
1 task
iamstuffed
added a commit
that referenced
this pull request
May 8, 2026
Address PR #49 review. Copilot reviewer flagged that setup-java's cache: 'gradle' uses the Actions cache API and the "no GitHub API access needed" comment was imprecise. Empirically the cache works under contents: read (cache save succeeded on the prior run), but gradle/actions/setup-gradle is the proper modern path — matches the desktop-examples worktree (PR #48) and cleanly separates JDK setup from build-cache wiring. - Drop `cache: 'gradle'` from actions/setup-java. - Add gradle/actions@50e97c2 (v6.1.0, SHA-pinned). - Refine the permissions-block comment: the Actions cache is gated by the ACTIONS_RUNTIME_TOKEN, not GITHUB_TOKEN, so contents: read is sufficient.
c618176 to
037ddd4
Compare
Three new desktop chat REPL CLIs under `JVM/`, `Linux/`, `Windows/` — REPL chat apps that download the default `LFM2.5-350M` (Q4_0) bundle on first run, cache it under `./leap_models/`, and stream assistant responses to stdout. All three share the same SDK API surface — `LeapDownloader().loadModel(modelName, quantizationType, progress)` → `runner.createConversation(systemPrompt)` → `conversation.generateResponse(line).collect { … }` — so the demos illustrate the SDK's manifest-resolution flow rather than requiring users to provide a model bundle path.
- **JVM** uses `ai.liquid.leap:leap-sdk-jvm`. The published JAR bundles JNI binaries for Linux x86_64 / aarch64 / macOS / Windows via `NativeLibLoader`, so one artifact runs on every desktop OS.
- **Linux** uses Kotlin/Native (`linuxX64`) + `leap-sdk-linuxx64` and the upstream `ai.liquid.leap.nativelibs` Gradle plugin to auto-extract the per-target `.so` set (umbrella + the runtime-dispatched `libggml-cpu-{alderlake,…,zen4}.so` backends) into `build/bin/linuxX64/releaseExecutable/` so the cinterop `\$ORIGIN` rpath finds them at runtime.
- **Windows** is the `mingwX64` mirror; same plugin auto-extracts the equivalent `.dll` set.
For Kotlin/Native (Linux + Windows): the leap-sdk's bundled Ktor CIO engine doesn't support TLS on Native, so each demo injects `HttpClient(Curl) { install(ContentNegotiation) { json(...) } }` into `LeapDownloader`. The per-target Ktor Curl artifacts statically link libcurl + openssl, so no system libraries are needed at build/run time.
Also adds:
- `.github/workflows/{jvm,linux,windows}-leap-chat-cli-test.yml` — three build + smoke-test workflows. Top-level `permissions: contents: read`, `persist-credentials: false` on checkout, `gradle/actions/setup-gradle@50e97c2c # v6.1.0` (SHA-pinned), and a Sonatype-snapshot regex whitelist on the cache-purge step. Concurrency group keyed by `workflow + ref` so a fast-following push cancels the in-flight run.
- `scripts/refresh-spm-if-needed.sh` — local script for iOS/macOS demos: detects when the upstream `leap-sdk` SPM tag has been force-pushed (compares local `Package.resolved` revisions against `git ls-remote`) and clears the relevant SPM caches + `Package.resolved` files. Idempotent.
- Root `README.md` adds JVM, Linux, Windows sections and Quick Start entries for each platform.
Bring `android-leap-chat-test.yml` up to parity with the desktop CLI workflows: - Concurrency group keyed by workflow + ref. - Snapshot-purge step that compares Sonatype's `<lastUpdated>` against a marker in `~/.gradle/caches/leap-snapshot-marker` and only wipes the cache when a SNAPSHOT pin was force-republished. Whitelists the parsed `SDK_VERSION` shape before interpolating into the `curl` URL. No-op now that we're on stable. - `--refresh-dependencies` on the `gradle` invocations so Gradle's metadata TTL doesn't mask a republished snapshot.
…FM2.5-350M, and adopt the LMD-only iOS import
Tracks `ai.liquid.leap:leap-sdk:0.10.6` on Maven Central + SPM `v0.10.6` on the leap-sdk release (both live as of 2026-05-12).
Android (eight demos):
- bump `leapSdk = "0.10.6"` across all `gradle/libs.versions.toml`
- drop the Sonatype Central Portal Snapshots maven block from every `settings.gradle.kts` — stable releases live on Maven Central proper
- switch the demo model from `LFM2-350M (Q8_0)` to `LFM2.5-350M (Q4_0)` — smaller (~250 MB vs 370 MB), faster cold start, exercises 0.10.6's CPU-dispatched llamacpp backend that picks the right `libggml-cpu-<arch>` for the runner's CPU. Updates the corresponding `MainActivity` / `ViewModel` model-id strings
iOS (six demos):
- pin SPM `revision: v0.10.6` in every `project.yml`
- switch the five demos that use the downloader path (LeapChat, LeapAudio, LeapSlogan, LeapVLM, RecipeGenerator) from `import LeapSDK` to `import LeapModelDownloader`. In 0.10.6 the LMD K/N framework re-exports every leap-sdk Kotlin type via its ObjC binding + SKIE-bundled Swift overlay, so one import covers both the download surface and the SDK types those demos use
- swap each of those demos' `OTHER_LDFLAGS` / `LD_RUNPATH_SEARCH_PATHS` / `Sign nested *.dylib` post-build scripts from `LeapSDK.framework/Frameworks` to `LeapModelDownloader.framework/Frameworks` and add `-lie_zip` for the download path
- `LeapVoiceAssistantDemo` stays on the `LeapUI` SPM product — `LeapUI` doesn't `export(project(":leap-sdk"))` in its K/N framework binary, so dual-importing `LeapSDK` + `LeapUi` here is unambiguous. Top-of-file comment in its `project.yml` documents the asymmetry
- adopt the renamed `LeapDownloader.loadModel(modelName:, quantizationType:, …)` kwargs (was `model:` / `quantization:`)
- swap demo model to `LFM2.5-350M` (Q4_0), same rationale as Android
macOS / Web / desktop CLIs:
- `macOS/LeapVoiceAssistantDemo/project.yml`, `macOS/LeapVLMExample/project.yml` — SPM `revision: v0.10.6`
- `Web/LeapVoiceAssistantDemo/gradle/libs.versions.toml` — `leapSdk = "0.10.6"`
- (JVM/Linux/Windows CLIs are introduced at 0.10.6 directly in the previous feat commit)
Local-test apparatus (new):
- `scripts/use-local-sdk.sh` rewrites each iOS demo's pbxproj from the remote `https://github.com/Liquid4All/leap-sdk` SPM ref to an `XCLocalSwiftPackageReference` pointing at a leap-android-sdk worktree. Run after `xcodegen generate` (which would otherwise overwrite the local ref each time). Idempotent
- `iOS/LOCAL_TESTING.md` documents the workflow end-to-end (build XCFrameworks → link symlinks → run the rewrite script) for contributors iterating on unpublished SDK changes
Docs:
- `iOS/README.md` + `Android/RecipeGenerator/README.md` updated for the new release URL + model name
bce4b0b to
b7492ab
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Three logical commits, bundled because they ship together. Rebased onto
mainafter the security-hardening PR #49 merged — earlier 41-commit + per-version iteration history flattened.1.
feat: add JVM/Linux/Windows desktop chat-cli demos(907e1d0)Three new desktop chat REPL CLIs under
JVM/,Linux/,Windows/— REPL chat apps that download the defaultLFM2.5-350M(Q4_0) bundle on first run, cache it under./leap_models/, and stream assistant responses to stdout. All three share the same SDK API surface —LeapDownloader().loadModel(modelName, quantizationType, progress)→runner.createConversation(systemPrompt)→conversation.generateResponse(line).collect { … }— so the demos illustrate the SDK's manifest-resolution flow rather than requiring users to provide a model bundle path.ai.liquid.leap:leap-sdk-jvm. The published JAR bundles JNI binaries for Linux x86_64 / aarch64 / macOS / Windows viaNativeLibLoader, so one artifact runs on every desktop OS.linuxX64) +leap-sdk-linuxx64and the upstreamai.liquid.leap.nativelibsGradle plugin to auto-extract the per-target.soset (umbrella + the runtime-dispatchedlibggml-cpu-{alderlake,…,zen4}.sobackends) intobuild/bin/linuxX64/releaseExecutable/so the cinterop$ORIGINrpath finds them at runtime.mingwX64mirror; same plugin auto-extracts the equivalent.dllset.For Kotlin/Native (Linux + Windows): the leap-sdk's bundled Ktor CIO engine doesn't support TLS on Native, so each demo injects
HttpClient(Curl) { install(ContentNegotiation) { json(...) } }intoLeapDownloader. The per-target Ktor Curl artifacts statically link libcurl + openssl, so no system libraries are needed at build/run time.Also adds:
.github/workflows/{jvm,linux,windows}-leap-chat-cli-test.yml— three build + smoke-test workflows. Top-levelpermissions: contents: read,persist-credentials: falseon checkout,gradle/actions/setup-gradle@50e97c2c # v6.1.0(SHA-pinned), and a Sonatype-snapshot regex whitelist on the cache-purge step. Concurrency group keyed byworkflow + refso a fast-following push cancels the in-flight run.scripts/refresh-spm-if-needed.sh— local script for iOS/macOS demos: detects when the upstreamleap-sdkSPM tag has been force-pushed (compares localPackage.resolvedrevisions againstgit ls-remote) and clears the relevant SPM caches +Package.resolvedfiles. Idempotent.README.mdadds JVM, Linux, Windows sections and Quick Start entries for each platform.2.
ci: add concurrency guard + snapshot purge to android workflow(70a3afc)Bring
android-leap-chat-test.ymlup to parity with the desktop CLI workflows:<lastUpdated>against a marker in~/.gradle/caches/leap-snapshot-markerand only wipes the cache when a SNAPSHOT pin was force-republished. Whitelists the parsedSDK_VERSIONshape before interpolating into thecurlURL. No-op now that we're on stable.--refresh-dependencieson thegradleinvocations so Gradle's metadata TTL doesn't mask a republished snapshot.3.
chore(0.10.6): bump every existing demo to leap-sdk 0.10.6, swap to LFM2.5-350M, and adopt the LMD-only iOS import(b7492ab)Tracks
ai.liquid.leap:leap-sdk:0.10.6on Maven Central + SPMv0.10.6on the leap-sdk release (both live as of 2026-05-12).Android (eight demos):
leapSdk = "0.10.6"across allgradle/libs.versions.tomlsettings.gradle.kts— stable releases live on Maven Central properLFM2-350M (Q8_0)toLFM2.5-350M (Q4_0)— smaller (~250 MB vs 370 MB), faster cold start, exercises 0.10.6's CPU-dispatched llamacpp backend that picks the rightlibggml-cpu-<arch>for the runner's CPU. Updates the correspondingMainActivity/ViewModelmodel-id strings.iOS (six demos):
revision: v0.10.6in everyproject.ymlimport LeapSDKtoimport LeapModelDownloader. In 0.10.6 the LMD K/N framework re-exports every leap-sdk Kotlin type via its ObjC binding + SKIE-bundled Swift overlay, so one import covers both the download surface and the SDK types those demos use.OTHER_LDFLAGS/LD_RUNPATH_SEARCH_PATHS/Sign nested *.dylibpost-build scripts fromLeapSDK.framework/FrameworkstoLeapModelDownloader.framework/Frameworksand add-lie_zipfor the download path.LeapVoiceAssistantDemostays on theLeapUISPM product —LeapUIdoesn'texport(project(":leap-sdk"))in its K/N framework binary, so dual-importingLeapSDK+LeapUihere is unambiguous. Top-of-file comment in itsproject.ymldocuments the asymmetry.LeapDownloader.loadModel(modelName:, quantizationType:, …)kwargs (wasmodel:/quantization:).LFM2.5-350M(Q4_0), same rationale as Android.macOS / Web:
macOS/LeapVoiceAssistantDemo/project.yml,macOS/LeapVLMExample/project.yml— SPMrevision: v0.10.6.Web/LeapVoiceAssistantDemo/gradle/libs.versions.toml—leapSdk = "0.10.6".Local-test apparatus (new):
scripts/use-local-sdk.shrewrites each iOS demo's pbxproj from the remotehttps://github.com/Liquid4All/leap-sdkSPM ref to anXCLocalSwiftPackageReferencepointing at aleap-android-sdkworktree. Run afterxcodegen generate(which would otherwise overwrite the local ref each time). Idempotent.iOS/LOCAL_TESTING.mddocuments the workflow end-to-end (build XCFrameworks → link symlinks → run the rewrite script) for contributors iterating on unpublished SDK changes.Docs:
iOS/README.md+Android/RecipeGenerator/README.mdupdated for the new release URL + model name.Test plan
0.10.5references replaced with0.10.6acrossgradle/libs.versions.toml,project.yml, and READMEs (verified bygrep -r "0\.10\.5"returning empty).project.ymlonly (no Xcode CI in this repo); manual Xcode resolve required.